commit 09c1bdd8748385d246c99c032d49dbffeaee9051 Author: snesrev <111028570+snesrev@users.noreply.github.com> Date: Sun Mar 5 07:03:54 2023 +0100 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a8e209c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.c text +*.h text +*.cpp text + +# Declare files that will always have CRLF line endings on checkout. +*.sln text eol=crlf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e8ef78d --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.DS_Store +*.dSYM +/.vs/ +/packages/ +/saves/ +*.o +/sm +/build/ +/sm.smc +SDL2.dll +/sm.exe +/glsl-shaders/ \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..6d95add --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,54 @@ +MIT License + +Copyright (c) 2023 snesrev +Copyright (c) 2021 elzo_d + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This is the license for Opus: + +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Copyright (c) 2008-2009 Gregory Maxwell + Written by Jean-Marc Valin and Gregory Maxwell */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ec295c1 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +TARGET_EXEC:=sm + +SRCS:=$(wildcard src/*.c src/snes/*.c) third_party/gl_core/gl_core_3_1.c +OBJS:=$(SRCS:%.c=%.o) + +PYTHON:=/usr/bin/env python3 +CFLAGS:=$(if $(CFLAGS),$(CFLAGS),-O2 -Werror ) +CFLAGS:=${CFLAGS} $(shell sdl2-config --cflags) -DSYSTEM_VOLUME_MIXER_AVAILABLE=0 -I. + +ifeq (${OS},Windows_NT) + WINDRES:=windres +# RES:=sm.res + SDLFLAGS:=-Wl,-Bstatic $(shell sdl2-config --static-libs) +else + SDLFLAGS:=$(shell sdl2-config --libs) -lm +endif + +.PHONY: all clean clean_obj + +all: $(TARGET_EXEC) +$(TARGET_EXEC): $(OBJS) $(RES) + $(CC) $^ -o $@ $(LDFLAGS) $(SDLFLAGS) + +%.o : %.c + $(CC) -c $(CFLAGS) $< -o $@ + +#$(RES): src/platform/win32/sm.rc +# @echo "Generating Windows resources" +# @$(WINDRES) $< -O coff -o $@ + +clean: clean_obj +clean_obj: + @$(RM) $(OBJS) $(TARGET_EXEC) diff --git a/README.md b/README.md new file mode 100644 index 0000000..766694f --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# sm +Early version. It has bugs and the code is messy. + +Put sm.smc in the root folder. When running, it will run both versions and compare frame by frame. If it detects a mismatch, it saves a snapshot in saves/ and displays a counter on screen counting down from 300. + diff --git a/other/annotate_funcs.py b/other/annotate_funcs.py new file mode 100644 index 0000000..b5cd0ef --- /dev/null +++ b/other/annotate_funcs.py @@ -0,0 +1,59 @@ +import re + +class FuncParser: + def __init__(self): + self.functions = [] + self.lines_prefix = [] + + def read(self, filename): + current_func_name = None + state = 0 + collect = [] + c = re.compile('^(?:static )?(?:inline )?[a-zA-Z0-9_]+ \\*? *([a-zA-Z0-9_]+)\\(.*\\) {( *//.*)?$') + for line in open(filename).read().splitlines(): +# print(line) + line = line.rstrip() + if m := c.match(line): + assert state != 1 + if state == 0: + self.lines_prefix = collect + collect = [] + current_func_name = m.group(1) + state = 1 + collect.append(line) + + if line == '}': + assert state == 1 + self.functions.append((current_func_name, collect)) + collect = [] + state = 2 + +funcs = {} + +for line in open('../funcs.h'): + if m := re.match('^#define fn([^ ]+) (0x[0-9A-Fa-f]+)', line): + name, addr = m.group(1), m.group(2) + funcs[name] = addr + +import glob +for fname in glob.glob('../sm_??.cpp'): + fp = FuncParser() + fp.read(fname) + + fout = open(fname, 'w') + for c in fp.lines_prefix: + print(c, file = fout) + + for a, b in fp.functions: + if a.endswith('_Async'): + a = a[:-6] + cmt = funcs.get(a) + if cmt == None: + print('noname ', a) + for line in b: + if cmt != None and line.endswith('{'): + print(line + ' // ' + cmt, file = fout) + cmt = None + else: + print(line, file = fout) + fout.close() \ No newline at end of file diff --git a/other/strip_some.py b/other/strip_some.py new file mode 100644 index 0000000..54d04f0 --- /dev/null +++ b/other/strip_some.py @@ -0,0 +1,17 @@ +import re +import glob + +all_data = '' +for fname in glob.glob('../sm_??.cpp'): + all_data += open(fname).read() + +assert 'Eproj_NorfairLavaquakeRocks_Func1' in all_data + + +for line in open('../funcs.h').read().splitlines(): + if m := re.match('^#define fn([^ ]+) (0x[0-9A-Fa-f]+)', line): + name, addr = m.group(1), m.group(2) + test1 = ('fn' + name) + test2 = f'FUNC16({name})' + if (test1 in all_data) or (test2) in all_data: + print(line) diff --git a/run_with_tcc.bat b/run_with_tcc.bat new file mode 100644 index 0000000..476fe4e --- /dev/null +++ b/run_with_tcc.bat @@ -0,0 +1,39 @@ +@echo off + +set SDL2=third_party\SDL2-2.24.1 + +IF NOT EXIST "third_party\tcc\tcc.exe" ( + ECHO: + ECHO ERROR: src\third_party\tcc\tcc.exe doesn't exist. Please verify that you have put it in the right location. + ECHO Download it from https://github.com/FitzRoyX/tinycc/releases/download/tcc_20221020/tcc_20221020.zip + ECHO It needs to be the 64-bit version. + ECHO: + PAUSE + EXIT /B 1 +) ELSE ( + REM +) + +IF NOT EXIST "%SDL2%\lib\x64\SDL2.dll" ( + ECHO: + ECHO ERROR: SDL is not unzipped properly into %SDL2% + ECHO Download it from https://github.com/libsdl-org/SDL/releases/download/release-2.24.1/SDL2-devel-2.24.1-VC.zip + ECHO: + PAUSE + EXIT /B 1 +) ELSE ( + REM +) + + +echo Building with TCC... +third_party\tcc\tcc.exe -osm.exe -DCOMPILER_TCC=1 -DSTBI_NO_SIMD=1 -DHAVE_STDINT_H=1 -D_HAVE_STDINT_H=1 -DSYSTEM_VOLUME_MIXER_AVAILABLE=0 -I%SDL2%/include -L%SDL2%/lib/x64 -lSDL2 -I. src/*.c src/snes/*.c third_party/gl_core/gl_core_3_1.c +IF ERRORLEVEL 1 goto GETOUT + +copy %SDL2%\lib\x64\SDL2.dll . + +echo Running... +sm.exe sm.smc + +:GETOUT +pause diff --git a/sm.ini b/sm.ini new file mode 100644 index 0000000..58cee75 --- /dev/null +++ b/sm.ini @@ -0,0 +1,93 @@ +[General] + +# Disable the SDL_Delay that happens each frame (Gives slightly better perf if your +# display is set to exactly 60hz) +DisableFrameDelay = 0 + +[Graphics] +# Window size ( Auto or WidthxHeight ) +WindowSize = Auto + +# Fullscreen mode (0=windowed, 1=desktop fullscreen, 2=fullscreen w/mode change) +Fullscreen = 0 + +# Window scale (1=100%, 2=200%, 3=300%, etc.) +WindowScale = 3 + +# Use an optimized (but potentially more buggy) SNES PPU implementation +NewRenderer = 1 + +# Display the world map with higher resolution +EnhancedMode7 = 1 + +# Don't keep the aspect ratio +IgnoreAspectRatio = 0 + +# Enable this option to remove the sprite limits per scan line +NoSpriteLimits = 1 + +# Use either SDL, SDL-Software, or OpenGL as the output method +# SDL-Software rendering might give better performance on Raspberry pi. +OutputMethod = SDL + +# Set to true to use linear filtering. Gives less crisp pixels. Works with SDL and OpenGL. +LinearFiltering = 0 + +# Set a glsl shader. Only supported with the OpenGL output method +# This can be the path to a .glsl or .glslp file +# Get them with: git clone https://github.com/snesrev/glsl-shaders +#Shader = glsl-shaders/hqx/hq4x.glslp + +[Sound] +EnableAudio = 1 + +# DSP frequency in samples per second (e.g. 48000, 44100, 32000, 22050, 11025) +AudioFreq = 32000 + +# number of separate sound channels (1=mono, 2=stereo) +AudioChannels = 2 + +# Audio buffer size in samples (power of 2; e.g., 4096, 2048, 1024) [try 1024 if sound is crackly]. The higher the more lag before you hear sounds. +AudioSamples = 512 + +[KeyMap] +# Change what keyboard keys map to the joypad +# Order: Up, Down, Left, Right, Select, Start, A, B, X, Y, L, R + +# This default is suitable for QWERTY keyboards. +Controls = Up, Down, Left, Right, Right Shift, Return, x, z, s, a, c, v + +# This default is suitable for QWERTZ keyboards. +#Controls = Up, Down, Left, Right, Right Shift, Return, x, y, s, a, c, v + +# This one is suitable for AZERTY keyboards. +#Controls = Up, Down, Left, Right, Right Shift, Return, x, w, s, q, c, v + +CheatLife = w +CheatJump = o +ClearKeyLog = k +StopReplay = l +Fullscreen = Alt+Return +Reset = Ctrl+r +Pause = Shift+p +PauseDimmed = p +Turbo = Tab +ReplayTurbo = t +WindowBigger = Ctrl+Up +WindowSmaller = Ctrl+Down + +VolumeUp = Shift+= +VolumeDown = Shift+- + +Load = F1, F2, F3, F4, F5, F6, F7, F8, F9, F10 +Save = Shift+F1,Shift+F2,Shift+F3,Shift+F4,Shift+F5,Shift+F6,Shift+F7,Shift+F8,Shift+F9,Shift+F10 +Replay= Ctrl+F1,Ctrl+F2,Ctrl+F3,Ctrl+F4,Ctrl+F5,Ctrl+F6,Ctrl+F7,Ctrl+F8,Ctrl+F9,Ctrl+F10 + +LoadRef = 1,2,3,4,5,6,7,8,9,0,-,=,Backspace +ReplayRef = Ctrl+1,Ctrl+2,Ctrl+3,Ctrl+4,Ctrl+5,Ctrl+6,Ctrl+7,Ctrl+8,Ctrl+9,Ctrl+0,Ctrl+-,Ctrl+=,Ctrl+Backspace + +[GamepadMap] +# Any keys used in KeyMap can be used also in this section. +# The shoulder button is called L1/Lb and L2, and the thumbstick button is called L3 +Controls = DpadUp, DpadDown, DpadLeft, DpadRight, Back, Start, B, A, Y, X, Lb, Rb + diff --git a/sm.sln b/sm.sln new file mode 100644 index 0000000..82a190e --- /dev/null +++ b/sm.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32825.248 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sm", "src/sm.vcxproj", "{1F8AB1B4-DAFB-4D6E-BF1E-F802FF5A52EE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1F8AB1B4-DAFB-4D6E-BF1E-F802FF5A52EE}.Debug|x64.ActiveCfg = Debug|x64 + {1F8AB1B4-DAFB-4D6E-BF1E-F802FF5A52EE}.Debug|x64.Build.0 = Debug|x64 + {1F8AB1B4-DAFB-4D6E-BF1E-F802FF5A52EE}.Debug|x86.ActiveCfg = Debug|Win32 + {1F8AB1B4-DAFB-4D6E-BF1E-F802FF5A52EE}.Debug|x86.Build.0 = Debug|Win32 + {1F8AB1B4-DAFB-4D6E-BF1E-F802FF5A52EE}.Release|x64.ActiveCfg = Release|x64 + {1F8AB1B4-DAFB-4D6E-BF1E-F802FF5A52EE}.Release|x64.Build.0 = Release|x64 + {1F8AB1B4-DAFB-4D6E-BF1E-F802FF5A52EE}.Release|x86.ActiveCfg = Release|Win32 + {1F8AB1B4-DAFB-4D6E-BF1E-F802FF5A52EE}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8F47385F-600A-41BA-AEF8-C47A2C0D15E6} + EndGlobalSection +EndGlobal diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..6c92daa --- /dev/null +++ b/src/config.c @@ -0,0 +1,461 @@ +#include "config.h" +#include "types.h" +#include +#include +#include +#include "features.h" +#include "util.h" + +enum { + kKeyMod_ScanCode = 0x200, + kKeyMod_Alt = 0x400, + kKeyMod_Shift = 0x800, + kKeyMod_Ctrl = 0x1000, +}; + +Config g_config; + +#define REMAP_SDL_KEYCODE(key) ((key) & SDLK_SCANCODE_MASK ? kKeyMod_ScanCode : 0) | (key) & (kKeyMod_ScanCode - 1) +#define _(x) REMAP_SDL_KEYCODE(x) +#define S(x) REMAP_SDL_KEYCODE(x) | kKeyMod_Shift +#define A(x) REMAP_SDL_KEYCODE(x) | kKeyMod_Alt +#define C(x) REMAP_SDL_KEYCODE(x) | kKeyMod_Ctrl +#define N 0 +static const uint16 kDefaultKbdControls[kKeys_Total] = { + 0, + // Controls + _(SDLK_UP), _(SDLK_DOWN), _(SDLK_LEFT), _(SDLK_RIGHT), _(SDLK_RSHIFT), _(SDLK_RETURN), _(SDLK_x), _(SDLK_z), _(SDLK_s), _(SDLK_a), _(SDLK_c), _(SDLK_v), + // LoadState + _(SDLK_F1), _(SDLK_F2), _(SDLK_F3), _(SDLK_F4), _(SDLK_F5), _(SDLK_F6), _(SDLK_F7), _(SDLK_F8), _(SDLK_F9), _(SDLK_F10), N, N, N, N, N, N, N, N, N, N, + // SaveState + S(SDLK_F1), S(SDLK_F2), S(SDLK_F3), S(SDLK_F4), S(SDLK_F5), S(SDLK_F6), S(SDLK_F7), S(SDLK_F8), S(SDLK_F9), S(SDLK_F10), N, N, N, N, N, N, N, N, N, N, + // Replay State + C(SDLK_F1), C(SDLK_F2), C(SDLK_F3), C(SDLK_F4), C(SDLK_F5), C(SDLK_F6), C(SDLK_F7), C(SDLK_F8), C(SDLK_F9), C(SDLK_F10), N, N, N, N, N, N, N, N, N, N, + // Load Ref State + _(SDLK_1), _(SDLK_2), _(SDLK_3), _(SDLK_4), _(SDLK_5), _(SDLK_6), _(SDLK_7), _(SDLK_8), _(SDLK_9), _(SDLK_0), _(SDLK_MINUS), _(SDLK_EQUALS), _(SDLK_BACKSPACE), N, N, N, N, N, N, N, + // Replay Ref State + C(SDLK_1), C(SDLK_2), C(SDLK_3), C(SDLK_4), C(SDLK_5), C(SDLK_6), C(SDLK_7), C(SDLK_8), C(SDLK_9), C(SDLK_0), C(SDLK_MINUS), C(SDLK_EQUALS), C(SDLK_BACKSPACE), N, N, N, N, N, N, N, + // CheatLife, CheatJump, ToggleWhichFrame, + _(SDLK_w), _(SDLK_q), S(SDLK_r), + // ClearKeyLog, StopReplay, Fullscreen, Reset, Pause, PauseDimmed, Turbo, ReplayTurbo, WindowBigger, WindowSmaller, DisplayPerf, ToggleRenderer + _(SDLK_k), _(SDLK_l), A(SDLK_RETURN), C(SDLK_r), S(SDLK_p), _(SDLK_p), _(SDLK_TAB), _(SDLK_t), N, N, _(SDLK_f), _(SDLK_r), +}; +#undef _ +#undef A +#undef C +#undef S +#undef N + +typedef struct KeyNameId { + const char *name; + uint16 id, size; +} KeyNameId; + +#define M(n) {#n, kKeys_##n, kKeys_##n##_Last - kKeys_##n + 1} +#define S(n) {#n, kKeys_##n, 1} +static const KeyNameId kKeyNameId[] = { + {"Null", kKeys_Null, 65535}, + M(Controls), M(Load), M(Save), M(Replay), M(LoadRef), M(ReplayRef), + S(CheatLife), S(CheatJump), S(ToggleWhichFrame), + S(ClearKeyLog), S(StopReplay), S(Fullscreen), S(Reset), + S(Pause), S(PauseDimmed), S(Turbo), S(ReplayTurbo), S(WindowBigger), S(WindowSmaller), S(VolumeUp), S(VolumeDown), S(DisplayPerf), S(ToggleRenderer), +}; +#undef S +#undef M +typedef struct KeyMapHashEnt { + uint16 key, cmd, next; +} KeyMapHashEnt; + +static uint16 keymap_hash_first[255]; +static KeyMapHashEnt *keymap_hash; +static int keymap_hash_size; +static bool has_keynameid[countof(kKeyNameId)]; + +static bool KeyMapHash_Add(uint16 key, uint16 cmd) { + if ((keymap_hash_size & 0xff) == 0) { + if (keymap_hash_size > 10000) + Die("Too many keys"); + keymap_hash = (KeyMapHashEnt*)realloc(keymap_hash, sizeof(KeyMapHashEnt) * (keymap_hash_size + 256)); + } + int i = keymap_hash_size++; + KeyMapHashEnt *ent = &keymap_hash[i]; + ent->key = key; + ent->cmd = cmd; + ent->next = 0; + int j = (uint32)key % 255; + + uint16 *cur = &keymap_hash_first[j]; + while (*cur) { + KeyMapHashEnt *ent = &keymap_hash[*cur - 1]; + if (ent->key == key) + return false; + cur = &ent->next; + } + *cur = i + 1; + return true; +} + +static int KeyMapHash_Find(uint16 key) { + int i = keymap_hash_first[key % 255]; + while (i) { + KeyMapHashEnt *ent = &keymap_hash[i - 1]; + if (ent->key == key) + return ent->cmd; + i = ent->next; + } + return 0; +} + +int FindCmdForSdlKey(SDL_Keycode code, SDL_Keymod mod) { + if (code & ~(SDLK_SCANCODE_MASK | 0x1ff)) + return 0; + int key = mod & KMOD_ALT ? kKeyMod_Alt : 0; + key |= mod & KMOD_CTRL ? kKeyMod_Ctrl : 0; + key |= mod & KMOD_SHIFT ? kKeyMod_Shift : 0; + key |= REMAP_SDL_KEYCODE(code); + return KeyMapHash_Find(key); +} + +static void ParseKeyArray(char *value, int cmd, int size) { + char *s; + int i = 0; + for (; i < size && (s = NextDelim(&value, ',')) != NULL; i++, cmd += (cmd != 0)) { + if (*s == 0) + continue; + int key_with_mod = 0; + for (;;) { + if (StringStartsWithNoCase(s, "Shift+")) { + key_with_mod |= kKeyMod_Shift, s += 6; + } else if (StringStartsWithNoCase(s, "Ctrl+")) { + key_with_mod |= kKeyMod_Ctrl, s += 5; + } else if (StringStartsWithNoCase(s, "Alt+")) { + key_with_mod |= kKeyMod_Alt, s += 4; + } else { + break; + } + } + SDL_Keycode key = SDL_GetKeyFromName(s); + if (key == SDLK_UNKNOWN) { + fprintf(stderr, "Unknown key: '%s'\n", s); + continue; + } + if (!KeyMapHash_Add(key_with_mod | REMAP_SDL_KEYCODE(key), cmd)) + fprintf(stderr, "Duplicate key: '%s'\n", s); + } +} + +typedef struct GamepadMapEnt { + uint32 modifiers; + uint16 cmd, next; +} GamepadMapEnt; + +static uint16 joymap_first[kGamepadBtn_Count]; +static GamepadMapEnt *joymap_ents; +static int joymap_size; +static bool has_joypad_controls; + +static int CountBits32(uint32 n) { + int count = 0; + for (; n != 0; count++) + n &= (n - 1); + return count; +} + +static void GamepadMap_Add(int button, uint32 modifiers, uint16 cmd) { + if ((joymap_size & 0xff) == 0) { + if (joymap_size > 1000) + Die("Too many joypad keys"); + joymap_ents = (GamepadMapEnt*)realloc(joymap_ents, sizeof(GamepadMapEnt) * (joymap_size + 64)); + if (!joymap_ents) Die("realloc failure"); + } + uint16 *p = &joymap_first[button]; + // Insert it as early as possible but before after any entry with more modifiers. + int cb = CountBits32(modifiers); + while (*p && cb < CountBits32(joymap_ents[*p - 1].modifiers)) + p = &joymap_ents[*p - 1].next; + int i = joymap_size++; + GamepadMapEnt *ent = &joymap_ents[i]; + ent->modifiers = modifiers; + ent->cmd = cmd; + ent->next = *p; + *p = i + 1; +} + +int FindCmdForGamepadButton(int button, uint32 modifiers) { + GamepadMapEnt *ent; + for(int e = joymap_first[button]; e != 0; e = ent->next) { + ent = &joymap_ents[e - 1]; + if ((modifiers & ent->modifiers) == ent->modifiers) + return ent->cmd; + } + return 0; +} + +static int ParseGamepadButtonName(const char **value) { + const char *s = *value; + // Longest substring first + static const char *const kGamepadKeyNames[] = { + "Back", "Guide", "Start", "L3", "R3", + "L1", "R1", "DpadUp", "DpadDown", "DpadLeft", "DpadRight", "L2", "R2", + "Lb", "Rb", "A", "B", "X", "Y" + }; + static const uint8 kGamepadKeyIds[] = { + kGamepadBtn_Back, kGamepadBtn_Guide, kGamepadBtn_Start, kGamepadBtn_L3, kGamepadBtn_R3, + kGamepadBtn_L1, kGamepadBtn_R1, kGamepadBtn_DpadUp, kGamepadBtn_DpadDown, kGamepadBtn_DpadLeft, kGamepadBtn_DpadRight, kGamepadBtn_L2, kGamepadBtn_R2, + kGamepadBtn_L1, kGamepadBtn_R1, kGamepadBtn_A, kGamepadBtn_B, kGamepadBtn_X, kGamepadBtn_Y, + }; + for (size_t i = 0; i != countof(kGamepadKeyNames); i++) { + const char *r = StringStartsWithNoCase(s, kGamepadKeyNames[i]); + if (r) { + *value = r; + return kGamepadKeyIds[i]; + } + } + return kGamepadBtn_Invalid; +} + +static const uint8 kDefaultGamepadCmds[] = { + kGamepadBtn_DpadUp, kGamepadBtn_DpadDown, kGamepadBtn_DpadLeft, kGamepadBtn_DpadRight, kGamepadBtn_Back, kGamepadBtn_Start, + kGamepadBtn_B, kGamepadBtn_A, kGamepadBtn_Y, kGamepadBtn_X, kGamepadBtn_L1, kGamepadBtn_R1, +}; + +static void ParseGamepadArray(char *value, int cmd, int size) { + char *s; + int i = 0; + for (; i < size && (s = NextDelim(&value, ',')) != NULL; i++, cmd += (cmd != 0)) { + if (*s == 0) + continue; + uint32 modifiers = 0; + const char *ss = s; + for (;;) { + int button = ParseGamepadButtonName(&ss); + if (button == kGamepadBtn_Invalid) BAD: { + fprintf(stderr, "Unknown gamepad button: '%s'\n", s); + break; + } + while (*ss == ' ' || *ss == '\t') ss++; + if (*ss == '+') { + ss++; + modifiers |= 1 << button; + } else if (*ss == 0) { + GamepadMap_Add(button, modifiers, cmd); + break; + } else + goto BAD; + } + } +} + +static void RegisterDefaultKeys(void) { + for (int i = 1; i < countof(kKeyNameId); i++) { + if (!has_keynameid[i]) { + int size = kKeyNameId[i].size, k = kKeyNameId[i].id; + for (int j = 0; j < size; j++, k++) + KeyMapHash_Add(kDefaultKbdControls[k], k); + } + } + if (!has_joypad_controls) { + for (int i = 0; i < countof(kDefaultGamepadCmds); i++) + GamepadMap_Add(kDefaultGamepadCmds[i], 0, kKeys_Controls + i); + } +} + +static int GetIniSection(const char *s) { + if (StringEqualsNoCase(s, "[KeyMap]")) + return 0; + if (StringEqualsNoCase(s, "[Graphics]")) + return 1; + if (StringEqualsNoCase(s, "[Sound]")) + return 2; + if (StringEqualsNoCase(s, "[General]")) + return 3; + if (StringEqualsNoCase(s, "[Features]")) + return 4; + if (StringEqualsNoCase(s, "[GamepadMap]")) + return 5; + return -1; +} + +bool ParseBool(const char *value, bool *result) { + bool rv = false; + switch (*value++ | 32) { + case '0': if (*value == 0) break; return false; + case 'f': if (StringEqualsNoCase(value, "alse")) break; return false; + case 'n': if (StringEqualsNoCase(value, "o")) break; return false; + case 'o': + rv = (*value | 32) == 'n'; + if (StringEqualsNoCase(value, rv ? "n" : "ff")) break; + return false; + case '1': rv = true; if (*value == 0) break; return false; + case 'y': rv = true; if (StringEqualsNoCase(value, "es")) break; return false; + case 't': rv = true; if (StringEqualsNoCase(value, "rue")) break; return false; + default: return false; + } + if (result) { + *result = rv; + return true; + } + return rv; +} + +static bool ParseBoolBit(const char *value, uint32 *data, uint32 mask) { + bool tmp; + if (!ParseBool(value, &tmp)) + return false; + *data = *data & ~mask | (tmp ? mask : 0); + return true; +} + +static bool HandleIniConfig(int section, const char *key, char *value) { + if (section == 0) { + for (int i = 0; i < countof(kKeyNameId); i++) { + if (StringEqualsNoCase(key, kKeyNameId[i].name)) { + has_keynameid[i] = true; + ParseKeyArray(value, kKeyNameId[i].id, kKeyNameId[i].size); + return true; + } + } + } else if (section == 5) { + for (int i = 0; i < countof(kKeyNameId); i++) { + if (StringEqualsNoCase(key, kKeyNameId[i].name)) { + if (i == 1) + has_joypad_controls = true; + ParseGamepadArray(value, kKeyNameId[i].id, kKeyNameId[i].size); + return true; + } + } + } else if (section == 1) { + if (StringEqualsNoCase(key, "WindowSize")) { + char *s; + if (StringEqualsNoCase(value, "Auto")){ + g_config.window_width = 0; + g_config.window_height = 0; + return true; + } + while ((s = NextDelim(&value, 'x')) != NULL) { + if(g_config.window_width == 0) { + g_config.window_width = atoi(s); + } else { + g_config.window_height = atoi(s); + return true; + } + } + } else if (StringEqualsNoCase(key, "EnhancedMode7")) { + return ParseBool(value, &g_config.enhanced_mode7); + } else if (StringEqualsNoCase(key, "NewRenderer")) { + return ParseBool(value, &g_config.new_renderer); + } else if (StringEqualsNoCase(key, "IgnoreAspectRatio")) { + return ParseBool(value, &g_config.ignore_aspect_ratio); + } else if (StringEqualsNoCase(key, "Fullscreen")) { + g_config.fullscreen = (uint8)strtol(value, (char**)NULL, 10); + return true; + } else if (StringEqualsNoCase(key, "WindowScale")) { + g_config.window_scale = (uint8)strtol(value, (char**)NULL, 10); + return true; + } else if (StringEqualsNoCase(key, "OutputMethod")) { + g_config.output_method = StringEqualsNoCase(value, "SDL-Software") ? kOutputMethod_SDLSoftware : + StringEqualsNoCase(value, "OpenGL") ? kOutputMethod_OpenGL : kOutputMethod_SDL; + return true; + } else if (StringEqualsNoCase(key, "LinearFiltering")) { + return ParseBool(value, &g_config.linear_filtering); + } else if (StringEqualsNoCase(key, "NoSpriteLimits")) { + return ParseBool(value, &g_config.no_sprite_limits); + } else if (StringEqualsNoCase(key, "LinkGraphics")) { + g_config.link_graphics = value; + return true; + } else if (StringEqualsNoCase(key, "Shader")) { + g_config.shader = *value ? value : NULL; + return true; + } + } else if (section == 2) { + if (StringEqualsNoCase(key, "EnableAudio")) { + return ParseBool(value, &g_config.enable_audio); + } else if (StringEqualsNoCase(key, "AudioFreq")) { + g_config.audio_freq = (uint16)strtol(value, (char**)NULL, 10); + return true; + } else if (StringEqualsNoCase(key, "AudioChannels")) { + g_config.audio_channels = (uint8)strtol(value, (char**)NULL, 10); + return true; + } else if (StringEqualsNoCase(key, "AudioSamples")) { + g_config.audio_samples = (uint16)strtol(value, (char**)NULL, 10); + return true; + } else if (StringEqualsNoCase(key, "EnableMSU")) { + if (StringEqualsNoCase(value, "opuz")) + g_config.enable_msu = kMsuEnabled_Opuz; + else if (StringEqualsNoCase(value, "deluxe")) + g_config.enable_msu = kMsuEnabled_MsuDeluxe; + else if (StringEqualsNoCase(value, "deluxe-opuz")) + g_config.enable_msu = kMsuEnabled_MsuDeluxe | kMsuEnabled_Opuz; + else + return ParseBool(value, (bool*)&g_config.enable_msu); + return true; + } else if (StringEqualsNoCase(key, "MSUPath")) { + g_config.msu_path = value; + return true; + } else if (StringEqualsNoCase(key, "MSUVolume")) { + g_config.msuvolume = atoi(value); + return true; + } else if (StringEqualsNoCase(key, "ResumeMSU")) { + return ParseBool(value, &g_config.resume_msu); + } + } else if (section == 3) { + if (StringEqualsNoCase(key, "Autosave")) { + g_config.autosave = (bool)strtol(value, (char**)NULL, 10); + return true; + } else if (StringEqualsNoCase(key, "DisplayPerfInTitle")) { + return ParseBool(value, &g_config.display_perf_title); + } else if (StringEqualsNoCase(key, "DisableFrameDelay")) { + return ParseBool(value, &g_config.disable_frame_delay); + } + } else if (section == 4) { + } + return false; +} + +static bool ParseOneConfigFile(const char *filename, int depth) { + char *filedata = (char*)ReadWholeFile(filename, NULL), *p; + if (!filedata) + return false; + + int section = -2; + g_config.memory_buffer = filedata; + + for (int lineno = 1; (p = NextLineStripComments(&filedata)) != NULL; lineno++) { + if (*p == 0) + continue; // empty line + if (*p == '[') { + section = GetIniSection(p); + if (section < 0) + fprintf(stderr, "%s:%d: Invalid .ini section %s\n", filename, lineno, p); + } else if (*p == '!' && SkipPrefix(p + 1, "include ")) { + char *tt = p + 8; + char *new_filename = ReplaceFilenameWithNewPath(filename, NextPossiblyQuotedString(&tt)); + if (depth > 10 || !ParseOneConfigFile(new_filename, depth + 1)) + fprintf(stderr, "Warning: Unable to read %s\n", new_filename); + free(new_filename); + } else if (section == -2) { + fprintf(stderr, "%s:%d: Expecting [section]\n", filename, lineno); + } else { + char *v = SplitKeyValue(p); + if (v == NULL) { + fprintf(stderr, "%s:%d: Expecting 'key=value'\n", filename, lineno); + continue; + } + if (section >= 0 && !HandleIniConfig(section, p, v)) + fprintf(stderr, "%s:%d: Can't parse '%s'\n", filename, lineno, p); + } + } + return true; +} + +void ParseConfigFile(const char *filename) { + g_config.msuvolume = 100; // default msu volume, 100% + + if (filename != NULL || !ParseOneConfigFile("sm.user.ini", 0)) { + if (filename == NULL) + filename = "sm.ini"; + if (!ParseOneConfigFile(filename, 0)) + fprintf(stderr, "Warning: Unable to read config file %s\n", filename); + } + RegisterDefaultKeys(); +} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..724965e --- /dev/null +++ b/src/config.h @@ -0,0 +1,107 @@ +#pragma once +#include "types.h" +#include + +enum { + kKeys_Null, + kKeys_Controls, + kKeys_Controls_Last = kKeys_Controls + 11, + kKeys_Load, + kKeys_Load_Last = kKeys_Load + 19, + kKeys_Save, + kKeys_Save_Last = kKeys_Save + 19, + kKeys_Replay, + kKeys_Replay_Last = kKeys_Replay + 19, + kKeys_LoadRef, + kKeys_LoadRef_Last = kKeys_LoadRef + 19, + kKeys_ReplayRef, + kKeys_ReplayRef_Last = kKeys_ReplayRef + 19, + kKeys_CheatLife, + kKeys_CheatJump, + kKeys_ToggleWhichFrame, + kKeys_ClearKeyLog, + kKeys_StopReplay, + kKeys_Fullscreen, + kKeys_Reset, + kKeys_Pause, + kKeys_PauseDimmed, + kKeys_Turbo, + kKeys_ReplayTurbo, + kKeys_WindowBigger, + kKeys_WindowSmaller, + kKeys_DisplayPerf, + kKeys_ToggleRenderer, + kKeys_VolumeUp, + kKeys_VolumeDown, + kKeys_Total, +}; + +enum { + kOutputMethod_SDL, + kOutputMethod_SDLSoftware, + kOutputMethod_OpenGL, +}; + +typedef struct Config { + int window_width; + int window_height; + bool enhanced_mode7; + bool new_renderer; + bool ignore_aspect_ratio; + uint8 fullscreen; + uint8 window_scale; + bool enable_audio; + bool linear_filtering; + uint8 output_method; + uint16 audio_freq; + uint8 audio_channels; + uint16 audio_samples; + bool autosave; + uint8 extended_aspect_ratio; + bool extend_y; + bool no_sprite_limits; + bool display_perf_title; + uint8 enable_msu; + bool resume_msu; + bool disable_frame_delay; + uint8 msuvolume; + uint32 features0; + + const char *link_graphics; + char *memory_buffer; + const char *shader; + const char *msu_path; +} Config; + +enum { + kMsuEnabled_Msu = 1, + kMsuEnabled_MsuDeluxe = 2, + kMsuEnabled_Opuz = 4, +}; +enum { + kGamepadBtn_Invalid = -1, + kGamepadBtn_A, + kGamepadBtn_B, + kGamepadBtn_X, + kGamepadBtn_Y, + kGamepadBtn_Back, + kGamepadBtn_Guide, + kGamepadBtn_Start, + kGamepadBtn_L3, + kGamepadBtn_R3, + kGamepadBtn_L1, + kGamepadBtn_R1, + kGamepadBtn_DpadUp, + kGamepadBtn_DpadDown, + kGamepadBtn_DpadLeft, + kGamepadBtn_DpadRight, + kGamepadBtn_L2, + kGamepadBtn_R2, + kGamepadBtn_Count, +}; + +extern Config g_config; + +void ParseConfigFile(const char *filename); +int FindCmdForSdlKey(SDL_Keycode code, SDL_Keymod mod); +int FindCmdForGamepadButton(int button, uint32 modifiers); diff --git a/src/enemy_types.h b/src/enemy_types.h new file mode 100644 index 0000000..a73bbf4 --- /dev/null +++ b/src/enemy_types.h @@ -0,0 +1,4071 @@ +typedef struct Enemy_Bang { +EnemyBase base; +uint16 bang_var_A; +uint16 bang_var_B; +uint16 bang_var_C; +uint16 bang_var_D; +uint16 bang_var_E; +uint16 bang_var_F; +uint16 bang_parameter_1; +uint16 bang_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 bang_var_00; + uint16 bang_var_01; + uint16 bang_var_02; + uint16 bang_var_03; + uint16 bang_var_04; + uint16 bang_var_05; + uint16 bang_var_06; + uint16 bang_var_07; + uint16 bang_var_08; + uint16 bang_var_09; + uint16 bang_var_0A; + uint16 bang_var_0B; + uint16 bang_var_0C; + uint16 bang_var_0D; + uint16 bang_var_0E; + uint16 bang_var_0F; + uint16 bang_var_10; + uint16 bang_var_11; + uint16 bang_var_12; + uint16 bang_var_13; + uint16 bang_var_14; + uint16 bang_var_15; + uint16 bang_var_16; + uint16 bang_var_17; + uint16 bang_var_18; + uint16 bang_var_19; + uint16 bang_var_1A; + uint16 bang_var_1B; + uint16 bang_var_1C; + uint16 bang_var_1D; + uint16 bang_var_1E; + uint16 bang_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 bang_var_20; + uint16 bang_var_21; + uint16 bang_var_22; + uint16 bang_var_23; + uint16 bang_var_24; + uint16 bang_var_25; + uint16 bang_var_26; + uint16 bang_var_27; + uint16 bang_var_28; + uint16 bang_var_29; + uint16 bang_var_2A; + uint16 bang_var_2B; + uint16 bang_var_2C; + uint16 bang_var_2D; + uint16 bang_var_2E; + uint16 bang_var_2F; + uint16 bang_var_30; + uint16 bang_var_31; + uint16 bang_var_32; + uint16 bang_var_33; + uint16 bang_var_34; + uint16 bang_var_35; + uint16 bang_var_36; + uint16 bang_var_37; + uint16 bang_var_38; + uint16 bang_var_39; + uint16 bang_var_3A; + uint16 bang_var_3B; + uint16 bang_var_3C; + uint16 bang_var_3D; + uint16 bang_var_3E; + uint16 bang_var_3F; +} Enemy_Bang; +typedef struct Enemy_Beetom { +EnemyBase base; +uint16 beetom_var_A; +uint16 beetom_var_B; +uint16 beetom_var_C; +uint16 beetom_var_D; +uint16 beetom_var_E; +uint16 beetom_var_F; +uint16 beetom_parameter_1; +uint16 beetom_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 beetom_var_00; + uint16 beetom_var_01; + uint16 beetom_var_02; + uint16 beetom_var_03; + uint16 beetom_var_04; + uint16 beetom_var_05; + uint16 beetom_var_06; + uint16 beetom_var_07; + uint16 beetom_var_08; + uint16 beetom_var_09; + uint16 beetom_var_0A; + uint16 beetom_var_0B; + uint16 beetom_var_0C; + uint16 beetom_var_0D; + uint16 beetom_var_0E; + uint16 beetom_var_0F; + uint16 beetom_var_10; + uint16 beetom_var_11; + uint16 beetom_var_12; + uint16 beetom_var_13; + uint16 beetom_var_14; + uint16 beetom_var_15; + uint16 beetom_var_16; + uint16 beetom_var_17; + uint16 beetom_var_18; + uint16 beetom_var_19; + uint16 beetom_var_1A; + uint16 beetom_var_1B; + uint16 beetom_var_1C; + uint16 beetom_var_1D; + uint16 beetom_var_1E; + uint16 beetom_var_1F; +} Enemy_Beetom; +typedef struct Enemy_Botwoon { +EnemyBase base; +uint16 botwoon_var_A; +uint16 botwoon_var_B; +uint16 botwoon_var_C; +uint16 botwoon_var_D; +uint16 botwoon_var_E; +uint16 botwoon_var_F; +uint16 botwoon_parameter_1; +uint16 botwoon_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 botwoon_var_00; + uint16 botwoon_var_01; + uint16 botwoon_var_02; + uint16 botwoon_var_03; + uint16 botwoon_var_04; + uint16 botwoon_var_05; + uint16 botwoon_var_06; + uint16 botwoon_var_07; + uint16 botwoon_var_08; + uint16 botwoon_var_09; + uint16 botwoon_var_0A; + uint16 botwoon_var_0B; + uint16 botwoon_var_0C; + uint16 botwoon_var_0D; + uint16 botwoon_var_0E; + uint16 botwoon_var_0F; + uint16 botwoon_var_10; + uint16 botwoon_var_11; + uint16 botwoon_var_12; + uint16 botwoon_var_13; + uint16 botwoon_var_14; + uint16 botwoon_var_15; + uint16 botwoon_var_16; + uint16 botwoon_var_17; + uint16 botwoon_var_18; + uint16 botwoon_var_19; + uint16 botwoon_var_1A; + uint16 botwoon_var_1B; + uint16 botwoon_var_1C; + uint16 botwoon_var_1D; + uint16 botwoon_var_1E; + uint16 botwoon_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 botwoon_var_20; + uint16 botwoon_var_21; + uint16 botwoon_var_22; + uint16 botwoon_var_23; + uint16 botwoon_var_24; + uint16 botwoon_var_25; + uint16 botwoon_var_26; + uint16 botwoon_var_27; + uint16 botwoon_var_28; + uint16 botwoon_var_29; + uint16 botwoon_var_2A; + uint16 botwoon_var_2B; + uint16 botwoon_var_2C; + uint16 botwoon_var_2D; + uint16 botwoon_var_2E; + uint16 botwoon_var_2F; + uint16 botwoon_var_30; + uint16 botwoon_var_31; + uint16 botwoon_var_32; + uint16 botwoon_var_33; + uint16 botwoon_var_34; + uint16 botwoon_var_35; + uint16 botwoon_var_36; + uint16 botwoon_var_37; + uint16 botwoon_var_38; + uint16 botwoon_var_39; + uint16 botwoon_var_3A; + uint16 botwoon_var_3B; + uint16 botwoon_var_3C; + uint16 botwoon_var_3D; + uint16 botwoon_var_3E; + uint16 botwoon_var_3F; +uint8 pad3[0x8800-0x8040]; + uint16 botwoon_var_40; + uint16 botwoon_var_41; + uint16 botwoon_var_42; + uint16 botwoon_var_43; + uint16 botwoon_var_44; + uint16 botwoon_var_45; + uint16 botwoon_var_46; + uint16 botwoon_var_47; + uint16 botwoon_var_48; + uint16 botwoon_var_49; + uint16 botwoon_var_4A; + uint16 botwoon_var_4B; + uint16 botwoon_var_4C; + uint16 botwoon_var_4D; + uint16 botwoon_var_4E; + uint16 botwoon_var_4F; + uint16 botwoon_var_50; + uint16 botwoon_var_51; + uint16 botwoon_var_52; + uint16 botwoon_var_53; + uint16 botwoon_var_54; + uint16 botwoon_var_55; + uint16 botwoon_var_56; + uint16 botwoon_var_57; + uint16 botwoon_var_58; + uint16 botwoon_var_59; + uint16 botwoon_var_5A; + uint16 botwoon_var_5B; + uint16 botwoon_var_5C; + uint16 botwoon_var_5D; + uint16 botwoon_var_5E; + uint16 botwoon_var_5F; +} Enemy_Botwoon; +typedef struct Enemy_Boulder { +EnemyBase base; +uint16 boulder_var_A; +uint16 boulder_var_B; +uint16 boulder_var_C; +uint16 boulder_var_D; +uint16 boulder_var_E; +uint16 boulder_var_F; +uint16 boulder_parameter_1; +uint16 boulder_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 boulder_var_00; + uint16 boulder_var_01; + uint16 boulder_var_02; + uint16 boulder_var_03; + uint16 boulder_var_04; + uint16 boulder_var_05; + uint16 boulder_var_06; + uint16 boulder_var_07; + uint16 boulder_var_08; + uint16 boulder_var_09; + uint16 boulder_var_0A; + uint16 boulder_var_0B; + uint16 boulder_var_0C; + uint16 boulder_var_0D; + uint16 boulder_var_0E; + uint16 boulder_var_0F; + uint16 boulder_var_10; + uint16 boulder_var_11; + uint16 boulder_var_12; + uint16 boulder_var_13; + uint16 boulder_var_14; + uint16 boulder_var_15; + uint16 boulder_var_16; + uint16 boulder_var_17; + uint16 boulder_var_18; + uint16 boulder_var_19; + uint16 boulder_var_1A; + uint16 boulder_var_1B; + uint16 boulder_var_1C; + uint16 boulder_var_1D; + uint16 boulder_var_1E; + uint16 boulder_var_1F; +} Enemy_Boulder; +typedef struct Enemy_BouncingGoofball { +EnemyBase base; +uint16 bgl_var_A; +uint16 bgl_var_B; +uint16 bgl_var_C; +uint16 bgl_var_D; +uint16 bgl_var_E; +uint16 bgl_var_F; +uint16 bgl_parameter_1; +uint16 bgl_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 bgl_var_00; + uint16 bgl_var_01; + uint16 bgl_var_02; + uint16 bgl_var_03; + uint16 bgl_var_04; + uint16 bgl_var_05; + uint16 bgl_var_06; + uint16 bgl_var_07; + uint16 bgl_var_08; + uint16 bgl_var_09; + uint16 bgl_var_0A; + uint16 bgl_var_0B; + uint16 bgl_var_0C; + uint16 bgl_var_0D; + uint16 bgl_var_0E; + uint16 bgl_var_0F; + uint16 bgl_var_10; + uint16 bgl_var_11; + uint16 bgl_var_12; + uint16 bgl_var_13; + uint16 bgl_var_14; + uint16 bgl_var_15; + uint16 bgl_var_16; + uint16 bgl_var_17; + uint16 bgl_var_18; + uint16 bgl_var_19; + uint16 bgl_var_1A; + uint16 bgl_var_1B; + uint16 bgl_var_1C; + uint16 bgl_var_1D; + uint16 bgl_var_1E; + uint16 bgl_var_1F; +} Enemy_BouncingGoofball; +typedef struct Enemy_CeresDoor { +EnemyBase base; +uint16 cdr_var_A; +uint16 cdr_var_B; +uint16 cdr_var_C; +uint16 cdr_var_D; +uint16 cdr_var_E; +uint16 cdr_var_F; +uint16 cdr_parameter_1; +uint16 cdr_parameter_2; +} Enemy_CeresDoor; +typedef struct Enemy_CeresRidley { +EnemyBase base; +uint16 cry_var_A; +uint16 cry_var_B; +uint16 cry_var_C; +uint16 cry_var_D; +uint16 cry_var_E; +uint16 cry_var_F; +uint16 cry_parameter_1; +uint16 cry_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 cry_var_00; + uint16 cry_var_01; + uint16 cry_var_02; + uint16 cry_var_03; + uint16 cry_var_04; + uint16 cry_var_05; + uint16 cry_var_06; + uint16 cry_var_07; + uint16 cry_var_08; + uint16 cry_var_09; + uint16 cry_var_0A; + uint16 cry_var_0B; + uint16 cry_var_0C; + uint16 cry_var_0D; + uint16 cry_var_0E; + uint16 cry_var_0F; + uint16 cry_var_10; + uint16 cry_var_11; + uint16 cry_var_12; + uint16 cry_var_13; + uint16 cry_var_14; + uint16 cry_var_15; + uint16 cry_var_16; + uint16 cry_var_17; + uint16 cry_var_18; + uint16 cry_var_19; + uint16 cry_var_1A; + uint16 cry_var_1B; + uint16 cry_var_1C; + uint16 cry_var_1D; + uint16 cry_var_1E; + uint16 cry_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 cry_var_20; + uint16 cry_var_21; + uint16 cry_var_22; + uint16 cry_var_23; + uint16 cry_var_24; + uint16 cry_var_25; + uint16 cry_var_26; + uint16 cry_var_27; + uint16 cry_var_28; + uint16 cry_var_29; + uint16 cry_var_2A; + uint16 cry_var_2B; + uint16 cry_var_2C; + uint16 cry_var_2D; + uint16 cry_var_2E; + uint16 cry_var_2F; + uint16 cry_var_30; + uint16 cry_var_31; + uint16 cry_var_32; + uint16 cry_var_33; + uint16 cry_var_34; + uint16 cry_var_35; + uint16 cry_var_36; + uint16 cry_var_37; + uint16 cry_var_38; + uint16 cry_var_39; + uint16 cry_var_3A; + uint16 cry_var_3B; + uint16 cry_var_3C; + uint16 cry_var_3D; + uint16 cry_var_3E; + uint16 cry_var_3F; +} Enemy_CeresRidley; +typedef struct Enemy_CeresSteam { +EnemyBase base; +uint16 csm_var_A; +uint16 csm_var_B; +uint16 csm_var_C; +uint16 csm_var_D; +uint16 csm_var_E; +uint16 csm_var_F; +uint16 csm_parameter_1; +uint16 csm_parameter_2; +} Enemy_CeresSteam; +typedef struct Enemy_Crocomire { +EnemyBase base; +uint16 crocom_var_A; +uint16 crocom_var_B; +uint16 crocom_var_C; +uint16 crocom_var_D; +uint16 crocom_var_E; +uint16 crocom_var_F; +uint16 crocom_parameter_1; +uint16 crocom_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 crocom_var_00; + uint16 crocom_var_01; + uint16 crocom_var_02; + uint16 crocom_var_03; + uint16 crocom_var_04; + uint16 crocom_var_05; + uint16 crocom_var_06; + uint16 crocom_var_07; + uint16 crocom_var_08; + uint16 crocom_var_09; + uint16 crocom_var_0A; + uint16 crocom_var_0B; + uint16 crocom_var_0C; + uint16 crocom_var_0D; + uint16 crocom_var_0E; + uint16 crocom_var_0F; + uint16 crocom_var_10; + uint16 crocom_var_11; + uint16 crocom_var_12; + uint16 crocom_var_13; + uint16 crocom_var_14; + uint16 crocom_var_15; + uint16 crocom_var_16; + uint16 crocom_var_17; + uint16 crocom_var_18; + uint16 crocom_var_19; + uint16 crocom_var_1A; + uint16 crocom_var_1B; + uint16 crocom_var_1C; + uint16 crocom_var_1D; + uint16 crocom_var_1E; + uint16 crocom_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 crocom_var_20; + uint16 crocom_var_21; + uint16 crocom_var_22; + uint16 crocom_var_23; + uint16 crocom_var_24; + uint16 crocom_var_25; + uint16 crocom_var_26; + uint16 crocom_var_27; + uint16 crocom_var_28; + uint16 crocom_var_29; + uint16 crocom_var_2A; + uint16 crocom_var_2B; + uint16 crocom_var_2C; + uint16 crocom_var_2D; + uint16 crocom_var_2E; + uint16 crocom_var_2F; + uint16 crocom_var_30; + uint16 crocom_var_31; + uint16 crocom_var_32; + uint16 crocom_var_33; + uint16 crocom_var_34; + uint16 crocom_var_35; + uint16 crocom_var_36; + uint16 crocom_var_37; + uint16 crocom_var_38; + uint16 crocom_var_39; + uint16 crocom_var_3A; + uint16 crocom_var_3B; + uint16 crocom_var_3C; + uint16 crocom_var_3D; + uint16 crocom_var_3E; + uint16 crocom_var_3F; +}Enemy_Crocomire; +typedef struct Enemy_Dachora { +EnemyBase base; +uint16 dachor_var_A; +uint16 dachor_var_B; +uint16 dachor_var_C; +uint16 dachor_var_D; +uint16 dachor_var_E; +uint16 dachor_var_F; +uint16 dachor_parameter_1; +uint16 dachor_parameter_2; +} Enemy_Dachora; +typedef struct Enemy_DeadEnemy { +EnemyBase base; +uint16 dey_var_A; +uint16 dey_var_B; +uint16 dey_var_C; +uint16 dey_var_D; +uint16 dey_var_E; +uint16 dey_var_F; +uint16 dey_parameter_1; +uint16 dey_parameter_2; +uint8 pad2[0x8000-0xFB8]; + uint16 dey_var_20; + uint16 dey_var_21; + uint16 dey_var_22; + uint16 dey_var_23; + uint16 dey_var_24; + uint16 dey_var_25; + uint16 dey_var_26; + uint16 dey_var_27; + uint16 dey_var_28; + uint16 dey_var_29; + uint16 dey_var_2A; + uint16 dey_var_2B; + uint16 dey_var_2C; + uint16 dey_var_2D; + uint16 dey_var_2E; + uint16 dey_var_2F; + uint16 dey_var_30; + uint16 dey_var_31; + uint16 dey_var_32; + uint16 dey_var_33; + uint16 dey_var_34; + uint16 dey_var_35; + uint16 dey_var_36; + uint16 dey_var_37; + uint16 dey_var_38; + uint16 dey_var_39; + uint16 dey_var_3A; + uint16 dey_var_3B; + uint16 dey_var_3C; + uint16 dey_var_3D; + uint16 dey_var_3E; + uint16 dey_var_3F; +} Enemy_DeadEnemy; +typedef struct Enemy_DeadMonsters { +EnemyBase base; +uint16 dms_var_A; +uint16 dms_var_B; +uint16 dms_var_C; +uint16 dms_var_D; +uint16 dms_var_E; +uint16 dms_var_F; +uint16 dms_parameter_1; +uint16 dms_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 dms_var_00; + uint16 dms_var_01; + uint16 dms_var_02; + uint16 dms_var_03; + uint16 dms_var_04; + uint16 dms_var_05; + uint16 dms_var_06; + uint16 dms_var_07; + uint16 dms_var_08; + uint16 dms_var_09; + uint16 dms_var_0A; + uint16 dms_var_0B; + uint16 dms_var_0C; + uint16 dms_var_0D; + uint16 dms_var_0E; + uint16 dms_var_0F; + uint16 dms_var_10; + uint16 dms_var_11; + uint16 dms_var_12; + uint16 dms_var_13; + uint16 dms_var_14; + uint16 dms_var_15; + uint16 dms_var_16; + uint16 dms_var_17; + uint16 dms_var_18; + uint16 dms_var_19; + uint16 dms_var_1A; + uint16 dms_var_1B; + uint16 dms_var_1C; + uint16 dms_var_1D; + uint16 dms_var_1E; + uint16 dms_var_1F; +uint8 pad3[0x8800-0x7840]; + uint16 dms_var_40; + uint16 dms_var_41; + uint16 dms_var_42; + uint16 dms_var_43; + uint16 dms_var_44; + uint16 dms_var_45; + uint16 dms_var_46; + uint16 dms_var_47; + uint16 dms_var_48; + uint16 dms_var_49; + uint16 dms_var_4A; + uint16 dms_var_4B; + uint16 dms_var_4C; + uint16 dms_var_4D; + uint16 dms_var_4E; + uint16 dms_var_4F; + uint16 dms_var_50; + uint16 dms_var_51; + uint16 dms_var_52; + uint16 dms_var_53; + uint16 dms_var_54; + uint16 dms_var_55; + uint16 dms_var_56; + uint16 dms_var_57; + uint16 dms_var_58; + uint16 dms_var_59; + uint16 dms_var_5A; + uint16 dms_var_5B; + uint16 dms_var_5C; + uint16 dms_var_5D; + uint16 dms_var_5E; + uint16 dms_var_5F; +} Enemy_DeadMonsters; +typedef struct Enemy_DeadSidehopper { +EnemyBase base; +uint16 dsr_var_A; +uint16 dsr_var_B; +uint16 dsr_var_C; +uint16 dsr_var_D; +uint16 dsr_var_E; +uint16 dsr_var_F; +uint16 dsr_parameter_1; +uint16 dsr_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 dsr_var_00; + uint16 dsr_var_01; + uint16 dsr_var_02; + uint16 dsr_var_03; + uint16 dsr_var_04; + uint16 dsr_var_05; + uint16 dsr_var_06; + uint16 dsr_var_07; + uint16 dsr_var_08; + uint16 dsr_var_09; + uint16 dsr_var_0A; + uint16 dsr_var_0B; + uint16 dsr_var_0C; + uint16 dsr_var_0D; + uint16 dsr_var_0E; + uint16 dsr_var_0F; + uint16 dsr_var_10; + uint16 dsr_var_11; + uint16 dsr_var_12; + uint16 dsr_var_13; + uint16 dsr_var_14; + uint16 dsr_var_15; + uint16 dsr_var_16; + uint16 dsr_var_17; + uint16 dsr_var_18; + uint16 dsr_var_19; + uint16 dsr_var_1A; + uint16 dsr_var_1B; + uint16 dsr_var_1C; + uint16 dsr_var_1D; + uint16 dsr_var_1E; + uint16 dsr_var_1F; +} Enemy_DeadSidehopper; +typedef struct Enemy_DeadTorizo { +EnemyBase base; +uint16 dto_var_A; +uint16 dto_var_B; +uint16 dto_var_C; +uint16 dto_var_D; +uint16 dto_var_E; +uint16 dto_var_F; +uint16 dto_parameter_1; +uint16 dto_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 dto_var_00; + uint16 dto_var_01; + uint16 dto_var_02; + uint16 dto_var_03; + uint16 dto_var_04; + uint16 dto_var_05; + uint16 dto_var_06; + uint16 dto_var_07; + uint16 dto_var_08; + uint16 dto_var_09; + uint16 dto_var_0A; + uint16 dto_var_0B; + uint16 dto_var_0C; + uint16 dto_var_0D; + uint16 dto_var_0E; + uint16 dto_var_0F; + uint16 dto_var_10; + uint16 dto_var_11; + uint16 dto_var_12; + uint16 dto_var_13; + uint16 dto_var_14; + uint16 dto_var_15; + uint16 dto_var_16; + uint16 dto_var_17; + uint16 dto_var_18; + uint16 dto_var_19; + uint16 dto_var_1A; + uint16 dto_var_1B; + uint16 dto_var_1C; + uint16 dto_var_1D; + uint16 dto_var_1E; + uint16 dto_var_1F; +} Enemy_DeadTorizo; +typedef struct Enemy_Draygon { +EnemyBase base; +uint16 draygon_var_A; +uint16 draygon_var_B; +uint16 draygon_var_C; +uint16 draygon_var_D; +uint16 draygon_var_E; +uint16 draygon_var_F; +uint16 draygon_parameter_1; +uint16 draygon_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 draygon_var_00; + uint16 draygon_var_01; + uint16 draygon_var_02; + uint16 draygon_var_03; + uint16 draygon_var_04; + uint16 draygon_var_05; + uint16 draygon_var_06; + uint16 draygon_var_07; + uint16 draygon_var_08; + uint16 draygon_var_09; + uint16 draygon_var_0A; + uint16 draygon_var_0B; + uint16 draygon_var_0C; + uint16 draygon_var_0D; + uint16 draygon_var_0E; + uint16 draygon_var_0F; + uint16 draygon_var_10; + uint16 draygon_var_11; + uint16 draygon_var_12; + uint16 draygon_var_13; + uint16 draygon_var_14; + uint16 draygon_var_15; + uint16 draygon_var_16; + uint16 draygon_var_17; + uint16 draygon_var_18; + uint16 draygon_var_19; + uint16 draygon_var_1A; + uint16 draygon_var_1B; + uint16 draygon_var_1C; + uint16 draygon_var_1D; + uint16 draygon_var_1E; + uint16 draygon_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 draygon_var_20; + uint16 draygon_var_21; + uint16 draygon_var_22; + uint16 draygon_var_23; + uint16 draygon_var_24; + uint16 draygon_var_25; + uint16 draygon_var_26; + uint16 draygon_var_27; + uint16 draygon_var_28; + uint16 draygon_var_29; + uint16 draygon_var_2A; + uint16 draygon_var_2B; + uint16 draygon_var_2C; + uint16 draygon_var_2D; + uint16 draygon_var_2E; + uint16 draygon_var_2F; + uint16 draygon_var_30; + uint16 draygon_var_31; + uint16 draygon_var_32; + uint16 draygon_var_33; + uint16 draygon_var_34; + uint16 draygon_var_35; + uint16 draygon_var_36; + uint16 draygon_var_37; + uint16 draygon_var_38; + uint16 draygon_var_39; + uint16 draygon_var_3A; + uint16 draygon_var_3B; + uint16 draygon_var_3C; + uint16 draygon_var_3D; + uint16 draygon_var_3E; + uint16 draygon_var_3F; +uint8 pad3[0x8800-0x8040]; + uint16 draygon_var_40; + uint16 draygon_var_41; + uint16 draygon_var_42; + uint16 draygon_var_43; + uint16 draygon_var_44; + uint16 draygon_var_45; + uint16 draygon_var_46; + uint16 draygon_var_47; + uint16 draygon_var_48; + uint16 draygon_var_49; + uint16 draygon_var_4A; + uint16 draygon_var_4B; + uint16 draygon_var_4C; + uint16 draygon_var_4D; + uint16 draygon_var_4E; + uint16 draygon_var_4F; + uint16 draygon_var_50; + uint16 draygon_var_51; + uint16 draygon_var_52; + uint16 draygon_var_53; + uint16 draygon_var_54; + uint16 draygon_var_55; + uint16 draygon_var_56; + uint16 draygon_var_57; + uint16 draygon_var_58; + uint16 draygon_var_59; + uint16 draygon_var_5A; + uint16 draygon_var_5B; + uint16 draygon_var_5C; + uint16 draygon_var_5D; + uint16 draygon_var_5E; + uint16 draygon_var_5F; +} Enemy_Draygon; +typedef struct Enemy_Elevator { +EnemyBase base; +uint16 elevat_var_A; +uint16 elevat_var_B; +uint16 elevat_var_C; +uint16 elevat_var_D; +uint16 elevat_var_E; +uint16 elevat_var_F; +uint16 elevat_parameter_1; +uint16 elevat_parameter_2; +} Enemy_Elevator; +typedef struct Enemy_EscapeDachora { +EnemyBase base; +uint16 eda_var_A; +uint16 eda_var_B; +uint16 eda_var_C; +uint16 eda_var_D; +uint16 eda_var_E; +uint16 eda_var_F; +uint16 eda_parameter_1; +uint16 eda_parameter_2; +} Enemy_EscapeDachora; +typedef struct Enemy_EscapeEtecoon { +EnemyBase base; +uint16 een_var_A; +uint16 een_var_B; +uint16 een_var_C; +uint16 een_var_D; +uint16 een_var_E; +uint16 een_var_F; +uint16 een_parameter_1; +uint16 een_parameter_2; +} Enemy_EscapeEtecoon; +typedef struct Enemy_Etecoon { +EnemyBase base; +uint16 etecoon_var_A; +uint16 etecoon_var_B; +uint16 etecoon_var_C; +uint16 etecoon_var_D; +uint16 etecoon_var_E; +uint16 etecoon_var_F; +uint16 etecoon_parameter_1; +uint16 etecoon_parameter_2; +} Enemy_Etecoon; +typedef struct Enemy_FakeKraid { +EnemyBase base; +uint16 fkd_var_A; +uint16 fkd_var_B; +uint16 fkd_var_C; +uint16 fkd_var_D; +uint16 fkd_var_E; +uint16 fkd_var_F; +uint16 fkd_parameter_1; +uint16 fkd_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 fkd_var_00; + uint16 fkd_var_01; + uint16 fkd_var_02; + uint16 fkd_var_03; + uint16 fkd_var_04; + uint16 fkd_var_05; + uint16 fkd_var_06; + uint16 fkd_var_07; + uint16 fkd_var_08; + uint16 fkd_var_09; + uint16 fkd_var_0A; + uint16 fkd_var_0B; + uint16 fkd_var_0C; + uint16 fkd_var_0D; + uint16 fkd_var_0E; + uint16 fkd_var_0F; + uint16 fkd_var_10; + uint16 fkd_var_11; + uint16 fkd_var_12; + uint16 fkd_var_13; + uint16 fkd_var_14; + uint16 fkd_var_15; + uint16 fkd_var_16; + uint16 fkd_var_17; + uint16 fkd_var_18; + uint16 fkd_var_19; + uint16 fkd_var_1A; + uint16 fkd_var_1B; + uint16 fkd_var_1C; + uint16 fkd_var_1D; + uint16 fkd_var_1E; + uint16 fkd_var_1F; +} Enemy_FakeKraid; +typedef struct Enemy_FireFlea { +EnemyBase base; +uint16 ffa_var_A; +uint16 ffa_var_B; +uint16 ffa_var_C; +uint16 ffa_var_D; +uint16 ffa_var_E; +uint16 ffa_var_F; +uint16 ffa_parameter_1; +uint16 ffa_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 ffa_var_00; + uint16 ffa_var_01; + uint16 ffa_var_02; + uint16 ffa_var_03; + uint16 ffa_var_04; + uint16 ffa_var_05; + uint16 ffa_var_06; + uint16 ffa_var_07; + uint16 ffa_var_08; + uint16 ffa_var_09; + uint16 ffa_var_0A; + uint16 ffa_var_0B; + uint16 ffa_var_0C; + uint16 ffa_var_0D; + uint16 ffa_var_0E; + uint16 ffa_var_0F; + uint16 ffa_var_10; + uint16 ffa_var_11; + uint16 ffa_var_12; + uint16 ffa_var_13; + uint16 ffa_var_14; + uint16 ffa_var_15; + uint16 ffa_var_16; + uint16 ffa_var_17; + uint16 ffa_var_18; + uint16 ffa_var_19; + uint16 ffa_var_1A; + uint16 ffa_var_1B; + uint16 ffa_var_1C; + uint16 ffa_var_1D; + uint16 ffa_var_1E; + uint16 ffa_var_1F; +} Enemy_FireFlea; +typedef struct Enemy_FireGeyser { +EnemyBase base; +uint16 fgr_var_A; +uint16 fgr_var_B; +uint16 fgr_var_C; +uint16 fgr_var_D; +uint16 fgr_var_E; +uint16 fgr_var_F; +uint16 fgr_parameter_1; +uint16 fgr_parameter_2; +}Enemy_FireGeyser; +typedef struct Enemy_FireZoomer { +EnemyBase base; +uint16 fzr_var_A; +uint16 fzr_var_B; +uint16 fzr_var_C; +uint16 fzr_var_D; +uint16 fzr_var_E; +uint16 fzr_var_F; +uint16 fzr_parameter_1; +uint16 fzr_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 fzr_var_00; + uint16 fzr_var_01; + uint16 fzr_var_02; + uint16 fzr_var_03; + uint16 fzr_var_04; + uint16 fzr_var_05; + uint16 fzr_var_06; + uint16 fzr_var_07; + uint16 fzr_var_08; + uint16 fzr_var_09; + uint16 fzr_var_0A; + uint16 fzr_var_0B; + uint16 fzr_var_0C; + uint16 fzr_var_0D; + uint16 fzr_var_0E; + uint16 fzr_var_0F; + uint16 fzr_var_10; + uint16 fzr_var_11; + uint16 fzr_var_12; + uint16 fzr_var_13; + uint16 fzr_var_14; + uint16 fzr_var_15; + uint16 fzr_var_16; + uint16 fzr_var_17; + uint16 fzr_var_18; + uint16 fzr_var_19; + uint16 fzr_var_1A; + uint16 fzr_var_1B; + uint16 fzr_var_1C; + uint16 fzr_var_1D; + uint16 fzr_var_1E; + uint16 fzr_var_1F; +}Enemy_FireZoomer; +typedef struct Enemy_Fireflea { +EnemyBase base; +uint16 firefl_var_A; +uint16 firefl_var_B; +uint16 firefl_var_C; +uint16 firefl_var_D; +uint16 firefl_var_E; +uint16 firefl_var_F; +uint16 firefl_parameter_1; +uint16 firefl_parameter_2; +}Enemy_Fireflea; +typedef struct Enemy_Flies { +EnemyBase base; +uint16 flies_var_A; +uint16 flies_var_B; +uint16 flies_var_C; +uint16 flies_var_D; +uint16 flies_var_E; +uint16 flies_var_F; +uint16 flies_parameter_1; +uint16 flies_parameter_2; +}Enemy_Flies; +typedef struct Enemy_Fune { +EnemyBase base; +uint16 fune_var_A; +uint16 fune_var_B; +uint16 fune_var_C; +uint16 fune_var_D; +uint16 fune_var_E; +uint16 fune_var_F; +uint16 fune_parameter_1; +uint16 fune_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 fune_var_00; + uint16 fune_var_01; + uint16 fune_var_02; + uint16 fune_var_03; + uint16 fune_var_04; + uint16 fune_var_05; + uint16 fune_var_06; + uint16 fune_var_07; + uint16 fune_var_08; + uint16 fune_var_09; + uint16 fune_var_0A; + uint16 fune_var_0B; + uint16 fune_var_0C; + uint16 fune_var_0D; + uint16 fune_var_0E; + uint16 fune_var_0F; + uint16 fune_var_10; + uint16 fune_var_11; + uint16 fune_var_12; + uint16 fune_var_13; + uint16 fune_var_14; + uint16 fune_var_15; + uint16 fune_var_16; + uint16 fune_var_17; + uint16 fune_var_18; + uint16 fune_var_19; + uint16 fune_var_1A; + uint16 fune_var_1B; + uint16 fune_var_1C; + uint16 fune_var_1D; + uint16 fune_var_1E; + uint16 fune_var_1F; +}Enemy_Fune; +typedef struct Enemy_Gripper { +EnemyBase base; +uint16 gripper_var_A; +uint16 gripper_var_B; +uint16 gripper_var_C; +uint16 gripper_var_D; +uint16 gripper_var_E; +uint16 gripper_var_F; +uint16 gripper_parameter_1; +uint16 gripper_parameter_2; +}Enemy_Gripper; +typedef struct Enemy_GunshipBottom { +EnemyBase base; +uint16 gbm_var_A; +uint16 gbm_var_B; +uint16 gbm_var_C; +uint16 gbm_var_D; +uint16 gbm_var_E; +uint16 gbm_var_F; +uint16 gbm_parameter_1; +uint16 gbm_parameter_2; +}Enemy_GunshipBottom; +typedef struct Enemy_GunshipTop { +EnemyBase base; +uint16 gtp_var_A; +uint16 gtp_var_B; +uint16 gtp_var_C; +uint16 gtp_var_D; +uint16 gtp_var_E; +uint16 gtp_var_F; +uint16 gtp_parameter_1; +uint16 gtp_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 gtp_var_00; + uint16 gtp_var_01; + uint16 gtp_var_02; + uint16 gtp_var_03; + uint16 gtp_var_04; + uint16 gtp_var_05; + uint16 gtp_var_06; + uint16 gtp_var_07; + uint16 gtp_var_08; + uint16 gtp_var_09; + uint16 gtp_var_0A; + uint16 gtp_var_0B; + uint16 gtp_var_0C; + uint16 gtp_var_0D; + uint16 gtp_var_0E; + uint16 gtp_var_0F; + uint16 gtp_var_10; + uint16 gtp_var_11; + uint16 gtp_var_12; + uint16 gtp_var_13; + uint16 gtp_var_14; + uint16 gtp_var_15; + uint16 gtp_var_16; + uint16 gtp_var_17; + uint16 gtp_var_18; + uint16 gtp_var_19; + uint16 gtp_var_1A; + uint16 gtp_var_1B; + uint16 gtp_var_1C; + uint16 gtp_var_1D; + uint16 gtp_var_1E; + uint16 gtp_var_1F; +}Enemy_GunshipTop; +typedef struct Enemy_HirisingSlowfalling { +EnemyBase base; +uint16 hsg_var_A; +uint16 hsg_var_B; +uint16 hsg_var_C; +uint16 hsg_var_D; +uint16 hsg_var_E; +uint16 hsg_var_F; +uint16 hsg_parameter_1; +uint16 hsg_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 hsg_var_00; + uint16 hsg_var_01; + uint16 hsg_var_02; + uint16 hsg_var_03; + uint16 hsg_var_04; + uint16 hsg_var_05; + uint16 hsg_var_06; + uint16 hsg_var_07; + uint16 hsg_var_08; + uint16 hsg_var_09; + uint16 hsg_var_0A; + uint16 hsg_var_0B; + uint16 hsg_var_0C; + uint16 hsg_var_0D; + uint16 hsg_var_0E; + uint16 hsg_var_0F; + uint16 hsg_var_10; + uint16 hsg_var_11; + uint16 hsg_var_12; + uint16 hsg_var_13; + uint16 hsg_var_14; + uint16 hsg_var_15; + uint16 hsg_var_16; + uint16 hsg_var_17; + uint16 hsg_var_18; + uint16 hsg_var_19; + uint16 hsg_var_1A; + uint16 hsg_var_1B; + uint16 hsg_var_1C; + uint16 hsg_var_1D; + uint16 hsg_var_1E; + uint16 hsg_var_1F; +}Enemy_HirisingSlowfalling; +typedef struct Enemy_HorizontalShootableShutter { +EnemyBase base; +uint16 hssr_var_A; +uint16 hssr_var_B; +uint16 hssr_var_C; +uint16 hssr_var_D; +uint16 hssr_var_E; +uint16 hssr_var_F; +uint16 hssr_parameter_1; +uint16 hssr_parameter_2; +} Enemy_HorizontalShootableShutter; +typedef struct Enemy_JetPowerRipper { +EnemyBase base; +uint16 jprr_var_A; +uint16 jprr_var_B; +uint16 jprr_var_C; +uint16 jprr_var_D; +uint16 jprr_var_E; +uint16 jprr_var_F; +uint16 jprr_parameter_1; +uint16 jprr_parameter_2; +}Enemy_JetPowerRipper; +typedef struct Enemy_Kago { +EnemyBase base; +uint16 kago_var_A; +uint16 kago_var_B; +uint16 kago_var_C; +uint16 kago_var_D; +uint16 kago_var_E; +uint16 kago_var_F; +uint16 kago_parameter_1; +uint16 kago_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 kago_var_00; + uint16 kago_var_01; + uint16 kago_var_02; + uint16 kago_var_03; + uint16 kago_var_04; + uint16 kago_var_05; + uint16 kago_var_06; + uint16 kago_var_07; + uint16 kago_var_08; + uint16 kago_var_09; + uint16 kago_var_0A; + uint16 kago_var_0B; + uint16 kago_var_0C; + uint16 kago_var_0D; + uint16 kago_var_0E; + uint16 kago_var_0F; + uint16 kago_var_10; + uint16 kago_var_11; + uint16 kago_var_12; + uint16 kago_var_13; + uint16 kago_var_14; + uint16 kago_var_15; + uint16 kago_var_16; + uint16 kago_var_17; + uint16 kago_var_18; + uint16 kago_var_19; + uint16 kago_var_1A; + uint16 kago_var_1B; + uint16 kago_var_1C; + uint16 kago_var_1D; + uint16 kago_var_1E; + uint16 kago_var_1F; +}Enemy_Kago; +typedef struct Enemy_KiHunter { +EnemyBase base; +uint16 khr_var_A; +uint16 khr_var_B; +uint16 khr_var_C; +uint16 khr_var_D; +uint16 khr_var_E; +uint16 khr_var_F; +uint16 khr_parameter_1; +uint16 khr_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 khr_var_00; + uint16 khr_var_01; + uint16 khr_var_02; + uint16 khr_var_03; + uint16 khr_var_04; + uint16 khr_var_05; + uint16 khr_var_06; + uint16 khr_var_07; + uint16 khr_var_08; + uint16 khr_var_09; + uint16 khr_var_0A; + uint16 khr_var_0B; + uint16 khr_var_0C; + uint16 khr_var_0D; + uint16 khr_var_0E; + uint16 khr_var_0F; + uint16 khr_var_10; + uint16 khr_var_11; + uint16 khr_var_12; + uint16 khr_var_13; + uint16 khr_var_14; + uint16 khr_var_15; + uint16 khr_var_16; + uint16 khr_var_17; + uint16 khr_var_18; + uint16 khr_var_19; + uint16 khr_var_1A; + uint16 khr_var_1B; + uint16 khr_var_1C; + uint16 khr_var_1D; + uint16 khr_var_1E; + uint16 khr_var_1F; +}Enemy_KiHunter; +typedef struct Enemy_Kraid { +EnemyBase base; +uint16 kraid_var_A; +uint16 kraid_var_B; +uint16 kraid_var_C; +uint16 kraid_var_D; +uint16 kraid_var_E; +uint16 kraid_var_F; +uint16 kraid_parameter_1; +uint16 kraid_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; +uint16 kraid_next; + uint16 field_2; + uint16 field_4; + uint16 kraid_thinking; + uint16 kraid_min_y_pos_eject; + uint16 kraid_mouth_flags; + uint16 kraid_healths_8ths[8]; + uint16 field_1C; + uint16 kraid_target_x; + uint16 kraid_healths_4ths[4]; + uint16 field_28; + uint16 kraid_hurt_frame; + uint16 kraid_hurt_frame_timer; + uint16 field_2E[9]; +}Enemy_Kraid; +typedef struct Enemy_LavaSeahorse { +EnemyBase base; +uint16 lse_var_A; +uint16 lse_var_B; +uint16 lse_var_C; +uint16 lse_var_D; +uint16 lse_var_E; +uint16 lse_var_F; +uint16 lse_parameter_1; +uint16 lse_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 lse_var_00; + uint16 lse_var_01; + uint16 lse_var_02; + uint16 lse_var_03; + uint16 lse_var_04; + uint16 lse_var_05; + uint16 lse_var_06; + uint16 lse_var_07; + uint16 lse_var_08; + uint16 lse_var_09; + uint16 lse_var_0A; + uint16 lse_var_0B; + uint16 lse_var_0C; + uint16 lse_var_0D; + uint16 lse_var_0E; + uint16 lse_var_0F; + uint16 lse_var_10; + uint16 lse_var_11; + uint16 lse_var_12; + uint16 lse_var_13; + uint16 lse_var_14; + uint16 lse_var_15; + uint16 lse_var_16; + uint16 lse_var_17; + uint16 lse_var_18; + uint16 lse_var_19; + uint16 lse_var_1A; + uint16 lse_var_1B; + uint16 lse_var_1C; + uint16 lse_var_1D; + uint16 lse_var_1E; + uint16 lse_var_1F; +}Enemy_LavaSeahorse; +typedef struct Enemy_LavaquakeRocks { +EnemyBase base; +uint16 lrs_var_A; +uint16 lrs_var_B; +uint16 lrs_var_C; +uint16 lrs_var_D; +uint16 lrs_var_E; +uint16 lrs_var_F; +uint16 lrs_parameter_1; +uint16 lrs_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 lrs_var_00; + uint16 lrs_var_01; + uint16 lrs_var_02; + uint16 lrs_var_03; + uint16 lrs_var_04; + uint16 lrs_var_05; + uint16 lrs_var_06; + uint16 lrs_var_07; + uint16 lrs_var_08; + uint16 lrs_var_09; + uint16 lrs_var_0A; + uint16 lrs_var_0B; + uint16 lrs_var_0C; + uint16 lrs_var_0D; + uint16 lrs_var_0E; + uint16 lrs_var_0F; + uint16 lrs_var_10; + uint16 lrs_var_11; + uint16 lrs_var_12; + uint16 lrs_var_13; + uint16 lrs_var_14; + uint16 lrs_var_15; + uint16 lrs_var_16; + uint16 lrs_var_17; + uint16 lrs_var_18; + uint16 lrs_var_19; + uint16 lrs_var_1A; + uint16 lrs_var_1B; + uint16 lrs_var_1C; + uint16 lrs_var_1D; + uint16 lrs_var_1E; + uint16 lrs_var_1F; +}Enemy_LavaquakeRocks; +typedef struct Enemy_LowerNorfairRio { +EnemyBase base; +uint16 lnro_var_A; +uint16 lnro_var_B; +uint16 lnro_var_C; +uint16 lnro_var_D; +uint16 lnro_var_E; +uint16 lnro_var_F; +uint16 lnro_parameter_1; +uint16 lnro_parameter_2; +}Enemy_LowerNorfairRio; +typedef struct Enemy_MaridiaBeybladeTurtle { +EnemyBase base; +uint16 mbte_var_A; +uint16 mbte_var_B; +uint16 mbte_var_C; +uint16 mbte_var_D; +uint16 mbte_var_E; +uint16 mbte_var_F; +uint16 mbte_parameter_1; +uint16 mbte_parameter_2; +}Enemy_MaridiaBeybladeTurtle; +typedef struct Enemy_MaridiaFish { +EnemyBase base; +uint16 mfh_var_A; +uint16 mfh_var_B; +uint16 mfh_var_C; +uint16 mfh_var_D; +uint16 mfh_var_E; +uint16 mfh_var_F; +uint16 mfh_parameter_1; +uint16 mfh_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 mfh_var_00; + uint16 mfh_var_01; + uint16 mfh_var_02; + uint16 mfh_var_03; + uint16 mfh_var_04; + uint16 mfh_var_05; + uint16 mfh_var_06; + uint16 mfh_var_07; + uint16 mfh_var_08; + uint16 mfh_var_09; + uint16 mfh_var_0A; + uint16 mfh_var_0B; + uint16 mfh_var_0C; + uint16 mfh_var_0D; + uint16 mfh_var_0E; + uint16 mfh_var_0F; + uint16 mfh_var_10; + uint16 mfh_var_11; + uint16 mfh_var_12; + uint16 mfh_var_13; + uint16 mfh_var_14; + uint16 mfh_var_15; + uint16 mfh_var_16; + uint16 mfh_var_17; + uint16 mfh_var_18; + uint16 mfh_var_19; + uint16 mfh_var_1A; + uint16 mfh_var_1B; + uint16 mfh_var_1C; + uint16 mfh_var_1D; + uint16 mfh_var_1E; + uint16 mfh_var_1F; +}Enemy_MaridiaFish; +typedef struct Enemy_MaridiaFloater { +EnemyBase base; +uint16 mfr_var_A; +uint16 mfr_var_B; +uint16 mfr_var_C; +uint16 mfr_var_D; +uint16 mfr_var_E; +uint16 mfr_var_F; +uint16 mfr_parameter_1; +uint16 mfr_parameter_2; +}Enemy_MaridiaFloater; +typedef struct Enemy_MaridiaLargeSnail { +EnemyBase base; +uint16 mlsl_var_A; +uint16 mlsl_var_B; +uint16 mlsl_var_C; +uint16 mlsl_var_D; +uint16 mlsl_var_E; +uint16 mlsl_var_F; +uint16 mlsl_parameter_1; +uint16 mlsl_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 mlsl_var_00; + uint16 mlsl_var_01; + uint16 mlsl_var_02; + uint16 mlsl_var_03; + uint16 mlsl_var_04; + uint16 mlsl_var_05; + uint16 mlsl_var_06; + uint16 mlsl_var_07; + uint16 mlsl_var_08; + uint16 mlsl_var_09; + uint16 mlsl_var_0A; + uint16 mlsl_var_0B; + uint16 mlsl_var_0C; + uint16 mlsl_var_0D; + uint16 mlsl_var_0E; + uint16 mlsl_var_0F; + uint16 mlsl_var_10; + uint16 mlsl_var_11; + uint16 mlsl_var_12; + uint16 mlsl_var_13; + uint16 mlsl_var_14; + uint16 mlsl_var_15; + uint16 mlsl_var_16; + uint16 mlsl_var_17; + uint16 mlsl_var_18; + uint16 mlsl_var_19; + uint16 mlsl_var_1A; + uint16 mlsl_var_1B; + uint16 mlsl_var_1C; + uint16 mlsl_var_1D; + uint16 mlsl_var_1E; + uint16 mlsl_var_1F; +}Enemy_MaridiaLargeSnail; +typedef struct Enemy_MaridiaPuffer { +EnemyBase base; +uint16 mpr_var_A; +uint16 mpr_var_B; +uint16 mpr_var_C; +uint16 mpr_var_D; +uint16 mpr_var_E; +uint16 mpr_var_F; +uint16 mpr_parameter_1; +uint16 mpr_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 mpr_var_00; + uint16 mpr_var_01; + uint16 mpr_var_02; + uint16 mpr_var_03; + uint16 mpr_var_04; + uint16 mpr_var_05; + uint16 mpr_var_06; + uint16 mpr_var_07; + uint16 mpr_var_08; + uint16 mpr_var_09; + uint16 mpr_var_0A; + uint16 mpr_var_0B; + uint16 mpr_var_0C; + uint16 mpr_var_0D; + uint16 mpr_var_0E; + uint16 mpr_var_0F; + uint16 mpr_var_10; + uint16 mpr_var_11; + uint16 mpr_var_12; + uint16 mpr_var_13; + uint16 mpr_var_14; + uint16 mpr_var_15; + uint16 mpr_var_16; + uint16 mpr_var_17; + uint16 mpr_var_18; + uint16 mpr_var_19; + uint16 mpr_var_1A; + uint16 mpr_var_1B; + uint16 mpr_var_1C; + uint16 mpr_var_1D; + uint16 mpr_var_1E; + uint16 mpr_var_1F; +uint8 pad3[0x8800-0x7840]; + uint16 mpr_var_40; + uint16 mpr_var_41; + uint16 mpr_var_42; + uint16 mpr_var_43; + uint16 mpr_var_44; + uint16 mpr_var_45; + uint16 mpr_var_46; + uint16 mpr_var_47; + uint16 mpr_var_48; + uint16 mpr_var_49; + uint16 mpr_var_4A; + uint16 mpr_var_4B; + uint16 mpr_var_4C; + uint16 mpr_var_4D; + uint16 mpr_var_4E; + uint16 mpr_var_4F; + uint16 mpr_var_50; + uint16 mpr_var_51; + uint16 mpr_var_52; + uint16 mpr_var_53; + uint16 mpr_var_54; + uint16 mpr_var_55; + uint16 mpr_var_56; + uint16 mpr_var_57; + uint16 mpr_var_58; + uint16 mpr_var_59; + uint16 mpr_var_5A; + uint16 mpr_var_5B; + uint16 mpr_var_5C; + uint16 mpr_var_5D; + uint16 mpr_var_5E; + uint16 mpr_var_5F; +}Enemy_MaridiaPuffer; +typedef struct Enemy_MaridiaRefillCandy { +EnemyBase base; +uint16 mrcy_var_A; +uint16 mrcy_var_B; +uint16 mrcy_var_C; +uint16 mrcy_var_D; +uint16 mrcy_var_E; +uint16 mrcy_var_F; +uint16 mrcy_parameter_1; +uint16 mrcy_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 mrcy_var_00; + uint16 mrcy_var_01; + uint16 mrcy_var_02; + uint16 mrcy_var_03; + uint16 mrcy_var_04; + uint16 mrcy_var_05; + uint16 mrcy_var_06; + uint16 mrcy_var_07; + uint16 mrcy_var_08; + uint16 mrcy_var_09; + uint16 mrcy_var_0A; + uint16 mrcy_var_0B; + uint16 mrcy_var_0C; + uint16 mrcy_var_0D; + uint16 mrcy_var_0E; + uint16 mrcy_var_0F; + uint16 mrcy_var_10; + uint16 mrcy_var_11; + uint16 mrcy_var_12; + uint16 mrcy_var_13; + uint16 mrcy_var_14; + uint16 mrcy_var_15; + uint16 mrcy_var_16; + uint16 mrcy_var_17; + uint16 mrcy_var_18; + uint16 mrcy_var_19; + uint16 mrcy_var_1A; + uint16 mrcy_var_1B; + uint16 mrcy_var_1C; + uint16 mrcy_var_1D; + uint16 mrcy_var_1E; + uint16 mrcy_var_1F; +}Enemy_MaridiaRefillCandy; +typedef struct Enemy_MaridiaSnail { +EnemyBase base; +uint16 msl_var_A; +uint16 msl_var_B; +uint16 msl_var_C; +uint16 msl_var_D; +uint16 msl_var_E; +uint16 msl_var_F; +uint16 msl_parameter_1; +uint16 msl_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 msl_var_00; + uint16 msl_var_01; + uint16 msl_var_02; + uint16 msl_var_03; + uint16 msl_var_04; + uint16 msl_var_05; + uint16 msl_var_06; + uint16 msl_var_07; + uint16 msl_var_08; + uint16 msl_var_09; + uint16 msl_var_0A; + uint16 msl_var_0B; + uint16 msl_var_0C; + uint16 msl_var_0D; + uint16 msl_var_0E; + uint16 msl_var_0F; + uint16 msl_var_10; + uint16 msl_var_11; + uint16 msl_var_12; + uint16 msl_var_13; + uint16 msl_var_14; + uint16 msl_var_15; + uint16 msl_var_16; + uint16 msl_var_17; + uint16 msl_var_18; + uint16 msl_var_19; + uint16 msl_var_1A; + uint16 msl_var_1B; + uint16 msl_var_1C; + uint16 msl_var_1D; + uint16 msl_var_1E; + uint16 msl_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 msl_var_20; + uint16 msl_var_21; + uint16 msl_var_22; + uint16 msl_var_23; + uint16 msl_var_24; + uint16 msl_var_25; + uint16 msl_var_26; + uint16 msl_var_27; + uint16 msl_var_28; + uint16 msl_var_29; + uint16 msl_var_2A; + uint16 msl_var_2B; + uint16 msl_var_2C; + uint16 msl_var_2D; + uint16 msl_var_2E; + uint16 msl_var_2F; + uint16 msl_var_30; + uint16 msl_var_31; + uint16 msl_var_32; + uint16 msl_var_33; + uint16 msl_var_34; + uint16 msl_var_35; + uint16 msl_var_36; + uint16 msl_var_37; + uint16 msl_var_38; + uint16 msl_var_39; + uint16 msl_var_3A; + uint16 msl_var_3B; + uint16 msl_var_3C; + uint16 msl_var_3D; + uint16 msl_var_3E; + uint16 msl_var_3F; +}Enemy_MaridiaSnail; +typedef struct Enemy_MaridiaSpikeyShell { +EnemyBase base; +uint16 mssl_var_A; +uint16 mssl_var_B; +uint16 mssl_var_C; +uint16 mssl_var_D; +uint16 mssl_var_E; +uint16 mssl_var_F; +uint16 mssl_parameter_1; +uint16 mssl_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 mssl_var_00; + uint16 mssl_var_01; + uint16 mssl_var_02; + uint16 mssl_var_03; + uint16 mssl_var_04; + uint16 mssl_var_05; + uint16 mssl_var_06; + uint16 mssl_var_07; + uint16 mssl_var_08; + uint16 mssl_var_09; + uint16 mssl_var_0A; + uint16 mssl_var_0B; + uint16 mssl_var_0C; + uint16 mssl_var_0D; + uint16 mssl_var_0E; + uint16 mssl_var_0F; + uint16 mssl_var_10; + uint16 mssl_var_11; + uint16 mssl_var_12; + uint16 mssl_var_13; + uint16 mssl_var_14; + uint16 mssl_var_15; + uint16 mssl_var_16; + uint16 mssl_var_17; + uint16 mssl_var_18; + uint16 mssl_var_19; + uint16 mssl_var_1A; + uint16 mssl_var_1B; + uint16 mssl_var_1C; + uint16 mssl_var_1D; + uint16 mssl_var_1E; + uint16 mssl_var_1F; +}Enemy_MaridiaSpikeyShell; +typedef struct Enemy_MaridiaTurtle { +EnemyBase base; +uint16 mte_var_A; +uint16 mte_var_B; +uint16 mte_var_C; +uint16 mte_var_D; +uint16 mte_var_E; +uint16 mte_var_F; +uint16 mte_parameter_1; +uint16 mte_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 mte_var_00; + uint16 mte_var_01; + uint16 mte_var_02; + uint16 mte_var_03; + uint16 mte_var_04; + uint16 mte_var_05; + uint16 mte_var_06; + uint16 mte_var_07; + uint16 mte_var_08; + uint16 mte_var_09; + uint16 mte_var_0A; + uint16 mte_var_0B; + uint16 mte_var_0C; + uint16 mte_var_0D; + uint16 mte_var_0E; + uint16 mte_var_0F; + uint16 mte_var_10; + uint16 mte_var_11; + uint16 mte_var_12; + uint16 mte_var_13; + uint16 mte_var_14; + uint16 mte_var_15; + uint16 mte_var_16; + uint16 mte_var_17; + uint16 mte_var_18; + uint16 mte_var_19; + uint16 mte_var_1A; + uint16 mte_var_1B; + uint16 mte_var_1C; + uint16 mte_var_1D; + uint16 mte_var_1E; + uint16 mte_var_1F; +}Enemy_MaridiaTurtle; +typedef struct Enemy_Metalee { +EnemyBase base; +uint16 metalee_var_A; +uint16 metalee_var_B; +uint16 metalee_var_C; +uint16 metalee_var_D; +uint16 metalee_var_E; +uint16 metalee_var_F; +uint16 metalee_parameter_1; +uint16 metalee_parameter_2; +}Enemy_Metalee; +typedef struct Enemy_Metroid { + EnemyBase base; + uint16 metroid_var_A; + uint16 metroid_var_B; + uint16 metroid_var_C; + uint16 metroid_var_D; + uint16 metroid_var_E; + uint16 metroid_var_F; + uint16 metroid_parameter_1; + uint16 metroid_parameter_2; + uint8 pad1[0x7800 - 0xFB8]; + uint16 metroid_var_00; + uint16 metroid_var_01; + uint16 metroid_var_02; + uint16 metroid_var_03; + uint16 metroid_var_04; + uint16 metroid_var_05; + uint16 metroid_var_06; + uint16 metroid_var_07; + uint16 metroid_var_08; + uint16 metroid_var_09; + uint16 metroid_var_0A; + uint16 metroid_var_0B; + uint16 metroid_var_0C; + uint16 metroid_var_0D; + uint16 metroid_var_0E; + uint16 metroid_var_0F; + uint16 metroid_var_10; + uint16 metroid_var_11; + uint16 metroid_var_12; + uint16 metroid_var_13; + uint16 metroid_var_14; + uint16 metroid_var_15; + uint16 metroid_var_16; + uint16 metroid_var_17; + uint16 metroid_var_18; + uint16 metroid_var_19; + uint16 metroid_var_1A; + uint16 metroid_var_1B; + uint16 metroid_var_1C; + uint16 metroid_var_1D; + uint16 metroid_var_1E; + uint16 metroid_var_1F; +}Enemy_Metroid; +typedef struct Enemy_MiniCrocomire { +EnemyBase base; +uint16 mce_var_A; +uint16 mce_var_B; +uint16 mce_var_C; +uint16 mce_var_D; +uint16 mce_var_E; +uint16 mce_var_F; +uint16 mce_parameter_1; +uint16 mce_parameter_2; +}Enemy_MiniCrocomire; +typedef struct Enemy_MiniDraygon { +EnemyBase base; +uint16 mdn_var_A; +uint16 mdn_var_B; +uint16 mdn_var_C; +uint16 mdn_var_D; +uint16 mdn_var_E; +uint16 mdn_var_F; +uint16 mdn_parameter_1; +uint16 mdn_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 mdn_var_00; + uint16 mdn_var_01; + uint16 mdn_var_02; + uint16 mdn_var_03; + uint16 mdn_var_04; + uint16 mdn_var_05; + uint16 mdn_var_06; + uint16 mdn_var_07; + uint16 mdn_var_08; + uint16 mdn_var_09; + uint16 mdn_var_0A; + uint16 mdn_var_0B; + uint16 mdn_var_0C; + uint16 mdn_var_0D; + uint16 mdn_var_0E; + uint16 mdn_var_0F; + uint16 mdn_var_10; + uint16 mdn_var_11; + uint16 mdn_var_12; + uint16 mdn_var_13; + uint16 mdn_var_14; + uint16 mdn_var_15; + uint16 mdn_var_16; + uint16 mdn_var_17; + uint16 mdn_var_18; + uint16 mdn_var_19; + uint16 mdn_var_1A; + uint16 mdn_var_1B; + uint16 mdn_var_1C; + uint16 mdn_var_1D; + uint16 mdn_var_1E; + uint16 mdn_var_1F; +}Enemy_MiniDraygon; +typedef struct Enemy_MiniMaridiaBeybladeTurtle { +EnemyBase base; +uint16 mmbte_var_A; +uint16 mmbte_var_B; +uint16 mmbte_var_C; +uint16 mmbte_var_D; +uint16 mmbte_var_E; +uint16 mmbte_var_F; +uint16 mmbte_parameter_1; +uint16 mmbte_parameter_2; +}Enemy_MiniMaridiaBeybladeTurtle; +typedef struct Enemy_MiniMaridiaTurtle { +EnemyBase base; +uint16 mmte_var_A; +uint16 mmte_var_B; +uint16 mmte_var_C; +uint16 mmte_var_D; +uint16 mmte_var_E; +uint16 mmte_var_F; +uint16 mmte_parameter_1; +uint16 mmte_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 mmte_var_00; + uint16 mmte_var_01; + uint16 mmte_var_02; + uint16 mmte_var_03; + uint16 mmte_var_04; + uint16 mmte_var_05; + uint16 mmte_var_06; + uint16 mmte_var_07; + uint16 mmte_var_08; + uint16 mmte_var_09; + uint16 mmte_var_0A; + uint16 mmte_var_0B; + uint16 mmte_var_0C; + uint16 mmte_var_0D; + uint16 mmte_var_0E; + uint16 mmte_var_0F; + uint16 mmte_var_10; + uint16 mmte_var_11; + uint16 mmte_var_12; + uint16 mmte_var_13; + uint16 mmte_var_14; + uint16 mmte_var_15; + uint16 mmte_var_16; + uint16 mmte_var_17; + uint16 mmte_var_18; + uint16 mmte_var_19; + uint16 mmte_var_1A; + uint16 mmte_var_1B; + uint16 mmte_var_1C; + uint16 mmte_var_1D; + uint16 mmte_var_1E; + uint16 mmte_var_1F; +}Enemy_MiniMaridiaTurtle; +typedef struct Enemy_Mochtroid { +EnemyBase base; +uint16 mochtr_var_A; +uint16 mochtr_var_B; +uint16 mochtr_var_C; +uint16 mochtr_var_D; +uint16 mochtr_var_E; +uint16 mochtr_var_F; +uint16 mochtr_parameter_1; +uint16 mochtr_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 mochtr_var_00; + uint16 mochtr_var_01; + uint16 mochtr_var_02; + uint16 mochtr_var_03; + uint16 mochtr_var_04; + uint16 mochtr_var_05; + uint16 mochtr_var_06; + uint16 mochtr_var_07; + uint16 mochtr_var_08; + uint16 mochtr_var_09; + uint16 mochtr_var_0A; + uint16 mochtr_var_0B; + uint16 mochtr_var_0C; + uint16 mochtr_var_0D; + uint16 mochtr_var_0E; + uint16 mochtr_var_0F; + uint16 mochtr_var_10; + uint16 mochtr_var_11; + uint16 mochtr_var_12; + uint16 mochtr_var_13; + uint16 mochtr_var_14; + uint16 mochtr_var_15; + uint16 mochtr_var_16; + uint16 mochtr_var_17; + uint16 mochtr_var_18; + uint16 mochtr_var_19; + uint16 mochtr_var_1A; + uint16 mochtr_var_1B; + uint16 mochtr_var_1C; + uint16 mochtr_var_1D; + uint16 mochtr_var_1E; + uint16 mochtr_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 mochtr_var_20; + uint16 mochtr_var_21; + uint16 mochtr_var_22; + uint16 mochtr_var_23; + uint16 mochtr_var_24; + uint16 mochtr_var_25; + uint16 mochtr_var_26; + uint16 mochtr_var_27; + uint16 mochtr_var_28; + uint16 mochtr_var_29; + uint16 mochtr_var_2A; + uint16 mochtr_var_2B; + uint16 mochtr_var_2C; + uint16 mochtr_var_2D; + uint16 mochtr_var_2E; + uint16 mochtr_var_2F; + uint16 mochtr_var_30; + uint16 mochtr_var_31; + uint16 mochtr_var_32; + uint16 mochtr_var_33; + uint16 mochtr_var_34; + uint16 mochtr_var_35; + uint16 mochtr_var_36; + uint16 mochtr_var_37; + uint16 mochtr_var_38; + uint16 mochtr_var_39; + uint16 mochtr_var_3A; + uint16 mochtr_var_3B; + uint16 mochtr_var_3C; + uint16 mochtr_var_3D; + uint16 mochtr_var_3E; + uint16 mochtr_var_3F; +}Enemy_Mochtroid; +typedef struct Enemy_MorphBallEye { +EnemyBase base; +uint16 mbee_var_A; +uint16 mbee_var_B; +uint16 mbee_var_C; +uint16 mbee_var_D; +uint16 mbee_var_E; +uint16 mbee_var_F; +uint16 mbee_parameter_1; +uint16 mbee_parameter_2; +}Enemy_MorphBallEye; +typedef struct Enemy_MotherBomb { +EnemyBase base; +uint16 mbb_var_A; +uint16 mbb_var_B; +uint16 mbb_var_C; +uint16 mbb_var_D; +uint16 mbb_var_E; +uint16 mbb_var_F; +uint16 mbb_parameter_1; +uint16 mbb_parameter_2; +}Enemy_MotherBomb; +typedef struct Enemy_MotherBrain { +EnemyBase base; +uint16 mbn_var_A; +uint16 mbn_var_B; +uint16 mbn_var_C; +uint16 mbn_var_D; +uint16 mbn_var_E; +uint16 mbn_var_F; +uint16 mbn_parameter_1; +uint16 mbn_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 mbn_var_00; + uint16 mbn_var_01; + uint16 mbn_var_02; + uint16 mbn_var_03; + uint16 mbn_var_04; + uint16 mbn_var_05; + uint16 mbn_var_06; + uint16 mbn_var_07; + uint16 mbn_var_08; + uint16 mbn_var_09; + uint16 mbn_var_0A; + uint16 mbn_var_0B; + uint16 mbn_var_0C; + uint16 mbn_var_0D; + uint16 mbn_var_0E; + uint16 mbn_var_0F; + uint16 mbn_var_10; + uint16 mbn_var_11; + uint16 mbn_var_12; + uint16 mbn_var_13; + uint16 mbn_var_14; + uint16 mbn_var_15; + uint16 mbn_var_16; + uint16 mbn_var_17; + uint16 mbn_var_18; + uint16 mbn_var_19; + uint16 mbn_var_1A; + uint16 mbn_var_1B; + uint16 mbn_var_1C; + uint16 mbn_var_1D; + uint16 mbn_var_1E; + uint16 mbn_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 mbn_var_20; + uint16 mbn_var_21; + uint16 mbn_var_22; + uint16 mbn_var_23; + uint16 mbn_var_24; + uint16 mbn_var_25; + uint16 mbn_var_26; + uint16 mbn_var_27; + uint16 mbn_var_28; + uint16 mbn_var_29; + uint16 mbn_var_2A; + uint16 mbn_var_2B; + uint16 mbn_var_2C; + uint16 mbn_var_2D; + uint16 mbn_var_2E; + uint16 mbn_var_2F; + uint16 mbn_var_30; + uint16 mbn_var_31; + uint16 mbn_var_32; + uint16 mbn_var_33; + uint16 mbn_var_34; + uint16 mbn_var_35; + uint16 mbn_var_36; + uint16 mbn_var_37; + uint16 mbn_var_38; + uint16 mbn_var_39; + uint16 mbn_var_3A; + uint16 mbn_var_3B; + uint16 mbn_var_3C; + uint16 mbn_var_3D; + uint16 mbn_var_3E; + uint16 mbn_var_3F; +}Enemy_MotherBrain; +typedef struct Enemy_MotherBrainBody { +EnemyBase base; +uint16 mbby_var_A; +uint16 mbby_var_B; +uint16 mbby_var_C; +uint16 mbby_var_D; +uint16 mbby_var_E; +uint16 mbby_var_F; +uint16 mbby_parameter_1; +uint16 mbby_parameter_2; +}Enemy_MotherBrainBody; +typedef struct Enemy_MotherBrainsTubesFalling { +EnemyBase base; +uint16 mbtfg_var_A; +uint16 mbtfg_var_B; +uint16 mbtfg_var_C; +uint16 mbtfg_var_D; +uint16 mbtfg_var_E; +uint16 mbtfg_var_F; +uint16 mbtfg_parameter_1; +uint16 mbtfg_parameter_2; +}Enemy_MotherBrainsTubesFalling; +typedef struct Enemy_NorfairErraticFireball { + EnemyBase base; + uint16 nefl_var_A; + uint16 nefl_var_B; + uint16 nefl_var_C; + uint16 nefl_var_D; + uint16 nefl_var_E; + uint16 nefl_var_F; + uint16 nefl_parameter_1; + uint16 nefl_parameter_2; +}Enemy_NorfairErraticFireball; +typedef struct Enemy_NorfairLavaMan { +EnemyBase base; +uint16 nlmn_var_A; +uint16 nlmn_var_B; +uint16 nlmn_var_C; +uint16 nlmn_var_D; +uint16 nlmn_var_E; +uint16 nlmn_var_F; +uint16 nlmn_parameter_1; +uint16 nlmn_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 nlmn_var_00; + uint16 nlmn_var_01; + uint16 nlmn_var_02; + uint16 nlmn_var_03; + uint16 nlmn_var_04; + uint16 nlmn_var_05; + uint16 nlmn_var_06; + uint16 nlmn_var_07; + uint16 nlmn_var_08; + uint16 nlmn_var_09; + uint16 nlmn_var_0A; + uint16 nlmn_var_0B; + uint16 nlmn_var_0C; + uint16 nlmn_var_0D; + uint16 nlmn_var_0E; + uint16 nlmn_var_0F; + uint16 nlmn_var_10; + uint16 nlmn_var_11; + uint16 nlmn_var_12; + uint16 nlmn_var_13; + uint16 nlmn_var_14; + uint16 nlmn_var_15; + uint16 nlmn_var_16; + uint16 nlmn_var_17; + uint16 nlmn_var_18; + uint16 nlmn_var_19; + uint16 nlmn_var_1A; + uint16 nlmn_var_1B; + uint16 nlmn_var_1C; + uint16 nlmn_var_1D; + uint16 nlmn_var_1E; + uint16 nlmn_var_1F; +}Enemy_NorfairLavaMan; +typedef struct Enemy_NorfairLavajumpingEnemy { + EnemyBase base; + uint16 nley_var_A; + uint16 nley_var_B; + uint16 nley_var_C; + uint16 nley_var_D; + uint16 nley_var_E; + uint16 nley_var_F; + uint16 nley_parameter_1; + uint16 nley_parameter_2; + uint8 pad1[0x7800 - 0xFB8]; + uint16 nley_var_00; + uint16 nley_var_01; + uint16 nley_var_02; + uint16 nley_var_03; + uint16 nley_var_04; + uint16 nley_var_05; + uint16 nley_var_06; + uint16 nley_var_07; + uint16 nley_var_08; + uint16 nley_var_09; + uint16 nley_var_0A; + uint16 nley_var_0B; + uint16 nley_var_0C; + uint16 nley_var_0D; + uint16 nley_var_0E; + uint16 nley_var_0F; + uint16 nley_var_10; + uint16 nley_var_11; + uint16 nley_var_12; + uint16 nley_var_13; + uint16 nley_var_14; + uint16 nley_var_15; + uint16 nley_var_16; + uint16 nley_var_17; + uint16 nley_var_18; + uint16 nley_var_19; + uint16 nley_var_1A; + uint16 nley_var_1B; + uint16 nley_var_1C; + uint16 nley_var_1D; + uint16 nley_var_1E; + uint16 nley_var_1F; +}Enemy_NorfairLavajumpingEnemy; +typedef struct Enemy_NorfairRio { +EnemyBase base; +uint16 nro_var_A; +uint16 nro_var_B; +uint16 nro_var_C; +uint16 nro_var_D; +uint16 nro_var_E; +uint16 nro_var_F; +uint16 nro_parameter_1; +uint16 nro_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 nro_var_00; + uint16 nro_var_01; + uint16 nro_var_02; + uint16 nro_var_03; + uint16 nro_var_04; + uint16 nro_var_05; + uint16 nro_var_06; + uint16 nro_var_07; + uint16 nro_var_08; + uint16 nro_var_09; + uint16 nro_var_0A; + uint16 nro_var_0B; + uint16 nro_var_0C; + uint16 nro_var_0D; + uint16 nro_var_0E; + uint16 nro_var_0F; + uint16 nro_var_10; + uint16 nro_var_11; + uint16 nro_var_12; + uint16 nro_var_13; + uint16 nro_var_14; + uint16 nro_var_15; + uint16 nro_var_16; + uint16 nro_var_17; + uint16 nro_var_18; + uint16 nro_var_19; + uint16 nro_var_1A; + uint16 nro_var_1B; + uint16 nro_var_1C; + uint16 nro_var_1D; + uint16 nro_var_1E; + uint16 nro_var_1F; +}Enemy_NorfairRio; +typedef struct Enemy_NuclearWaffle { +EnemyBase base; +uint16 nwe_var_A; +uint16 nwe_var_B; +uint16 nwe_var_C; +uint16 nwe_var_D; +uint16 nwe_var_E; +uint16 nwe_var_F; +uint16 nwe_parameter_1; +uint16 nwe_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 nwe_var_00; + uint16 nwe_var_01; + uint16 nwe_var_02; + uint16 nwe_var_03; + uint16 nwe_var_04; + uint16 nwe_var_05; + uint16 nwe_var_06; + uint16 nwe_var_07; + uint16 nwe_var_08; + uint16 nwe_var_09; + uint16 nwe_var_0A; + uint16 nwe_var_0B; + uint16 nwe_var_0C; + uint16 nwe_var_0D; + uint16 nwe_var_0E; + uint16 nwe_var_0F; + uint16 nwe_var_10; + uint16 nwe_var_11; + uint16 nwe_var_12; + uint16 nwe_var_13; + uint16 nwe_var_14; + uint16 nwe_var_15; + uint16 nwe_var_16; + uint16 nwe_var_17; + uint16 nwe_var_18; + uint16 nwe_var_19; + uint16 nwe_var_1A; + uint16 nwe_var_1B; + uint16 nwe_var_1C; + uint16 nwe_var_1D; + uint16 nwe_var_1E; + uint16 nwe_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 nwe_var_20; + uint16 nwe_var_21; + uint16 nwe_var_22; + uint16 nwe_var_23; + uint16 nwe_var_24; + uint16 nwe_var_25; + uint16 nwe_var_26; + uint16 nwe_var_27; + uint16 nwe_var_28; + uint16 nwe_var_29; + uint16 nwe_var_2A; + uint16 nwe_var_2B; + uint16 nwe_var_2C; + uint16 nwe_var_2D; + uint16 nwe_var_2E; + uint16 nwe_var_2F; + uint16 nwe_var_30; + uint16 nwe_var_31; + uint16 nwe_var_32; + uint16 nwe_var_33; + uint16 nwe_var_34; + uint16 nwe_var_35; + uint16 nwe_var_36; + uint16 nwe_var_37; + uint16 nwe_var_38; + uint16 nwe_var_39; + uint16 nwe_var_3A; + uint16 nwe_var_3B; + uint16 nwe_var_3C; + uint16 nwe_var_3D; + uint16 nwe_var_3E; + uint16 nwe_var_3F; +}Enemy_NuclearWaffle; +typedef struct Enemy_Phantoon { +EnemyBase base; +uint16 phant_var_A; +uint16 phant_var_B; +uint16 phant_var_C; +uint16 phant_var_D; +uint16 phant_var_E; +uint16 phant_var_F; +uint16 phant_parameter_1; +uint16 phant_parameter_2; +}Enemy_Phantoon; +typedef struct Enemy_PipeBug { +EnemyBase base; +uint16 pbg_var_A; +uint16 pbg_var_B; +uint16 pbg_var_C; +uint16 pbg_var_D; +uint16 pbg_var_E; +uint16 pbg_var_F; +uint16 pbg_parameter_1; +uint16 pbg_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 pbg_var_00; + uint16 pbg_var_01; + uint16 pbg_var_02; + uint16 pbg_var_03; + uint16 pbg_var_04; + uint16 pbg_var_05; + uint16 pbg_var_06; + uint16 pbg_var_07; + uint16 pbg_var_08; + uint16 pbg_var_09; + uint16 pbg_var_0A; + uint16 pbg_var_0B; + uint16 pbg_var_0C; + uint16 pbg_var_0D; + uint16 pbg_var_0E; + uint16 pbg_var_0F; + uint16 pbg_var_10; + uint16 pbg_var_11; + uint16 pbg_var_12; + uint16 pbg_var_13; + uint16 pbg_var_14; + uint16 pbg_var_15; + uint16 pbg_var_16; + uint16 pbg_var_17; + uint16 pbg_var_18; + uint16 pbg_var_19; + uint16 pbg_var_1A; + uint16 pbg_var_1B; + uint16 pbg_var_1C; + uint16 pbg_var_1D; + uint16 pbg_var_1E; + uint16 pbg_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 pbg_var_20; + uint16 pbg_var_21; + uint16 pbg_var_22; + uint16 pbg_var_23; + uint16 pbg_var_24; + uint16 pbg_var_25; + uint16 pbg_var_26; + uint16 pbg_var_27; + uint16 pbg_var_28; + uint16 pbg_var_29; + uint16 pbg_var_2A; + uint16 pbg_var_2B; + uint16 pbg_var_2C; + uint16 pbg_var_2D; + uint16 pbg_var_2E; + uint16 pbg_var_2F; + uint16 pbg_var_30; + uint16 pbg_var_31; + uint16 pbg_var_32; + uint16 pbg_var_33; + uint16 pbg_var_34; + uint16 pbg_var_35; + uint16 pbg_var_36; + uint16 pbg_var_37; + uint16 pbg_var_38; + uint16 pbg_var_39; + uint16 pbg_var_3A; + uint16 pbg_var_3B; + uint16 pbg_var_3C; + uint16 pbg_var_3D; + uint16 pbg_var_3E; + uint16 pbg_var_3F; +}Enemy_PipeBug; +typedef struct Enemy_PlatformThatFallsWithSamus { +EnemyBase base; +uint16 ptfwss_var_A; +uint16 ptfwss_var_B; +uint16 ptfwss_var_C; +uint16 ptfwss_var_D; +uint16 ptfwss_var_E; +uint16 ptfwss_var_F; +uint16 ptfwss_parameter_1; +uint16 ptfwss_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 ptfwss_var_00; + uint16 ptfwss_var_01; + uint16 ptfwss_var_02; + uint16 ptfwss_var_03; + uint16 ptfwss_var_04; + uint16 ptfwss_var_05; + uint16 ptfwss_var_06; + uint16 ptfwss_var_07; + uint16 ptfwss_var_08; + uint16 ptfwss_var_09; + uint16 ptfwss_var_0A; + uint16 ptfwss_var_0B; + uint16 ptfwss_var_0C; + uint16 ptfwss_var_0D; + uint16 ptfwss_var_0E; + uint16 ptfwss_var_0F; + uint16 ptfwss_var_10; + uint16 ptfwss_var_11; + uint16 ptfwss_var_12; + uint16 ptfwss_var_13; + uint16 ptfwss_var_14; + uint16 ptfwss_var_15; + uint16 ptfwss_var_16; + uint16 ptfwss_var_17; + uint16 ptfwss_var_18; + uint16 ptfwss_var_19; + uint16 ptfwss_var_1A; + uint16 ptfwss_var_1B; + uint16 ptfwss_var_1C; + uint16 ptfwss_var_1D; + uint16 ptfwss_var_1E; + uint16 ptfwss_var_1F; +}Enemy_PlatformThatFallsWithSamus; +typedef struct Enemy_Reflec { +EnemyBase base; +uint16 reflec_var_A; +uint16 reflec_var_B; +uint16 reflec_var_C; +uint16 reflec_var_D; +uint16 reflec_var_E; +uint16 reflec_var_F; +uint16 reflec_parameter_1; +uint16 reflec_parameter_2; +}Enemy_Reflec; +typedef struct Enemy_Ridley { +EnemyBase base; +uint16 ridley_var_A; +uint16 ridley_var_B; +uint16 ridley_var_C; +uint16 ridley_var_D; +uint16 ridley_var_E; +uint16 ridley_var_F; +uint16 ridley_parameter_1; +uint16 ridley_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 ridley_var_00; + uint16 ridley_var_01; + uint16 ridley_var_02; + uint16 ridley_var_03; + uint16 ridley_var_04; + uint16 ridley_var_05; + uint16 ridley_var_06; + uint16 ridley_var_07; + uint16 ridley_var_08; + uint16 ridley_var_09; + uint16 ridley_var_0A; + uint16 ridley_var_0B; + uint16 ridley_var_0C; + uint16 ridley_var_0D; + uint16 ridley_var_0E; + uint16 ridley_var_0F; + uint16 ridley_var_10; + uint16 ridley_var_11; + uint16 ridley_var_12; + uint16 ridley_var_13; + uint16 ridley_var_14; + uint16 ridley_var_15; + uint16 ridley_var_16; + uint16 ridley_var_17; + uint16 ridley_var_18; + uint16 ridley_var_19; + uint16 ridley_var_1A; + uint16 ridley_var_1B; + uint16 ridley_var_1C; + uint16 ridley_var_1D; + uint16 ridley_var_1E; + uint16 ridley_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 ridley_var_20; + uint16 ridley_var_21; + uint16 ridley_var_22; + uint16 ridley_var_23; + uint16 ridley_var_24; + uint16 ridley_var_25; + uint16 ridley_var_26; + uint16 ridley_var_27; + uint16 ridley_var_28; + uint16 ridley_var_29; + uint16 ridley_var_2A; + uint16 ridley_var_2B; + uint16 ridley_var_2C; + uint16 ridley_var_2D; + uint16 ridley_var_2E; + uint16 ridley_var_2F; + uint16 ridley_var_30; + uint16 ridley_var_31; + uint16 ridley_var_32; + uint16 ridley_var_33; + uint16 ridley_var_34; + uint16 ridley_var_35; + uint16 ridley_var_36; + uint16 ridley_var_37; + uint16 ridley_var_38; + uint16 ridley_var_39; + uint16 ridley_var_3A; + uint16 ridley_var_3B; + uint16 ridley_var_3C; + uint16 ridley_var_3D; + uint16 ridley_var_3E; + uint16 ridley_var_3F; +uint8 pad3[0x8800-0x8040]; + uint16 ridley_var_40; + uint16 ridley_var_41; + uint16 ridley_var_42; + uint16 ridley_var_43; + uint16 ridley_var_44; + uint16 ridley_var_45; + uint16 ridley_var_46; + uint16 ridley_var_47; + uint16 ridley_var_48; + uint16 ridley_var_49; + uint16 ridley_var_4A; + uint16 ridley_var_4B; + uint16 ridley_var_4C; + uint16 ridley_var_4D; + uint16 ridley_var_4E; + uint16 ridley_var_4F; + uint16 ridley_var_50; + uint16 ridley_var_51; + uint16 ridley_var_52; + uint16 ridley_var_53; + uint16 ridley_var_54; + uint16 ridley_var_55; + uint16 ridley_var_56; + uint16 ridley_var_57; + uint16 ridley_var_58; + uint16 ridley_var_59; + uint16 ridley_var_5A; + uint16 ridley_var_5B; + uint16 ridley_var_5C; + uint16 ridley_var_5D; + uint16 ridley_var_5E; + uint16 ridley_var_5F; +}Enemy_Ridley; +typedef struct Enemy_RidleysExplosion { +EnemyBase base; +uint16 ren_var_A; +uint16 ren_var_B; +uint16 ren_var_C; +uint16 ren_var_D; +uint16 ren_var_E; +uint16 ren_var_F; +uint16 ren_parameter_1; +uint16 ren_parameter_2; +}Enemy_RidleysExplosion; +typedef struct Enemy_Rinka { +EnemyBase base; +uint16 rinka_var_A; +uint16 rinka_var_B; +uint16 rinka_var_C; +uint16 rinka_var_D; +uint16 rinka_var_E; +uint16 rinka_var_F; +uint16 rinka_parameter_1; +uint16 rinka_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 rinka_var_00; + uint16 rinka_var_01; + uint16 rinka_var_02; + uint16 rinka_var_03; + uint16 rinka_var_04; + uint16 rinka_var_05; + uint16 rinka_var_06; + uint16 rinka_var_07; + uint16 rinka_var_08; + uint16 rinka_var_09; + uint16 rinka_var_0A; + uint16 rinka_var_0B; + uint16 rinka_var_0C; + uint16 rinka_var_0D; + uint16 rinka_var_0E; + uint16 rinka_var_0F; + uint16 rinka_var_10; + uint16 rinka_var_11; + uint16 rinka_var_12; + uint16 rinka_var_13; + uint16 rinka_var_14; + uint16 rinka_var_15; + uint16 rinka_var_16; + uint16 rinka_var_17; + uint16 rinka_var_18; + uint16 rinka_var_19; + uint16 rinka_var_1A; + uint16 rinka_var_1B; + uint16 rinka_var_1C; + uint16 rinka_var_1D; + uint16 rinka_var_1E; + uint16 rinka_var_1F; +}Enemy_Rinka; +typedef struct Enemy_Rio { +EnemyBase base; +uint16 rio_var_A; +uint16 rio_var_B; +uint16 rio_var_C; +uint16 rio_var_D; +uint16 rio_var_E; +uint16 rio_var_F; +uint16 rio_parameter_1; +uint16 rio_parameter_2; +}Enemy_Rio; +typedef struct Enemy_Ripper { +EnemyBase base; +uint16 ripper_var_A; +uint16 ripper_var_B; +uint16 ripper_var_C; +uint16 ripper_var_D; +uint16 ripper_var_E; +uint16 ripper_var_F; +uint16 ripper_parameter_1; +uint16 ripper_parameter_2; +}Enemy_Ripper; +typedef struct Enemy_RisingFallingPlatform { +EnemyBase base; +uint16 rfpm_var_A; +uint16 rfpm_var_B; +uint16 rfpm_var_C; +uint16 rfpm_var_D; +uint16 rfpm_var_E; +uint16 rfpm_var_F; +uint16 rfpm_parameter_1; +uint16 rfpm_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 rfpm_var_00; + uint16 rfpm_var_01; + uint16 rfpm_var_02; + uint16 rfpm_var_03; + uint16 rfpm_var_04; + uint16 rfpm_var_05; + uint16 rfpm_var_06; + uint16 rfpm_var_07; + uint16 rfpm_var_08; + uint16 rfpm_var_09; + uint16 rfpm_var_0A; + uint16 rfpm_var_0B; + uint16 rfpm_var_0C; + uint16 rfpm_var_0D; + uint16 rfpm_var_0E; + uint16 rfpm_var_0F; + uint16 rfpm_var_10; + uint16 rfpm_var_11; + uint16 rfpm_var_12; + uint16 rfpm_var_13; + uint16 rfpm_var_14; + uint16 rfpm_var_15; + uint16 rfpm_var_16; + uint16 rfpm_var_17; + uint16 rfpm_var_18; + uint16 rfpm_var_19; + uint16 rfpm_var_1A; + uint16 rfpm_var_1B; + uint16 rfpm_var_1C; + uint16 rfpm_var_1D; + uint16 rfpm_var_1E; + uint16 rfpm_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 rfpm_var_20; + uint16 rfpm_var_21; + uint16 rfpm_var_22; + uint16 rfpm_var_23; + uint16 rfpm_var_24; + uint16 rfpm_var_25; + uint16 rfpm_var_26; + uint16 rfpm_var_27; + uint16 rfpm_var_28; + uint16 rfpm_var_29; + uint16 rfpm_var_2A; + uint16 rfpm_var_2B; + uint16 rfpm_var_2C; + uint16 rfpm_var_2D; + uint16 rfpm_var_2E; + uint16 rfpm_var_2F; + uint16 rfpm_var_30; + uint16 rfpm_var_31; + uint16 rfpm_var_32; + uint16 rfpm_var_33; + uint16 rfpm_var_34; + uint16 rfpm_var_35; + uint16 rfpm_var_36; + uint16 rfpm_var_37; + uint16 rfpm_var_38; + uint16 rfpm_var_39; + uint16 rfpm_var_3A; + uint16 rfpm_var_3B; + uint16 rfpm_var_3C; + uint16 rfpm_var_3D; + uint16 rfpm_var_3E; + uint16 rfpm_var_3F; +}Enemy_RisingFallingPlatform; +typedef struct Enemy_Roach { +EnemyBase base; +uint16 roach_var_A; +uint16 roach_var_B; +uint16 roach_var_C; +uint16 roach_var_D; +uint16 roach_var_E; +uint16 roach_var_F; +uint16 roach_parameter_1; +uint16 roach_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 roach_var_00; + uint16 roach_var_01; + uint16 roach_var_02; + uint16 roach_var_03; + uint16 roach_var_04; + uint16 roach_var_05; + uint16 roach_var_06; + uint16 roach_var_07; + uint16 roach_var_08; + uint16 roach_var_09; + uint16 roach_var_0A; + uint16 roach_var_0B; + uint16 roach_var_0C; + uint16 roach_var_0D; + uint16 roach_var_0E; + uint16 roach_var_0F; + uint16 roach_var_10; + uint16 roach_var_11; + uint16 roach_var_12; + uint16 roach_var_13; + uint16 roach_var_14; + uint16 roach_var_15; + uint16 roach_var_16; + uint16 roach_var_17; + uint16 roach_var_18; + uint16 roach_var_19; + uint16 roach_var_1A; + uint16 roach_var_1B; + uint16 roach_var_1C; + uint16 roach_var_1D; + uint16 roach_var_1E; + uint16 roach_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 roach_var_20; + uint16 roach_var_21; + uint16 roach_var_22; + uint16 roach_var_23; + uint16 roach_var_24; + uint16 roach_var_25; + uint16 roach_var_26; + uint16 roach_var_27; + uint16 roach_var_28; + uint16 roach_var_29; + uint16 roach_var_2A; + uint16 roach_var_2B; + uint16 roach_var_2C; + uint16 roach_var_2D; + uint16 roach_var_2E; + uint16 roach_var_2F; + uint16 roach_var_30; + uint16 roach_var_31; + uint16 roach_var_32; + uint16 roach_var_33; + uint16 roach_var_34; + uint16 roach_var_35; + uint16 roach_var_36; + uint16 roach_var_37; + uint16 roach_var_38; + uint16 roach_var_39; + uint16 roach_var_3A; + uint16 roach_var_3B; + uint16 roach_var_3C; + uint16 roach_var_3D; + uint16 roach_var_3E; + uint16 roach_var_3F; +}Enemy_Roach; +typedef struct Enemy_Shaktool { +EnemyBase base; +uint16 shakt_var_A; +uint16 shakt_var_B; +uint16 shakt_var_C; +uint16 shakt_var_D; +uint16 shakt_var_E; +uint16 shakt_var_F; +uint16 shakt_parameter_1; +uint16 shakt_parameter_2; +}Enemy_Shaktool; +typedef struct Enemy_ShitroidInCutscene { +EnemyBase base; +uint16 sice_var_A; +uint16 sice_var_B; +uint16 sice_var_C; +uint16 sice_var_D; +uint16 sice_var_E; +uint16 sice_var_F; +uint16 sice_parameter_1; +uint16 sice_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 sice_var_00; + uint16 sice_var_01; + uint16 sice_var_02; + uint16 sice_var_03; + uint16 sice_var_04; + uint16 sice_var_05; + uint16 sice_var_06; + uint16 sice_var_07; + uint16 sice_var_08; + uint16 sice_var_09; + uint16 sice_var_0A; + uint16 sice_var_0B; + uint16 sice_var_0C; + uint16 sice_var_0D; + uint16 sice_var_0E; + uint16 sice_var_0F; + uint16 sice_var_10; + uint16 sice_var_11; + uint16 sice_var_12; + uint16 sice_var_13; + uint16 sice_var_14; + uint16 sice_var_15; + uint16 sice_var_16; + uint16 sice_var_17; + uint16 sice_var_18; + uint16 sice_var_19; + uint16 sice_var_1A; + uint16 sice_var_1B; + uint16 sice_var_1C; + uint16 sice_var_1D; + uint16 sice_var_1E; + uint16 sice_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 sice_var_20; + uint16 sice_var_21; + uint16 sice_var_22; + uint16 sice_var_23; + uint16 sice_var_24; + uint16 sice_var_25; + uint16 sice_var_26; + uint16 sice_var_27; + uint16 sice_var_28; + uint16 sice_var_29; + uint16 sice_var_2A; + uint16 sice_var_2B; + uint16 sice_var_2C; + uint16 sice_var_2D; + uint16 sice_var_2E; + uint16 sice_var_2F; + uint16 sice_var_30; + uint16 sice_var_31; + uint16 sice_var_32; + uint16 sice_var_33; + uint16 sice_var_34; + uint16 sice_var_35; + uint16 sice_var_36; + uint16 sice_var_37; + uint16 sice_var_38; + uint16 sice_var_39; + uint16 sice_var_3A; + uint16 sice_var_3B; + uint16 sice_var_3C; + uint16 sice_var_3D; + uint16 sice_var_3E; + uint16 sice_var_3F; +}Enemy_ShitroidInCutscene; +typedef struct Enemy_Shitroid { +EnemyBase base; +uint16 shitr_var_A; +uint16 shitr_var_B; +uint16 shitr_var_C; +uint16 shitr_var_D; +uint16 shitr_var_E; +uint16 shitr_var_F; +uint16 shitr_parameter_1; +uint16 shitr_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 shitr_var_00; + uint16 shitr_var_01; + uint16 shitr_var_02; + uint16 shitr_var_03; + uint16 shitr_var_04; + uint16 shitr_var_05; + uint16 shitr_var_06; + uint16 shitr_var_07; + uint16 shitr_var_08; + uint16 shitr_var_09; + uint16 shitr_var_0A; + uint16 shitr_var_0B; + uint16 shitr_var_0C; + uint16 shitr_var_0D; + uint16 shitr_var_0E; + uint16 shitr_var_0F; + uint16 shitr_var_10; + uint16 shitr_var_11; + uint16 shitr_var_12; + uint16 shitr_var_13; + uint16 shitr_var_14; + uint16 shitr_var_15; + uint16 shitr_var_16; + uint16 shitr_var_17; + uint16 shitr_var_18; + uint16 shitr_var_19; + uint16 shitr_var_1A; + uint16 shitr_var_1B; + uint16 shitr_var_1C; + uint16 shitr_var_1D; + uint16 shitr_var_1E; + uint16 shitr_var_1F; +}Enemy_Shitroid; +typedef struct Enemy_Sidehopper { +EnemyBase base; +uint16 sideh_var_A; +uint16 sideh_var_B; +uint16 sideh_var_C; +uint16 sideh_var_D; +uint16 sideh_var_E; +uint16 sideh_var_F; +uint16 sideh_parameter_1; +uint16 sideh_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 sideh_var_00; + uint16 sideh_var_01; + uint16 sideh_var_02; + uint16 sideh_var_03; + uint16 sideh_var_04; + uint16 sideh_var_05; + uint16 sideh_var_06; + uint16 sideh_var_07; + uint16 sideh_var_08; + uint16 sideh_var_09; + uint16 sideh_var_0A; + uint16 sideh_var_0B; + uint16 sideh_var_0C; + uint16 sideh_var_0D; + uint16 sideh_var_0E; + uint16 sideh_var_0F; + uint16 sideh_var_10; + uint16 sideh_var_11; + uint16 sideh_var_12; + uint16 sideh_var_13; + uint16 sideh_var_14; + uint16 sideh_var_15; + uint16 sideh_var_16; + uint16 sideh_var_17; + uint16 sideh_var_18; + uint16 sideh_var_19; + uint16 sideh_var_1A; + uint16 sideh_var_1B; + uint16 sideh_var_1C; + uint16 sideh_var_1D; + uint16 sideh_var_1E; + uint16 sideh_var_1F; +}Enemy_Sidehopper; +typedef struct Enemy_Skree { +EnemyBase base; +uint16 skree_var_A; +uint16 skree_var_B; +uint16 skree_var_C; +uint16 skree_var_D; +uint16 skree_var_E; +uint16 skree_var_F; +uint16 skree_parameter_1; +uint16 skree_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 skree_var_00; + uint16 skree_var_01; + uint16 skree_var_02; + uint16 skree_var_03; + uint16 skree_var_04; + uint16 skree_var_05; + uint16 skree_var_06; + uint16 skree_var_07; + uint16 skree_var_08; + uint16 skree_var_09; + uint16 skree_var_0A; + uint16 skree_var_0B; + uint16 skree_var_0C; + uint16 skree_var_0D; + uint16 skree_var_0E; + uint16 skree_var_0F; + uint16 skree_var_10; + uint16 skree_var_11; + uint16 skree_var_12; + uint16 skree_var_13; + uint16 skree_var_14; + uint16 skree_var_15; + uint16 skree_var_16; + uint16 skree_var_17; + uint16 skree_var_18; + uint16 skree_var_19; + uint16 skree_var_1A; + uint16 skree_var_1B; + uint16 skree_var_1C; + uint16 skree_var_1D; + uint16 skree_var_1E; + uint16 skree_var_1F; +}Enemy_Skree; +typedef struct Enemy_SpacePirates { +EnemyBase base; +uint16 sps_var_A; +uint16 sps_var_B; +uint16 sps_var_C; +uint16 sps_var_D; +uint16 sps_var_E; +uint16 sps_var_F; +uint16 sps_parameter_1; +uint16 sps_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 sps_var_00; + uint16 sps_var_01; + uint16 sps_var_02; + uint16 sps_var_03; + uint16 sps_var_04; + uint16 sps_var_05; + uint16 sps_var_06; + uint16 sps_var_07; + uint16 sps_var_08; + uint16 sps_var_09; + uint16 sps_var_0A; + uint16 sps_var_0B; + uint16 sps_var_0C; + uint16 sps_var_0D; + uint16 sps_var_0E; + uint16 sps_var_0F; + uint16 sps_var_10; + uint16 sps_var_11; + uint16 sps_var_12; + uint16 sps_var_13; + uint16 sps_var_14; + uint16 sps_var_15; + uint16 sps_var_16; + uint16 sps_var_17; + uint16 sps_var_18; + uint16 sps_var_19; + uint16 sps_var_1A; + uint16 sps_var_1B; + uint16 sps_var_1C; + uint16 sps_var_1D; + uint16 sps_var_1E; + uint16 sps_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 sps_var_20; + uint16 sps_var_21; + uint16 sps_var_22; + uint16 sps_var_23; + uint16 sps_var_24; + uint16 sps_var_25; + uint16 sps_var_26; + uint16 sps_var_27; + uint16 sps_var_28; + uint16 sps_var_29; + uint16 sps_var_2A; + uint16 sps_var_2B; + uint16 sps_var_2C; + uint16 sps_var_2D; + uint16 sps_var_2E; + uint16 sps_var_2F; + uint16 sps_var_30; + uint16 sps_var_31; + uint16 sps_var_32; + uint16 sps_var_33; + uint16 sps_var_34; + uint16 sps_var_35; + uint16 sps_var_36; + uint16 sps_var_37; + uint16 sps_var_38; + uint16 sps_var_39; + uint16 sps_var_3A; + uint16 sps_var_3B; + uint16 sps_var_3C; + uint16 sps_var_3D; + uint16 sps_var_3E; + uint16 sps_var_3F; +}Enemy_SpacePirates; +typedef struct Enemy_SpikeShootingPlant { +EnemyBase base; +uint16 sspt_var_A; +uint16 sspt_var_B; +uint16 sspt_var_C; +uint16 sspt_var_D; +uint16 sspt_var_E; +uint16 sspt_var_F; +uint16 sspt_parameter_1; +uint16 sspt_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 sspt_var_00; + uint16 sspt_var_01; + uint16 sspt_var_02; + uint16 sspt_var_03; + uint16 sspt_var_04; + uint16 sspt_var_05; + uint16 sspt_var_06; + uint16 sspt_var_07; + uint16 sspt_var_08; + uint16 sspt_var_09; + uint16 sspt_var_0A; + uint16 sspt_var_0B; + uint16 sspt_var_0C; + uint16 sspt_var_0D; + uint16 sspt_var_0E; + uint16 sspt_var_0F; + uint16 sspt_var_10; + uint16 sspt_var_11; + uint16 sspt_var_12; + uint16 sspt_var_13; + uint16 sspt_var_14; + uint16 sspt_var_15; + uint16 sspt_var_16; + uint16 sspt_var_17; + uint16 sspt_var_18; + uint16 sspt_var_19; + uint16 sspt_var_1A; + uint16 sspt_var_1B; + uint16 sspt_var_1C; + uint16 sspt_var_1D; + uint16 sspt_var_1E; + uint16 sspt_var_1F; +}Enemy_SpikeShootingPlant; +typedef struct Enemy_SpikeyPlatform { +EnemyBase base; +uint16 spm_var_A; +uint16 spm_var_B; +uint16 spm_var_C; +uint16 spm_var_D; +uint16 spm_var_E; +uint16 spm_var_F; +uint16 spm_parameter_1; +uint16 spm_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 spm_var_00; + uint16 spm_var_01; + uint16 spm_var_02; + uint16 spm_var_03; + uint16 spm_var_04; + uint16 spm_var_05; + uint16 spm_var_06; + uint16 spm_var_07; + uint16 spm_var_08; + uint16 spm_var_09; + uint16 spm_var_0A; + uint16 spm_var_0B; + uint16 spm_var_0C; + uint16 spm_var_0D; + uint16 spm_var_0E; + uint16 spm_var_0F; + uint16 spm_var_10; + uint16 spm_var_11; + uint16 spm_var_12; + uint16 spm_var_13; + uint16 spm_var_14; + uint16 spm_var_15; + uint16 spm_var_16; + uint16 spm_var_17; + uint16 spm_var_18; + uint16 spm_var_19; + uint16 spm_var_1A; + uint16 spm_var_1B; + uint16 spm_var_1C; + uint16 spm_var_1D; + uint16 spm_var_1E; + uint16 spm_var_1F; +}Enemy_SpikeyPlatform; +typedef struct Enemy_SporeSpawn { +EnemyBase base; +uint16 ssn_var_A; +uint16 ssn_var_B; +uint16 ssn_var_C; +uint16 ssn_var_D; +uint16 ssn_var_E; +uint16 ssn_var_F; +uint16 ssn_parameter_1; +uint16 ssn_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 ssn_var_00; + uint16 ssn_var_01; + uint16 ssn_var_02; + uint16 ssn_var_03; + uint16 ssn_var_04; + uint16 ssn_var_05; + uint16 ssn_var_06; + uint16 ssn_var_07; + uint16 ssn_var_08; + uint16 ssn_var_09; + uint16 ssn_var_0A; + uint16 ssn_var_0B; + uint16 ssn_var_0C; + uint16 ssn_var_0D; + uint16 ssn_var_0E; + uint16 ssn_var_0F; + uint16 ssn_var_10; + uint16 ssn_var_11; + uint16 ssn_var_12; + uint16 ssn_var_13; + uint16 ssn_var_14; + uint16 ssn_var_15; + uint16 ssn_var_16; + uint16 ssn_var_17; + uint16 ssn_var_18; + uint16 ssn_var_19; + uint16 ssn_var_1A; + uint16 ssn_var_1B; + uint16 ssn_var_1C; + uint16 ssn_var_1D; + uint16 ssn_var_1E; + uint16 ssn_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 ssn_var_20; + uint16 ssn_var_21; + uint16 ssn_var_22; + uint16 ssn_var_23; + uint16 ssn_var_24; + uint16 ssn_var_25; + uint16 ssn_var_26; + uint16 ssn_var_27; + uint16 ssn_var_28; + uint16 ssn_var_29; + uint16 ssn_var_2A; + uint16 ssn_var_2B; + uint16 ssn_var_2C; + uint16 ssn_var_2D; + uint16 ssn_var_2E; + uint16 ssn_var_2F; + uint16 ssn_var_30; + uint16 ssn_var_31; + uint16 ssn_var_32; + uint16 ssn_var_33; + uint16 ssn_var_34; + uint16 ssn_var_35; + uint16 ssn_var_36; + uint16 ssn_var_37; + uint16 ssn_var_38; + uint16 ssn_var_39; + uint16 ssn_var_3A; + uint16 ssn_var_3B; + uint16 ssn_var_3C; + uint16 ssn_var_3D; + uint16 ssn_var_3E; + uint16 ssn_var_3F; +uint8 pad3[0x8800-0x8040]; + uint16 ssn_var_40; + uint16 ssn_var_41; + uint16 ssn_var_42; + uint16 ssn_var_43; + uint16 ssn_var_44; + uint16 ssn_var_45; + uint16 ssn_var_46; + uint16 ssn_var_47; + uint16 ssn_var_48; + uint16 ssn_var_49; + uint16 ssn_var_4A; + uint16 ssn_var_4B; + uint16 ssn_var_4C; + uint16 ssn_var_4D; + uint16 ssn_var_4E; + uint16 ssn_var_4F; + uint16 ssn_var_50; + uint16 ssn_var_51; + uint16 ssn_var_52; + uint16 ssn_var_53; + uint16 ssn_var_54; + uint16 ssn_var_55; + uint16 ssn_var_56; + uint16 ssn_var_57; + uint16 ssn_var_58; + uint16 ssn_var_59; + uint16 ssn_var_5A; + uint16 ssn_var_5B; + uint16 ssn_var_5C; + uint16 ssn_var_5D; + uint16 ssn_var_5E; + uint16 ssn_var_5F; +}Enemy_SporeSpawn; +typedef struct Enemy_StoneZoomer { +EnemyBase base; +uint16 szr_var_A; +uint16 szr_var_B; +uint16 szr_var_C; +uint16 szr_var_D; +uint16 szr_var_E; +uint16 szr_var_F; +uint16 szr_parameter_1; +uint16 szr_parameter_2; +}Enemy_StoneZoomer; +typedef struct Enemy_ThinHoppingBlobs { +EnemyBase base; +uint16 thbs_var_A; +uint16 thbs_var_B; +uint16 thbs_var_C; +uint16 thbs_var_D; +uint16 thbs_var_E; +uint16 thbs_var_F; +uint16 thbs_parameter_1; +uint16 thbs_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 thbs_var_00; + uint16 thbs_var_01; + uint16 thbs_var_02; + uint16 thbs_var_03; + uint16 thbs_var_04; + uint16 thbs_var_05; + uint16 thbs_var_06; + uint16 thbs_var_07; + uint16 thbs_var_08; + uint16 thbs_var_09; + uint16 thbs_var_0A; + uint16 thbs_var_0B; + uint16 thbs_var_0C; + uint16 thbs_var_0D; + uint16 thbs_var_0E; + uint16 thbs_var_0F; + uint16 thbs_var_10; + uint16 thbs_var_11; + uint16 thbs_var_12; + uint16 thbs_var_13; + uint16 thbs_var_14; + uint16 thbs_var_15; + uint16 thbs_var_16; + uint16 thbs_var_17; + uint16 thbs_var_18; + uint16 thbs_var_19; + uint16 thbs_var_1A; + uint16 thbs_var_1B; + uint16 thbs_var_1C; + uint16 thbs_var_1D; + uint16 thbs_var_1E; + uint16 thbs_var_1F; +}Enemy_ThinHoppingBlobs; +typedef struct Enemy_TimedShutter { +EnemyBase base; +uint16 tsr_var_A; +uint16 tsr_var_B; +uint16 tsr_var_C; +uint16 tsr_var_D; +uint16 tsr_var_E; +uint16 tsr_var_F; +uint16 tsr_parameter_1; +uint16 tsr_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 tsr_var_00; + uint16 tsr_var_01; + uint16 tsr_var_02; + uint16 tsr_var_03; + uint16 tsr_var_04; + uint16 tsr_var_05; + uint16 tsr_var_06; + uint16 tsr_var_07; + uint16 tsr_var_08; + uint16 tsr_var_09; + uint16 tsr_var_0A; + uint16 tsr_var_0B; + uint16 tsr_var_0C; + uint16 tsr_var_0D; + uint16 tsr_var_0E; + uint16 tsr_var_0F; + uint16 tsr_var_10; + uint16 tsr_var_11; + uint16 tsr_var_12; + uint16 tsr_var_13; + uint16 tsr_var_14; + uint16 tsr_var_15; + uint16 tsr_var_16; + uint16 tsr_var_17; + uint16 tsr_var_18; + uint16 tsr_var_19; + uint16 tsr_var_1A; + uint16 tsr_var_1B; + uint16 tsr_var_1C; + uint16 tsr_var_1D; + uint16 tsr_var_1E; + uint16 tsr_var_1F; +uint8 pad3[0x8800-0x7840]; + uint16 tsr_var_40; + uint16 tsr_var_41; + uint16 tsr_var_42; + uint16 tsr_var_43; + uint16 tsr_var_44; + uint16 tsr_var_45; + uint16 tsr_var_46; + uint16 tsr_var_47; + uint16 tsr_var_48; + uint16 tsr_var_49; + uint16 tsr_var_4A; + uint16 tsr_var_4B; + uint16 tsr_var_4C; + uint16 tsr_var_4D; + uint16 tsr_var_4E; + uint16 tsr_var_4F; + uint16 tsr_var_50; + uint16 tsr_var_51; + uint16 tsr_var_52; + uint16 tsr_var_53; + uint16 tsr_var_54; + uint16 tsr_var_55; + uint16 tsr_var_56; + uint16 tsr_var_57; + uint16 tsr_var_58; + uint16 tsr_var_59; + uint16 tsr_var_5A; + uint16 tsr_var_5B; + uint16 tsr_var_5C; + uint16 tsr_var_5D; + uint16 tsr_var_5E; + uint16 tsr_var_5F; +}Enemy_TimedShutter; +typedef struct Enemy_Torizo { +EnemyBase base; +uint16 toriz_var_A; +uint16 toriz_var_B; +uint16 toriz_var_C; +uint16 toriz_var_D; +uint16 toriz_var_E; +uint16 toriz_var_F; +uint16 toriz_parameter_1; +uint16 toriz_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 toriz_var_00; + uint16 toriz_var_01; + uint16 toriz_var_02; + uint16 toriz_var_03; + uint16 toriz_var_04; + uint16 toriz_var_05; + uint16 toriz_var_06; + uint16 toriz_var_07; + uint16 toriz_var_08; + uint16 toriz_var_09; + uint16 toriz_var_0A; + uint16 toriz_var_0B; + uint16 toriz_var_0C; + uint16 toriz_var_0D; + uint16 toriz_var_0E; + uint16 toriz_var_0F; + uint16 toriz_var_10; + uint16 toriz_var_11; + uint16 toriz_var_12; + uint16 toriz_var_13; + uint16 toriz_var_14; + uint16 toriz_var_15; + uint16 toriz_var_16; + uint16 toriz_var_17; + uint16 toriz_var_18; + uint16 toriz_var_19; + uint16 toriz_var_1A; + uint16 toriz_var_1B; + uint16 toriz_var_1C; + uint16 toriz_var_1D; + uint16 toriz_var_1E; + uint16 toriz_var_1F; +}Enemy_Torizo; +typedef struct Enemy_WalkingLavaSeahorse { +EnemyBase base; +uint16 wlse_var_A; +uint16 wlse_var_B; +uint16 wlse_var_C; +uint16 wlse_var_D; +uint16 wlse_var_E; +uint16 wlse_var_F; +uint16 wlse_parameter_1; +uint16 wlse_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 wlse_var_00; + uint16 wlse_var_01; + uint16 wlse_var_02; + uint16 wlse_var_03; + uint16 wlse_var_04; + uint16 wlse_var_05; + uint16 wlse_var_06; + uint16 wlse_var_07; + uint16 wlse_var_08; + uint16 wlse_var_09; + uint16 wlse_var_0A; + uint16 wlse_var_0B; + uint16 wlse_var_0C; + uint16 wlse_var_0D; + uint16 wlse_var_0E; + uint16 wlse_var_0F; + uint16 wlse_var_10; + uint16 wlse_var_11; + uint16 wlse_var_12; + uint16 wlse_var_13; + uint16 wlse_var_14; + uint16 wlse_var_15; + uint16 wlse_var_16; + uint16 wlse_var_17; + uint16 wlse_var_18; + uint16 wlse_var_19; + uint16 wlse_var_1A; + uint16 wlse_var_1B; + uint16 wlse_var_1C; + uint16 wlse_var_1D; + uint16 wlse_var_1E; + uint16 wlse_var_1F; +}Enemy_WalkingLavaSeahorse; +typedef struct Enemy_Waver { +EnemyBase base; +uint16 waver_var_A; +uint16 waver_var_B; +uint16 waver_var_C; +uint16 waver_var_D; +uint16 waver_var_E; +uint16 waver_var_F; +uint16 waver_parameter_1; +uint16 waver_parameter_2; +}Enemy_Waver; +typedef struct Enemy_WreckedShipGhost { +EnemyBase base; +uint16 wsgt_var_A; +uint16 wsgt_var_B; +uint16 wsgt_var_C; +uint16 wsgt_var_D; +uint16 wsgt_var_E; +uint16 wsgt_var_F; +uint16 wsgt_parameter_1; +uint16 wsgt_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 wsgt_var_00; + uint16 wsgt_var_01; + uint16 wsgt_var_02; + uint16 wsgt_var_03; + uint16 wsgt_var_04; + uint16 wsgt_var_05; + uint16 wsgt_var_06; + uint16 wsgt_var_07; + uint16 wsgt_var_08; + uint16 wsgt_var_09; + uint16 wsgt_var_0A; + uint16 wsgt_var_0B; + uint16 wsgt_var_0C; + uint16 wsgt_var_0D; + uint16 wsgt_var_0E; + uint16 wsgt_var_0F; + uint16 wsgt_var_10; + uint16 wsgt_var_11; + uint16 wsgt_var_12; + uint16 wsgt_var_13; + uint16 wsgt_var_14; + uint16 wsgt_var_15; + uint16 wsgt_var_16; + uint16 wsgt_var_17; + uint16 wsgt_var_18; + uint16 wsgt_var_19; + uint16 wsgt_var_1A; + uint16 wsgt_var_1B; + uint16 wsgt_var_1C; + uint16 wsgt_var_1D; + uint16 wsgt_var_1E; + uint16 wsgt_var_1F; +}Enemy_WreckedShipGhost; +typedef struct Enemy_WreckedShipOrangeZoomer { +EnemyBase base; +uint16 wsozr_var_A; +uint16 wsozr_var_B; +uint16 wsozr_var_C; +uint16 wsozr_var_D; +uint16 wsozr_var_E; +uint16 wsozr_var_F; +uint16 wsozr_parameter_1; +uint16 wsozr_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 wsozr_var_00; + uint16 wsozr_var_01; + uint16 wsozr_var_02; + uint16 wsozr_var_03; + uint16 wsozr_var_04; + uint16 wsozr_var_05; + uint16 wsozr_var_06; + uint16 wsozr_var_07; + uint16 wsozr_var_08; + uint16 wsozr_var_09; + uint16 wsozr_var_0A; + uint16 wsozr_var_0B; + uint16 wsozr_var_0C; + uint16 wsozr_var_0D; + uint16 wsozr_var_0E; + uint16 wsozr_var_0F; + uint16 wsozr_var_10; + uint16 wsozr_var_11; + uint16 wsozr_var_12; + uint16 wsozr_var_13; + uint16 wsozr_var_14; + uint16 wsozr_var_15; + uint16 wsozr_var_16; + uint16 wsozr_var_17; + uint16 wsozr_var_18; + uint16 wsozr_var_19; + uint16 wsozr_var_1A; + uint16 wsozr_var_1B; + uint16 wsozr_var_1C; + uint16 wsozr_var_1D; + uint16 wsozr_var_1E; + uint16 wsozr_var_1F; +}Enemy_WreckedShipOrangeZoomer; +typedef struct Enemy_WreckedShipOrbs { + EnemyBase base; + uint16 wsos_var_A; + uint16 wsos_var_B; + uint16 wsos_var_C; + uint16 wsos_var_D; + uint16 wsos_var_E; + uint16 wsos_var_F; + uint16 wsos_parameter_1; + uint16 wsos_parameter_2; + uint8 pad1[0x7800 - 0xFB8]; + uint16 wsos_var_00; + uint16 wsos_var_01; + uint16 wsos_var_02; + uint16 wsos_var_03; + uint16 wsos_var_04; + uint16 wsos_var_05; + uint16 wsos_var_06; + uint16 wsos_var_07; + uint16 wsos_var_08; + uint16 wsos_var_09; + uint16 wsos_var_0A; + uint16 wsos_var_0B; + uint16 wsos_var_0C; + uint16 wsos_var_0D; + uint16 wsos_var_0E; + uint16 wsos_var_0F; + uint16 wsos_var_10; + uint16 wsos_var_11; + uint16 wsos_var_12; + uint16 wsos_var_13; + uint16 wsos_var_14; + uint16 wsos_var_15; + uint16 wsos_var_16; + uint16 wsos_var_17; + uint16 wsos_var_18; + uint16 wsos_var_19; + uint16 wsos_var_1A; + uint16 wsos_var_1B; + uint16 wsos_var_1C; + uint16 wsos_var_1D; + uint16 wsos_var_1E; + uint16 wsos_var_1F; +}Enemy_WreckedShipOrbs; +typedef struct Enemy_WreckedShipRobot { +EnemyBase base; +uint16 wsrt_var_A; +uint16 wsrt_var_B; +uint16 wsrt_var_C; +uint16 wsrt_var_D; +uint16 wsrt_var_E; +uint16 wsrt_var_F; +uint16 wsrt_parameter_1; +uint16 wsrt_parameter_2; +} Enemy_WreckedShipRobot; +typedef struct Enemy_WreckedShipSpark { +EnemyBase base; +uint16 wssk_var_A; +uint16 wssk_var_B; +uint16 wssk_var_C; +uint16 wssk_var_D; +uint16 wssk_var_E; +uint16 wssk_var_F; +uint16 wssk_parameter_1; +uint16 wssk_parameter_2; +} Enemy_WreckedShipSpark; +typedef struct Enemy_YappingMaw { +EnemyBase base; +uint16 ymw_var_A; +uint16 ymw_var_B; +uint16 ymw_var_C; +uint16 ymw_var_D; +uint16 ymw_var_E; +uint16 ymw_var_F; +uint16 ymw_parameter_1; +uint16 ymw_parameter_2; +uint8 pad1[0x7800 - 0xFB8]; + uint16 ymw_var_00; + uint16 ymw_var_01; + uint16 ymw_var_02; + uint16 ymw_var_03; + uint16 ymw_var_04; + uint16 ymw_var_05; + uint16 ymw_var_06; + uint16 ymw_var_07; + uint16 ymw_var_08; + uint16 ymw_var_09; + uint16 ymw_var_0A; + uint16 ymw_var_0B; + uint16 ymw_var_0C; + uint16 ymw_var_0D; + uint16 ymw_var_0E; + uint16 ymw_var_0F; + uint16 ymw_var_10; + uint16 ymw_var_11; + uint16 ymw_var_12; + uint16 ymw_var_13; + uint16 ymw_var_14; + uint16 ymw_var_15; + uint16 ymw_var_16; + uint16 ymw_var_17; + uint16 ymw_var_18; + uint16 ymw_var_19; + uint16 ymw_var_1A; + uint16 ymw_var_1B; + uint16 ymw_var_1C; + uint16 ymw_var_1D; + uint16 ymw_var_1E; + uint16 ymw_var_1F; +uint8 pad2[0x8000-0x7840]; + uint16 ymw_var_20; + uint16 ymw_var_21; + uint16 ymw_var_22; + uint16 ymw_var_23; + uint16 ymw_var_24; + uint16 ymw_var_25; + uint16 ymw_var_26; + uint16 ymw_var_27; + uint16 ymw_var_28; + uint16 ymw_var_29; + uint16 ymw_var_2A; + uint16 ymw_var_2B; + uint16 ymw_var_2C; + uint16 ymw_var_2D; + uint16 ymw_var_2E; + uint16 ymw_var_2F; + uint16 ymw_var_30; + uint16 ymw_var_31; + uint16 ymw_var_32; + uint16 ymw_var_33; + uint16 ymw_var_34; + uint16 ymw_var_35; + uint16 ymw_var_36; + uint16 ymw_var_37; + uint16 ymw_var_38; + uint16 ymw_var_39; + uint16 ymw_var_3A; + uint16 ymw_var_3B; + uint16 ymw_var_3C; + uint16 ymw_var_3D; + uint16 ymw_var_3E; + uint16 ymw_var_3F; +uint8 pad3[0x8800-0x8040]; + uint16 ymw_var_40; + uint16 ymw_var_41; + uint16 ymw_var_42; + uint16 ymw_var_43; + uint16 ymw_var_44; + uint16 ymw_var_45; + uint16 ymw_var_46; + uint16 ymw_var_47; + uint16 ymw_var_48; + uint16 ymw_var_49; + uint16 ymw_var_4A; + uint16 ymw_var_4B; + uint16 ymw_var_4C; + uint16 ymw_var_4D; + uint16 ymw_var_4E; + uint16 ymw_var_4F; + uint16 ymw_var_50; + uint16 ymw_var_51; + uint16 ymw_var_52; + uint16 ymw_var_53; + uint16 ymw_var_54; + uint16 ymw_var_55; + uint16 ymw_var_56; + uint16 ymw_var_57; + uint16 ymw_var_58; + uint16 ymw_var_59; + uint16 ymw_var_5A; + uint16 ymw_var_5B; + uint16 ymw_var_5C; + uint16 ymw_var_5D; + uint16 ymw_var_5E; + uint16 ymw_var_5F; +} Enemy_YappingMaw; +typedef struct Enemy_Zebetites { +EnemyBase base; +uint16 zebet_var_A; +uint16 zebet_var_B; +uint16 zebet_var_C; +uint16 zebet_var_D; +uint16 zebet_var_E; +uint16 zebet_var_F; +uint16 zebet_parameter_1; +uint16 zebet_parameter_2; +} Enemy_Zebetites; +typedef struct Ram8000_Default { + uint16 var_20; + uint16 var_21; + uint16 var_22; + uint16 var_23; + uint16 var_24; + uint16 var_25; + uint16 var_26; + uint16 var_27; + uint16 var_28; + uint16 var_29; + uint16 var_2A; + uint16 var_2B; + uint16 var_2C; + uint16 var_2D; + uint16 var_2E; + uint16 var_2F; + uint16 var_30; + uint16 var_31; + uint16 var_32; + uint16 var_33; + uint16 var_34; + uint16 var_35; + uint16 var_36; + uint16 var_37; + uint16 var_38; + uint16 var_39; + uint16 var_3A; + uint16 var_3B; + uint16 var_3C; + uint16 var_3D; + uint16 var_3E; + uint16 var_3F; +} Ram8000_Default; +typedef struct Ram8800_Default { + uint16 var_40; + uint16 var_41; + uint16 var_42; + uint16 var_43; + uint16 var_44; + uint16 var_45; + uint16 var_46; + uint16 var_47; + uint16 var_48; + uint16 var_49; + uint16 var_4A; + uint16 var_4B; + uint16 var_4C; + uint16 var_4D; + uint16 var_4E; + uint16 var_4F; + uint16 var_50; + uint16 var_51; + uint16 var_52; + uint16 var_53; + uint16 var_54; + uint16 var_55; + uint16 var_56; + uint16 var_57; + uint16 var_58; + uint16 var_59; + uint16 var_5A; + uint16 var_5B; + uint16 var_5C; + uint16 var_5D; + uint16 var_5E; + uint16 var_5F; +} Ram8800_Default; + + +typedef struct EnemyData EnemyData; +typedef struct EnemySpawnData EnemySpawnData; +typedef union ExtraEnemyRam7800 ExtraEnemyRam7800; +typedef union ExtraEnemyRam8000 ExtraEnemyRam8000; + +static inline EnemyData *gEnemyData(int o) { return (EnemyData *)(g_ram + 0xF78 + o); } +static inline EnemySpawnData *gEnemySpawnData(int o) { return (EnemySpawnData *)(g_ram + 0x7000 + o); } +static inline ExtraEnemyRam7800 *gExtraEnemyRam7800(int o) { return (ExtraEnemyRam7800 *)(g_ram + 0x7800 + o); } +static inline ExtraEnemyRam8000 *gExtraEnemyRam8000(int o) { return (ExtraEnemyRam8000 *)(g_ram + 0x8000 + o); } + + +typedef struct Ram8000_Default Ram8000_Default; static inline Ram8000_Default *gRam8000_Default(int o) { return (Ram8000_Default *)(g_ram + 0x8000 + o); } +struct Ram8800_Default; static inline Ram8800_Default *gRam8800_Default(int o) { return (Ram8800_Default *)(g_ram + 0x8800 + o); } + + +struct Enemy_Bang; static inline Enemy_Bang *Get_Bang(int o) { return (Enemy_Bang *)(g_ram + 0xF78 + o); } +struct Enemy_Beetom; static inline Enemy_Beetom *Get_Beetom(int o) { return (Enemy_Beetom *)(g_ram + 0xF78 + o); } +struct Enemy_Botwoon; static inline Enemy_Botwoon *Get_Botwoon(int o) { return (Enemy_Botwoon *)(g_ram + 0xF78 + o); } +struct Enemy_Boulder; static inline Enemy_Boulder *Get_Boulder(int o) { return (Enemy_Boulder *)(g_ram + 0xF78 + o); } +struct Enemy_BouncingGoofball; static inline Enemy_BouncingGoofball *Get_BouncingGoofball(int o) { return (Enemy_BouncingGoofball *)(g_ram + 0xF78 + o); } +struct Enemy_CeresDoor; static inline Enemy_CeresDoor *Get_CeresDoor(int o) { return (Enemy_CeresDoor *)(g_ram + 0xF78 + o); } +struct Enemy_CeresRidley; static inline Enemy_CeresRidley *Get_CeresRidley(int o) { return (Enemy_CeresRidley *)(g_ram + 0xF78 + o); } +struct Enemy_CeresSteam; static inline Enemy_CeresSteam *Get_CeresSteam(int o) { return (Enemy_CeresSteam *)(g_ram + 0xF78 + o); } +struct Enemy_Crocomire; static inline Enemy_Crocomire *Get_Crocomire(int o) { return (Enemy_Crocomire *)(g_ram + 0xF78 + o); } +struct Enemy_Dachora; static inline Enemy_Dachora *Get_Dachora(int o) { return (Enemy_Dachora *)(g_ram + 0xF78 + o); } +struct Enemy_DeadEnemy; static inline Enemy_DeadEnemy *Get_DeadEnemy(int o) { return (Enemy_DeadEnemy *)(g_ram + 0xF78 + o); } +struct Enemy_DeadMonsters; static inline Enemy_DeadMonsters *Get_DeadMonsters(int o) { return (Enemy_DeadMonsters *)(g_ram + 0xF78 + o); } +struct Enemy_DeadSidehopper; static inline Enemy_DeadSidehopper *Get_DeadSidehopper(int o) { return (Enemy_DeadSidehopper *)(g_ram + 0xF78 + o); } +struct Enemy_DeadTorizo; static inline Enemy_DeadTorizo *Get_DeadTorizo(int o) { return (Enemy_DeadTorizo *)(g_ram + 0xF78 + o); } +struct Enemy_Draygon; static inline Enemy_Draygon *Get_Draygon(int o) { return (Enemy_Draygon *)(g_ram + 0xF78 + o); } +struct Enemy_Elevator; static inline Enemy_Elevator *Get_Elevator(int o) { return (Enemy_Elevator *)(g_ram + 0xF78 + o); } +struct Enemy_EscapeDachora; static inline Enemy_EscapeDachora *Get_EscapeDachora(int o) { return (Enemy_EscapeDachora *)(g_ram + 0xF78 + o); } +struct Enemy_EscapeEtecoon; static inline Enemy_EscapeEtecoon *Get_EscapeEtecoon(int o) { return (Enemy_EscapeEtecoon *)(g_ram + 0xF78 + o); } +struct Enemy_Etecoon; static inline Enemy_Etecoon *Get_Etecoon(int o) { return (Enemy_Etecoon *)(g_ram + 0xF78 + o); } +struct Enemy_FakeKraid; static inline Enemy_FakeKraid *Get_FakeKraid(int o) { return (Enemy_FakeKraid *)(g_ram + 0xF78 + o); } +struct Enemy_FireFlea; static inline Enemy_FireFlea *Get_FireFlea(int o) { return (Enemy_FireFlea *)(g_ram + 0xF78 + o); } +struct Enemy_FireGeyser; static inline Enemy_FireGeyser *Get_FireGeyser(int o) { return (Enemy_FireGeyser *)(g_ram + 0xF78 + o); } +struct Enemy_FireZoomer; static inline Enemy_FireZoomer *Get_FireZoomer(int o) { return (Enemy_FireZoomer *)(g_ram + 0xF78 + o); } +struct Enemy_Fireflea; static inline Enemy_Fireflea *Get_Fireflea(int o) { return (Enemy_Fireflea *)(g_ram + 0xF78 + o); } +struct Enemy_Flies; static inline Enemy_Flies *Get_Flies(int o) { return (Enemy_Flies *)(g_ram + 0xF78 + o); } +struct Enemy_Fune; static inline Enemy_Fune *Get_Fune(int o) { return (Enemy_Fune *)(g_ram + 0xF78 + o); } +struct Enemy_Gripper; static inline Enemy_Gripper *Get_Gripper(int o) { return (Enemy_Gripper *)(g_ram + 0xF78 + o); } +struct Enemy_GunshipBottom; static inline Enemy_GunshipBottom *Get_GunshipBottom(int o) { return (Enemy_GunshipBottom *)(g_ram + 0xF78 + o); } +struct Enemy_GunshipTop; static inline Enemy_GunshipTop *Get_GunshipTop(int o) { return (Enemy_GunshipTop *)(g_ram + 0xF78 + o); } +struct Enemy_HirisingSlowfalling; static inline Enemy_HirisingSlowfalling *Get_HirisingSlowfalling(int o) { return (Enemy_HirisingSlowfalling *)(g_ram + 0xF78 + o); } +struct Enemy_HorizontalShootableShutter; static inline Enemy_HorizontalShootableShutter *Get_HorizontalShootableShutter(int o) { return (Enemy_HorizontalShootableShutter *)(g_ram + 0xF78 + o); } +struct Enemy_JetPowerRipper; static inline Enemy_JetPowerRipper *Get_JetPowerRipper(int o) { return (Enemy_JetPowerRipper *)(g_ram + 0xF78 + o); } +struct Enemy_Kago; static inline Enemy_Kago *Get_Kago(int o) { return (Enemy_Kago *)(g_ram + 0xF78 + o); } +struct Enemy_KiHunter; static inline Enemy_KiHunter *Get_KiHunter(int o) { return (Enemy_KiHunter *)(g_ram + 0xF78 + o); } +struct Enemy_Kraid; static inline Enemy_Kraid *Get_Kraid(int o) { return (Enemy_Kraid *)(g_ram + 0xF78 + o); } +struct Enemy_LavaSeahorse; static inline Enemy_LavaSeahorse *Get_LavaSeahorse(int o) { return (Enemy_LavaSeahorse *)(g_ram + 0xF78 + o); } +struct Enemy_LavaquakeRocks; static inline Enemy_LavaquakeRocks *Get_LavaquakeRocks(int o) { return (Enemy_LavaquakeRocks *)(g_ram + 0xF78 + o); } +struct Enemy_LowerNorfairRio; static inline Enemy_LowerNorfairRio *Get_LowerNorfairRio(int o) { return (Enemy_LowerNorfairRio *)(g_ram + 0xF78 + o); } +struct Enemy_MaridiaBeybladeTurtle; static inline Enemy_MaridiaBeybladeTurtle *Get_MaridiaBeybladeTurtle(int o) { return (Enemy_MaridiaBeybladeTurtle *)(g_ram + 0xF78 + o); } +struct Enemy_MaridiaFish; static inline Enemy_MaridiaFish *Get_MaridiaFish(int o) { return (Enemy_MaridiaFish *)(g_ram + 0xF78 + o); } +struct Enemy_MaridiaFloater; static inline Enemy_MaridiaFloater *Get_MaridiaFloater(int o) { return (Enemy_MaridiaFloater *)(g_ram + 0xF78 + o); } +struct Enemy_MaridiaLargeSnail; static inline Enemy_MaridiaLargeSnail *Get_MaridiaLargeSnail(int o) { return (Enemy_MaridiaLargeSnail *)(g_ram + 0xF78 + o); } +struct Enemy_MaridiaPuffer; static inline Enemy_MaridiaPuffer *Get_MaridiaPuffer(int o) { return (Enemy_MaridiaPuffer *)(g_ram + 0xF78 + o); } +struct Enemy_MaridiaRefillCandy; static inline Enemy_MaridiaRefillCandy *Get_MaridiaRefillCandy(int o) { return (Enemy_MaridiaRefillCandy *)(g_ram + 0xF78 + o); } +struct Enemy_MaridiaSnail; static inline Enemy_MaridiaSnail *Get_MaridiaSnail(int o) { return (Enemy_MaridiaSnail *)(g_ram + 0xF78 + o); } +struct Enemy_MaridiaSpikeyShell; static inline Enemy_MaridiaSpikeyShell *Get_MaridiaSpikeyShell(int o) { return (Enemy_MaridiaSpikeyShell *)(g_ram + 0xF78 + o); } +struct Enemy_MaridiaTurtle; static inline Enemy_MaridiaTurtle *Get_MaridiaTurtle(int o) { return (Enemy_MaridiaTurtle *)(g_ram + 0xF78 + o); } +struct Enemy_Metalee; static inline Enemy_Metalee *Get_Metalee(int o) { return (Enemy_Metalee *)(g_ram + 0xF78 + o); } +struct Enemy_Metroid; static inline Enemy_Metroid *Get_Metroid(int o) { return (Enemy_Metroid *)(g_ram + 0xF78 + o); } +struct Enemy_MiniCrocomire; static inline Enemy_MiniCrocomire *Get_MiniCrocomire(int o) { return (Enemy_MiniCrocomire *)(g_ram + 0xF78 + o); } +struct Enemy_MiniDraygon; static inline Enemy_MiniDraygon *Get_MiniDraygon(int o) { return (Enemy_MiniDraygon *)(g_ram + 0xF78 + o); } +struct Enemy_MiniMaridiaBeybladeTurtle; static inline Enemy_MiniMaridiaBeybladeTurtle *Get_MiniMaridiaBeybladeTurtle(int o) { return (Enemy_MiniMaridiaBeybladeTurtle *)(g_ram + 0xF78 + o); } +struct Enemy_MiniMaridiaTurtle; static inline Enemy_MiniMaridiaTurtle *Get_MiniMaridiaTurtle(int o) { return (Enemy_MiniMaridiaTurtle *)(g_ram + 0xF78 + o); } +struct Enemy_Mochtroid; static inline Enemy_Mochtroid *Get_Mochtroid(int o) { return (Enemy_Mochtroid *)(g_ram + 0xF78 + o); } +struct Enemy_MorphBallEye; static inline Enemy_MorphBallEye *Get_MorphBallEye(int o) { return (Enemy_MorphBallEye *)(g_ram + 0xF78 + o); } +struct Enemy_MotherBomb; static inline Enemy_MotherBomb *Get_MotherBomb(int o) { return (Enemy_MotherBomb *)(g_ram + 0xF78 + o); } +struct Enemy_MotherBrain; static inline Enemy_MotherBrain *Get_MotherBrain(int o) { return (Enemy_MotherBrain *)(g_ram + 0xF78 + o); } +struct Enemy_MotherBrainBody; static inline Enemy_MotherBrainBody *Get_MotherBrainBody(int o) { return (Enemy_MotherBrainBody *)(g_ram + 0xF78 + o); } +struct Enemy_MotherBrainsTubesFalling; static inline Enemy_MotherBrainsTubesFalling *Get_MotherBrainsTubesFalling(int o) { return (Enemy_MotherBrainsTubesFalling *)(g_ram + 0xF78 + o); } +struct Enemy_NorfairErraticFireball; static inline Enemy_NorfairErraticFireball *Get_NorfairErraticFireball(int o) { return (Enemy_NorfairErraticFireball *)(g_ram + 0xF78 + o); } +struct Enemy_NorfairLavaMan; static inline Enemy_NorfairLavaMan *Get_NorfairLavaMan(int o) { return (Enemy_NorfairLavaMan *)(g_ram + 0xF78 + o); } +struct Enemy_NorfairLavajumpingEnemy; static inline Enemy_NorfairLavajumpingEnemy *Get_NorfairLavajumpingEnemy(int o) { return (Enemy_NorfairLavajumpingEnemy *)(g_ram + 0xF78 + o); } +struct Enemy_NorfairRio; static inline Enemy_NorfairRio *Get_NorfairRio(int o) { return (Enemy_NorfairRio *)(g_ram + 0xF78 + o); } +struct Enemy_NuclearWaffle; static inline Enemy_NuclearWaffle *Get_NuclearWaffle(int o) { return (Enemy_NuclearWaffle *)(g_ram + 0xF78 + o); } +struct Enemy_Phantoon; static inline Enemy_Phantoon *Get_Phantoon(int o) { return (Enemy_Phantoon *)(g_ram + 0xF78 + o); } +struct Enemy_PipeBug; static inline Enemy_PipeBug *Get_PipeBug(int o) { return (Enemy_PipeBug *)(g_ram + 0xF78 + o); } +struct Enemy_PlatformThatFallsWithSamus; static inline Enemy_PlatformThatFallsWithSamus *Get_PlatformThatFallsWithSamus(int o) { return (Enemy_PlatformThatFallsWithSamus *)(g_ram + 0xF78 + o); } +struct Enemy_Reflec; static inline Enemy_Reflec *Get_Reflec(int o) { return (Enemy_Reflec *)(g_ram + 0xF78 + o); } +struct Enemy_Ridley; static inline Enemy_Ridley *Get_Ridley(int o) { return (Enemy_Ridley *)(g_ram + 0xF78 + o); } +struct Enemy_RidleysExplosion; static inline Enemy_RidleysExplosion *Get_RidleysExplosion(int o) { return (Enemy_RidleysExplosion *)(g_ram + 0xF78 + o); } +struct Enemy_Rinka; static inline Enemy_Rinka *Get_Rinka(int o) { return (Enemy_Rinka *)(g_ram + 0xF78 + o); } +struct Enemy_Rio; static inline Enemy_Rio *Get_Rio(int o) { return (Enemy_Rio *)(g_ram + 0xF78 + o); } +struct Enemy_Ripper; static inline Enemy_Ripper *Get_Ripper(int o) { return (Enemy_Ripper *)(g_ram + 0xF78 + o); } +struct Enemy_RisingFallingPlatform; static inline Enemy_RisingFallingPlatform *Get_RisingFallingPlatform(int o) { return (Enemy_RisingFallingPlatform *)(g_ram + 0xF78 + o); } +struct Enemy_Roach; static inline Enemy_Roach *Get_Roach(int o) { return (Enemy_Roach *)(g_ram + 0xF78 + o); } +struct Enemy_Shaktool; static inline Enemy_Shaktool *Get_Shaktool(int o) { return (Enemy_Shaktool *)(g_ram + 0xF78 + o); } +struct Enemy_ShitroidInCutscene; static inline Enemy_ShitroidInCutscene *Get_ShitdroidInCutscene(int o) { return (Enemy_ShitroidInCutscene *)(g_ram + 0xF78 + o); } +struct Enemy_Shitroid; static inline Enemy_Shitroid *Get_Shitroid(int o) { return (Enemy_Shitroid *)(g_ram + 0xF78 + o); } +struct Enemy_ShitroidInCutscene; static inline Enemy_ShitroidInCutscene *Get_ShitroidInCutscene(int o) { return (Enemy_ShitroidInCutscene *)(g_ram + 0xF78 + o); } +struct Enemy_Sidehopper; static inline Enemy_Sidehopper *Get_Sidehopper(int o) { return (Enemy_Sidehopper *)(g_ram + 0xF78 + o); } +struct Enemy_Skree; static inline Enemy_Skree *Get_Skree(int o) { return (Enemy_Skree *)(g_ram + 0xF78 + o); } +struct Enemy_SpacePirates; static inline Enemy_SpacePirates *Get_SpacePirates(int o) { return (Enemy_SpacePirates *)(g_ram + 0xF78 + o); } +struct Enemy_SpikeShootingPlant; static inline Enemy_SpikeShootingPlant *Get_SpikeShootingPlant(int o) { return (Enemy_SpikeShootingPlant *)(g_ram + 0xF78 + o); } +struct Enemy_SpikeyPlatform; static inline Enemy_SpikeyPlatform *Get_SpikeyPlatform(int o) { return (Enemy_SpikeyPlatform *)(g_ram + 0xF78 + o); } +struct Enemy_SporeSpawn; static inline Enemy_SporeSpawn *Get_SporeSpawn(int o) { return (Enemy_SporeSpawn *)(g_ram + 0xF78 + o); } +struct Enemy_StoneZoomer; static inline Enemy_StoneZoomer *Get_StoneZoomer(int o) { return (Enemy_StoneZoomer *)(g_ram + 0xF78 + o); } +struct Enemy_ThinHoppingBlobs; static inline Enemy_ThinHoppingBlobs *Get_ThinHoppingBlobs(int o) { return (Enemy_ThinHoppingBlobs *)(g_ram + 0xF78 + o); } +struct Enemy_TimedShutter; static inline Enemy_TimedShutter *Get_TimedShutter(int o) { return (Enemy_TimedShutter *)(g_ram + 0xF78 + o); } +struct Enemy_Torizo; static inline Enemy_Torizo *Get_Torizo(int o) { return (Enemy_Torizo *)(g_ram + 0xF78 + o); } +struct Enemy_WalkingLavaSeahorse; static inline Enemy_WalkingLavaSeahorse *Get_WalkingLavaSeahorse(int o) { return (Enemy_WalkingLavaSeahorse *)(g_ram + 0xF78 + o); } +struct Enemy_Waver; static inline Enemy_Waver *Get_Waver(int o) { return (Enemy_Waver *)(g_ram + 0xF78 + o); } +struct Enemy_WreckedShipGhost; static inline Enemy_WreckedShipGhost *Get_WreckedShipGhost(int o) { return (Enemy_WreckedShipGhost *)(g_ram + 0xF78 + o); } +struct Enemy_WreckedShipOrangeZoomer; static inline Enemy_WreckedShipOrangeZoomer *Get_WreckedShipOrangeZoomer(int o) { return (Enemy_WreckedShipOrangeZoomer *)(g_ram + 0xF78 + o); } +struct Enemy_WreckedShipOrbs; static inline Enemy_WreckedShipOrbs *Get_WreckedShipOrbs(int o) { return (Enemy_WreckedShipOrbs *)(g_ram + 0xF78 + o); } +struct Enemy_WreckedShipRobot; static inline Enemy_WreckedShipRobot *Get_WreckedShipRobot(int o) { return (Enemy_WreckedShipRobot *)(g_ram + 0xF78 + o); } +struct Enemy_WreckedShipSpark; static inline Enemy_WreckedShipSpark *Get_WreckedShipSpark(int o) { return (Enemy_WreckedShipSpark *)(g_ram + 0xF78 + o); } +struct Enemy_YappingMaw; static inline Enemy_YappingMaw *Get_YappingMaw(int o) { return (Enemy_YappingMaw *)(g_ram + 0xF78 + o); } +struct Enemy_Zebetites; static inline Enemy_Zebetites *Get_Zebetites(int o) { return (Enemy_Zebetites *)(g_ram + 0xF78 + o); } + diff --git a/src/features.h b/src/features.h new file mode 100644 index 0000000..0240f00 --- /dev/null +++ b/src/features.h @@ -0,0 +1,9 @@ +// This file declares extensions to the base game +#ifndef ZELDA3_FEATURES_H_ +#define ZELDA3_FEATURES_H_ + +#include "types.h" + +// Special RAM locations that are unused but I use for compat things. + +#endif // ZELDA3_FEATURES_H_ diff --git a/src/funcs.h b/src/funcs.h new file mode 100644 index 0000000..044ff70 --- /dev/null +++ b/src/funcs.h @@ -0,0 +1,9511 @@ +#include "types.h" + + +// Bank 80 +uint16 CheckEventHappened(uint16 a); +uint16 NextRandom(void); +uint16 PrepareBitAccess(uint16 a); +uint8 CalculateLayer2Xpos(void); +uint8 CalculateLayer2Ypos(void); +uint8 CheckBossBitForCurArea(uint16 a); +uint8 DoorTransition_Down(void); +uint8 DoorTransition_Left(void); +uint8 DoorTransition_Right(void); +uint8 DoorTransition_Up(void); +uint8 HasQueuedMusic(void); +uint8 ProcessTimer(void); +uint8 ProcessTimer_CeresStart(void); +uint8 ProcessTimer_Decrement(void); +uint8 ProcessTimer_Empty(void); +uint8 ProcessTimer_InitialDelay(void); +uint8 ProcessTimer_MotherBrainStart(void); +uint8 ProcessTimer_MovementDelayed(void); +uint8 ProcessTimer_MovingIntoPlace(void); +uint8 j_ProcessTimer_Decrement(void); +void APU_UploadBank(void); +void AddGrappleToHudTilemap(void); +void AddMissilesToHudTilemap(void); +void AddPowerBombsToHudTilemap(void); +void AddSuperMissilesToHudTilemap(void); +void AddToTilemapInner(uint16 k, uint16 j); +void AddXrayToHudTilemap(void); +void CalculateBgScrollAndLayerPositionBlocks(void); +void CalculateBgScrolls(void); +void CalculateLayer2PosAndScrollsWhenScrolling(void); +void ClearBG2Tilemap(void); +void ClearBossBitForCurArea(uint16 a); +void ClearEventHappened(uint16 a); +void ClearFXTilemap(void); +void ClearOamExt(void); +void ClearTimerRam(void); +void ConfigureMode7RotationMatrix(void); +void CopySuperMetroidString(void); +void DebugScrollPosSaveLoad(void); +void DecompressToMem(void); +void DecompressToMem_IpArg(const void* p); +void DecompressToVRAM(void); +void DisableIrqInterrupts(void); +void DisableNMI(void); +void DisplayViewablePartOfRoom(void); +void DoorTransitionScrollingSetup(void); +void DoorTransitionScrollingSetup_Down(void); +void DoorTransitionScrollingSetup_Left(void); +void DoorTransitionScrollingSetup_Right(void); +void DoorTransitionScrollingSetup_Up(void); +void DrawThreeHudDigits(uint16 a, uint16 k); +void DrawTimer(void); +void DrawTimerSpritemap(uint16 a, uint16 j); +void DrawTwoHudDigits(uint16 a, uint16 k); +void DrawTwoTimerDigits(uint16 a, uint16 k); +void EnableIrqInterrupts(void); +void EnableIrqInterruptsNow(void); +void EnableNMI(void); +void FixDoorsMovingUp(void); +void Irq_FollowDoorTransition(void); +void HandleAutoscrolling_X(void); +void HandleAutoscrolling_Y(void); +void HandleFadeIn(void); +void ClearUnusedOam(void); +void HandleFadeOut(void); +void HandleHudTilemap(void); +void HandleMusicQueue(void); +void HandleScrollingWhenTriggeringScrollDown(void); +void HandleScrollingWhenTriggeringScrollLeft(void); +void HandleScrollingWhenTriggeringScrollRight(void); +void HandleScrollingWhenTriggeringScrollUp(void); +void InitializeCpuIoRegs(void); +void InitializeHud(void); +void InitializePpuIoRegs(void); +void InvalidInterrupt_Crash(void); +void IrqHandler_0_Nothing(void); +void IrqHandler_10_StartOfDoor_EndHud(void); +void IrqHandler_12_Draygon_BeginHud(void); +void IrqHandler_14_Draygon_EndHud(void); +void IrqHandler_16_VerticalDoor_BeginHud(void); +void IrqHandler_18_VerticalDoor_EndHud(void); +void IrqHandler_20_VerticalDoor_EndDraw(void); +void IrqHandler_22_HorizDoor_BeginHud(void); +void IrqHandler_24_HorizDoor_EndHud(void); +void IrqHandler_26_HorizDoor_EndDraw(void); +void IrqHandler_2_DisableIRQ(void); +void IrqHandler_4_Main_BeginHudDraw(void); +void IrqHandler_6_Main_EndHudDraw(void); +void IrqHandler_8_StartOfDoor_BeginHud(void); +void Irq_DoorTransitionVramUpdate(void); +void WaitForIrqDoorTransitionVramUpdate(void); +void LoadFromLoadStation(void); +void LoadMirrorOfExploredMapTiles(void); +void Multiply16x16(uint16 a, uint16 j); +void NMI_ProcessMode7Queue(void); +void NMI_ProcessMode7QueueInner(uint16 k); +void NMI_ProcessVramReadQueue(void); +void NMI_ProcessVramWriteQueue(void); +void NmiProcessAnimtilesVramTransfers(void); +void NmiTransferSamusToVram(void); +void NmiUpdateIoRegisters(void); +void NmiUpdatePalettesAndOam(void); +void Nmi_ProcessHorizScrollingDma(void); +void Nmi_ProcessVertScrollingDma(void); +CoroutineRet Play20FramesOfMusic_Async(void); +void QueueClearingOfFxTilemap(void); +void QueueMode7Transfers(uint8 db, uint16 k); +void QueueMusic_Delayed8(uint16 a); +void QueueMusic_DelayedY(uint16 a, uint16 j); +void QueueSfx1_Internal(uint16 a); +void QueueSfx1_Max1(uint16 a); +void QueueSfx1_Max15(uint16 a); +void QueueSfx1_Max3(uint16 a); +void QueueSfx1_Max6(uint16 a); +void QueueSfx1_Max9(uint16 a); +void QueueSfx2_Internal(uint16 a); +void QueueSfx2_Max1(uint16 a); +void QueueSfx2_Max15(uint16 a); +void QueueSfx2_Max3(uint16 a); +void QueueSfx2_Max6(uint16 a); +void QueueSfx2_Max9(uint16 a); +void QueueSfx3_Internal(uint16 a); +void QueueSfx3_Max1(uint16 a); +void QueueSfx3_Max15(uint16 a); +void QueueSfx3_Max3(uint16 a); +void QueueSfx3_Max6(uint16 a); +void QueueSfx3_Max9(uint16 a); +void ReadJoypadInputs(void); +void ReleaseButtonsFilter(uint16 a); +void ResumeGameplay(void); +void SaveExploredMapTilesToSaved(void); +void ScreenOff(void); +void ScreenOn(void); +void SetBossBitForCurArea(uint16 a); +void SetElevatorsAsUsed(void); +void SetEventHappened(uint16 a); +void SetTimerMinutes(uint16 a); +void SetupDmaTransfer(const void* p); +CoroutineRet StartGameplay_Async(void); +void ToggleHudItemHighlight(uint16 a, uint16 k); +void UpdateBackgroundDataRow(void); +void UpdateBgGraphicsWhenScrolling(void); +void UpdateBgScrollOffsets(void); +void UpdateLevelDataRow(void); +void UpdateLevelOrBackgroundDataColumn(uint16 k); +void UpdateLevelOrBackgroundDataRow(uint16 k); +void UpdatePreviousLayerBlocks(void); +void UpdateScrollVarsUpdateMap(void); +void UploadBackgroundDataColumn(void); +void UploadLevelDataColumn(void); +void Vector_IRQ(void); +void Vector_NMI(void); +CoroutineRet Vector_RESET_Async(void); +void VerifySRAM(void); +CoroutineRet WaitForNMI_Async(void); +CoroutineRet WaitForNMI_NoUpdate_Async(void); +void WriteLotsOf0x1c2f(void); +void memset7E(uint16 k, uint16 a, uint16 j); +void memset7F(uint16 k, uint16 a, uint16 j); +void sub_8088EB(uint16 a); +void sub_8088FE(uint16 a); +void sub_808911(uint16 a); + +// Bank 81 +uint16 CheckIfFileSelectMapAreaCanBeSelected(uint16 a); +uint16 DecAndWraparoundTo5(uint16 a); +uint16 HandleRoomSelectMapExpandingSquareTrans(void); +uint16 WraparoundFrom6to0(uint16 a); +uint8 LoadFromSram(uint16 a); +uint8 LoadFromSram_(uint16 a); +void AddExpandingSqTransLeftIndirHDMA(uint16 a, uint16 k, uint16 j); +uint16 AddExpandingSqTransRightIndirHDMA(uint16 a, uint16 k, uint16 j); +void ClearMenuTilemap(void); +void ConfigureWindow1ForExpandingSquare(void); +void DebugGameOverMenu(void); +void DrawAreaSelectMapLabels(void); +void DrawBeamGrappleSpritemap(uint16 a); +void DrawEnemyProjectileSpritemapWithBaseTile(uint8 db, uint16 j); +void DrawEnemyProjectileSpritemapWithBaseTileOffscreen(uint8 db, uint16 j); +void DrawFileCopyClearConfirmation(void); +void DrawFileCopyConfirmationSaveFileInfo(void); +void DrawFileCopySaveFileInfo(void); +void DrawFileCopySaveSlotAInfo(void); +void DrawFileCopySaveSlotBInfo(void); +void DrawFileCopySaveSlotCInfo(void); +void DrawFileCopySelectDestinationSaveFileInfo(void); +void DrawFileSelectSamusHelmets(void); +void DrawFileSelectSlotSamusHelmet(uint16 k); +void DrawFileSelectionHealth(uint16 a, uint16 k); +void DrawFileSelectionTime(uint16 a, uint16 k); +void DrawMenuSpritemap(uint16 a, uint16 k, uint16 j); +void DrawProjectileSpritemap(uint16 k); +void DrawSamusSpritemap(uint16 a, uint16 k, uint16 j); +void DrawSpritemap(uint8 db, uint16 j); +void DrawSpritemapOffScreen(uint16 j); +void DrawSpritemapWithBaseTile(uint8 db, uint16 j); +void DrawSpritemapWithBaseTile2(uint8 db, uint16 j); +void DrawSpritemapWithBaseTileOffscreen(uint8 db, uint16 j); +void FileSelectClearRestOfMenuTilemapRow(uint16 k); +void FileSelectMap(void); +void FileSelectMap_0(void); +void FileSelectMap_1(void); +void FileSelectMap_10_RoomSelectMap(void); +void FileSelectMap_11(void); +void FileSelectMap_13(void); +void FileSelectMap_14(void); +void FileSelectMap_15_ClearTileMap(void); +void FileSelectMap_16_LoadPalettes(void); +void FileSelectMap_18(void); +void FileSelectMap_20_SetupExpandingSquare(void); +void FileSelectMap_21_MoveExpandingSquare(void); +void FileSelectMap_22(void); +void FileSelectMap_2_LoadAreaSelectForegroundTilemap(void); +void FileSelectMap_3_LoadAreaSelectBackgroundTilemap(void); +void FileSelectMap_4_SetupExpandingSquareTransition(void); +void FileSelectMap_5_ExpandingSquare(void); +void FileSelectMap_6_AreaSelectMap(void); +void FileSelectMap_7_PrepExpandSquareTransToRoomMap(void); +void FileSelectMap_8_ExpandSquareTransToRoomSelectMap(void); +void FileSelectMap_9_InitRoomSelectMap(void); +void FileSelectMenu(void); +void FileSelectMenu_0_FadeOutConfigGfx(void); +void FileSelectMenu_10_FileCopySelectDest(void); +void FileSelectMenu_11_InitializeConfirm(void); +void FileSelectMenu_12_FileCopyConfirm(void); +void FileSelectMenu_13_FileCopyDoIt(void); +void FileSelectMenu_14_CopyCompleted(void); +void FileSelectMenu_15_FadeOutToMain(void); +void FileSelectMenu_16(void); +void FileSelectMenu_17_FadeInToMain(void); +void FileSelectMenu_18(void); +void FileSelectMenu_1_LoadFileSelectMenuBG2(void); +void FileSelectMenu_20_FileClearInit(void); +void FileSelectMenu_22_FileClearSelectSlot(void); +void FileSelectMenu_23_FileClearInitConfirm(void); +void FileSelectMenu_24_FileClearConfirm(void); +void FileSelectMenu_25_FileClearDoClear(void); +void FileSelectMenu_26_ClearCompleted(void); +void FileSelectMenu_2_InitMain(void); +void FileSelectMenu_30(void); +void FileSelectMenu_31_TurnSamusHelmet(void); +void FileSelectMenu_32_FadeOutToOptions(void); +void FileSelectMenu_33_FadeOutToTitle(void); +void FileSelectMenu_3_FadeInToMain(void); +void FileSelectMenu_4_Main(void); +void FileSelectMenu_5_FadeOutFromMain(void); +void FileSelectMenu_6_FileCopyInit(void); +void FileSelectMenu_7_FadeInFromMain(void); +void FileSelectMenu_8(void); +void FileSelectMenu_9_InitializeSelectDest(void); +void FileSelectMenu_Func1(void); +void GameOverMenu(void); +void GameOverMenu_0_FadeOutConfigGfx(void); +void GameOverMenu_1_Init(void); +void GameOverMenu_24_FadeIn(void); +void GameOverMenu_2_PlayMusic(void); +void GameOverMenu_3_FadeIn(void); +void GameOverMenu_3_Main(void); +void GameOverMenu_4_Main(void); +void GameOverMenu_5_Continue(void); +void GameOverMenu_5_FadeOutToGameMap(void); +void GameOverMenu_6_LoadGameMapView(void); +void GameOverMenu_7_FadeOutToSoftReset(void); +void HandleFileCopyArrowPalette(void); +void HandleFileSelectMapScrollArrows(void); +void InitFileSelectMenuFileClear(void); +void LoadActiveAreaMapForegroundColors(uint16 k); +void LoadAreaMapForegroundColors(uint16 j); +void LoadAreaSelectBackgroundTilemap(uint16 j); +void LoadDebugGameOverMenuTilemaps(void); +void LoadFileSelectPalettes(void); +void LoadInactiveAreaMapForegroundColors(uint16 k); +void LoadInitialMenuTiles(void); +void LoadMenuExitTilemap(void); +void LoadMenuPalettes(void); +void LoadMenuTilemap(uint16 k, uint16 j); +void MapVramForMenu(void); +void NewSaveFile(void); +void PackMapToSave(void); +void QueueTransferOfMenuTilemapToVramBG1(void); +void RestorePalettesAndIoAfterDebugGameover(void); +void SaveToSram(uint16 a); +void SelectFileSelectMapArea(void); +void SetFileClearMenuMissilePos(void); +void SetFileCopyMenuSelectionMissilePosition(void); +void SetInitialFileCopyMenuSelection(void); +void SetXCoordToInvalidPos(uint16 k); +void SetupInitialExpandingSquareHDMA(void); +void SetupRoomSelectMapExpandingSquareTransHDMA(void); +void SwitchActiveFileSelectMapArea(void); +void UnpackMapFromSave(void); +void sub_818A5F(uint16 j); +void sub_819591(void); +void sub_81A3D1(uint16 k); +void sub_81AEC8(void); +void SoftReset(void); + +// Bank 82 +uint16 CalculateNthTransitionColorComponentFromXtoY(uint16 a, uint16 k, uint16 j); +uint16 CalculateNthTransitionColorFromXtoY(uint16 a, uint16 k, uint16 j); +uint16 CheckIfMapPositionIsExplored(uint16 k, uint16 j); +uint16 DetermineBottommostMapColumn(void); +uint16 DetermineLeftmostMapColumn(void); +uint16 DetermineRightmostMapColumn(void); +uint16 DetermineTopmostMapColumn(void); +uint16 EquipmentScreenCategory_Boots_MoveUpInBoots(uint16 k); +uint16 EquipmentScreenMoveLowerOnSuitsMisc(uint16 k); +uint16 EquipmentScreenMoveToBottomOfBeams(uint16 k); +uint16 EquipmentScreenMoveToReserveTanks(void); +uint16 LoadLibraryBackgroundFunc_0_DONE(uint16 j); +uint16 LoadLibraryBackgroundFunc_2_TransferToVram(uint16 j); +uint16 LoadLibraryBackgroundFunc_4_Decompress(uint16 j); +uint16 LoadLibraryBackgroundFunc_6_ClearFxTilemap(uint16 j); +uint16 LoadLibraryBackgroundFunc_8_TransferToVramAndSetBg3(uint16 j); +uint16 LoadLibraryBackgroundFunc_A_ClearBG2Tilemap(uint16 j); +uint16 LoadLibraryBackgroundFunc_C_ClearKraidLayer2(uint16 j); +uint16 LoadLibraryBackgroundFunc_E_DoorDependentTransferToVram(uint16 j); +uint16 MapScrolling_GetSpeedIndex(void); +uint16 MultiplyBy8(uint16 k); +uint16 OptionsInstr_8C64(uint16 k, uint16 j); +uint16 OptionsInstr_8C79(uint16 k, uint16 j); +uint16 OptionsInstr_8C89(uint16 k, uint16 j); +uint16 OptionsInstr_8C93(uint16 k, uint16 j); +uint16 OptionsInstr_Destroy(uint16 k, uint16 j); +uint16 OptionsInstr_Goto(uint16 k, uint16 j); +uint16 OptionsInstr_SetPreInstr(uint16 k, uint16 j); +uint16 UpdateBackgroundCommand_0_Finish(uint16 j); +uint16 UpdateBackgroundCommand_2_TransferToVram(uint16 j); +uint16 UpdateBackgroundCommand_4_Decompression(uint16 j); +uint16 UpdateBackgroundCommand_6_ClearFxTilemap(uint16 j); +uint16 UpdateBackgroundCommand_8_TransferToVramAndSetBg3(uint16 j); +uint16 UpdateBackgroundCommand_A_ClearBg2Tilemap(uint16 j); +uint16 UpdateBackgroundCommand_C_ClearKraidBg2Tilemap(uint16 j); +uint16 UpdateBackgroundCommand_E_DoorDependentTransferToVRAM(uint16 j); +uint16 UpdateSamusPositionIndicatorAnimation(void); +uint8 AdvanceGradualColorChangeOfPalette(uint16 k, uint16 j); +uint8 AdvancePaletteFadeForAllPalettes(void); +uint8 AdvancePaletteFadeForAllPalettes_0xc(void); +uint8 AdvancePaletteFade_BgPalette6(void); +uint8 CheckIfColoredDoorCapSpawned(void); +uint8 CreateOptionsMenuObject_(uint16 a, uint16 j); +CoroutineRet DoorTransitionFunction_HandleElevator(void); +CoroutineRet DoorTransitionFunction_Wait48frames(void); +uint8 OptionsMenuFunc8(void); +uint8 RefillHealthFromReserveTanks(void); +uint8 sub_82DAF7(uint16 a); +uint8 sub_82DB0C(uint16 a); +void BabyMetroidPlaySfx0x23(void); +void BabyMetroidPlaySfx0x26(void); +void BabyMetroidPlaySfx0x27(void); +void BackupBG2TilemapForPauseMenu(void); +void BackupGameplayPalettesAndLoadForPause(void); +void BackupSomeGfxStateForPause(void); +void CalculateBgScrolls_Unpause(void); +void CancelSoundEffects(void); +void CheckForNextDemo(void); +void ClearBg2Tilemap(void); +void ClearFxTilemap(void); +void ClearKraidBg2Tilemap(void); +void ClearPauseMenuData(void); +void ClearSamusBeamTiles(void); +void ContinueInitGameplayResume(void); +void ContinueInitPauseMenu(void); +void CopyToVramAtNextInterrupt(const void* p); +void Copy_R22_Bytes(uint16 k); +void CreatePlmsExecuteDoorAsmRoomSetup(void); +void DeleteAllOptionsMenuObjects_(void); +void DemoRoom_ChargeBeamRoomScroll21(void); +void DemoRoom_SetBG2TilemapBase(void); +void DemoRoom_SetBrinstarBossBits(void); +void DemoRoom_SetKraidFunctionTimer(void); +void DetermineMapScrollLimits(void); +void DisplayMapElevatorDestinations(void); +CoroutineRet DoorTransitionFunction_FadeOutScreen(void); +CoroutineRet DoorTransitionFunction_FixDoorsMovingUp(void); +CoroutineRet DoorTransitionFunction_LoadDoorHeaderEtc(void); +CoroutineRet DoorTransitionFunction_LoadMoreThings_Async(void); +CoroutineRet DoorTransitionFunction_PlaceSamusLoadTiles(void); +CoroutineRet DoorTransitionFunction_ScrollScreenToAlignment(void); +CoroutineRet DoorTransitionFunction_SetupNewRoom(void); +CoroutineRet DoorTransitionFunction_SetupScrolling(void); +CoroutineRet DoorTransitionFunction_WaitForSoundsToFinish(void); +CoroutineRet DoorTransition_FadeInScreenAndFinish(void); +CoroutineRet DoorTransition_HandleTransition(void); +CoroutineRet DoorTransition_WaitForMusicToClear(void); +void DrawBabyMetroid(uint16 k); +void DrawBorderAroundDataClearMode(void); +void DrawBorderAroundDataCopyMode(void); +void DrawBorderAroundSamusData(void); +void DrawBossMapIcons(uint16 a, uint16 k); +void DrawDebugElevatorMapIcons(uint16 a, uint16 k); +void DrawDebugSaveMapIcons(uint16 a, uint16 k); +void DrawFileCopyArrow(void); +void DrawFileSelectMapIcons(void); +void DrawLrHighlight(void); +void DrawMapIcons(void); +void DrawMapIconsOfType(uint16 a); +void DrawMapScrollArrowAndCheckToScroll(uint8 db, uint16 k); +void DrawMenuSelectionMissile(void); +void DrawOptionsMenuSpritemaps(void); +void DrawPauseMenuDuringFadeIn(void); +void DrawPauseMenuDuringFadeout(void); +void DrawPauseScreenSpriteAnim(uint16 a, uint16 k, uint16 j); +void DrawRoomSelectMap(void); +void DrawRoomSelectMapAreaLabel(void); +void DrawSaveStationMapIcon(uint16 a, uint16 k); +void DrawSimpleMapIcons(uint16 a, uint16 k); +void EnsureSamusDrawnEachFrame(void); +void EquipmentScreenCategory_Boots(void); +void EquipmentScreenCategory_Boots_MoveResponse(void); +void EquipmentScreenCategory_ButtonResponse(void); +void EquipmentScreenCategory_Suit(void); +void EquipmentScreenCategory_Suit_MoveResponse(void); +void EquipmentScreenCategory_Tanks(void); +void EquipmentScreenCategory_Tanks_0(void); +void EquipmentScreenCategory_Tanks_1(void); +void EquipmentScreenCategory_Weapons(void); +void EquipmentScreenCategory_Weapons_MoveButtons(void); +void EquipmentScreenCategory_Weapons_PlazmaSpazerCheck(void); +void EquipmentScreenDisplayReserveTankAmount(void); +void EquipmentScreenDisplayReserveTankAmount_(void); +void EquipmentScreenDisplayReserves_PaletteSetup(void); +void EquipmentScreenDrawItemSelector(void); +void EquipmentScreenEnergyArrowGlow_Off(void); +void EquipmentScreenEnergyArrowGlow_On(void); +void EquipmentScreenGlowingArrow(void); +void EquipmentScreenGlowingArrowAnimated(void); +void EquipmentScreenGlowingArrowSolidOff(void); +void EquipmentScreenGlowingArrowSolidOn(void); +void EquipmentScreenHandleDpad(void); +void EquipmentScreenHudReserveAutoTilemap_Off(void); +void EquipmentScreenHudReserveAutoTilemap_On_BUGGY(void); +void EquipmentScreenMain(void); +void EquipmentScreenMoveToBeams(uint16 k); +void EquipmentScreenMoveToHighJumpOrLowerInBoots(uint16 k); +void EquipmentScreenMoveToScrewOrHigherOnSuits(uint16 k); +void EquipmentScreenSetupReserveMode(void); +void EquipmentScreenTransferBG1Tilemap(void); +void FinishProcessingGameOverBabyMetroidAsm(void); +void GameOptionsMenuFunc_0(void); +void GameOptionsMenuItemFunc_0(void); +void GameOptionsMenuItemFunc_2_ToggleJapanese(void); +void GameOptionsMenuItemFunc_4(void); +void GameOptionsMenuSpecialSettings_0(void); +void GameOptionsMenuSpecialSettings_2(void); +void GameOptionsMenu_1_LoadingOptionsScreen(void); +void GameOptionsMenu_2_FadeInOptionsScreen(void); +void GameOptionsMenu_3_OptionsScreen(void); +void GameOptionsMenu_4_StartGame(void); +void GameOptionsMenu_5_DissolveOutScreen(void); +void GameOptionsMenu_6_DissolveInScreen(void); +void GameOptionsMenu_7_ControllerSettings(void); +void GameOptionsMenu_8_SpecialSettings(void); +void GameOptionsMenu_9_ScrollControllerSettingsDown(void); +void GameOptionsMenu_A_ScrollControllerSettingsUp(void); +void GameOptionsMenu_B_TransitionBackToFileSelect(void); +void GameOptionsMenu_C_FadeOutOptionsScreenToStart(void); +CoroutineRet GameState_0_Reset_Async(void); +CoroutineRet GameState_10_LoadingNextRoom_Async(void); +CoroutineRet GameState_11_LoadingNextRoom_Async(void); +CoroutineRet GameState_12_Pausing_Darkening_Async(void); +CoroutineRet GameState_13_Pausing_Async(void); +CoroutineRet GameState_14_Paused_Async(void); +CoroutineRet GameState_15_Paused_Async(void); +CoroutineRet GameState_16_Unpausing_Async(void); +CoroutineRet GameState_17_Unpausing_Async(void); +CoroutineRet GameState_18_Unpausing(void); +CoroutineRet GameState_19_SamusNoHealth(void); +CoroutineRet GameState_1_OpeningCinematic(void); +CoroutineRet GameState_20_SamusNoHealth_BlackOut(void); +CoroutineRet GameState_21_SamusNoHealth(void); +CoroutineRet GameState_22_SamusNoHealth_Dying(void); +CoroutineRet GameState_23_SamusNoHealth_Flashing(void); +CoroutineRet GameState_24_SamusNoHealth_Explosion(void); +CoroutineRet GameState_25_SamusNoHealth_BlackOut(void); +CoroutineRet GameState_26_GameOverMenu(void); +CoroutineRet GameState_27_ReserveTanksAuto(void); +CoroutineRet GameState_28_Unused(void); +CoroutineRet GameState_29_DebugGameOverMenu(void); +CoroutineRet GameState_2_GameOptionsMenu(void); +CoroutineRet GameState_3_Null(void); +CoroutineRet GameState_32_MadeItToCeresElevator(void); +CoroutineRet GameState_33_BlackoutFromCeres(void); +CoroutineRet GameState_35_TimeUp(void); +CoroutineRet GameState_36_WhitingOutFromTimeUp(void); +CoroutineRet GameState_37_CeresGoesBoomWithSamus(void); +CoroutineRet GameState_38_SamusEscapesFromZebes(void); +CoroutineRet GameState_39_EndingAndCredits(void); +CoroutineRet GameState_41_TransitionToDemo(void); +CoroutineRet GameState_42_PlayingDemo_Async(void); +CoroutineRet GameState_43_TransitionFromDemo(void); +CoroutineRet GameState_44_TransitionFromDemo(void); +CoroutineRet GameState_4_FileSelectMenus(void); +CoroutineRet GameState_5_FileSelectMap(void); +CoroutineRet GameState_7_MainGameplayFadeIn(void); +CoroutineRet GameState_8_MainGameplay(void); +CoroutineRet GameState_9_HitDoorBlock(void); +void HandleGameOverBabyMetroid(void); +void HandleMapScrollArrows(void); +void HandlePauseMenuLRPressHighlight(void); +void HandlePauseScreenLR(void); +void HandlePauseScreenLrInput(void); +void HandlePauseScreenPaletteAnimation(void); +void HandlePauseScreenStart(void); +void HandleSamusOutOfHealthAndGameTile(void); +void HandleSoundEffects(void); +void HighlightPauseScreenButton(void); +CoroutineRet InitAndLoadGameData_Async(void); +void InitCpuForGameplay(void); +void InitIoForGameplay(void); +void InitPpuForGameplay(void); +void JmpFuncA(uint16 a); +void LoaadDesinationRoomCreBitset(void); +void LoadCRETilesTilesetTilesAndPalette(void); +void LoadCRETilesTilesetTilesAndPalette_(void); +void LoadColorsForSpritesBeamsAndEnemies(void); +void LoadControllerOptionsFromControllerBindings(void); +void LoadDemoRoomData(void); +void LoadDestinationRoomThings(void); +void LoadDoorHeader(void); +void LoadEnemyGfxToVram(void); +void LoadEquipmentScreenEquipmentTilemaps(void); +void LoadEqupmentScreenReserveHealthTilemap(void); +void LoadInitialPalette(void); +void LoadLevelDataAndOtherThings(void); +void LoadLevelScrollAndCre(void); +void LoadLibraryBackground(void); +void LoadMapExploredIfElevator(void); +void LoadNewMusicTrackIfChanged(void); +void LoadPauseMenuMapTilemap(void); +void LoadPauseMenuMapTilemapAndAreaLabel(void); +void LoadPauseMenuTilesAndClearBG2(void); +void LoadPauseScreenBaseTilemaps(void); +void LoadRoomHeader(void); +void LoadRoomMusic(void); +void LoadStateHeader(void); +void LoadStdBG3andSpriteTilesClearTilemaps(void); +void MainGameLoopStarter(void); +void MainPauseRoutine(void); +void MapScreenDrawSamusPositionIndicator(void); +void MapScrolling(void); +void MapScrolling_0_None(void); +void MapScrolling_1_Left(void); +void MapScrolling_2_Right(void); +void MapScrolling_3_Up(void); +void MapScrolling_4_Down(void); +void MapScrolling_Common(void); +void NullFunc(void); +void OptionsMenuControllerFunc_0(void); +void OptionsMenuControllerFunc_7(void); +void OptionsMenuControllerFunc_8(void); +void OptionsMenuFunc1(void); +void OptionsMenuFunc2(uint16 k); +void OptionsMenuFunc4(void); +void OptionsMenuFunc5(uint16 a, uint16 k, uint16 j); +void OptionsMenuFunc6(void); +void OptionsMenuFunc7(void); +void OptionsMenu_AddToVramQueue(void); +void OptionsPreInstr_F2A9(uint16 k); +void OptionsPreInstr_F376(uint16 k); +void OptionsPreInstr_F3A0(uint16 k); +void OptionsPreInstr_F3E2(uint16 k); +void OptionsPreInstr_F42C(uint16 k); +void OptionsPreInstr_nullsub_57(uint16 k); +void PauseMenu_0_MapScreen(void); +void PauseMenu_1_EquipmentScreen(void); +void PauseMenu_2(void); +void PauseMenu_3_MapToEquipment_Load(void); +void PauseMenu_4_MapToEquipment_FadeIn(void); +void PauseMenu_5(void); +void PauseMenu_6_EquipmentToMap_Load(void); +void PauseMenu_7_EquipmentToMap_FadeIn(void); +void PlayRoomMusicTrackAfterAFrames(uint16 a); +void PointlessFunctionStupidToo(void); +void QueueSamusMovementSfx(void); +void ResetPauseMenuAnimations(void); +void ResetSoundQueues(void); +void RestoreBG2TilemapFromPauseScreen(void); +void RestoreSomeGfxStateForPause(void); +void SaveMapExploredifElevator(void); +void SetPaletteOfR22TilemapBytesToR18(void); +void SetPauseScreenButtonLabelPalettes(void); +void SetPauseScreenButtonLabelPalettes_0(void); +void SetPauseScreenButtonLabelPalettes_1(void); +void SetPauseScreenButtonLabelPalettes_2(void); +void SetupMapScrollingForFileSelectMap(void); +void SetupMapScrollingForPauseMenu(uint16 a); +void SetupPpuForGameplayResume(void); +void SetupPpuForPauseMenu(void); +void SfxHandlers_0_SendToApu(uint16 j); +void SfxHandlers_1_WaitForAck(uint16 j); +void SfxHandlers_2_ClearRequest(uint16 j); +void SfxHandlers_3_WaitForAck(uint16 j); +void SfxHandlers_4_Reset(uint16 j); +void ShowSpareCpu(void); +void SpawnDoorClosingPLM(void); +CoroutineRet DoorTransition_C_HandleAnimTiles(void); +void UpdateBeamTilesAndPalette_Unpause(void); +void UpdateMusicTrackIndex(void); +void UpdatePauseMenuLRStartVramTilemap(void); +void WaitUntilEndOfVblankAndEnableIrq(void); +void WriteSamusWireframeTilemap(void); +void WriteSamusWireframeTilemapAndQueue(void); + +void sub_82A425(void); +void sub_82A42A(void); +void sub_82A47B(void); +void sub_82A4A9(void); +void sub_82B932(void); +void sub_82BB7F(uint16 a); +void sub_82BBDD(void); +void sub_82DB41(void); +void sub_82F296(uint16 j); +void sub_82F34B(uint16 j); +void sub_82F353(uint16 j); +void sub_82F35B(uint16 j); +void sub_82F363(uint16 j); +void sub_82F369(uint16 j); +void sub_82F404(uint16 k); +void sub_82F419(uint16 j); + +// Bank 84 +uint16 PlmInstr_ABD6(uint16 k, uint16 j); +uint16 PlmInstr_ActivateEnergyStation(uint16 j, uint16 k); +uint16 PlmInstr_ActivateMapStation(uint16 j, uint16 k); +uint16 PlmInstr_ActivateMissileStation(uint16 j, uint16 k); +uint16 PlmInstr_ActivateSaveStationAndGotoIfNo(uint16 j, uint16 k); +uint16 PlmInstr_Call(uint16 j, uint16 k); +uint16 PlmInstr_CallFunction(uint16 j, uint16 k); +uint16 PlmInstr_ClearChargeBeamCounter(uint16 j, uint16 k); +uint16 PlmInstr_ClearMusicQueueAndQueueTrack(uint16 j, uint16 k); +uint16 PlmInstr_ClearPreInstr(uint16 j, uint16 k); +uint16 PlmInstr_ClearTrigger(uint16 j, uint16 k); +uint16 PlmInstr_CollectAmmoMissileTank(uint16 j, uint16 k); +uint16 PlmInstr_CollectAmmoPowerBombTank(uint16 j, uint16 k); +uint16 PlmInstr_CollectAmmoSuperMissileTank(uint16 j, uint16 k); +uint16 PlmInstr_CollectHealthEnergyTank(uint16 j, uint16 k); +uint16 PlmInstr_CollectHealthReserveTank(uint16 j, uint16 k); +uint16 PlmInstr_CopyFromRamToVram(uint16 j, uint16 k); +uint16 PlmInstr_DamageDraygonTurret(uint16 j, uint16 k); +uint16 PlmInstr_DamageDraygonTurret2(uint16 j, uint16 k); +uint16 PlmInstr_DamageDraygonTurretFacingDownLeft(uint16 j, uint16 k); +uint16 PlmInstr_DamageDraygonTurretFacingDownRight(uint16 j, uint16 k); +uint16 PlmInstr_DamageDraygonTurretFacingUpLeft(uint16 j, uint16 k); +uint16 PlmInstr_DamageDraygonTurretFacingUpRight(uint16 j, uint16 k); +uint16 PlmInstr_DealDamage_2(uint16 j, uint16 k); +uint16 PlmInstr_DecrementAndBranchNonzero(uint16 j, uint16 k); +uint16 PlmInstr_Delete(uint16 j, uint16 k); +uint16 PlmInstr_DiagonalEarthquake(uint16 j, uint16 k); +uint16 PlmInstr_DisableSamusControls(uint16 j, uint16 k); +uint16 PlmInstr_DisplayGameSavedMessageBox(uint16 j, uint16 k); +uint16 PlmInstr_Draw0x38FramesOfLeftTreadmill(uint16 j, uint16 k); +uint16 PlmInstr_Draw0x38FramesOfRightTreadmill(uint16 j, uint16 k); +uint16 PlmInstr_DrawItemFrame0(uint16 j, uint16 k); +uint16 PlmInstr_DrawItemFrame1(uint16 j, uint16 k); +uint16 PlmInstr_DrawItemFrame_Common(uint16 j, uint16 k); +uint16 PlmInstr_DrawPlmBlock(uint16 j, uint16 k); +uint16 PlmInstr_DrawPlmBlock_(uint16 j, uint16 k); +uint16 PlmInstr_E63B(uint16 k, uint16 j); +uint16 PlmInstr_EnableMovementAndSetSaveStationUsed(uint16 j, uint16 k); +uint16 PlmInstr_EnableSamusControls(uint16 j, uint16 k); +uint16 PlmInstr_EnableWaterPhysics(uint16 j, uint16 k); +uint16 PlmInstr_FxBaseYPos_0x2D2(uint16 j, uint16 k); +uint16 PlmInstr_GiveInvincibility(uint16 j, uint16 k); +uint16 PlmInstr_Goto(uint16 j, uint16 k); +uint16 PlmInstr_GotoIfBossBitSet(uint16 j, uint16 k); +uint16 PlmInstr_GotoIfChozoSet(uint16 j, uint16 k); +uint16 PlmInstr_GotoIfDoorBitSet(uint16 j, uint16 k); +uint16 PlmInstr_GotoIfEventSet(uint16 j, uint16 k); +uint16 PlmInstr_GotoIfItemBitSet(uint16 j, uint16 k); +uint16 PlmInstr_GotoIfMissilesFull(uint16 j, uint16 k); +uint16 PlmInstr_GotoIfRoomArgLess(uint16 j, uint16 k); +uint16 PlmInstr_GotoIfSamusHealthFull(uint16 j, uint16 k); +uint16 PlmInstr_GotoIfSamusNear(uint16 j, uint16 k); +uint16 PlmInstr_IncrementArgumentAndJGE(uint16 j, uint16 k); +uint16 PlmInstr_IncrementDoorHitCounterAndJGE(uint16 j, uint16 k); +uint16 PlmInstr_JumpIfSamusHasNoBombs(uint16 j, uint16 k); +uint16 PlmInstr_LoadItemPlmGfx(uint16 j, uint16 k); +uint16 PlmInstr_MovePlmDownOneBlock(uint16 j, uint16 k); +uint16 PlmInstr_MovePlmDownOneBlock_0(uint16 j, uint16 k); +uint16 PlmInstr_MovePlmRight4Blocks(uint16 j, uint16 k); +uint16 PlmInstr_MoveUpAndMakeBlueDoorFacingLeft(uint16 j, uint16 k); +uint16 PlmInstr_MoveUpAndMakeBlueDoorFacingRight(uint16 j, uint16 k); +uint16 PlmInstr_PickupBeamAndShowMessage(uint16 j, uint16 k); +uint16 PlmInstr_PickupEquipmentAddGrappleShowMessage(uint16 j, uint16 k); +uint16 PlmInstr_PickupEquipmentAddXrayShowMessage(uint16 j, uint16 k); +uint16 PlmInstr_PickupEquipmentAndShowMessage(uint16 j, uint16 k); +uint16 PlmInstr_PlaceSamusOnSaveStation(uint16 j, uint16 k); +uint16 PlmInstr_PreInstr(uint16 j, uint16 k); +uint16 PlmInstr_ProcessAirScrollUpdate(uint16 j, uint16 k); +uint16 PlmInstr_ProcessSolidScrollUpdate(uint16 j, uint16 k); +uint16 PlmInstr_QueueMusic(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx1_Max1(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx1_Max15(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx1_Max3(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx1_Max6(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx1_Max9(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx2_Max1(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx2_Max15(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx2_Max3(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx2_Max6(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx2_Max9(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx3_Max1(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx3_Max15(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx3_Max6(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx3_Max9(uint16 j, uint16 k); +uint16 PlmInstr_QueueSfx_Max3(uint16 j, uint16 k); +uint16 PlmInstr_QueueSong1MusicTrack(uint16 j, uint16 k); +uint16 PlmInstr_Return(uint16 j, uint16 k); +uint16 PlmInstr_Scroll_0_1_Blue(uint16 j, uint16 k); +uint16 PlmInstr_SetBTS(uint16 j, uint16 k); +uint16 PlmInstr_SetBtsTo1(uint16 j, uint16 k); +uint16 PlmInstr_SetCrittersEscapedEvent(uint16 j, uint16 k); +uint16 PlmInstr_SetEvent(uint16 j, uint16 k); +uint16 PlmInstr_SetGreyDoorPreInstr(uint16 j, uint16 k); +uint16 PlmInstr_SetItemBit(uint16 j, uint16 k); +uint16 PlmInstr_SetLinkReg(uint16 j, uint16 k); +uint16 PlmInstr_SetRoomChozoBit(uint16 j, uint16 k); +uint16 PlmInstr_SetTimer(uint16 j, uint16 k); +uint16 PlmInstr_ShootEyeDoorProjectileWithProjectileArg(uint16 j, uint16 k); +uint16 PlmInstr_Sleep(uint16 j, uint16 k); +uint16 PlmInstr_Spawn10shardsAnd6n00bs(uint16 j, uint16 k); +uint16 PlmInstr_SpawnEnemyProjectile(uint16 j, uint16 k); +uint16 PlmInstr_SpawnEyeDoorSmokeProjectile(uint16 j, uint16 k); +uint16 PlmInstr_SpawnEyeDoorSweatEnemyProjectile(uint16 j, uint16 k); +uint16 PlmInstr_SpawnFourMotherBrainGlass(uint16 j, uint16 k); +uint16 PlmInstr_SpawnN00bTubeCrackEnemyProjectile(uint16 j, uint16 k); +uint16 PlmInstr_SpawnTorizoStatueBreaking(uint16 j, uint16 k); +uint16 PlmInstr_SpawnTwoEyeDoorSmoke(uint16 j, uint16 k); +uint16 PlmInstr_TransferWreckedShipChozoSpikesToSlopes(uint16 j, uint16 k); +uint16 PlmInstr_TransferWreckedShipSlopesToChozoSpikes(uint16 j, uint16 k); +uint16 PlmInstr_WakeEnemyProjectileAtPlmPos(uint16 j, uint16 k); +uint16 SetBtsTo0x10AdvanceRow(uint16 k); +uint16 SetBtsTo0x10AdvanceRowUp(uint16 k); +uint8 ActivateStationIfSamusCannonLinedUp(uint16 a, uint16 j); +uint8 PlmSetup_B638_Rightwards_Extension(uint16 j); +uint8 PlmSetup_B63F_Leftwards_Extension(uint16 j); +uint8 PlmSetup_B643_Downwards_Extension(uint16 j); +uint8 PlmSetup_B647_Upwards_Extension(uint16 j); +uint8 PlmSetup_B6D3_MapStation(uint16 j); +uint8 PlmSetup_B6E3_EnergyStationRightAccess(uint16 j); +uint8 PlmSetup_B6E7_EnergyStationLeftAccess(uint16 j); +uint8 PlmSetup_B6EF_MissileStationRightAccess(uint16 j); +uint8 PlmSetup_B6F3_MissileStationLeftAccess(uint16 j); +uint8 PlmSetup_B6FF_ScrollBlockTouch(uint16 j); +uint8 PlmSetup_B703_ScrollPLM(uint16 j); +uint8 PlmSetup_B707_SolidScrollPLM(uint16 j); +uint8 PlmSetup_B70F_IcePhysics(uint16 j); +uint8 PlmSetup_B71F_SubmergingQuicksand(uint16 j); +uint8 PlmSetup_B723_SandfallsSlow(uint16 j); +uint8 PlmSetup_B727_SandFallsFast(uint16 j); +uint8 PlmSetup_B737_SubmergingQuicksand(uint16 j); +uint8 PlmSetup_B73B_B73F_SandFalls(uint16 j); +uint8 PlmSetup_B767_ClearShitroidInvisibleWall(uint16 j); +uint8 PlmSetup_B76B_SaveStationTrigger(uint16 j); +uint8 PlmSetup_B76F_SaveStation(uint16 j); +uint8 PlmSetup_B7EB_EnableSoundsIn32Frames(uint16 j); +uint8 PlmSetup_B974(uint16 j); +uint8 PlmSetup_B9C1_CrittersEscapeBlock(uint16 j); +uint8 PlmSetup_B9ED_CrittersEscapeBlock(uint16 j); +uint8 PlmSetup_BB30_CrateriaMainstreetEscape(uint16 j); +uint8 PlmSetup_BTS_Brinstar_0x80_Floorplant(uint16 j); +uint8 PlmSetup_BTS_Brinstar_0x81_Ceilingplant(uint16 j); +uint8 PlmSetup_Bts47_MapStationRightAccess(uint16 j); +uint8 PlmSetup_Bts4_MapStationLeftAccess(uint16 j); +uint8 PlmSetup_C73A_UpwardsGateShootblock(uint16 j); +uint8 PlmSetup_C794_GreyDoor(uint16 j); +uint8 PlmSetup_C806_LeftGreenGateTrigger(uint16 j); +uint8 PlmSetup_C80A_RightGreenGateTrigger(uint16 j); +uint8 PlmSetup_C80E_LeftRedGateTrigger(uint16 j); +uint8 PlmSetup_C812_RightRedGateTrigger(uint16 j); +uint8 PlmSetup_C816_LeftBlueGateTrigger(uint16 j); +uint8 PlmSetup_C81A_RightBlueGateTrigger(uint16 j); +uint8 PlmSetup_C81E_LeftYellowGateTrigger(uint16 j); +uint8 PlmSetup_C822_RightYellowGateTrigger(uint16 j); +uint8 PlmSetup_C826_DownwardsOpenGate(uint16 j); +uint8 PlmSetup_C82A_DownwardsClosedGate(uint16 j); +uint8 PlmSetup_C82E_UpwardsOpenGate(uint16 j); +uint8 PlmSetup_C832_UpwardsClosedGate(uint16 j); +uint8 PlmSetup_C836_DownwardsGateShootblock(uint16 j); +uint8 PlmSetup_ClearShitroidInvisibleWall(uint16 j); +uint8 PlmSetup_CrumbleBotwoonWall(uint16 j); +uint8 PlmSetup_D028_D02C_Unused(uint16 j); +uint8 PlmSetup_D08C_CrumbleBlock(uint16 j); +uint8 PlmSetup_D08C_SuperMissileBlockRespawning(uint16 j); +uint8 PlmSetup_D094_EnemyBreakableBlock(uint16 j); +uint8 UNUSED_sub_84B3E3(uint16 j); +uint8 PlmSetup_D0D8_ClearVflag(uint16 j); +uint8 PlmSetup_D0D8_SetVFlag(uint16 j); +uint8 PlmSetup_D0DC_BreakableGrappleBlock(uint16 j); +uint8 PlmSetup_D0E8_GiveSamusDamage(uint16 j); +uint8 PlmSetup_D113_LowerNorfairChozoRoomPlug(uint16 j); +uint8 PlmSetup_D127(uint16 j); +uint8 PlmSetup_D138(uint16 j); +uint8 PlmSetup_D6DA_LowerNorfairChozoHandTrigger(uint16 j); +uint8 PlmSetup_D6F2_WreckedShipChozoHandTrigger(uint16 j); +uint8 PlmSetup_D700_MakePlmAirBlock_Unused(uint16 j); +uint8 PlmSetup_D704_AlteranateLowerNorfairChozoHand_Unused(uint16 j); +uint8 PlmSetup_D708_LowerNorfairChozoBlockUnused(uint16 j); +uint8 PlmSetup_D70C_NoobTube(uint16 j); +uint8 PlmSetup_DeactivatePlm(uint16 j); +uint8 PlmSetup_DeletePlmIfAreaTorizoDead(uint16 j); +uint8 PlmSetup_Door_Blue(uint16 j); +uint8 PlmSetup_Door_Colored(uint16 j); +uint8 PlmSetup_Door_Strange(uint16 j); +uint8 PlmSetup_DraygonCannon(uint16 j); +uint8 PlmSetup_DraygonCannonFacingDiagonalLeft(uint16 j); +uint8 PlmSetup_DraygonCannonFacingDiagonalRight(uint16 j); +uint8 PlmSetup_DraygonCannonFacingLeft(uint16 j); +uint8 PlmSetup_DraygonCannonFacingRight(uint16 j); +uint8 PlmSetup_EyeDoor(uint16 j); +uint8 PlmSetup_EyeDoorEye(uint16 j); +uint8 PlmSetup_MakeBllockChozoHandTrigger(uint16 j); +uint8 PlmSetup_MotherBrainGlass(uint16 j); +uint8 PlmSetup_MotherBrainRoomEscapeDoor(uint16 j); +uint8 PlmSetup_PlmB6DF_EnergyStation(uint16 j); +uint8 PlmSetup_PlmB6EB_EnergyStation(uint16 j); +uint8 PlmSetup_QuicksandSurface(uint16 j); +uint8 PlmSetup_QuicksandSurfaceB(uint16 j); +uint8 PlmSetup_QuicksandSurfaceB_0(uint16 j); +uint8 PlmSetup_QuicksandSurfaceB_1(uint16 j); +uint8 PlmSetup_QuicksandSurfaceB_2(uint16 j); +uint8 PlmSetup_RespawningBombBlock(uint16 j); +uint8 PlmSetup_RespawningBombBlock2(uint16 j); +uint8 PlmSetup_RespawningCrumbleBlock(uint16 j); +uint8 PlmSetup_RespawningPowerBombBlock(uint16 j); +uint8 PlmSetup_RespawningShotBlock(uint16 j); +uint8 PlmSetup_RespawningSpeedBoostBlock(uint16 j); +uint8 PlmSetup_ReturnCarryClear(uint16 j); +uint8 PlmSetup_ReturnCarrySet(uint16 j); +uint8 PlmSetup_SetMetroidRequiredClearState(uint16 j); +uint8 PlmSetup_SetrupWreckedShipEntrance(uint16 j); +uint8 PlmSetup_ShaktoolsRoom(uint16 j); +uint8 PlmSetup_SpeedBoosterEscape(uint16 j); +uint8 SpawnPLM(uint16 a); +uint8 WakePlmIfSamusIsBelowAndRightOfTarget(uint16 k); +uint8 sub_84B9F1(uint16 j); +uint8 sub_84C63F(uint16 j); +uint8 sub_84C647(uint16 j); +uint8 sub_84C64C(uint16 j, uint16 a); +uint8 sub_84EE4D(uint16 j); +uint8 sub_84EE52(uint16 j); +uint8 sub_84EE57(uint16 j); +uint8 sub_84EE5C(uint16 j); +uint8 sub_84EE5F(uint16 j, uint16 a); +uint8 sub_84EE64(uint16 j); +uint8 sub_84EE77(uint16 j); +uint8 sub_84EE7C(uint16 j); +uint8 sub_84EE81(uint16 j); +uint8 sub_84EE86(uint16 j); +uint8 sub_84EE89(uint16 j, uint16 a); +uint8 sub_84EE8E(uint16 j); +uint8 sub_84EEAB(uint16 j); +void CalculatePlmBlockCoords(uint16 k); +void CalculatePlmDrawTilemapVramDst(uint16 k); +void ClearPLMs(void); +void ClearSoundsWhenGoingThroughDoor(void); +void DeletePlm(uint16 j); +void DisablePLMs(void); +void DrawPlm(uint16 k); +void EnablePLMs(void); +void LoadRoomPlmGfx(void); +void LoadXrayBlocks(void); +void PartiallyQueueVramForSingleScreenPlm(uint16 a, uint16 k); +void PlaySpinJumpSoundIfSpinJumping(void); +CoroutineRet PlmHandler_Async(void); +void PlmPreInstr_AdvanceLavaSamusMovesLeft(uint16 k); +void PlmPreInstr_B7EB_DecTimerEnableSoundsDeletePlm(uint16 k); +void PlmPreInstr_DeletePlmAndSpawnTriggerIfBlockDestroyed(uint16 k); +void PlmPreInstr_Empty2(void); +void PlmPreInstr_EscapeRoomBeforeOldTourianEscapeShaft(uint16 k); +void PlmPreInstr_GoToLinkInstrIfShot(uint16 k); +void PlmPreInstr_GoToLinkInstrIfShotWithAnyMissile(uint16 k); +void PlmPreInstr_GoToLinkInstrIfShotWithPowerBomb(uint16 k); +void PlmPreInstr_GoToLinkInstrIfShotWithSuperMissile(uint16 k); +void PlmPreInstr_GoToLinkInstruction(uint16 k); +void PlmPreInstr_GotoLinkIfBoss1Dead(uint16 k); +void PlmPreInstr_GotoLinkIfCrittersEscaped(uint16 k); +void PlmPreInstr_GotoLinkIfEnemyDeathQuotaOk(uint16 k); +void PlmPreInstr_GotoLinkIfMiniBossDead(uint16 k); +void PlmPreInstr_GotoLinkIfShotWithSuperMissile(uint16 k); +void PlmPreInstr_GotoLinkIfTorizoDead(uint16 k); +void PlmPreInstr_GotoLinkIfTourianStatueFinishedProcessing(uint16 k); +void PlmPreInstr_GotoLinkIfTriggered(uint16 k); +void PlmPreInstr_IncrementRoomArgIfShotBySuperMissile(uint16 k); +void PlmPreInstr_OldTourianEscapeShaftEscape(uint16 k); +void PlmPreInstr_PlayDudSound(uint16 k); +void PlmPreInstr_PositionSamusAndInvincible(uint16 k); +void PlmPreInstr_SetMetroidsClearState_Ev0x10(uint16 k); +void PlmPreInstr_SetMetroidsClearState_Ev0x11(uint16 k); +void PlmPreInstr_SetMetroidsClearState_Ev0x12(uint16 k); +void PlmPreInstr_SetMetroidsClearState_Ev0x13(uint16 k); +void PlmPreInstr_ShaktoolsRoom(uint16 k); +void PlmPreInstr_WakeAndLavaIfBoosterCollected(uint16 k); +void PlmPreInstr_WakeIfTriggered(uint16 k); +void PlmPreInstr_WakeOnKeyPress(uint16 k); +void PlmPreInstr_WakePLMAndStartFxMotionSamusFarLeft(uint16 k); +void PlmPreInstr_WakePlmIfRoomArgumentDoorIsSet(uint16 k); +void PlmPreInstr_WakePlmIfSamusHasBombs(uint16 k); +void PlmPreInstr_WakePlmIfTriggered(uint16 k); +void PlmPreInstr_WakePlmIfTriggeredOrSamusAbovePlm(uint16 k); +void PlmPreInstr_WakePlmIfTriggeredOrSamusBelowPlm(uint16 k); +void PlmSetup_QuicksandSurface_0(uint16 j); +void PlmSetup_QuicksandSurface_1(uint16 j); +void PlmSetup_QuicksandSurface_2(uint16 j); +void ProcessPlmDrawInstruction(uint16 k); +void SetBts0x10FiveStepsDown(uint16 j); +void SetBts0x10FiveStepsUp(uint16 j); +void SetGoldenTorizoPalette(uint16 a); +void SkipDebugDrawInstructionsForScrollPlms(uint16 j); +void SpawnHardcodedPlm(const void* p); +void SpawnMotherBrainGlassShatteringShard(uint16 a); +void SpawnRoomPLM(uint16 k); +void WriteLevelDataBlockTypeAndBts(uint16 k, uint16 a); + +void sub_84D7EF(uint16 k); + +// Bank 85 +int DisplayMessageBox_Poll(uint16 a); +void DisplayMessageBox(uint16 a); +CoroutineRet DisplayMessageBox_Async(uint16 a); +uint16 WriteMessageTilemap(void); +void ClearMessageBoxBg3Tilemap(void); +CoroutineRet CloseMessageBox_Async(void); +void DrawRunButtonAndSetupPpuForLargeMessageBox(void); +void DrawShootButtonAndSetupPpuForLargeMessageBox(void); +void DrawSpecialButtonAndSetupPpuForLargeMessageBox(uint16 a); +CoroutineRet HandleMessageBoxInteraction_Async(void); +void InitializeMessageBox(void); +void InitializePpuForMessageBoxes(void); +CoroutineRet OpenMessageBox_Async(void); +void PlaySavingSoundEffect(void); +void RestorePpuForMessageBox(void); +void SetupMessageBoxBg3YscrollHdma(void); +void SetupPpuForActiveMessageBox(void); +void SetupPpuForLargeMessageBox(void); +void SetupPpuForSmallMessageBox(void); +void ToggleSaveConfirmationSelection(void); +void WriteLargeMessageBoxTilemap(void); +void MsgBoxMakeHdmaTable(void); +void WriteSmallMessageBoxTilemap(void); + +// Bank 86 +uint16 CheckIfEnemyProjectileIsOffScreen(uint16 k); +uint16 EnemyProjInstr_SetPreInstrA(uint16 k, uint16 j); +uint16 EprojInstr_868D55(uint16 k, uint16 j); +uint16 EprojInstr_868D99(uint16 k, uint16 j); +uint16 EprojInstr_9270(uint16 k, uint16 j); +uint16 EprojInstr_95BA(uint16 k, uint16 j); +uint16 EprojInstr_95ED(uint16 k, uint16 j); +uint16 EprojInstr_9620(uint16 k, uint16 j); +uint16 EprojInstr_980E(uint16 k, uint16 j); +uint16 EprojInstr_A3BE(uint16 k, uint16 j); +uint16 EprojInstr_Add12ToY(uint16 k, uint16 j); +uint16 EprojInstr_AddToYpos(uint16 k, uint16 j); +uint16 EprojInstr_AssignNewN00bTubeShardVelocity(uint16 k, uint16 j); +uint16 EprojInstr_BB24(uint16 k, uint16 j); +uint16 EprojInstr_CalculateDirectionTowardsSamus(uint16 k, uint16 j); +uint16 EprojInstr_CallFunc(uint16 k, uint16 j); +uint16 EprojInstr_CallFuncWithParam(uint16 k, uint16 j); +uint16 EprojInstr_ClearPreInstr(uint16 k, uint16 j); +uint16 EprojInstr_ClearProjectileProperties(uint16 k, uint16 j); +uint16 EprojInstr_D15C(uint16 k, uint16 j); +uint16 EprojInstr_D1B6(uint16 k, uint16 j); +uint16 EprojInstr_D1C7(uint16 k, uint16 j); +uint16 EprojInstr_D1CE(uint16 k, uint16 j); +uint16 EprojInstr_D62A(uint16 k, uint16 j); +uint16 EprojInstr_DC5A(uint16 k, uint16 j); +uint16 EprojInstr_DFEA(uint16 k, uint16 j); +uint16 EprojInstr_DecTimerAndGotoIfNonZero(uint16 k, uint16 j); +uint16 EprojInstr_DecTimerAndGotoRelIfNonZero(uint16 k, uint16 j); +uint16 EprojInstr_Delete(uint16 k, uint16 j); +uint16 EprojInstr_DisableCollisionWithSamus(uint16 k, uint16 j); +uint16 EprojInstr_DisableCollisionWithSamusProj(uint16 k, uint16 j); +uint16 EprojInstr_DisableCollisionsWithSamus(uint16 k, uint16 j); +uint16 EprojInstr_ECE3(uint16 k, uint16 j); +uint16 EprojInstr_ED17(uint16 k, uint16 j); +uint16 EprojInstr_EEAF(uint16 k, uint16 j); +uint16 EprojInstr_Earthquake(uint16 k, uint16 j); +uint16 EprojInstr_EnableCollisionWithSamus(uint16 k, uint16 j); +uint16 EprojInstr_EnableCollisionWithSamusProj(uint16 k, uint16 j); +uint16 EprojInstr_Goto(uint16 k, uint16 j); +uint16 EprojInstr_GotoDependingOnXDirection(uint16 k, uint16 j); +uint16 EprojInstr_GotoIfFunc1(uint16 k, uint16 j); +uint16 EprojInstr_GotoRel(uint16 k, uint16 j); +uint16 EprojInstr_GotoWithProbability25(uint16 k, uint16 j); +uint16 EprojInstr_HandleRespawningEnemy(uint16 k, uint16 j); +uint16 EprojInstr_MotherBrainPurpleBreathIsActive(uint16 k, uint16 j); +uint16 EprojInstr_MoveRandomlyWithinRadius(uint16 k, uint16 j); +uint16 EprojInstr_MoveY_Minus4(uint16 k, uint16 j); +uint16 EprojInstr_QueueMusic(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx1_Max1(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx1_Max15(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx1_Max3(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx1_Max6(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx1_Max9(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx2_24(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx2_9(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx2_B(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx2_Max1(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx2_Max15(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx2_Max3(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx2_Max6(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx2_Max9(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx3_Max1(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx3_Max15(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx3_Max3(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx3_Max6(uint16 k, uint16 j); +uint16 EprojInstr_QueueSfx3_Max9(uint16 k, uint16 j); +uint16 EprojInstr_ResetXYpos1(uint16 k, uint16 j); +uint16 EprojInstr_ResetXYpos2(uint16 k, uint16 j); +uint16 EprojInstr_SetHighPriority(uint16 k, uint16 j); +uint16 EprojInstr_SetLowPriority(uint16 k, uint16 j); +uint16 EprojInstr_SetN00bTubeShardX(uint16 k, uint16 j); +uint16 EprojInstr_SetPreInstrAndRun(uint16 k, uint16 j); +uint16 EprojInstr_SetPreInstr_(uint16 k, uint16 j); +uint16 EprojInstr_SetProjectileProperties(uint16 k, uint16 j); +uint16 EprojInstr_SetTimer(uint16 k, uint16 j); +uint16 EprojInstr_SetToDieOnContact(uint16 k, uint16 j); +uint16 EprojInstr_SetToNotDieOnContact(uint16 k, uint16 j); +uint16 EprojInstr_SetXvelRandom(uint16 k, uint16 j); +uint16 EprojInstr_SetXyRadius(uint16 k, uint16 j); +uint16 EprojInstr_SetXyRadiusZero(uint16 k, uint16 j); +uint16 EprojInstr_SetYVel(uint16 k, uint16 j); +uint16 EprojInstr_Sleep(uint16 k, uint16 j); +uint16 EprojInstr_SpawnEnemyDrops(uint16 k, uint16 j); +uint16 EprojInstr_SpawnEnemyDrops_0(uint16 k, uint16 j); +uint16 EprojInstr_SpawnSporesEproj(uint16 k, uint16 j); +uint16 EprojInstr_SpawnTourianStatueUnlockingParticle(uint16 k, uint16 j); +uint16 EprojInstr_SpawnTourianStatueUnlockingParticleTail(uint16 k, uint16 j); +uint16 EprojInstr_SwitchJump(uint16 k, uint16 j); +uint16 EprojInstr_UserPalette0(uint16 k, uint16 j); +uint16 EprojInstr_WriteColorsToPalette(uint16 k, uint16 j); +uint16 EprojPreInstrHelper_DBF2_Func2(uint16 k); +uint16 EprojPreInstrHelper_SpikeShootingPlantSpikes_Func2(uint16 k); +uint16 EprojPreInstr_NorfairLavaquakeRocks_Inner2(uint16 k); +uint16 Eproj_FuncE722(uint16 k); +uint16 Eproj_PhantomFireballs_Func2(uint16 k); +uint16 Math_MultByCos(uint16 a); +uint16 Math_MultBySin(uint16 a); +uint16 Math_MultBySinCos(uint16 a); +uint16 MoveEprojWithVelocity(uint16 k); +uint16 MoveEprojWithVelocityX(uint16 k); +uint16 MoveEprojWithVelocityY(uint16 k); +uint16 RandomDropRoutine(uint16 k); +uint16 sub_86B13E(uint16 k, uint16 j); +uint16 sub_86B183(uint16 k, uint16 j); +uint16 sub_86DFA0(uint16 k); +uint16 sub_86E0B0(uint16 k); +uint16 sub_86EC18(uint16 k); +uint8 CheckForBlueRingCollisionWithRoom(uint16 k); +uint8 CheckForCollisionWithShitroid_DoubleRet(uint16 k); +uint8 EnemyProjectileBlockCollisition_CheckHorizontal(uint16 k); +uint8 EnemyProjectileBlockCollisition_CheckVertical(uint16 k); +uint8 EnemyProjectileBlockCollisition_Horiz(uint16 k); +uint8 EnemyProjectileBlockCollisition_Vertical(uint16 k); +uint8 EprojColl_8506(void); +uint8 EprojColl_858E(void); +uint8 EprojColl_85AD(void); +uint8 EprojColl_85C2(uint16 a, uint16 k); +uint8 EprojColl_8676(uint16 a, uint16 k, uint16 j); +uint8 EprojColl_873D(void); +uint8 EprojColl_874E(void); +uint8 EprojColl_ClearCarry(void); +uint8 EprojColl_SetCarry(void); +uint8 EprojColl_Unknown8536(void); +uint8 Eproj_CheckForBombCollisionWithRect(void); +uint8 Eproj_CheckForCollisionWithSamus(uint16 k); +uint8 Eproj_CheckForEnemyCollisionWithRect(uint16 k); +uint8 Eproj_MotherBrainRoomTurretBullets_CheckIfTurretOnScreen(uint16 k); +uint8 MotherBrainBomb_Bomb_CollDetect_DoubleRet(uint16 k); +uint8 MoveMotherBrainBomb(uint16 k, uint16 a); +void BlueRingContactExplosion(uint16 k); +void ClearEnemyProjectiles(void); +void DisableEnemyProjectiles(void); +void DrawEnemyProjectiles(uint16 k); +void DrawHighPriorityEnemyProjectiles(void); +void DrawLowPriorityEnemyProjectiles(void); +void EnableEnemyProjectiles(void); +void EnemyProjInstr_SetPreInstrB(uint16 k); +void EnemyProjInstr_SpawnEnemyDropsWithDraygonsEyeDrops(uint16 k); +void EnemyProj_Init_0x8aaf(uint16 j); +void EnemyProj_Init_0x8bc2_SkreeDownRight(uint16 j); +void EnemyProj_Init_0x8bd0_SkreeUpRight(uint16 j); +void EnemyProj_Init_0x8bde_SkreeDownLeft(uint16 j); +void EnemyProj_Init_0x8bec_SkreeUpLeft(uint16 j); +void EnemyProj_PreInit_0x8aaf(uint16 k); +void EnemyProj_PreInstr_SkreeParticle(uint16 k); +void EprojColl_8676_Fixed(void); +void EprojIni_TourianStatueUnlockingParticleTail(uint16 j); +void EprojInit_8E6C(uint16 j); +void EprojInit_9634(uint16 j); +void EprojInit_9642_RidleysFireball(uint16 j); +void EprojInit_9660_FireballExplosion(uint16 j); +void EprojInit_966C(uint16 j); +void EprojInit_967A(uint16 j); +void EprojInit_9688(uint16 j); +void EprojInit_9696(uint16 j); +void EprojInit_9734_CeresFallingDebris(uint16 j); +void EprojInit_A379(uint16 j); +void EprojInit_A977(uint16 j); +void EprojInit_AB07(uint16 j); +void EprojInit_BDA2(uint16 j); +void EprojInit_BombTorizoDeathExplosion(uint16 j); +void EprojInit_BombTorizoExplosiveSwipe(uint16 j); +void EprojInit_BombTorizoLowHealthDrool(uint16 j); +void EprojInit_BombTorizoLowHealthExplode(uint16 j); +void EprojInit_BombTorizoLowHealthInitialDrool(uint16 j); +void EprojInit_BombTorizoStatueBreaking(uint16 j); +void EprojInit_BombTorizosChozoOrbs(uint16 j); +void EprojInit_BotwoonsBody(uint16 j); +void EprojInit_BotwoonsSpit(uint16 j); +void EprojInit_CeresElevatorPad(uint16 j); +void EprojInit_CeresElevatorPlatform(uint16 j); +void EprojInit_ClosedDownwardsShotGate(uint16 j); +void EprojInit_ClosedUpwardsShotGate(uint16 j); +void EprojInit_Common(uint16 j, uint16 k, uint16 a); +void EprojInit_CrocomireBridgeCrumbling(uint16 j); +void EprojInit_CrocomireProjectile(uint16 j); +void EprojInit_CrocomireSpikeWallPieces(uint16 j); +void EprojInit_DBF2(uint16 j); +void EprojInit_DraygonsGunk(uint16 j); +void EprojInit_DraygonsWallTurretProjs(uint16 j); +void EprojInit_EnemyDeathExplosion(uint16 j); +void EprojInit_EyeDoorProjectile(uint16 j); +void EprojInit_EyeDoorSmoke(uint16 j); +void EprojInit_EyeDoorSweat(uint16 j); +void EprojInit_F337(uint16 j); +void EprojInit_GoldenTorizoEgg(uint16 j); +void EprojInit_GoldenTorizoEyeBeam(uint16 j); +void EprojInit_GoldenTorizoSuperMissile(uint16 j); +void EprojInit_GoldenTorizosChozoOrbs(uint16 j); +void EprojInit_KagosBugs(uint16 j); +void EprojInit_KiHunterAcidSpitCommon(uint16 k, uint16 j); +void EprojInit_KiHunterAcidSpitLeft(uint16 j); +void EprojInit_KiHunterAcidSpitRight(uint16 j); +void EprojInit_LavaSeahorseFireball(uint16 j); +void EprojInit_LavaThrownByLavaman(uint16 j); +void EprojInit_MaridiaFloatersSpikes(uint16 j); +void EprojInit_MiniKraidSpikes(uint16 j, uint16 a); +void EprojInit_MiniKraidSpikesLeft(uint16 j); +void EprojInit_MiniKraidSpikesRight(uint16 j); +void EprojInit_MiniKraidSpit(uint16 j); +void EprojInit_MotherBrainBomb(uint16 j); +void EprojInit_MotherBrainDeathBeemFired(uint16 j); +void EprojInit_MotherBrainEscapeDoorParticles(uint16 j); +void EprojInit_MotherBrainGlassShatteringShard(uint16 j); +void EprojInit_MotherBrainGlassShatteringSparkle(uint16 j); +void EprojInit_MotherBrainPurpleBreathBig(uint16 j); +void EprojInit_MotherBrainPurpleBreathSmall(uint16 j); +void EprojInit_MotherBrainRainbowBeam(uint16 j); +void EprojInit_MotherBrainRoomTurretBullets(uint16 j); +void EprojInit_MotherBrainRoomTurrets(uint16 j); +void EprojInit_MotherBrainTubeFalling(uint16 j); +void EprojInit_MotherBrainsDeathExplosion(uint16 j); +void EprojInit_MotherBrainsDrool(uint16 j); +void EprojInit_MotherBrainsDrool_Falling(uint16 k); +void EprojInit_MotherBrainsRainbowBeamExplosion(uint16 j); +void EprojInit_N00bTubeCrack(uint16 j); +void EprojInit_N00bTubeReleasedAirBubbles(uint16 j); +void EprojInit_N00bTubeShards(uint16 j); +void EprojInit_NamiFuneFireball(uint16 j); +void EprojInit_NamiFuneFireball_MoveX1(uint16 k); +void EprojInit_NamiFuneFireball_MoveX2(uint16 k); +void EprojInit_NorfairLavaquakeRocks(uint16 j); +void EprojInit_NuclearWaffleBody(uint16 j); +void EprojInit_PhantoonDestroyableFireballs(uint16 j); +void EprojInit_PhantoonStartingFireballs(uint16 j); +void EprojInit_PirateClaw(uint16 j); +void EprojInit_PirateMotherBrainLaser(uint16 j); +void EprojInit_RocksFallingKraidCeiling(uint16 j); +void EprojInit_RocksKraidSpits(uint16 j); +void EprojInit_RocksWhenKraidRises(uint16 j); +void EprojInit_SaveStationElectricity(uint16 j); +void EprojInit_ShaktoolAttackFrontCircle(uint16 k); +void EprojInit_ShaktoolAttackMiddleBackCircle(uint16 j); +void EprojInit_Sparks(uint16 j); +void EprojInit_SpawnedGate_Common(uint16 j, uint16 a); +void EprojInit_SpawnedShotGate(uint16 j); +void EprojInit_SporeSpawnStalk(uint16 j); +void EprojInit_SporeSpawners(uint16 j); +void EprojInit_Spores(uint16 j); +void EprojInit_TimeBombSetJapaneseText(uint16 j); +void EprojInit_TorizoLandingDustCloudLeftFoot(uint16 j); +void EprojInit_TorizoSonicBoom(uint16 j); +void EprojInit_TourianEscapeShaftFakeWallExplode(uint16 j); +void EprojInit_TourianLandingDustCloudsRightFoot(uint16 j); +void EprojInit_TourianStatueBaseDecoration(uint16 j); +void EprojInit_TourianStatueDustClouds(uint16 j); +void EprojInit_TourianStatueEyeGlow(uint16 j); +void EprojInit_TourianStatuePhantoon(uint16 j); +void EprojInit_TourianStatueRidley(uint16 j); +void EprojInit_TourianStatueSoul(uint16 j); +void EprojInit_TourianStatueUnlockingParticle(uint16 j); +void EprojInit_TourianStatueUnlockingParticleWaterSplash(uint16 j); +void EprojInit_WalkingLavaSeahorseFireball(uint16 j); +void EprojInit_WreckedShipChozoSpikeFootsteps(uint16 j); +void EprojInit_WreckedShipRobotLaserCommon(uint16 k, uint16 j); +void EprojInit_WreckedShipRobotLaserDown(uint16 j); +void EprojInit_WreckedShipRobotLaserHorizontal(uint16 j); +void EprojInit_WreckedShipRobotLaserUp(uint16 j); +void EprojInit_YappingMawsBody(uint16 j); +void EprojInst_DustCloudOrExplosion(uint16 j); +void EprojPowerBombCollision(uint16 k); +void EprojPreInit_MiniKraidSpit(uint16 k); +void EprojPreInit_MotherBrainsDeathExplosion_0(uint16 k); +void EprojPreInstrHelper_SpikeShootingPlantSpikes_Func1(uint16 k); +void EprojPreInstr_8DCA(uint16 k); +void EprojPreInstr_8E6C(uint16 k); +void EprojPreInstr_9634(uint16 k); +void EprojPreInstr_9642_RidleysFireball(uint16 k); +void EprojPreInstr_966C(uint16 k); +void EprojPreInstr_9688(uint16 k); +void EprojPreInstr_96A4(uint16 k); +void EprojPreInstr_96C0(uint16 k); +void EprojPreInstr_96CE(uint16 k); +void EprojPreInstr_9734_CeresFallingDebris(uint16 k); +void EprojPreInstr_A977(uint16 k); +void EprojPreInstr_AB07(uint16 k); +void EprojPreInstr_B237(uint16 k); +void EprojPreInstr_BA42(uint16 k); +void EprojPreInstr_BE12(uint16 k); +void EprojPreInstr_BombTorizosChozoOrbs(uint16 k); +void EprojPreInstr_BotwoonsBody(uint16 k); +void EprojPreInstr_BotwoonsSpit(uint16 k); +void EprojPreInstr_C84D(uint16 k); +void EprojPreInstr_CeresElevatorPad(uint16 k); +void EprojPreInstr_CeresElevatorPlatform(uint16 k); +void EprojPreInstr_CrocomireBridgeCrumbling(uint16 k); +void EprojPreInstr_CrocomireProjectile(uint16 k); +void EprojPreInstr_CrocomireSpikeWallPieces(uint16 k); +void EprojPreInstr_D0EC(uint16 k); +void EprojPreInstr_D128(uint16 k); +void EprojPreInstr_DBF2(uint16 k); +void EprojPreInstr_DBF2_Func1(uint16 k); +void EprojPreInstr_DBF2_MoveX1(uint16 k); +void EprojPreInstr_DBF2_MoveX2(uint16 k); +void EprojPreInstr_DraygonsGunk_8E0F(uint16 k); +void EprojPreInstr_DraygonsTurret_8DFF(uint16 k); +void EprojPreInstr_DustCloudOrExplosion(uint16 k); +void EprojPreInstr_E605(uint16 k); +void EprojPreInstr_Empty(uint16 k); +void EprojPreInstr_Empty2(uint16 k); +void EprojPreInstr_EyeDoorProjectile(uint16 k); +void EprojPreInstr_EyeDoorSweat(uint16 k); +void EprojPreInstr_GoldenTorizoEgg(uint16 k); +void EprojPreInstr_GoldenTorizoEyeBeam(uint16 k); +void EprojPreInstr_GoldenTorizoSuperMissile(uint16 k); +void EprojPreInstr_GoldenTorizosChozoOrbs(uint16 k); +void EprojPreInstr_KagosBugs(uint16 k); +void EprojPreInstr_KagosBugs_Func1(uint16 k); +void EprojPreInstr_KagosBugs_Func2(uint16 k); +void EprojPreInstr_KraidRocks(uint16 k); +void EprojPreInstr_MaridiaFloatersSpikes(uint16 k); +void EprojPreInstr_MiniKraidSpikes(uint16 k); +void EprojPreInstr_MotherBrainBomb(uint16 k); +void EprojPreInstr_MotherBrainGlassShatteringShard(uint16 k); +void EprojPreInstr_MotherBrainRainbowBeam(uint16 k); +void EprojPreInstr_MotherBrainRoomTurretBullets(uint16 k); +void EprojPreInstr_MotherBrainRoomTurrets(uint16 k); +void EprojPreInstr_MotherBrainTubeFalling(uint16 k); +void EprojPreInstr_MotherBrainsExplodedDoorParticles(uint16 k); +void EprojPreInstr_MotherBrainsRainbowBeamExplosion(uint16 k); +void EprojPreInstr_N00bTubeShards(uint16 k); +void EprojPreInstr_NamiFuneFireball(uint16 k); +void EprojPreInstr_NorfairLavaquakeRocks(uint16 k); +void EprojPreInstr_NorfairLavaquakeRocks_Inner(uint16 k); +void EprojPreInstr_PhantoonDestroyableFireballs(uint16 k); +void EprojPreInstr_PhantoonDestroyableFireballs_2(uint16 k); +void EprojPreInstr_PhantoonDestroyableFireballs_3(uint16 k); +void EprojPreInstr_PhantoonStartingFireballs(uint16 k); +void EprojPreInstr_PhantoonStartingFireballs2(uint16 k); +void EprojPreInstr_PhantoonStartingFireballs3(uint16 k); +void EprojPreInstr_PhantoonStartingFireballsB(uint16 k); +void EprojPreInstr_PhantoonStartingFireballsB_2(uint16 k); +void EprojPreInstr_Pickup(uint16 k); +void EprojPreInstr_PirateClawThrownLeft(uint16 k); +void EprojPreInstr_PirateClawThrownRight(uint16 k); +void EprojPreInstr_PirateMotherBrainLaser_MoveLeft(uint16 k); +void EprojPreInstr_PirateMotherBrainLaser_MoveRight(uint16 k); +void EprojPreInstr_PrePhantomRoom(uint16 j); +void EprojPreInstr_RocksFallingKraidCeiling(uint16 k); +void EprojPreInstr_Sparks(uint16 k); +void EprojPreInstr_SpikeShootingPlantSpikes(uint16 k); +void EprojPreInstr_SpikeShootingPlantSpikes_0_MoveX1(uint16 j); +void EprojPreInstr_SpikeShootingPlantSpikes_1_MoveY1(uint16 j); +void EprojPreInstr_SpikeShootingPlantSpikes_2_MoveX2(uint16 j); +void EprojPreInstr_SpikeShootingPlantSpikes_4_MoveY2(uint16 j); +void EprojPreInstr_SpikeShootingPlantSpikes_6_MoveX1Y1(uint16 j); +void EprojPreInstr_SpikeShootingPlantSpikes_7_MoveX2Y1(uint16 j); +void EprojPreInstr_SpikeShootingPlantSpikes_8_MoveX1Y2(uint16 j); +void EprojPreInstr_SpikeShootingPlantSpikes_9_MoveX2Y2(uint16 j); +void EprojPreInstr_SpikeShootingPlantSpikes_MoveX1(uint16 k); +void EprojPreInstr_SpikeShootingPlantSpikes_MoveX2(uint16 k); +void EprojPreInstr_SpikeShootingPlantSpikes_MoveY1(uint16 k); +void EprojPreInstr_SpikeShootingPlantSpikes_MoveY2(uint16 k); +void EprojPreInstr_SporeSpawners(uint16 k); +void EprojPreInstr_Spores(uint16 k); +void EprojPreInstr_TimeBombSetJapaneseText(uint16 k); +void EprojPreInstr_TorizoSonicBoom(uint16 k); +void EprojPreInstr_TourianStatueSoul(uint16 k); +void EprojPreInstr_TourianStatueStuff(uint16 k); +void EprojPreInstr_TourianStatueUnlockingParticle(uint16 k); +void EprojPreInstr_TourianStatueUnlockingParticleWaterSplash(uint16 k); +void EprojPreInstr_WalkingLavaSeahorseFireball(uint16 k); +void EprojPreInstr_WreckedShipRobotLaser(uint16 k); +void EprojPreInstr_nullsub_297(void); +void EprojPreInstr_nullsub_83(void); +void EprojPreInstr_nullsub_98(void); +void EprojPreInstr_nullsub_99(void); +void EprojRunAll(void); +void EprojRunOne(uint16 k); +void Eproj_AngleToSamus(uint16 j); +void Eproj_BotwonsBodyFunction_Dying(uint16 k); +void Eproj_BotwonsBodyFunction_Dying2(uint16 k); +void Eproj_BotwonsBodyFunction_DyingFalling(uint16 k); +void Eproj_BotwoonsBodyHurtFlashHandling1(uint16 k); +void Eproj_BotwoonsBodyHurtFlashHandling2(uint16 j); +void Eproj_BotwoonsBody_Main(uint16 k); +void Eproj_DeleteIfYposOutside(uint16 k); +void Eproj_Earthqhake5(uint16 k); +void Eproj_FuncE73E_MoveXY(uint16 k); +void Eproj_InitForCollDetect(uint16 k); +void Eproj_InitXYVelRandom(uint16 j, uint16 k); +void Eproj_LavaThrownByLavaman_MoveX1(uint16 k); +void Eproj_LavaThrownByLavaman_MoveX2(uint16 k); +void Eproj_MotherBrainRoomTurretBullets_Func2(uint16 k); +void Eproj_MotherBrainsBlueRingLasers(uint16 j); +void Eproj_MoveToBlueRingSpawnPosition(uint16 k); +void Eproj_NamiFuneFireball_After(uint16 k); +void Eproj_NorfairLavaquakeRocks_Func1(uint16 k); +void Eproj_NorfairLavaquakeRocks_Func2(uint16 k); +void Eproj_NorfairLavaquakeRocks_Func3(uint16 k); +void Eproj_PhantomFireballs_Func1(uint16 j, uint16 a); +void Eproj_Pickup_BigHealth(void); +void Eproj_Pickup_Missiles(void); +void Eproj_Pickup_PowerBombs(void); +void Eproj_Pickup_SmallHealth(void); +void Eproj_Pickup_SuperMissiles(void); +void Eproj_SetVelTowardsSamus1(uint16 k); +void Eproj_SetVelTowardsSamus2(uint16 k); +void Eproj_SetXvelRandom(uint16 k); +void Eproj_SetYvelRandom(uint16 k); +void GetValuesForScreenShaking(void); +void Math_Mult16U(void); +void MotherBrainTubeFallingFunc_Falling(uint16 k); +void MotherBrainTubeFallingFunc_GenerateExplosion(uint16 k); +void QueueSmallExplosionSfx(void); +void RespawnEnemy(uint16 a); +void SetAreaDependentEprojProperties(uint16 j); +void SetAreaDependentEprojPropertiesEx(uint16 k, uint16 j); +void SpawnEnemyProjectileWithGfx(uint16 a, uint16 k, uint16 j); +void SpawnEnemyProjectileWithRoomGfx(uint16 j, uint16 a); +void SpawnMotherBrainDeathBeam(uint16 k); +void sub_8690B3(uint16 k); +void sub_869DA5(uint16 k); +void sub_86A301(uint16 j); +void sub_86A887(uint16 k); +void sub_86A91A(uint16 v0); +void sub_86B0B9(uint16 k); +void sub_86B0DD(uint16 k); +void sub_86B279(uint16 k, uint16 a); +void sub_86B535(uint16 k); +void sub_86BB30(uint16 j); +void sub_86C320(uint16 k); +void sub_86C42E(uint16 k); +void sub_86C605(uint16 j); +void sub_86CFD5(uint16 k); +void sub_86CFE6(uint16 k); +void sub_86CFF8(uint16 k); +void sub_86D7BF(uint16 k); +void sub_86D7DE(uint16 k); +void sub_86D83D(uint16 k); +void sub_86D89F(uint16 k); +void sub_86D8DF(uint16 k); +void sub_86D992(uint16 k); +void sub_86DCC3(uint16 j); +void sub_86E049(uint16 k); +void sub_86E0A4(uint16 k); +void sub_86EC0C(uint16 k); + +// Bank 87 +uint16 AnimtilesInstr_Clear3PaletteColors(uint16 k, uint16 j); +uint16 AnimtilesInstr_DecrementTimerAndGoto(uint16 k, uint16 j); +uint16 AnimtilesInstr_DecrementTimerAndGotoRel(uint16 k, uint16 j); +uint16 AnimtilesInstr_Delete(uint16 k, uint16 j); +uint16 AnimtilesInstr_Goto(uint16 k, uint16 j); +uint16 AnimtilesInstr_GotoIfBossBitSet(uint16 k, uint16 j); +uint16 AnimtilesInstr_GotoIfBossBitSetInArea(uint16 k, uint16 j); +uint16 AnimtilesInstr_GotoIfEventHappened(uint16 k, uint16 j); +uint16 AnimtilesInstr_GotoIfTourianStatueBusy(uint16 k, uint16 j); +uint16 AnimtilesInstr_GotoRel(uint16 k, uint16 j); +uint16 AnimtilesInstr_QueueMusic(uint16 k, uint16 j); +uint16 AnimtilesInstr_QueueSfx1(uint16 k, uint16 j); +uint16 AnimtilesInstr_QueueSfx2(uint16 k, uint16 j); +uint16 AnimtilesInstr_QueueSfx3(uint16 k, uint16 j); +uint16 AnimtilesInstr_SetBossBit(uint16 k, uint16 j); +uint16 AnimtilesInstr_SetEventHappened(uint16 k, uint16 j); +uint16 AnimtilesInstr_SetTimer(uint16 k, uint16 j); +uint16 AnimtilesInstr_SpawnPalfxObj(uint16 k, uint16 j); +uint16 AnimtilesInstr_SpawnTourianStatueEyeGlow(uint16 k, uint16 j); +uint16 AnimtilesInstr_SpawnTourianStatueSoul(uint16 k, uint16 j); +uint16 AnimtilesInstr_TourianStatueClearState(uint16 k, uint16 j); +uint16 AnimtilesInstr_TourianStatueSetState(uint16 k, uint16 j); +uint16 AnimtilesInstr_WaitUntilAreaBossDead_DoubleRet(uint16 k, uint16 j); +uint16 AnimtilesInstr_Write8PaletteColors(uint16 k, uint16 j); +void AnimtilesHandler(void); +void ClearAnimtiles(void); +void DisableAnimtiles(void); +void EnableAnimtiles(void); +void ProcessAnimtilesObject(void); +void SpawnAnimtiles(uint16 j); + +// Bank 88 +uint16 CalculatePowerBombHdmaScaled_LeftOfScreen(uint16 k, uint16 j, uint8 multval); +uint16 CalculatePowerBombHdmaScaled_OnScreen(uint16 k, uint16 j, uint8 multval); +uint16 CalculatePowerBombHdmaScaled_RightOfScreen(uint16 k, uint16 j, uint8 multval); +uint16 HdmaobjInsr_ConfigTitleSequenceGradientHDMA(uint16 k, uint16 j); +uint16 HdmaobjInstr_1938_RandomNumber(uint16 k, uint16 j); +uint16 HdmaobjInstr_B3A9(uint16 k, uint16 j); +uint16 HdmaobjInstr_CallFarFunc(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_ClearPreInstr(uint16 k, uint16 j); +uint16 HdmaobjInstr_DecrementAndGoto(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_DecrementAndGotoRel(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_Delete(uint16 k, uint16 j); +uint16 HdmaobjInstr_E4BD(uint16 k, uint16 j); +uint16 HdmaobjInstr_EC9F_ClearVars(uint16 k, uint16 j); +uint16 HdmaobjInstr_Goto(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_GotoIfEventHappened(uint16 k, uint16 j); +uint16 HdmaobjInstr_GotoRel(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_InitMorphBallEyeBeamHdma(uint16 k, uint16 j); +uint16 HdmaobjInstr_SetFlagB(uint16 k, uint16 j); +uint16 HdmaobjInstr_SetFlagB_Copy(uint16 k, uint16 j); +uint16 HdmaobjInstr_SetFlagB_Copy2(uint16 k, uint16 j); +uint16 HdmaobjInstr_SetFlagB_Copy3(uint16 k, uint16 j); +uint16 HdmaobjInstr_SetHdmaControl(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_SetHdmaTableBank(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_SetHdmaTablePtr(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_SetHdmaTarget(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_SetIndirectHdmaDataBank(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_SetPreInstr(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_SetTimer(uint8 db, uint16 k, uint16 j); +uint16 HdmaobjInstr_SetVideoMode1(uint16 k, uint16 j); +uint16 HdmaobjInstr_Skip(uint16 k, uint16 j); +uint16 HdmaobjInstr_Sleep(uint16 k, uint16 j); +uint16 LayerBlendFunc_10(uint16 j); +uint16 LayerBlendFunc_14(uint16 j); +uint16 LayerBlendFunc_16(uint16 j); +uint16 LayerBlendFunc_18(uint16 j); +uint16 LayerBlendFunc_1A(uint16 j); +uint16 LayerBlendFunc_1C(uint16 j); +uint16 LayerBlendFunc_24(uint16 j); +uint16 LayerBlendFunc_26(uint16 j); +uint16 LayerBlendFunc_28(uint16 j); +uint16 LayerBlendFunc_2A(uint16 j); +uint16 LayerBlendFunc_2C(uint16 j); +uint16 LayerBlendFunc_2E(uint16 j); +uint16 LayerBlendFunc_32(uint16 j); +uint16 LayerBlendFunc_34(uint16 j); +uint16 LayerBlendFunc_4_PhantoonIntro(uint16 j); +uint16 LayerBlendFunc_6(uint16 j); +uint16 LayerBlendFunc_8(uint16 j); +uint16 LayerBlendFunc_A(uint16 j); +uint16 LayerBlendFunc_C(uint16 j); +uint16 MotherBrainRisingHdmaObject(void); +uint16 SetupSomeHdmaTablesBG3(void); +uint16 SpawnHdmaObject(uint8 db, const void* p); +uint16 SpawnHdmaObjectInner(uint16 k, uint16 *p); +uint16 SpawnMotherBrainRainbowBeamHdma(void); +uint16 nullsub_10(uint16 j); +uint16 nullsub_11(uint16 j); +uint16 nullsub_9(uint16 j); +uint8 AdvanceSuitPickupColorMathSubscreenToWhite(void); +uint8 AdvanceSuitPickupColorMathToBlue(void); +uint8 AdvanceSuitPickupColorMathToOrange(void); +uint8 GravitySuitPickup_3(void); +uint8 GravitySuitPickup_6(void); +uint8 RaiseOrLowerFx(void); +uint8 VariaSuitPickup_0_LightBeamAppears(void); +uint8 VariaSuitPickup_1(void); +uint8 VariaSuitPickup_2_LightBeamWidens(void); +uint8 VariaSuitPickup_3(void); +uint8 VariaSuitPickup_4_LightBeamShrinks(void); +uint8 VariaSuitPickup_5_LightBeamDissipates(void); +uint8 VariaSuitPickup_6(void); +void CalculateCrystalFlashHdmaDataTablesScaled_LeftOfScreen(uint16 k, uint16 j); +void CalculateCrystalFlashHdmaDataTablesScaled_OnScreen(uint16 k, uint16 j); +void CalculateCrystalFlashHdmaDataTablesScaled_RightOfScreen(uint16 k, uint16 j); +void CalculateCrystalFlashHdmaObjectTablePtrs(uint16 k); +void CalculatePowerBombHdmaObjectTablePtrs(uint16 k); +void CalculatePowerBombHdmaTablePointers(uint16 k); +void CalculatePowerBombHdma_LeftOfScreen(uint16 k, uint16 j); +void CalculatePowerBombHdma_OnScreen(uint16 k, uint16 j); +void CalculatePowerBombHdma_RightOfScreen(uint16 k, uint16 j); +void CalculateXrayHdmaTable(void); +void CinematicFunction_Intro_Func133(void); +void CrystalFlashCleanup(uint16 k); +void CrystalFlashSetupPart1(void); +void CrystalFlashSetupPart2(void); +void DamageSamusInTopRow(void); +void DisableHdmaObjects(void); +void EnableHdmaObjects(void); +void ExpandingContractingHdmaEffect(void); +void FxHandleTide(void); +void FxRisingFunction_C428_WaterNormal(void); +void FxRisingFunction_LavaAcid(void); +void FxRisingFunction_LavaAcid_Raising(void); +void FxRisingFunction_LavaAcid_WaitToRise(void); +void FxRisingFunction_WaterRising(void); +void FxRisingFunction_WaterWaitToRise(void); +void FxTypeFunc_20(void); +void FxTypeFunc_22_ScrollingSky(void); +void FxTypeFunc_24(void); +void FxTypeFunc_26_TourianEntranceStatue(void); +void FxTypeFunc_28_CeresRidley(void); +void FxTypeFunc_2C_Haze(void); +void FxTypeFunc_2_Lava(void); +void FxTypeFunc_4_Acid(void); +void FxTypeFunc_6_Water(void); +void FxTypeFunc_8_Spores(void); +void FxTypeFunc_A_Rain(void); +void FxTypeFunc_C(void); +void FxTypeFunc_CeresElevator(void); +void HandleEarthquakeSoundEffect(void); +void HandleLayerBlendingPowerBomb(uint16 j); +void HandleLayerBlendingXrayCanShowBlocks(void); +void HandleLayerBlendingXrayCantShowBlocks(void); +void HandleLayerBlendingXrayFirefleaRoom(void); +void HandleMovingXrayUpDown(void); +void Handle_LavaAcidBG2YScroll_Func1(uint16 k); +void Handle_LavaAcidBG2YScroll_Func2(uint16 k); +void Handle_LavaAcidBG2YScroll_Func3(uint16 k); +void HdmaFunc_A786(uint16 k); +void HdmaObjectHandler(void); +void HdmaobjInstructionHandler(uint16 k); +void HdmaobjPreInstr_BG3Xscroll(uint16 k); +void HdmaobjPreInstr_Backdrop_TitleSequenceGradient(uint16 k); +void HdmaobjPreInstr_BombTorizoHazeColorMathBgColor(uint16 k); +void HdmaobjPreInstr_CheckLotsOfEventsHappened(uint16 k); +void HdmaobjPreInstr_ColorMathControlB_TitleGradient(uint16 k); +void HdmaobjPreInstr_CrystalFlash_CustomLayerBlend(uint16 k); +void HdmaobjPreInstr_CrystalFlash_Stage1_Explosion(uint16 k); +void HdmaobjPreInstr_CrystalFlash_Stage2_AfterGlow(uint16 k); +void HdmaobjPreInstr_DC23(uint16 k); +void HdmaobjPreInstr_DC69(uint16 k); +void HdmaobjPreInstr_DCBA(uint16 k); +void HdmaobjPreInstr_DF94(uint16 k); +void HdmaobjPreInstr_E449(uint16 k); +void HdmaobjPreInstr_E567(uint16 k); +void HdmaobjPreInstr_E7BC(uint16 k); +void HdmaobjPreInstr_E9E6(uint16 k); +void HdmaobjPreInstr_EA3C(uint16 k); +void HdmaobjPreInstr_EACB(uint16 k); +void HdmaobjPreInstr_ECB6(uint16 k); +void HdmaobjPreInstr_FirefleaBG3XScroll(uint16 k); +void HdmaobjPreInstr_FogBG3Scroll(uint16 k); +void HdmaobjPreInstr_FxType22_BG3Yscroll(uint16 k); +void HdmaobjPreInstr_GravitySuitPickup(uint16 k); +void HdmaobjPreInstr_HazeColorMathSubscreen_CeresRidleyAlive(uint16 k); +void HdmaobjPreInstr_HazeColorMathSubscreen_CeresRidleyDead(uint16 k); +void HdmaobjPreInstr_HazeColorMathSubscreen_FadedIn(uint16 k); +void HdmaobjPreInstr_HazeColorMathSubscreen_FadingIn(uint16 k); +void HdmaobjPreInstr_HazeColorMathSubscreen_FadingOut(uint16 k); +void HdmaobjPreInstr_IntroCutsceneCrossfade(uint16 k); +void HdmaobjPreInstr_LavaAcidBG2YScroll(uint16 k); +void HdmaobjPreInstr_LavaAcidBG3YScroll(uint16 k); +void HdmaobjPreInstr_PowerBombExplode_ExplosionWhite(uint16 k); +void HdmaobjPreInstr_PowerBombExplode_ExplosionYellow(uint16 k); +void HdmaobjPreInstr_PowerBombExplode_PreExplosionWhite(uint16 k); +void HdmaobjPreInstr_PowerBombExplode_PreExplosionYellow(uint16 k); +void HdmaobjPreInstr_PowerBombExplode_SetWindowConf(uint16 k); +void HdmaobjPreInstr_PowerBombExplode_Stage5_Afterglow(uint16 k); +void HdmaobjPreInstr_RainBg3Scroll(uint16 k); +void HdmaobjPreInstr_SkyLandBG2Xscroll(uint16 k); +void HdmaobjPreInstr_SkyLandBG2Xscroll2(uint16 k); +void HdmaobjPreInstr_SkyLandBG2XscrollInner(uint16 k); +void HdmaobjPreInstr_SporesBG3Xscroll(uint16 k); +void HdmaobjPreInstr_VariaSuitPickup(uint16 k); +void HdmaobjPreInstr_WaterBG2XScroll(uint16 k); +void HdmaobjPreInstr_WaterBG2XScroll_Func1(uint16 k); +void HdmaobjPreInstr_WaterBG2XScroll_Func2(uint16 k); +void HdmaobjPreInstr_WaterBG3XScroll(uint16 k); +void HdmaobjPreInstr_Xray(uint16 k); +void HdmaobjPreInstr_XrayFunc0_NoBeam(uint16 k); +void HdmaobjPreInstr_XrayFunc1_BeamWidening(uint16 k); +void HdmaobjPreInstr_XrayFunc2_FullBeam(uint16 k); +void HdmaobjPreInstr_XrayFunc3_DeactivateBeam(uint16 k); +void HdmaobjPreInstr_XrayFunc4_DeactivateBeam(uint16 k); +void HdmaobjPreInstr_XrayFunc5_DeactivateBeam(uint16 k); +void Hdmaobj_CleanUpTryCrystalFlash(uint16 k); +void Hdmaobj_ExplodeWhite(void); +void Hdmaobj_ExplodeYellow(void); +void Hdmaobj_PreExplodeWhite(void); +void Hdmaobj_PreExplodeYellow(void); +void InitializeLayerBlending(void); +void InitializeRainbowBeam(void); +void InitializeSpecialEffectsForNewRoom(void); +void LayerBlendPowerBombFunc_0(void); +void LayerBlendPowerBombFunc_4(void); +void LayerBlendPowerBombFunc_6(void); +void LayerBlendingHandler(void); +void MoveXrayDown(void); +void MoveXrayUp(void); +void PauseHook_Empty(void); +void RoomCode_ScrollingSkyLand(void); +void RoomMainAsm_ScrollingSky(void); +void RoomMainAsm_ScrollingSkyOcean(void); +void RoomSetupAsm_ScrollingSkyOcean(void); +void SpawnBG3ScrollHdmaObject(void); +void SpawnBombTorizoHaze(void); +void SpawnCrystalFlashHdmaObjs(void); +void SpawnHdmaObjectToSlot0xA(uint8 db, const void* p); +void SpawnIntroCutsceneCrossfadeHdma(void); +void SpawnMorphBallEyeBeamHdma(void); +void SpawnPowerBombExplosion(void); +void SpawnTitleScreenGradientObjs(void); +void WaitUntilEndOfVblankAndClearHdma(void); + +void sub_8882AC(void); +void sub_88D916(void); +void sub_88DA9F(uint16 k); +void sub_88DBCB(uint16 k); +void sub_88DE18(uint16 k, uint16 a); +void sub_88DF34(void); +void sub_88DF3D(void); +void sub_88DF46(void); +void sub_88E487(uint16 a); +void sub_88E7ED(void); +void sub_88E987(uint16 k); + +// Bank 89 +void LoadFXHeader(void); +void LoadFxEntry(uint16 a); +void RoomCode_CeresElevatorShaft(void); + +// Bank 8B +uint16 CalcItemPercentageCount(uint16 k, uint16 j); +uint16 CalcSinMult(uint16 k); +uint16 CinematicBgInstr_Delete(uint16 k, uint16 j); +uint16 CinematicBgInstr_Func16(uint16 k, uint16 j); +uint16 CinematicBgInstr_Func17(uint16 k, uint16 j); +uint16 CinematicBgInstr_Goto(uint16 k, uint16 j); +uint16 CinematicBgInstr_HandleCreateJpnText_Page1(uint16 k, uint16 j); +uint16 CinematicBgInstr_HandleCreateJpnText_Page2(uint16 k, uint16 j); +uint16 CinematicBgInstr_HandleCreateJpnText_Page3(uint16 k, uint16 j); +uint16 CinematicBgInstr_HandleCreateJpnText_Page4(uint16 k, uint16 j); +uint16 CinematicBgInstr_HandleCreateJpnText_Page5(uint16 k, uint16 j); +uint16 CinematicBgInstr_SetSomeStuffForSpriteObject_14(uint16 k, uint16 j); +uint16 CinematicBgInstr_SpawnMarkerWaitInput_Page1(uint16 k, uint16 j); +uint16 CinematicBgInstr_SpawnMarkerWaitInput_Page2(uint16 k, uint16 j); +uint16 CinematicBgInstr_SpawnMarkerWaitInput_Page3(uint16 k, uint16 j); +uint16 CinematicBgInstr_SpawnMarkerWaitInput_Page4(uint16 k, uint16 j); +uint16 CinematicBgInstr_SpawnMarkerWaitInput_Page5(uint16 k, uint16 j); +uint16 CinematicCommonInstr_Func69(uint16 k, uint16 j); +uint16 CinematicCommonInstr_Func70(uint16 k, uint16 j); +uint16 CinematicFunction_Intro_Func146(uint16 k, uint16 j); +uint16 CinematicFunction_Intro_Func147(uint16 k, uint16 j); +uint16 CinematicFunction_Intro_Func219(uint16 k, uint16 j); +uint16 CinematicGetTilemapOffsetForTile(void); +uint16 CinematicSetPal1(uint16 k, uint16 j); +uint16 CinematicSetPal2(uint16 k, uint16 j); +uint16 CinematicSetPal3(uint16 k, uint16 j); +uint16 CinematicSetPal4(uint16 k, uint16 j); +uint16 CinematicSprInstr_9CE1(uint16 k, uint16 j); +uint16 CinematicSprInstr_9D5D(uint16 k, uint16 j); +uint16 CinematicSprInstr_9DD6(uint16 k, uint16 j); +uint16 CinematicSprInstr_9F19(uint16 k, uint16 j); +uint16 CinematicSprInstr_C9A5(uint16 k, uint16 j); +uint16 CinematicSprInstr_C9AF(uint16 k, uint16 j); +uint16 CinematicSprInstr_C9BD(uint16 k, uint16 j); +uint16 CinematicSprInstr_C9C7(uint16 k, uint16 j); +uint16 CinematicSprInstr_CallFunc(uint16 k, uint16 j); +uint16 CinematicSprInstr_CallFuncWithArg(uint16 k, uint16 j); +uint16 CinematicSprInstr_ClearPreInstr(uint16 k, uint16 j); +uint16 CinematicSprInstr_DecTimerGoto(uint16 k, uint16 j); +uint16 CinematicSprInstr_DecTimerGotoRel(uint16 k, uint16 j); +uint16 CinematicSprInstr_Delete(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func181(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func182(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func183(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func185(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func186(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func187(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func190(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func192(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func193(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func194(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func195(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func196(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func197(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func198(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func208(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func211(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func213(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func214(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func217(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func218(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func43(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func8(uint16 k, uint16 j); +uint16 CinematicSprInstr_Func9(uint16 k, uint16 j); +uint16 CinematicSprInstr_Goto(uint16 k, uint16 j); +uint16 CinematicSprInstr_GotoRel(uint16 k, uint16 j); +uint16 CinematicSprInstr_SetPreInstr(uint16 k, uint16 j); +uint16 CinematicSprInstr_SetTimer(uint16 k, uint16 j); +uint16 CinematicSprInstr_Sleep(uint16 k, uint16 j); +uint16 CinematicSprInstr_SpawnCeresExplosions1(uint16 k, uint16 j); +uint16 CinematicSprInstr_SpawnCeresExplosions3(uint16 k, uint16 j); +uint16 CinematicSprInstr_SpawnIntroRinkas01(uint16 k, uint16 j); +uint16 CinematicSprInstr_SpawnIntroRinkas23(uint16 k, uint16 j); +uint16 CinematicSprInstr_SpawnMetroidEggParticles(uint16 k, uint16 j); +uint16 CinematicSprInstr_StartIntroPage2(uint16 k, uint16 j); +uint16 CinematicSprInstr_StartIntroPage3(uint16 k, uint16 j); +uint16 CinematicSprInstr_StartIntroPage4(uint16 k, uint16 j); +uint16 CinematicSprInstr_StartIntroPage5(uint16 k, uint16 j); +uint16 CinematicSprInstr_sub_8B9EF0(uint16 k, uint16 j); +uint16 IntroObject_DecTimerGoto(uint16 k, uint16 j); +uint16 IntroObject_Delete(uint16 k, uint16 j); +uint16 IntroObject_Goto(uint16 k, uint16 j); +uint16 IntroObject_SetTimer(uint16 k, uint16 j); +uint16 Mode7Instr_ClearPreInstr(uint16 k, uint16 j); +uint16 Mode7Instr_DecTimerAndGoto(uint16 k, uint16 j); +uint16 Mode7Instr_Delete(uint16 k, uint16 j); +uint16 Mode7Instr_Goto(uint16 k, uint16 j); +uint16 Mode7Instr_SetPreInstr(uint16 k, uint16 j); +uint16 Mode7Instr_SetTimer(uint16 k, uint16 j); +uint16 PlayBabyMetroidCry1(uint16 k, uint16 j); +uint16 PlayBabyMetroidCry2(uint16 k, uint16 j); +uint16 PlayBabyMetroidCry3(uint16 k, uint16 j); +uint8 AdvanceFastScreenFadeIn(void); +uint8 AdvanceFastScreenFadeOut(void); +uint8 AdvanceSlowScreenFadeIn(void); +uint8 AdvanceSlowScreenFadeOut(void); +uint8 SpawnCimenaticSpriteObjectInner(uint16 k, uint16 j); +uint8 SpawnCinematicBgObject(uint16 j, uint16 a); +uint8 SpawnCinematicSpriteObject(uint16 j, uint16 a); +uint8 SpawnCinematicSpriteObjectToR18(uint16 j, uint16 a); +uint8 SpawnMode7Object(uint16 j, uint16 a); +void AddNintentoLogoToOam(void); +void CalcCeresSteamPos_Mode7(void); +void CalcExplosion_Mode7(uint16 k); +void CalcSinCos(uint16 a, uint16 j); +void CinematicBgPreInstr_SamusBlink(uint16 k); +void CinematicFunc_Func1(void); +void CinematicFunc_Func10(void); +void CinematicFunc_Func2(void); +void CinematicFunc_Func4(void); +void CinematicFunc_Func5(void); +void CinematicFunc_Func7(void); +void CinematicFunc_Func9(void); +void CinematicFunc_Intro_FadeOut(void); +void CinematicFunc_Intro_QueueGalaxyIsAtPeace(void); +void CinematicFunc_Intro_SetupTextPage2(void); +void CinematicFunc_Intro_WaitFadeinShowText(void); +void CinematicFunc_Intro_WaitForFadeOut(void); +void CinematicFunc_Intro_WaitForFadeinSleep(void); +void CinematicFunc_Intro_WaitForQueueWait4secs(void); +void CinematicFunc_Nothing(void); +void CinematicFunctionBlackoutFromCeres(void); +void CinematicFunctionEscapeFromCebes(void); +void CinematicFunctionNone(void); +void CinematicFunctionOpening(void); +void CinematicFunction_F0B8(uint16 j); +void CinematicFunction_Intro_DrawInitJpn(void); +void CinematicFunction_Intro_FadeIn(void); +void CinematicFunction_Intro_Fadestuff(void); +void CinematicFunction_Intro_Fadestuff2(void); +void CinematicFunction_Intro_Func100(uint16 j); +void CinematicFunction_Intro_Func101(uint16 j); +void CinematicFunction_Intro_Func102(uint16 j); +void CinematicFunction_Intro_Func104(uint16 j); +void CinematicFunction_Intro_Func105(void); +void CinematicFunction_Intro_Func106(void); +void CinematicFunction_Intro_Func107(void); +void CinematicFunction_Intro_Func108(void); +void CinematicFunction_Intro_Func109(void); +void CinematicFunction_Intro_Func11(void); +void CinematicFunction_Intro_Func110(void); +void CinematicFunction_Intro_Func111(void); +void CinematicFunction_Intro_Func112(void); +void CinematicFunction_Intro_Func113(void); +void CinematicFunction_Intro_Func114(void); +void CinematicFunction_Intro_Func115(void); +void CinematicFunction_Intro_Func116(void); +void CinematicFunction_Intro_Func117(void); +void CinematicFunction_Intro_Func118(void); +void CinematicFunction_Intro_Func119(void); +void CinematicFunction_Intro_Func12(void); +void CinematicFunction_Intro_Func120(void); +void CinematicFunction_Intro_Func121(void); +void CinematicFunction_Intro_Func122(void); +void CinematicFunction_Intro_Func123(void); +void CinematicFunction_Intro_Func124(void); +void CinematicFunction_Intro_Func125(void); +void CinematicFunction_Intro_Func126(void); +void CinematicFunction_Intro_Func127(void); +void CinematicFunction_Intro_Func128(uint16 a); +void CinematicFunction_Intro_Func129(void); +void CinematicFunction_Intro_Func13(void); +void CinematicFunction_Intro_Func130(void); +void CinematicFunction_Intro_Func131(void); +void CinematicFunction_Intro_Func132(void); +void CinematicFunction_Intro_Func134(void); +void CinematicFunction_Intro_Func135(void); +void CinematicFunction_Intro_Func136(void); +void CinematicFunction_Intro_Func137(void); +void CinematicFunction_Intro_Func138(void); +void CinematicFunction_Intro_Func139(void); +void CinematicFunction_Intro_Func140(void); +void CinematicFunction_Intro_Func141(void); +void CinematicFunction_Intro_Func142(void); +void CinematicFunction_Intro_Func143(void); +void CinematicFunction_Intro_Func144(void); +void CinematicFunction_Intro_Func145(void); +void CinematicFunction_Intro_Func148(void); +void CinematicFunction_Intro_Func149(void); +void CinematicFunction_Intro_Func15(void); +void CinematicFunction_Intro_Func150(uint16 j); +void CinematicFunction_Intro_Func151(uint16 k); +void CinematicFunction_Intro_Func152(uint16 j); +void CinematicFunction_Intro_Func153(uint16 j); +void CinematicFunction_Intro_Func154(uint16 j); +void CinematicFunction_Intro_Func155(uint16 j); +void CinematicFunction_Intro_Func156(uint16 j); +void CinematicFunction_Intro_Func157(uint16 j); +void CinematicFunction_Intro_Func158(uint16 j); +void CinematicFunction_Intro_Func159(uint16 j); +void CinematicFunction_Intro_Func15b(void); +void CinematicFunction_Intro_Func160(uint16 j, uint16 a); +void CinematicFunction_Intro_Func161(uint16 j); +void CinematicFunction_Intro_Func162(uint16 j); +void CinematicFunction_Intro_Func163(uint16 j); +void CinematicFunction_Intro_Func164(uint16 j); +void CinematicFunction_Intro_Func165(uint16 j); +void CinematicFunction_Intro_Func166(uint16 j); +void CinematicFunction_Intro_Func167(uint16 j); +void CinematicFunction_Intro_Func168(uint16 j); +void CinematicFunction_Intro_Func169(uint16 j); +void CinematicFunction_Intro_Func170(uint16 j); +void CinematicFunction_Intro_Func171(uint16 j); +void CinematicFunction_Intro_Func172(uint16 j); +void CinematicFunction_Intro_Func173(uint16 j); +void CinematicFunction_Intro_Func174(uint16 j); +void CinematicFunction_Intro_Func175(uint16 j); +void CinematicFunction_Intro_Func176(uint16 j); +void CinematicFunction_Intro_Func177(uint16 j); +void CinematicFunction_Intro_Func178(uint16 j); +void CinematicFunction_Intro_Func179(uint16 k); +void CinematicFunction_Intro_Func18(void); +void CinematicFunction_Intro_Func180(uint16 k); +void CinematicFunction_Intro_Func184(uint16 j); +void CinematicFunction_Intro_Func189(uint16 k); +void CinematicFunction_Intro_Func189b(uint16 k); +void CinematicFunction_Intro_Func19(uint16 k); +void CinematicFunction_Intro_Func191(uint16 k); +void CinematicFunction_Intro_Func199(uint16 k); +void CinematicFunction_Intro_Func20(uint16 j); +void CinematicFunction_Intro_Func200(uint16 k); +void CinematicFunction_Intro_Func201(uint16 k); +void CinematicFunction_Intro_Func202(uint16 k); +void CinematicFunction_Intro_Func203(uint16 k); +void CinematicFunction_Intro_Func204(uint16 k); +void CinematicFunction_Intro_Func205(uint16 k); +void CinematicFunction_Intro_Func206(uint16 k); +void CinematicFunction_Intro_Func207(uint16 k); +uint16 CinematicFunction_Intro_Func21(uint16 k, uint16 j); +void CinematicFunction_Intro_Func210_EndingSamusFall(uint16 k); +void CinematicFunction_Intro_Func215(uint16 k); +void CinematicFunction_Intro_Func216(void); +void CinematicFunction_Intro_Func22(uint16 k); +uint16 CinematicFunction_Intro_Func23(uint16 k, uint16 j); +void CinematicFunction_Intro_Func24(uint16 k); +uint16 CinematicFunction_Intro_Func25(uint16 k, uint16 j); +uint16 CinematicFunction_Intro_Func26(uint16 k, uint16 j); +void CinematicFunction_Intro_Func27(uint16 k); +uint16 CinematicFunction_Intro_Func28(uint16 k, uint16 j); +uint16 CinematicFunction_Intro_Func29(uint16 k, uint16 j); +void CinematicFunction_Intro_Func30(uint16 k); +uint16 CinematicFunction_Intro_Func31(uint16 k, uint16 j); +uint16 CinematicFunction_Intro_Func32(uint16 k, uint16 j); +void CinematicFunction_Intro_Func33(void); +void CinematicFunction_Intro_Func34(void); +void CinematicFunction_Intro_Func35(uint16 j); +void CinematicFunction_Intro_Func36(uint16 k); +void CinematicFunction_Intro_Func37(uint16 k); +void CinematicFunction_Intro_Func39(uint16 k); +void CinematicFunction_Intro_Func40(void); +void CinematicFunction_Intro_Func42(uint16 j); +void CinematicFunction_Intro_Func44(uint16 k); +void CinematicFunction_Intro_Func45(uint16 k); +void CinematicFunction_Intro_Func46(uint16 j); +void CinematicFunction_Intro_Func47(uint16 j); +void CinematicFunction_Intro_Func48(uint16 k); +void CinematicFunction_Intro_Func49(uint16 j); +void CinematicFunction_Intro_Func50(uint16 k); +void CinematicFunction_Intro_Func51(uint16 k); +void CinematicFunction_Intro_Func52(uint16 k); +void CinematicFunction_Intro_Func53(uint16 k); +void CinematicFunction_Intro_Func54(void); +void CinematicFunction_Intro_Func55(void); +void CinematicFunction_Intro_Func56(void); +void CinematicFunction_Intro_Func57(uint16 j); +void CinematicFunction_Intro_Func58(uint16 k); +void CinematicFunction_Intro_Func59(uint16 j); +void CinematicFunction_Intro_Func60(uint16 k); +void CinematicFunction_Intro_Func61(uint16 j); +void CinematicFunction_Intro_Func62(uint16 k); +void CinematicFunction_Intro_Func63(uint16 j); +void CinematicFunction_Intro_Func64(uint16 k); +void CinematicFunction_Intro_Func65(uint16 j); +void CinematicFunction_Intro_Func66(uint16 k); +void CinematicFunction_Intro_Func67(void); +void CinematicFunction_Intro_Func68(uint16 j); +void CinematicFunction_Intro_Func71(uint16 j); +void CinematicFunction_Intro_Func72(void); +void CinematicFunction_Intro_Func73(void); +void CinematicFunction_Intro_Func74(void); +void CinematicFunction_Intro_Func75(void); +void CinematicFunction_Intro_Func76(void); +void CinematicFunction_Intro_Func77(void); +void CinematicFunction_Intro_Func78(uint16 j); +void CinematicFunction_Intro_Func80(uint16 j); +void CinematicFunction_Intro_Func81(uint16 j); +void CinematicFunction_Intro_Func82(uint16 k); +void CinematicFunction_Intro_Func83(uint16 j); +void CinematicFunction_Intro_Func84(void); +void CinematicFunction_Intro_Func85(void); +void CinematicFunction_Intro_Func86(void); +void CinematicFunction_Intro_Func87(void); +void CinematicFunction_Intro_Func88(void); +void CinematicFunction_Intro_Func89(uint16 j); +void CinematicFunction_Intro_Func90(uint16 k); +void CinematicFunction_Intro_Func91(uint16 k); +void CinematicFunction_Intro_Func92(uint16 j); +void CinematicFunction_Intro_Func93(uint16 k); +void CinematicFunction_Intro_Func94(uint16 k); +void CinematicFunction_Intro_Func95(void); +void CinematicFunction_Intro_Func96(uint16 k); +void CinematicFunction_Intro_Func97(uint16 k); +void CinematicFunction_Intro_Func98(uint16 j); +void CinematicFunction_Intro_Func99(uint16 j); +void CinematicFunction_Intro_Initial(void); +void CinematicFunction_Intro_LastMetroidCaptivity(void); +void CinematicFunction_Intro_Page2(void); +void CinematicFunction_Intro_Page3(void); +void CinematicFunction_Intro_Page4(void); +void CinematicFunction_Intro_Page5(void); +void CinematicFunction_Intro_SetupStuff(void); +void CinematicFunction_Intro_SetupTransitionToGameplay(void); +uint16 CinematicFunction_Intro_ThenWaitInputSetupBabyMetroid(uint16 k, uint16 j); +void CinematicFunction_Intro_WaitInputSetupBabyMetroid(void); +void CinematicFunction_Intro_WaitInputSetupMotherBrainFight(void); +void CinematicFunction_Intro_XfadeGameplayFade(void); +void CinematicFunction_Intro_XfadeScientistFade(void); +void CinematicFunction_nullsub_116(uint16 j); +void CinematicFunction_nullsub_298(void); +void CinematicSprPreInstr_A903(uint16 k); +void CinematicSprPreInstr_B82E(uint16 k); +void CinematicSprPreInstr_C489(uint16 k); +void CinematicSprPreInstr_F35A(uint16 k); +void CinematicSprPreInstr_F528(uint16 k); +void CinematicSprPreInstr_F57F(uint16 k); +void CinematicSprPreInstr_nullsub_300(void); +void CinematicSpriteInit_0(uint16 j); +void CinematicSpriteInit_1(uint16 j); +void CinematicSpriteInit_2(uint16 j); +void CinematicSpriteInit_3(uint16 j); +void CinematicSpriteInit_4(uint16 j); +void CinematicSpriteInit_5(uint16 j); +void CinematicSpriteInit_6(uint16 j); +void CinematicSpriteInit_7(uint16 j); +void CinematicSpriteInit_8(uint16 j); +void CinematicSpriteInit_9(uint16 j); +void CinematicUpdateSomeBg(void); +void ClearCinematicBgObjects(uint16 a); +void ClearCinematicSprites(void); +void ClearEnglishTextTilemap(void); +void ClearJapaneseTextTiles(void); +void ClearYColorsFromIndexX(uint16 k, uint16 j); +void ComposeFadingPalettes(void); +void ConfigureTitleSequenceGradientHDMA(void); +void CopyPalettesToFadingPalettes(void); +void CreditsObject_Func1(uint16 j); +void CreditsObject_Init(uint16 j); +void CreditsObject_Process(void); +void CreditsObject_ProcessOne(void); +void DecomposePaletteDataForFading(void); +void DisableCinematicBgObjects(void); +void DisableCinematicBgTilemapUpdates(void); +void DisableTextGlowObjects_(void); +void DrawCinematicSpriteObjects_Ending(void); +void DrawCinematicSpriteObjects_Intro(void); +void DrawIntroSprites(void); +void EnableCinematicBgObjects(void); +void EnableCinematicBgTilemapUpdates(void); +void EnableCinematicBgTilemapUpdates_(void); +uint16 EnableCinematicBgTilemapUpdates__(uint16 k, uint16 j); +uint16 EnableCinematicBgTilemapUpdates__0(uint16 k, uint16 j); +void EnableTextGlowObjects_(void); +void FadeInYColorsFromIndexX(uint16 k, uint16 j); +void FadeOutYColorsFromIndexX(uint16 k, uint16 j); +CoroutineRet GameState_1_OpeningCinematic_(void); +CoroutineRet GameState_37_CeresGoesBoomWithSamus_(void); +CoroutineRet GameState_39_EndingAndCredits_(void); +void HandleCinematicBgObjects(void); +void HandleCinematicSprites(void); +void HandleCinematicsTransitions(void); +void HandleCinematicsTransitions_1(void); +void HandleCinematicsTransitions_2(void); +void HandleCinematicsTransitions_3(void); +void HandleFadeIn_(void); +void HandleMode7Objects(void); +void HandleMode7TransformationMatrix(void); +void HandleMode7TransformationNoRotation(void); +void HandleSamusDuringIntro(void); +void HandleTextGlowObjects(void); +CoroutineRet InitializeIoDisplayLogo_Async(void); +void Instr_StartIntroPage_Common(void); +void LoadTitleSequenceGraphics(void); +void MaybeHandleCinematicBgObjects(void); +void MaybeSkipCinematics(void); +void MoveUnusedSpritesOffScreen_IGNORE(void); +void Mult0x80Add(void); +void ProcessCinematicBgObject(uint16 k); +void ProcessCinematicBgObject_DrawChar(uint16 k, uint16 j); +void ProcessCinematicBgObject_DrawToBgTilemap(uint16 k, uint16 j); +void ProcessCinematicBgObject_DrawToTextTilemap(uint16 k, uint16 j); +void ProcessCinematicBgObject_Nothing(uint16 k, uint16 j); +void ProcessCinematicBgObject_Unk1(uint16 k, uint16 j); +void ProcessCinematicBgObject_Unk2(uint16 k, uint16 j); +void ProcessCinematicBgObjectsInstrs(uint16 k); +void ProcessCinematicSpriteInstructionList(uint16 k); +void ProcessMode7ObjectInstructions(uint16 k); +void ProcessTextGlowObject(void); +void ResetButtonAssignmentsToDefault(void); +void RevertButtonConfig(void); +void Samus_CalcPos_Mode7(void); +void SetPpuBackdropBlack(void); +void SetPpuBackdropSomeColor(void); +void SetSomeStuffForSpriteObject_10(uint16 j); +void SetSomeStuffForSpriteObject_11(uint16 k); +void SetSomeStuffForSpriteObject_12(uint16 j); +void SetSomeStuffForSpriteObject_13(uint16 k); +void SetSomeStuffForSpriteObject_15(void); +void SetSomeStuffForSpriteObject_16(void); +void SetSomeStuffForSpriteObject_17(uint16 j); +void SetSomeStuffForSpriteObject_18(uint16 k); +void SetSomeStuffForSpriteObject_2(uint16 j); +void SetSomeStuffForSpriteObject_3(uint16 j); +void SetSomeStuffForSpriteObject_4_MetroidEgg(uint16 k); +void SetSomeStuffForSpriteObject_6(uint16 j); +void SetSomeStuffForSpriteObject_7(uint16 k); +void SetSomeStuffForSpriteObject_8(uint16 j); +void SetSomeStuffForSpriteObject_9(uint16 k); +void SetupPpuForTitleSequence(void); +void SetupPpu_3_Mode7(void); +void SetupPpu_4_Mode1(void); +void SetupPpu_5_Mode7(void); +void SetupPpu_6_Mode1(void); +void SetupPpu_7_Mode1(void); +void SetupPpu_Intro(void); +void Smult16x16Shr16(void); +void SpawnTextGlowObject(uint16 j); +void TransferJapaneseTextTilesToVram(void); +void Umult16x16Shr16(void); +void UpdateCinematicBgTilemap(void); +void UpdateSamusEyesTilemap(void); +void sub_8B94E1(void); +void sub_8B9743(void); +void sub_8B9CCF(uint16 k); +void sub_8B9CDE(void); +uint16 sub_8BB51E(uint16 k, uint16 j); + +// Bank 8D +PairU16 PalInstr_ClearPreInstr(uint16 k, uint16 j); +PairU16 PalInstr_ColorPlus15(uint16 k, uint16 j); +PairU16 PalInstr_ColorPlus2(uint16 k, uint16 j); +PairU16 PalInstr_ColorPlus3(uint16 k, uint16 j); +PairU16 PalInstr_ColorPlus4(uint16 k, uint16 j); +PairU16 PalInstr_ColorPlus8(uint16 k, uint16 j); +PairU16 PalInstr_ColorPlus9(uint16 k, uint16 j); +PairU16 PalInstr_DecTimerGoto(uint16 k, uint16 j); +PairU16 PalInstr_DecTimerGotoRel(uint16 k, uint16 j); +PairU16 PalInstr_Delete(uint16 k, uint16 j); +PairU16 PalInstr_Finish(uint16 k, uint16 j); +PairU16 PalInstr_Goto(uint16 k, uint16 j); +PairU16 PalInstr_GotoRel(uint16 k, uint16 j); +PairU16 PalInstr_QueueMusic(uint16 k, uint16 j); +PairU16 PalInstr_QueueSfx1(uint16 k, uint16 j); +PairU16 PalInstr_QueueSfx2(uint16 k, uint16 j); +PairU16 PalInstr_QueueSfx3(uint16 k, uint16 j); +PairU16 PalInstr_SetColorIndex(uint16 k, uint16 j); +PairU16 PalInstr_SetPalfxIndex(uint16 k, uint16 j); +PairU16 PalInstr_SetPreInstr(uint16 k, uint16 j); +PairU16 PalInstr_SetTimer(uint16 k, uint16 j); +PairU16 PalInstr_SetTimerIfBossBit(uint16 k, uint16 j); +void ClearPaletteFXObjects(void); +void DisablePaletteFx(void); +void EnablePaletteFx(void); +void PalFx_ProcessOne(uint16 k); +void PalInit_E1BC(uint16 k, uint16 j); +void PalInit_F761_Norfair1(uint16 k, uint16 j); +void PalInit_F779_Brinstar8(uint16 k, uint16 j); +void PalPreInstr_CheckEnemy0Health(uint16 k); +void PalPreInstr_DeletePalfxIfMinibossDead(uint16 k); +void PalPreInstr_E1BC(uint16 k); +void PalPreInstr_F621(uint16 k); +void PalPreInstr_SamusInHeat(uint16 k); +void PalPreInstr_SwitchIfYpos(uint16 k); +void PalPreInstr_SwitchIfYpos2(uint16 k); +void PalPreInstr_nullsub_129(uint16 k); +void PaletteFxHandler(void); +void SpawnPalfxObject(uint16 j); +void sub_8DC589(void); + +// Bank 8F +uint16 RoomDefStateSelect_Door(uint16 k); +uint16 RoomDefStateSelect_Finish(uint16 k); +uint16 RoomDefStateSelect_IsBossDead(uint16 k); +uint16 RoomDefStateSelect_IsEventSet(uint16 k); +uint16 RoomDefStateSelect_MorphBallMissiles(uint16 k); +uint16 RoomDefStateSelect_PowerBombs(uint16 k); +uint16 RoomDefStateSelect_TourianBoss01(uint16 k); +void DoorCode_CeresElevatorShaft(void); +void DoorCode_CeresElevatorShaft_2(void); +void DoorCode_ResetElevatubeNorthExit(void); +void DoorCode_ResetElevatubeSouthExit(void); +void DoorCode_Scroll0_Blue(void); +void DoorCode_Scroll13_Blue(void); +void DoorCode_Scroll6_Green(void); +void DoorCode_Scroll_17_Blue(void); +void DoorCode_Scroll_1_4_Green(void); +void DoorCode_Scroll_2_Blue(void); +void DoorCode_Scroll_3_Green(void); +void DoorCode_Scroll_4Blue_8Green(void); +void DoorCode_Scroll_4_Blue(void); +void DoorCode_Scroll_6_Green(void); +void DoorCode_Scroll_8toB_Red(void); +void DoorCode_Scroll_LotsRed(void); +void DoorCode_SetScroll_0(void); +void DoorCode_SetScroll_1(void); +void DoorCode_SetScroll_10(void); +void DoorCode_SetScroll_11(void); +void DoorCode_SetScroll_12(void); +void DoorCode_SetScroll_13(void); +void DoorCode_SetScroll_14(void); +void DoorCode_SetScroll_15(void); +void DoorCode_SetScroll_16(void); +void DoorCode_SetScroll_17(void); +void DoorCode_SetScroll_18(void); +void DoorCode_SetScroll_19(void); +void DoorCode_SetScroll_2(void); +void DoorCode_SetScroll_20(void); +void DoorCode_SetScroll_21(void); +void DoorCode_SetScroll_22(void); +void DoorCode_SetScroll_23(void); +void DoorCode_SetScroll_24(void); +void DoorCode_SetScroll_25(void); +void DoorCode_SetScroll_26(void); +void DoorCode_SetScroll_27(void); +void DoorCode_SetScroll_28(void); +void DoorCode_SetScroll_29(void); +void DoorCode_SetScroll_3(void); +void DoorCode_SetScroll_30(void); +void DoorCode_SetScroll_31(void); +void DoorCode_SetScroll_32(void); +void DoorCode_SetScroll_33(void); +void DoorCode_SetScroll_34(void); +void DoorCode_SetScroll_35(void); +void DoorCode_SetScroll_36(void); +void DoorCode_SetScroll_37(void); +void DoorCode_SetScroll_38(void); +void DoorCode_SetScroll_39(void); +void DoorCode_SetScroll_4(void); +void DoorCode_SetScroll_40(void); +void DoorCode_SetScroll_41(void); +void DoorCode_SetScroll_42(void); +void DoorCode_SetScroll_43(void); +void DoorCode_SetScroll_44(void); +void DoorCode_SetScroll_45(void); +void DoorCode_SetScroll_46(void); +void DoorCode_SetScroll_47(void); +void DoorCode_SetScroll_48(void); +void DoorCode_SetScroll_49(void); +void DoorCode_SetScroll_5(void); +void DoorCode_SetScroll_50(void); +void DoorCode_SetScroll_53(void); +void DoorCode_SetScroll_54(void); +void DoorCode_SetScroll_55(void); +void DoorCode_SetScroll_56(void); +void DoorCode_SetScroll_57(void); +void DoorCode_SetScroll_58(void); +void DoorCode_SetScroll_59(void); +void DoorCode_SetScroll_6(void); +void DoorCode_SetScroll_60(void); +void DoorCode_SetScroll_61(void); +void DoorCode_SetScroll_62(void); +void DoorCode_SetScroll_63(void); +void DoorCode_SetScroll_64(void); +void DoorCode_SetScroll_65(void); +void DoorCode_SetScroll_7(void); +void DoorCode_SetScroll_8(void); +void DoorCode_SetScroll_9(void); +void DoorCode_SetupElevatubeFromNorth(void); +void DoorCode_SetupElevatubeFromSouth(void); +void DoorCode_StartWreckedShipTreadmillWest(void); +void DoorCode_StartWreckedSkipTreadmill_East(void); +void HandleRoomDefStateSelect(uint16 k); +void PauseHook_DraygonRoom(void); +void RoomCode_8FC8C8(void); +void RoomCode_CeresColorMathHdma(void); +void RoomCode_CeresColorMathHdma_BgBase(void); +void RoomCode_CeresElevatorShaft_(void); +void RoomCode_CrocomireShaking(void); +void RoomCode_Elevatube(void); +void RoomCode_Escape4_SetMediumHorizRoomShake(void); +void RoomCode_ExplodeShakes(void); +void RoomCode_GenRandomExplodes(void); +void RoomCode_GenRandomExplodes_4th(void); +void RoomCode_GenRandomExplodes_Nonblank(void); +void RoomCode_HandleCeresRidleyGetaway(void); +void RoomCode_RidleyRoomShaking(void); +void RoomCode_ScrollRightDachora(void); +void RoomCode_ScrollingSkyLand_(void); +void RoomCode_ScrollingSkyLand_Shakes(void); +void RoomCode_ScrollingSkyOcean_(void); +void RoomCode_SetCeresDoorSolid(void); +void RoomCode_SetCollectedMap(void); +void RoomCode_SetLightHorizRoomShake(void); +void RoomCode_SetMediumHorizRoomShake(void); +void RoomCode_SetPauseCodeForDraygon(void); +void RoomCode_SetZebesTimebombEvent(void); +void RoomCode_SetupShaktoolRoomPlm(void); +void RoomCode_ShakeScreenHorizDiag(void); +void RoomCode_ShakeScreenHorizDiagStrong(void); +void RoomCode_SpawnCeresFallingDebris(void); +void RoomSetup_AfterSavingAnimals(void); +void RoomSetup_AutoDestroyWallAfterEscape(void); +void RoomSetup_RunStatueUnlockAnims(void); +void RoomSetup_ScrollingSkyLand(void); +void RoomSetup_ScrollingSkyOcean(void); +void RoomSetup_ShakeDuringEscape(void); +void RoomSetup_TurnWallIntoShotblocks(void); +void RunDoorSetupCode(void); +void RunRoomMainCode(void); +void RunRoomSetupCode(void); +void UnpauseHook_DraygonRoom(void); + +// Bank 90 +PairU16 Samus_CalcSpritemapPos(uint16 k); +PairU16 Samus_CalcSpritemapPos_Crouch(uint16 j); +PairU16 Samus_CalcSpritemapPos_Default(uint16 j); +PairU16 Samus_CalcSpritemapPos_Special(uint16 j); +PairU16 Samus_CalcSpritemapPos_Standing(uint16 j); +uint16 CallSomeSamusCode(uint16 a); +uint16 Projectile_SinLookup_Inner(uint16 k); +uint16 Samus_AnimDelayFunc_0to5(uint16 j); +uint16 Samus_AnimDelayFunc_11_SelectDelaySequenceWalljump(uint16 j); +uint16 Samus_AnimDelayFunc_12_TransToPose(uint16 j); +uint16 Samus_AnimDelayFunc_13_TransToPose(uint16 j); +uint16 Samus_AnimDelayFunc_14_Goto(uint16 j); +uint16 Samus_AnimDelayFunc_15_GotoStart(uint16 j); +uint16 Samus_AnimDelayFunc_6_GotoStartIfLittleHealth(uint16 j); +uint16 Samus_AnimDelayFunc_7(uint16 j); +uint16 Samus_AnimDelayFunc_8_AutoJumpHack(uint16 j); +uint16 Samus_AnimDelayFunc_9_TransToPose(uint16 j); +uint16 Samus_DetermineGrappleSwingSpeed_X(void); +uint16 Samus_DetermineSpeedTableEntryPtr_X(void); +uint16 Samus_HandleSpeedBoosterAnimDelay(uint16 j); +uint16 UNUSED_Samus_AnimDelayFunc_10(uint16 j); +uint8 ClearCarry(void); +uint8 DeleteProjectileIfFarOffScreen(void); +uint8 FireSba(void); +uint8 FireSba_ClearCarry(void); +uint8 FireSba_FireIce(void); +uint8 FireSba_FirePlasma(void); +uint8 FireSba_FireSpazer(void); +uint8 FireSba_FireWave(void); +uint8 Hdmaobj_CrystalFlash(void); +uint8 HudSelectionHandler_MorphBall_Helper(void); +uint8 HudSelectionHandler_MorphBall_Helper2(void); +uint8 InitProjectilePositionDirection(void); +uint8 SamusBottomDrawn_0_Standing(void); +uint8 SamusBottomDrawn_1(void); +uint8 SamusBottomDrawn_14_WallJump(void); +uint8 SamusBottomDrawn_19_DamageBoost(void); +uint8 SamusBottomDrawn_1B(void); +uint8 SamusBottomDrawn_3_SpinJump(void); +uint8 SamusBottomDrawn_4(void); +uint8 SamusBottomDrawn_A_Knockback(void); +uint8 SamusBottomDrawn_F_Transitions(void); +uint8 SamusCode_00_LockSamus(void); +uint8 SamusCode_01_UnlockSamus(void); +uint8 SamusCode_02_ReachCeresElevator(void); +uint8 SamusCode_03(void); +uint8 SamusCode_04(void); +uint8 SamusCode_04_06_Common(void); +uint8 SamusCode_05_SetupDrained(void); +uint8 SamusCode_06_LockToStation(void); +uint8 SamusCode_07_SetupForElevator(void); +uint8 SamusCode_08_SetupForCeresStart(void); +uint8 SamusCode_08_SetupForZebesStart(void); +uint8 SamusCode_0A_ClearDrawHandler(void); +uint8 SamusCode_0B_DrawHandlerDefault(void); +uint8 SamusCode_0C_UnlockFromMapStation(void); +uint8 SamusCode_0D_IsGrappleActive(void); +uint8 SamusCode_0E(void); +uint8 SamusCode_0F_EnableTimerHandling(void); +uint8 SamusCode_10(void); +uint8 SamusCode_11_15_Common(void); +uint8 SamusCode_11_SetupForDeath(void); +uint8 SamusCode_12_SetSuperPaletteFlag0(void); +uint8 SamusCode_12_SetSuperPaletteFlag1(void); +uint8 SamusCode_14(void); +uint8 SamusCode_15_CalledBySuitAcquision(void); +uint8 SamusCode_16(void); +uint8 SamusCode_17_DisableRainbowSamusAndStandUp(void); +uint8 SamusCode_17_FreezeDrainedSamus(void); +uint8 SamusCode_18(void); +uint8 SamusCode_1A(void); +uint8 SamusCode_1B_CheckedLockSamus(void); +uint8 SamusCode_1C(void); +uint8 SamusCode_1D_ClearSoundInDoor(void); +uint8 SamusCode_1E(void); +uint8 SamusCode_1F(void); +uint8 Samus_CalcBaseSpeed_NoDecel_X(uint16 k); +uint8 Samus_CanFireBeam(void); +uint8 Samus_CanFireSuperMissile(void); +uint8 Samus_CheckAndMoveY(void); +uint8 Samus_EndSuperJump(void); +uint8 Samus_Func26(void); +uint8 Samus_GrappleWallJumpCheck(void); +uint8 Samus_HitInterrupt_Ball(void); +uint8 Samus_HitInterrupt_Falling(void); +uint8 Samus_HitInterrupt_KnockbackGrapple(void); +uint8 Samus_HitInterrupt_Shinespark(void); +uint8 Samus_HitInterrupt_Stand(void); +uint8 Samus_HitInterrupt_Turning(void); +uint8 Samus_HitInterrupt_Unused(void); +uint8 Samus_MoveY_Simple_(void); +uint8 Samus_SetupForBeingDrained(void); +uint8 Samus_WallJumpCheck(void); +uint8 SetupBombJump_1(void); +uint8 SetupBombJump_1A(void); +uint8 SetupBombJump_2(void); +uint8 SetupBombJump_4(void); +uint8 SetupBombJump_StandCrouch(void); +uint8 SwitchToHudHandler_Grapple(void); +uint8 SwitchToHudHandler_Missiles(void); +uint8 SwitchToHudHandler_Nothing(void); +uint8 SwitchToHudHandler_PowerBombs(void); +uint8 SwitchToHudHandler_SuperMissiles(void); +uint8 SwitchToHudHandler_Xray(void); +uint8 UNUSED_SamusBottomDrawn_D(void); +uint8 UpdateArmCannonIsOpenFlag(void); +void AdjustMapBitsForMapPageSpill(void); +void AdvanceArmCannonFrame(void); +void AtmosphericTypeFunc_1_FootstepSplash(uint16 k, uint16 j); +void AtmosphericTypeFunc_3_DivingSplash(uint16 k, uint16 j); +void AtmosphericTypeFunc_4_LavaSurfaceDmg(uint16 k, uint16 j); +void AtmosphericTypeFunc_5_Bubbles(uint16 k, uint16 j); +void AtmosphericTypeFunc_67_Dust(uint16 k, uint16 j); +void AtmosphericTypeFunc_Common(uint16 j, uint16 a); +void BombSpread(void); +void Bomb_Func2(void); +void CheckBeamCollByDir(uint16 k); +void CheckBeamCollByDir_0459(void); +void CheckBeamCollByDir_1368(void); +void CheckBeamCollByDir_2(void); +void CheckBeamCollByDir_7(void); +void ClearFlareAnimationState(void); +void ClearProjectile(uint16 k); +void DisableMinimapAndMarkBossRoomAsExplored(void); +void DrawFlareAnimationComponent(uint16 k); +void DrawSamusAndProjectiles(void); +void DrawTimer_(void); +void FireChargedBeam(void); +void FireEndOfSpazerSba(uint16 j); +void FireHyperBeam(void); +void FireUnchargedBeam(void); +void Grapple_Func1(void); +void HandleArmCannonOpenState(void); +void HandleAtmosphericEffects(void); +void HandleAutoJumpHack(void); +void HandleChargingBeamGfxAudio(void); +void HandleControllerInputForGamePhysics(void); +void HandleDemoRecorder_1(void); +void HandleDemoRecorder_3(void); +void HandleProjectile(void); +void HandleProjectileTrails(void); +void HandleSamusMovementAndPause(void); +void HandleSwitchingHudSelection(void); +void HudSelectionHandler_CrouchEtcTrans(void); +void HudSelectionHandler_GrabbedByDraygon(void); +void HudSelectionHandler_Grappling(void); +void HudSelectionHandler_JumpEtc(void); +void HudSelectionHandler_MissilesOrSuperMissiles(void); +void HudSelectionHandler_MorphBall(void); +void HudSelectionHandler_Normal(void); +void HudSelectionHandler_NothingOrPowerBombs(void); +void HudSelectionHandler_TurningAround(void); +void HudSelectionHandler_Xray(void); +void InitializeMiniMapBroken(void); +void InitializeProjectileSpeed(uint16 k); +void InitializeProjectileSpeedOfType(void); +void KillProjectile(uint16 k); +void KillProjectileFunc_0(uint16 j); +void KillProjectileFunc_1(uint16 j); +void KillProjectileFunc_2(uint16 j); +void KillProjectileFunc_3(uint16 j); +void KillProjectileFunc_4(uint16 j); +void KillProjectileFunc_6(uint16 j); +void KillProjectileFunc_7(uint16 j); +void KillProjectileFunc_8(uint16 j); +void LiquidPhysicsType_0(void); +void LiquidPhysicsType_24_LavaAcid(void); +void LiquidPhysicsType_6_Water(void); +void LoadProjectilePalette(uint16 a); +void LoadProjectilePalette_(uint16 a); +void MainScrollingRoutine(void); +void MarkMapTileAboveSamusAsExplored(void); +void MarkMapTileAsExplored(void); +void Missile_Func1(uint16 k); +void Missile_Func2(void); +void MoveSamusWithControlPad(void); +void PowerBomb_Func3(void); +void ProjInstr_MoveLeftProjectileTrailDown(uint16 j); +void ProjInstr_MoveLeftProjectileTrailUp(uint16 j); +void ProjInstr_MoveRightProjectileTrailDown(uint16 j); +void ProjPreInstr_BeamOrIceWave(uint16 k); +void ProjPreInstr_Beam_NoWaveBeam(uint16 k); +void ProjPreInstr_Bomb(uint16 k); +void ProjPreInstr_Dir0459(uint16 k); +void ProjPreInstr_Dir1368(uint16 k); +void ProjPreInstr_Dir27(uint16 k); +void ProjPreInstr_Empty(void); +void ProjPreInstr_EndOfSpazerSba(uint16 k); +void ProjPreInstr_Func1(uint16 k); +void ProjPreInstr_HyperBeam(uint16 k); +void ProjPreInstr_IceSba(uint16 k); +void ProjPreInstr_IceSba2(uint16 k); +void ProjPreInstr_Missile(uint16 k); +void ProjPreInstr_Missile_Func0459(uint16 k); +void ProjPreInstr_Missile_Func1368(uint16 k); +void ProjPreInstr_Missile_Func27(uint16 k); +void ProjPreInstr_PlasmaSba(uint16 k); +void ProjPreInstr_PlasmaSbaFunc_0(uint16 j); +void ProjPreInstr_PlasmaSbaFunc_1(uint16 j); +void ProjPreInstr_PlasmaSbaFunc_2(uint16 j); +void ProjPreInstr_PowerBomb(uint16 k); +void ProjPreInstr_SpazerSba(uint16 k); +void ProjPreInstr_SpazerSba_FuncA_0(uint16 k); +void ProjPreInstr_SpazerSba_FuncA_1(uint16 k); +void ProjPreInstr_SpazerSba_FuncA_2(uint16 k); +void ProjPreInstr_SpazerSba_FuncA_3(uint16 k); +void ProjPreInstr_SpazerSba_FuncB_0(uint16 j); +void ProjPreInstr_SpazerSba_FuncB_1(uint16 j); +void ProjPreInstr_SpazerSba_FuncB_2(uint16 j); +void ProjPreInstr_SpeedEcho(uint16 k); +void ProjPreInstr_SpreadBomb(uint16 k); +void ProjPreInstr_SuperMissile(uint16 k); +void ProjPreInstr_SuperMissile_Func0459(uint16 k); +void ProjPreInstr_SuperMissile_Func1368(uint16 k); +void ProjPreInstr_SuperMissile_Func27(uint16 k); +void ProjPreInstr_UnknownProj8027(uint16 k); +void ProjPreInstr_WavePlasmaEtc(uint16 k); +void ProjPreInstr_WavePlasmaEtc_0459(uint16 k); +void ProjPreInstr_WavePlasmaEtc_1368(uint16 k); +void ProjPreInstr_WavePlasmaEtc_27(uint16 k); +void ProjPreInstr_WaveSba(uint16 k); +void ProjPreInstr_Wave_Shared(uint16 k); +void ProjectileReflection(void); +void Projectile_Func4(uint16 k); +void Projectile_Func7_Shinespark(void); +void Projectile_SinLookup(uint16 j, uint16 a); +void ResetProjectileData(void); +void RunFrameHandlerGamma(void); +void RunSamusMovementHandler(void); +void SamusCrouchingEtcFunc(void); +void SamusDisplayHandler_SamusReceivedFatal(void); +void SamusDisplayHandler_UsingElevator(void); +void SamusDrawHandler_Default(void); +void SamusDrawSprites(void); +void SamusMoveHandler_CrystalFlashMain(void); +void SamusMoveHandler_CrystalFlashMain_0(void); +void SamusMoveHandler_CrystalFlashMain_1(void); +void SamusMoveHandler_CrystalFlashMain_2(void); +void SamusMoveHandler_CrystalFlashStart(void); +void SamusMovementType_Xray(void); +void Samus_AlignBottomWithPrevPose(void); +void Samus_Animate(void); +void Samus_Animate_AcidFx(void); +void Samus_Animate_LavaFx(void); +void Samus_Animate_NoFx(void); +void Samus_Animate_SubmergedLavaAcid(void); +void Samus_Animate_WaterFx(void); +void Samus_ArmCannon_Draw(void); +void Samus_BombJumpFallingXMovement_(void); +void Samus_BombJumpFallingYMovement_(void); +void Samus_BombJumpRisingXMovement_(void); +void Samus_BombJumpRisingYMovement_(void); +void Samus_CalcBaseSpeed_X(uint16 k); +void Samus_CalcDisplacementMoveLeft(void); +void Samus_CalcDisplacementMoveRight(void); +void Samus_CalcDistanceMoved_X(void); +void Samus_CalcDistanceMoved_Y(void); +void Samus_CalcSpeed_X(void); +void Samus_CalcSpritemapPos_Default_(void); +void Samus_CallInputHandler(void); +void Samus_CheckStartFalling(void); +void Samus_ClearMoveVars(void); +void Samus_ClearXSpeedIfColl(void); +void Samus_DetermineAccel_Y(void); +void Samus_Draw(void); +void Samus_DrawDuringDeathAnim(void); +void Samus_DrawEcho(uint16 j); +void Samus_DrawEchoes(void); +void Samus_DrawHandler_EndOfShinespark(void); +void Samus_DrawManyEchoes(void); +void Samus_DrawShinesparkCrashEchoProjectiles(void); +void Samus_DrawShinesparkCrashEchoes(uint16 k); +void Samus_DrawStartingDeathAnim(void); +void Samus_DrawWhenNotAnimatingOrDying(void); +void Samus_FallingMovement(void); +void Samus_FootstepGraphics(void); +void Samus_FootstepGraphics_1(void); +void Samus_FootstepGraphics_Crateria(void); +void Samus_FootstepGraphics_Maridia(void); +void Samus_FrameHandlerAlfa_Func11(void); +void Samus_FrameHandlerAlfa_Func12(void); +void Samus_FrameHandlerAlfa_Func13(void); +void Samus_FrameHandlerBeta_Func14(void); +void Samus_FrameHandlerBeta_Func17(void); +void Samus_Func1(void); +void Samus_Func10(void); +void Samus_Func15(void); +void Samus_Func16(void); +void Samus_Func18(void); +void Samus_Func19(void); +void Samus_Func2(void); +void Samus_Func20_(void); +void Samus_Func25_ShineSpark(void); +void Samus_Func3(void); +void Samus_Func4(void); +void Samus_Func5(void); +void Samus_Func6(void); +void Samus_Func7(void); +void Samus_Func8(void); +void Samus_Func9(void); +void Samus_GetBottomBoundary(void); +void Samus_GetTopBottomBoundary(void); +void Samus_GrabbedByDraygonFrameHandler(void); +void Samus_HandleAnimDelay(void); +void Samus_HandleCooldown(void); +void Samus_HandleExtraRunspeedX(void); +void Samus_HandleHudSpecificBehaviorAndProjs(void); +void Samus_HandleMovement_DrainedCrouching(void); +void Samus_HandleMovement_X(void); +void Samus_HandleNormalAnimDelay(uint16 j); +void Samus_HandlePeriodicDamage(void); +void Samus_HandleScroll_X(void); +void Samus_HandleScroll_Y(void); +void Samus_HitInterruption(void); +void Samus_HorizontalBombJump(void); +void Samus_InitBombJump(void); +void Samus_InitJump(void); +void Samus_InitWallJump(void); +void Samus_InputHandler_E913(void); +void Samus_InputHandler_E91D(void); +void Samus_JumpCheck(void); +void Samus_JumpingMovement(void); +void Samus_LowHealthCheck(void); +void Samus_LowHealthCheck_(void); +void Samus_LowHealthCheck_0(void); +void Samus_MorphedBouncingMovement(void); +void Samus_MorphedFallingMovement(void); +void Samus_MoveDown(void); +void Samus_MoveDown_NoColl(void); +void Samus_MoveDown_SetPoseCalcInput(void); +void Samus_MoveExtraY(void); +void Samus_MoveHandlerShinesparkWindup(void); +void Samus_MoveHandlerVerticalShinespark(void); +void Samus_MoveHandler_BombJumpFunc1(void); +void Samus_MoveHandler_BombJumpMain(void); +void Samus_MoveHandler_BombJumpStart(void); +void Samus_MoveHandler_F072(void); +void Samus_MoveHandler_Knockback(void); +void Samus_MoveHandler_Knockback_0(void); +void Samus_MoveHandler_Knockback_3(void); +void Samus_MoveHandler_Knockback_Down(void); +void Samus_MoveHandler_Knockback_Up(void); +void Samus_MoveHandler_ReleaseFromGrapple(void); +void Samus_MoveHandler_ShinesparkCrash(void); +void Samus_MoveHandler_ShinesparkCrashEchoCircle(void); +void Samus_MoveHandler_ShinesparkCrashFinish(void); +void Samus_MoveHandler_ShinesparkCrash_0(void); +void Samus_MoveHandler_ShinesparkCrash_1(void); +void Samus_MoveHandler_ShinesparkCrash_2(void); +void Samus_MoveHandler_Shinespark_Diag(void); +void Samus_MoveHandler_Shinespark_Horiz(void); +void Samus_MoveLeft(void); +void Samus_MoveLeft_NoColl(void); +void Samus_MoveRight(void); +void Samus_MoveRight_NoColl(void); +void Samus_MoveUp(void); +void Samus_MoveUp_NoColl(void); +void Samus_MoveUp_SetPoseCalcInput(void); +void Samus_MoveX(void); +void Samus_MoveY_WithSpeedCalc(void); +void Samus_Move_NoBaseSpeed_X(void); +void Samus_Move_NoSpeedCalc_Y(void); +void Samus_MovementHandler_Normal(void); +void Samus_Movement_00_Standing(void); +void Samus_Movement_01_Running(void); +void Samus_Movement_02_NormalJumping(void); +void Samus_Movement_03_SpinJumping(void); +void Samus_Movement_04_MorphBallOnGround(void); +void Samus_Movement_05_Crouching(void); +void Samus_Movement_06_Falling(void); +void Samus_Movement_07_Unused(void); +void Samus_Movement_08_MorphBallFalling(void); +void Samus_Movement_09_Unused(void); +void Samus_Movement_0A_KnockbackOrCrystalFlashEnding(void); +void Samus_Movement_0B_Unused(void); +void Samus_Movement_0C_Unused(void); +void Samus_Movement_0D_Unused(void); +void Samus_Movement_0E_TurningAroundOnGround(void); +void Samus_Movement_0F_CrouchingEtcTransition(void); +void Samus_Movement_10_Moonwalking(void); +void Samus_Movement_11_SpringBallOnGround(void); +void Samus_Movement_12_SpringBallInAir(void); +void Samus_Movement_13_SpringBallFalling(void); +void Samus_Movement_14_WallJumping(void); +void Samus_Movement_15_RanIntoWall(void); +void Samus_Movement_16_Grappling(void); +void Samus_Movement_17_TurningAroundJumping(void); +void Samus_Movement_18_TurningAroundFalling(void); +void Samus_Movement_19_DamageBoost(void); +void Samus_Movement_1A_GrabbedByDraygon(void); +void Samus_Movement_1B_ShinesparkEtc(void); +void Samus_PauseCheck(void); +void Samus_PostGrappleCollisionDetect(void); +void Samus_PushOutOfRidleysWay(void); +void Samus_ReleaseFromDraygon(void); +void Samus_ReleaseFromDraygon_(void); +void Samus_ScrollFinishedHook_SporeSpawnFight(void); +void Samus_SetGrabbedByDraygonPose(uint16 a); +void Samus_SetPushedOutOfCeresRidley(void); +void Samus_SetRadius(void); +void Samus_SetSpeedForKnockback_Y(void); +void Samus_ShinesparkMove_X(void); +void Samus_ShinesparkMove_Y(void); +void Samus_ShootCheck(void); +void Samus_SpawnAirBubbles(void); +void Samus_SpawnWaterSplash(void); +void Samus_SpinJumpMovement(void); +void Samus_UpdatePreviousPose(void); +void Samus_UpdateSpeedEchoPos(void); +void Samus_UpdateSuitPaletteIndex(void); +void Samus_VerticalBombJump(void); +void SetContactDamageIndexAndUpdateMinimap(void); +void SetInitialProjectileSpeed(void); +void SetLiquidPhysicsType(void); +void SetupBombJump(void); +void SpawnProjectileTrail(uint16 k); +void SuperMissileBlockCollDetect_X(void); +void SuperMissileBlockCollDetect_Y(void); +void SwappedAmmoRoutine(void); +void UpdateBeamTilesAndPalette(void); +void UpdateMinimap(void); +void UpdateMinimapInside(void); +void WaveBeam_CheckColl(uint16 k); +void WaveBeam_CheckColl_0459(void); +void WaveBeam_CheckColl_1368(void); +void WaveBeam_CheckColl_2(void); +void WaveBeam_CheckColl_7(void); +void WriteBeamPalette_A(uint16 a); +void WriteBeamPalette_Y(uint16 j); +void kSamusMoveHandler_CrystalFlashFinish(void); +void sub_90EB55(void); +void sub_90EB86(void); + +// Bank 91 +PairU16 Xray_HandleXrayedBlock(uint16 k); +uint16 DemoInstr_ClearPreInstr(uint16 k, uint16 j); +uint16 DemoInstr_DecTimerAndGoto(uint16 k, uint16 j); +uint16 DemoInstr_Disable(uint16 k, uint16 j); +uint16 DemoInstr_Finish(uint16 k, uint16 j); +uint16 DemoInstr_Func2(uint16 k, uint16 j); +uint16 DemoInstr_Func3(uint16 k, uint16 j); +uint16 DemoInstr_Goto(uint16 k, uint16 j); +uint16 DemoInstr_SetPreInstr(uint16 k, uint16 j); +uint16 DemoInstr_SetTimer(uint16 k, uint16 j); +uint16 Xray_Func10(uint16 j); +uint16 Xray_Func11(uint16 j); +uint16 Xray_Func21(uint16 j); +uint16 Xray_Func5(void); +uint16 Xray_Func7(uint16 j); +uint16 Xray_Func8(uint16 j); +uint16 Xray_Func9(uint16 j); +uint8 CanXrayShowBlocks(void); +uint8 HandleBeamChargePalettes(void); +uint8 HandleCollDueToChangedPose_Block_CollAbove(void); +uint8 HandleCollDueToChangedPose_Block_CollBelow(void); +uint8 HandleCollDueToChangedPose_Block_CollBoth(void); +uint8 HandleCollDueToChangedPose_Block_NoColl(void); +uint8 HandleCollDueToChangedPose_Solid_CollAbove(void); +uint8 HandleCollDueToChangedPose_Solid_CollBelow(void); +uint8 HandleCollDueToChangedPose_Solid_CollBoth(void); +uint8 HandleCollDueToChangedPose_Solid_NoColl(void); +uint8 HandleVisorPalette(void); +uint8 MaybeUnused_sub_91F7F4(void); +uint8 MaybeUnused_sub_91F840(void); +uint8 MaybeUnused_sub_91F8B0(void); +uint8 SamusFunc_F404(void); +uint8 SamusFunc_F468_CrouchTransEtc(void); +uint8 SamusFunc_F468_Crouching(void); +uint8 SamusFunc_F468_DamageBoost(void); +uint8 SamusFunc_F468_DamageBoost_(void); +uint8 SamusFunc_F468_Falling(void); +uint8 SamusFunc_F468_Moonwalking(void); +uint8 SamusFunc_F468_MorphBall(void); +uint8 SamusFunc_F468_NormalJump(void); +uint8 SamusFunc_F468_Running(void); +uint8 SamusFunc_F468_Shinespark(void); +uint8 SamusFunc_F468_SpinJump(void); +uint8 SamusFunc_F468_Springball(void); +uint8 SamusFunc_F468_Standing(void); +uint8 SamusFunc_F468_TurnAroundFalling(void); +uint8 SamusFunc_F468_TurnAroundJumping(void); +uint8 SamusFunc_F468_TurningAroundOnGround(void); +uint8 SamusFunc_F468_Unused(void); +uint8 SamusFunc_F468_WallJumping(void); +uint8 Samus_CheckWalkedIntoSomething(void); +uint8 Samus_CrouchTrans(void); +uint8 Samus_HandleCrystalFlashPals(void); +uint8 Samus_HandleScrewAttackSpeedBoostingPals(void); +uint8 Samus_HandleShinesparkingPals(void); +uint8 Samus_HandleTransFromBlockColl_1_0(void); +uint8 Samus_HandleTransFromBlockColl_1_1(void); +uint8 Samus_HandleTransFromBlockColl_1_2(void); +uint8 Samus_HandleTransFromBlockColl_1_3(void); +uint8 Samus_HandleTransFromBlockColl_1_5(void); +uint8 Samus_HandleTransitionsA_5_1_0(void); +uint8 Samus_HandleTransitionsA_5_1_2(void); +uint8 Samus_HandleTransitionsA_5_1_5(void); +uint8 Samus_HandleTransitionsB_1_0(void); +uint8 Samus_HandleTransitionsB_1_10(void); +uint8 Samus_HandleTransitionsB_1_11(void); +uint8 Samus_HandleTransitionsB_1_4(void); +uint8 Samus_HandleTransitionsB_1_6(void); +uint8 Samus_HandleTransitionsB_1_7(void); +uint8 Samus_HandleXrayPals(void); +uint8 Samus_MorphBallBounceNoSpringballTrans(void); +uint8 Samus_MorphBallBounceSpringballTrans(void); +uint8 Samus_MorphTrans(void); +uint8 Samus_Pose_Func2(void); +uint8 Samus_SpeedBoosterShinePals(void); +uint8 Samus_StandOrUnmorphTrans(void); +uint8 SomeMotherBrainScripts_0(void); +uint8 SomeMotherBrainScripts_1(void); +uint8 SomeMotherBrainScripts_2(void); +uint8 SomeMotherBrainScripts_3_EnableHyperBeam(void); +uint8 SomeMotherBrainScripts_4(void); +uint8 Xray_Initialize(void); +uint8 nullsub_164(void); +void CalculateXrayHdmaTable_OriginOffScreen(uint16 k, uint16 j); +void CalculateXrayHdmaTable_OriginOnScreen(uint16 k, uint16 j); +void CanXrayShowBlocks_(void); +void CopyToSamusSuitPalette(uint16 k); +void CopyToSamusSuitTargetPalette(uint16 k); +void DemoObjectInputHandler(void); +void DemoPreInstr_864F(void); +void DemoPreInstr_866A(void); +void DemoPreInstr_8AB0(void); +void DemoPreInstr_CheckLeaveDemo(void); +void DemoPreInstr_nullsub_162(void); +void DemoSetFunc_0(void); +void DemoSetFunc_1(void); +void DemoSetFunc_2(void); +void DemoSetFunc_3(void); +void DemoSetFunc_4(void); +void DemoSetFunc_5(void); +void DemoSetFunc_6(void); +void DemoSetFunc_7(void); +void DemoSetFunc_Common(uint16 a); +void DisableDemoInput(void); +void DrawDemoRecorderFrameCounter(void); +void EnableDemoInput(void); +void GameState_28_Unused_(void); +void GravitySuitPickup(void); +void HandleCollDueToChangedPose(void); +void HandleJumpTransition(void); +void HandleJumpTransition_NormalJump(void); +void HandleJumpTransition_SpinJump(void); +void HandleJumpTransition_SpringBallInAir(void); +void HandleJumpTransition_WallJump(void); +void HandleLandingGraphics(void); +void HandleLandingGraphics_Brinstar(void); +void HandleLandingGraphics_Ceres(void); +void HandleLandingGraphics_Crateria(void); +void HandleLandingGraphics_Maridia(void); +void HandleLandingGraphics_Norfair(void); +void HandleLandingGraphics_Tourian(void); +void HandleLandingSoundEffectsAndGfx(void); +void HandleMiscSamusPalette(void); +void HdmaobjPreInstr_XraySetup(uint16 k); +void InitializeSuitPickupHdma(void); +void LoadBlockToXrayTilemap(uint16 a, uint16 k, uint16 j); +void LoadDemoData(void); +void LoadDemoInputObject(uint16 a, uint16 j); +void MakeSamusFaceForward(void); +void PauseDemoRecorder(void); +void ProcessDemoInputObject(void); +void ResetDemoData(void); +void ResponsibleForXrayStandupGlitch(void); +void SamusFunc_E633(void); +void SamusFunc_E633_0(void); +void SamusFunc_E633_17(void); +void SamusFunc_E633_20(void); +void SamusFunc_E633_3(void); +void SamusFunc_E633_4(void); +void SamusFunc_EC80(void); +void SamusFunc_F1D3(void); +void SamusFunc_F433(void); +void SamusFunc_F468(void); +void SamusFunc_FA0A(void); +void Samus_CancelSpeedBoost(void); +void Samus_Copy10PalColors(uint16 j); +void Samus_Copy6PalColors(uint16 j); +void Samus_DealDamage(uint16 a); +void Samus_Func20(void); +void Samus_HandlePalette(void); +void Samus_HandleTransFromBlockColl(void); +void Samus_HandleTransFromBlockColl_1(void); +void Samus_HandleTransFromBlockColl_2(void); +void Samus_HandleTransFromBlockColl_3(void); +void Samus_HandleTransFromBlockColl_4(void); +void Samus_HandleTransFromBlockColl_5(void); +void Samus_HandleTransitions(void); +void Samus_HandleTransitionsA_1(void); +void Samus_HandleTransitionsA_2(void); +void Samus_HandleTransitionsA_5(void); +void Samus_HandleTransitionsA_5_1(void); +void Samus_HandleTransitionsA_5_2(void); +void Samus_HandleTransitionsA_5_4(void); +void Samus_HandleTransitionsA_5_5(void); +void Samus_HandleTransitionsA_5_6(void); +void Samus_HandleTransitionsA_6(void); +void Samus_HandleTransitionsA_7(void); +void Samus_HandleTransitionsA_8(void); +void Samus_HandleTransitionsB_1(void); +void Samus_HandleTransitionsB_10(void); +void Samus_HandleTransitionsB_2(void); +void Samus_HandleTransitionsB_3(void); +void Samus_HandleTransitionsB_4(void); +void Samus_HandleTransitionsB_5(void); +void Samus_HandleTransitionsB_8(void); +void Samus_HandleTransitionsB_9(void); +void Samus_HandleTransitionsB_9B(void); +void Samus_HandleTransitionsC_1(void); +void Samus_HandleTransitionsC_2(void); +void Samus_HandleTransitionsC_3(void); +void Samus_HandleTransitionsC_4(void); +void Samus_HandleTransitionsC_5(void); +void Samus_HandleTransitionsC_6(void); +void Samus_HandleTransitionsC_7(void); +void Samus_HandleTransitionsC_8(void); +void Samus_Initialize(void); +void Samus_InputHandler(void); +void Samus_Input_00_Standing(void); +void Samus_Input_01_Running(void); +void Samus_Input_02_NormalJumping(void); +void Samus_Input_03_SpinJumping(void); +void Samus_Input_04_MorphBallOnGround(void); +void Samus_Input_05_Crouching(void); +void Samus_Input_06_Falling(void); +void Samus_Input_07_Unused(void); +void Samus_Input_08_MorphBallFalling(void); +void Samus_Input_09_Unused(void); +void Samus_Input_0A_KnockbackOrCrystalFlashEnding(void); +void Samus_Input_0B_Unused(void); +void Samus_Input_0C_Unused(void); +void Samus_Input_0D_Unused(void); +void Samus_Input_0E_TurningAroundOnGround(void); +void Samus_Input_0F_CrouchingEtcTransition(void); +void Samus_Input_10_Moonwalking(void); +void Samus_Input_11_SpringBallOnGround(void); +void Samus_Input_12_SpringBallInAir(void); +void Samus_Input_13_SpringBallFalling(void); +void Samus_Input_14_WallJumping(void); +void Samus_Input_15_RanIntoWall(void); +void Samus_Input_16_Grappling(void); +void Samus_Input_17_TurningAroundJumping(void); +void Samus_Input_18_TurningAroundFalling(void); +void Samus_Input_19_DamageBoost(void); +void Samus_Input_1A_GrabbedByDraygon(void); +void Samus_Input_1B_ShinesparkEtc(void); +void Samus_LoadSuitPalette(void); +void Samus_LoadSuitTargetPalette(void); +void Samus_LookupTransitionTable(void); +void Samus_Pose_CancelGrapple(void); +void Samus_RestoreHealth(uint16 a); +void Samus_RestoreMissiles(uint16 a); +void Samus_RestorePowerBombs(uint16 a); +void Samus_RestoreSuperMissiles(uint16 a); +void Samus_SetAnimationFrameIfPoseChanged(void); +void Samus_UpdatePreviousPose_0(void); +void SomeMotherBrainScripts(uint16 a); +void TranslateCustomControllerBindingsToDefault(void); +void VariaSuitPickup(void); +void XrayHdmaFunc_BeamAimedD(void); +void XrayHdmaFunc_BeamAimedDD(uint16 j); +void XrayHdmaFunc_BeamAimedDDL(uint16 j); +void XrayHdmaFunc_BeamAimedDDR(uint16 j); +void XrayHdmaFunc_BeamAimedL(void); +void XrayHdmaFunc_BeamAimedR(void); +void XrayHdmaFunc_BeamAimedU(void); +void XrayHdmaFunc_BeamAimedUU(uint16 j); +void XrayHdmaFunc_BeamAimedUUL(uint16 j); +void XrayHdmaFunc_BeamAimedUUR(uint16 j); +void XrayHdmaFunc_BeamHoriz(void); +void XrayHdmaOnScreen_BeamAimedD(void); +void XrayHdmaOnScreen_BeamAimedDD(uint16 j); +void XrayHdmaOnScreen_BeamAimedDDL(uint16 j); +void XrayHdmaOnScreen_BeamAimedDDR(uint16 j); +void XrayHdmaOnScreen_BeamAimedL(void); +void XrayHdmaOnScreen_BeamAimedR(void); +void XrayHdmaOnScreen_BeamAimedU(void); +void XrayHdmaOnScreen_BeamAimedUU(uint16 j); +void XrayHdmaOnScreen_BeamAimedUUL(uint16 j); +void XrayHdmaOnScreen_BeamAimedUUR(uint16 j); +void XrayHdmaOnScreen_BeamHoriz(void); +void XrayRunHandler(void); +void Xray_Func12(uint16 j); +void Xray_Func13(uint16 a); +void Xray_Func14(uint16 j); +void Xray_Func15(uint16 j); +void Xray_Func16(uint16 a); +void Xray_Func20(void); +void Xray_Func6(void); +void Xray_Func6B(void); +void Xray_Func6C(void); +void Xray_Func6D(void); +void Xray_SetupStage1_FreezeTimeBackup(uint16 k); +void Xray_SetupStage2_ReadBg1_2ndScreen(void); +void Xray_SetupStage3_ReadBg1_1stScreen(void); +void Xray_SetupStage4(void); +void Xray_SetupStage4_Func1(void); +void Xray_SetupStage4_Func2(void); +void Xray_SetupStage4_Func3(void); +void Xray_SetupStage5(void); +void Xray_SetupStage6(void); +void Xray_SetupStage7(void); +void Xray_SetupStage8_SetBackdropColor(void); +void Xray_SomeDivide(void); +void sub_91D2D1(void); +void sub_91EFC3(void); + +// Bank 92 +uint8 PlaySamusFanfare(void); +void DrawSamusSuitExploding(void); +void SetSamusTilesDefsForCurAnim(void); +void Unused_SamusTileViewer(void); + +// Bank 93 +uint16 Proj93Instr_Delete(uint16 k, uint16 j); +uint16 Proj93Instr_Goto(uint16 k, uint16 j); +uint16 Proj93Instr_GotoIfLess(uint16 k, uint16 j); +void DrawBombAndProjectileExplosions(void); +void DrawPlayerExplosions2(void); +void InitializeBombExplosion(uint16 k); +void InitializeInstrForMissile(uint16 k); +void InitializeInstrForSuperMissile(uint16 k); +void InitializeProjectile(uint16 k); +void InitializeSbaProjectile(uint16 k); +void InitializeShinesparkEchoOrSpazerSba(uint16 k); +void KillProjectileInner(uint16 k); +void ProjectileInsts_GetValue(uint16 k); +void RunProjectileInstructions(void); +void sub_9382FD(void); + +// Bank 94 +uint16 BlockColl_GetBlockIndexAbove(uint16 k); +uint16 BlockColl_GetBlockIndexBelow(uint16 k); +uint16 BlockColl_GetBlockIndexLeft(uint16 k); +uint16 BlockColl_GetBlockIndexRight(uint16 k); +uint16 ClearCarry_0(void); +uint16 GrappleInstr_Goto(uint16 j); +uint16 PostGrappleColl_Horiz(uint16 k); +uint16 PostGrappleColl_Horiz_Slope(void); +uint16 PostGrappleColl_Horiz_Slope_NonSquare(uint16 k); +uint16 PostGrappleColl_Horiz_Slope_Square(uint16 k); +uint16 PostGrappleColl_Horiz_Solid(void); +uint16 PostGrappleColl_Vert(uint16 k); +uint16 PostGrappleColl_Vert_Slope(void); +uint16 PostGrappleColl_Vert_Slope_NonSquare(uint16 k); +uint16 PostGrappleColl_Vert_Solid(void); +uint16 PostGrappleColl_Vertical_Slope_Square(uint16 k); +uint8 BlockBombedReact_Special(void); +uint8 BlockCollGrappleBeam(void); +uint8 BlockCollMissileHoriz(uint16 k); +uint8 BlockCollMissileVert(uint16 k); +uint8 BlockCollNoWaveBeamHoriz(uint16 k); +uint8 BlockCollNoWaveBeamVert(uint16 k); +uint8 BlockCollSpreadBomb(uint16 k); +uint8 BlockCollWaveBeamHoriz(uint16 k); +uint8 BlockCollWaveBeamVert(uint16 k); +uint8 BlockColl_Handle_Horiz(void); +uint8 BlockColl_Handle_Vert_LeftToRight(void); +uint8 BlockColl_Handle_Vert_RightToLeft(void); +uint8 BlockColl_Horiz_BombBlock(void); +uint8 BlockColl_Horiz_BombableAir(void); +uint8 BlockColl_Horiz_CheckColl(uint16 k); +uint8 BlockColl_Horiz_Door(void); +uint8 BlockColl_Horiz_Slope(void); +uint8 BlockColl_Horiz_Slope_NonSquare(void); +uint8 BlockColl_Horiz_Slope_Square(uint16 a, uint16 k); +uint8 BlockColl_Horiz_SolidShootGrappleBlock(void); +uint8 BlockColl_Horiz_SpecialAir(void); +uint8 BlockColl_Horiz_SpecialBlock(void); +uint8 BlockColl_Horiz_SpikeBlock(void); +uint8 BlockColl_Vert_BombBlock(void); +uint8 BlockColl_Vert_BombableAir(void); +uint8 BlockColl_Vert_CheckColl(uint16 k); +uint8 BlockColl_Vert_Door(void); +uint8 BlockColl_Vert_Slope(void); +uint8 BlockColl_Vert_Slope_NonSquare(uint16 k); +uint8 BlockColl_Vert_Slope_Square(uint16 a, uint16 k); +uint8 BlockColl_Vert_SolidShootGrappleBlock(void); +uint8 BlockColl_Vert_SpecialAir(void); +uint8 BlockColl_Vert_SpecialBlock(void); +uint8 BlockColl_Vert_SpikeAir(void); +uint8 BlockColl_Vert_SpikeBlock(void); +uint8 BlockFunc_ABB0(void); +uint8 BlockFunc_ABE6(void); +uint8 BlockFunc_AC31(void); +uint8 BlockFunc_AEE3(void); +uint8 BlockFunc_AF0D(uint16 k); +uint8 BlockInsideReact_ShootableAir(void); +uint8 BlockInsideReact_Slope(void); +uint8 BlockInsideReact_SpecialAir(void); +uint8 BlockInsideReact_Special_(void); +uint8 BlockInsideReact_SpikeAir(void); +uint8 BlockInsideReact_SpikeAir_BTS1(void); +uint8 BlockReactGrapple(void); +uint8 BlockReactGrapple_GrappleBlock(void); +uint8 BlockReactGrapple_SpikeBlock(void); +uint8 BlockReact_AA64(void); +uint8 BlockReact_AA64_SpikeAir(void); +uint8 BlockReact_AA64_SpikeBlock(void); +uint8 BlockReact_BombableAir(void); +uint8 BlockReact_BombableBlock(void); +uint8 BlockReact_HorizExt(void); +uint8 BlockReact_Shootable(void); +uint8 BlockReact_ShootableAir(void); +uint8 BlockReact_VertExt(void); +uint8 BlockShotReactHoriz(uint16 k); +uint8 BlockShotReactHoriz_Slope(void); +uint8 BlockShotReactHoriz_Slope_NonSquare(void); +uint8 BlockShotReactHoriz_Slope_Square(uint16 a, uint16 k); +uint8 BlockShotReactVert(uint16 k); +uint8 BlockShotReactVert_Slope(void); +uint8 BlockShotReactVert_Slope_NonSquare(void); +uint8 BlockShotReactVert_Slope_Square(uint16 a, uint16 k); +uint8 BlockShotReact_Slope_NonSquare(uint16 j, uint16 k); +uint8 ClearCarrySetZero(void); +uint8 ClearCarryZero(void); +uint8 ClearCarry_1(void); +uint8 ClearCarry_10(void); +uint8 ClearCarry_11(void); +uint8 ClearCarry_2(void); +uint8 ClearCarry_3(void); +uint8 ClearCarry_4(void); +uint8 ClearCarry_5(void); +uint8 ClearCarry_6(void); +uint8 ClearCarry_7(void); +uint8 ClearCarry_9(void); +uint8 CollDetectDueToPoseChange_SingleBlock(void); +uint8 HandleMovementAndCollForSamusGrapple(void); +uint8 MaybeUnused_sub_9497DA(void); +uint8 MaybeUnused_sub_9497F2(void); +uint8 Samus_CollDetectChangedPose(void); +uint8 Samus_MoveDown_NoSolidColl(void); +uint8 Samus_MoveRight_NoSolidColl(void); +uint8 SetCarry_0(void); +uint8 SetCarry_1(void); +uint8 SetCarry_2(void); +uint8 SetCarry_3(void); +uint8 WallJumpBlockCollDetect(void); +uint8 sub_949D5D(void); +void AbsoluteValueOfInt32(void); +void AbsoluteValueOfInt32_0(void); +void BlockBombedReact(uint16 k); +void BlockColl_BombExplosion(uint16 k); +void BlockColl_SpikeBlock_BTS0(void); +void BlockColl_SpikeBlock_BTS1(void); +void BlockColl_SpikeBlock_BTS3(void); +void BlockFunc_9C73(uint16 k); +void BlockFunc_A06A(uint16 k); +void BlockFunc_A0F4(uint16 a); +void BlockFunc_A11A(uint16 a); +void BlockFunc_A957(void); +void BlockFunc_AC11(void); +void BlockGetSomePos1(uint16 k); +void BlockGetSomePos2(uint16 k); +void BlockInsideDetection(void); +void BlockInsideReact_SpecialAir_10(void); +void BlockInsideReact_SpecialAir_11(void); +void BlockInsideReact_SpecialAir_70(void); +void BlockInsideReact_SpecialAir_8(void); +void BlockInsideReact_SpecialAir_9(void); +void BlockInsideReact_SpecialAir_Default(void); +void BlockInsideReact_SpikeAir_BTS2(void); +void BombOrPowerBomb_Func1(uint16 k); +void CalculateBlockAt(void); +void ClearCarry_8(void); +void DrawGrappleOams(uint16 j); +void DrawGrappleOams2(void); +void DrawGrappleOams3(void); +void GrappleFunc_AF87(void); +void HandleGrappleBeamGfx(void); +void PostGrappleCollisionDetect_Down(void); +void PostGrappleCollisionDetect_Left(void); +void PostGrappleCollisionDetect_Right(void); +void PostGrappleCollisionDetect_Up(void); +void PostGrappleCollisionDetect_X(void); +void PostGrappleCollisionDetect_Y(void); +void Samus_AlignYPosSlope(void); +void Samus_GetXposSpan(void); +void Samus_GetYposSpan(void); + +// Bank 9B +int CheckBannedDraygonGrappleDirs(uint16 a); +int ProcessEnemyGrappleBeamColl(uint16 a); +uint16 GameState_24_SamusNoHealth_Explosion_2(void); +uint16 GameState_24_SamusNoHealth_Explosion_Helper(void); +uint16 HandleSamusDeathSequence(void); +uint8 CheckIfGrappleIsConnectedToBlock(void); +uint8 ClearCarry_12(void); +uint8 HandleSpecialGrappleBeamAngles(void); +void CancelGrappleBeamIfIncompatiblePose(void); +void CopyPalettesForSamusDeath(uint16 k); +void DrawSamusStartingDeathAnim_(void); +void GameState_24_SamusNoHealth_Explosion_1(void); +void GrappleBeamFunc_BB64(void); +void GrappleBeamFunc_BC1F(void); +void GrappleBeamFunc_BCFF(void); +void GrappleBeamFunc_BD44(void); +void GrappleBeamFunc_BD95(void); +void GrappleBeamFunc_BE98(void); +void GrappleBeamFunc_BEEB(void); +void GrappleBeamFunc_BF1B(void); +void GrappleBeamFunc_C832(void); +void GrappleBeamFunc_C9CE(void); +void GrappleBeamFunc_Cancel(void); +void GrappleBeamFunc_ConnectedLockedInPlace(void); +void GrappleBeamFunc_Connected_Swinging(void); +void GrappleBeamFunc_FireGoToCancel(void); +void GrappleBeamFunc_Firing(void); +void GrappleBeamFunc_Inactive(void); +void GrappleBeamFunc_ReleaseFromSwing(void); +void GrappleBeamFunc_Wallgrab(void); +void GrappleBeamHandler(void); +void GrappleBeam_Func2(void); +void GrappleNext_CrouchAimDownLeft(void); +void GrappleNext_CrouchAimDownRight(void); +void GrappleNext_CrouchAimLeft(void); +void GrappleNext_CrouchAimRight(void); +void GrappleNext_StandAimDownLeft(void); +void GrappleNext_StandAimDownRight(void); +void GrappleNext_StandAimLeft(void); +void GrappleNext_StandAimRight(void); +void GrappleNext_SwingAntiClockwise(void); +void GrappleNext_SwingClockwise(void); +void HandleConnectingGrapple(void); +void HandleConnectingGrapple_StuckInPlace(void); +void HandleConnectingGrapple_Swinging(void); +void HandleGrappleBeamFlare(void); +void HandleSamusDeathSequence_Helper2(void); +void ProjectileTrail_Func5(uint16 k, uint16 j); +void PropelSamusFromGrappleSwing(void); +void QueueTransferOfSamusDeathSequence(uint16 j); +void StartSamusDeathAnimation(void); +void UNUSED_sub_9BB8D5(void); +void UNUSED_sub_9BBA31(void); +void UNUSED_sub_9BC759(void); +void UpdateGrappleBeamTiles(void); +void UpdateGrappleBeamTilesAndIncrFlameCtr(void); + +// Bank A0 +uint16 Abs16(uint16 a); +uint16 CalculateAngleFromXY(void); +uint16 CalculateAngleFromXY_(void); +uint16 CalculateAngleFromXY_0(uint16 div); +uint16 CalculateAngleFromXY_1(uint16 div); +uint16 CalculateAngleFromXY_2(uint16 div); +uint16 CalculateAngleFromXY_3(uint16 div); +uint16 CalculateAngleFromXY_4(uint16 div); +uint16 CalculateAngleFromXY_5(uint16 div); +uint16 CalculateAngleFromXY_6(uint16 div); +uint16 CalculateAngleFromXY_7(uint16 div); +uint16 CalculateAngleOfEnemyXfromEnemyY(uint16 k, uint16 j); +uint16 CalculateAngleOfSamusFromEnemy(uint16 k); +uint16 CalculateAngleOfSamusFromEproj(uint16 k); +uint16 CheckIfEnemyIsOnScreen(void); +uint16 CheckIfEnemyTouchesSamus(uint16 k); +uint16 CosineMult8bit(uint16 a); +uint16 DetermineDirectionOfSamusFromEnemy(void); +uint16 EnemyFunc_AC67(uint16 k); +uint16 EnemyFunc_ACA8(void); +uint16 EnemyFunc_ADA3(uint16 a); +uint16 EnemyInstr_ClearAiPreInstr(uint16 k, uint16 j); +uint16 EnemyInstr_CopyToVram(uint16 k, uint16 j); +uint16 EnemyInstr_DecTimerAndGoto(uint16 k, uint16 j); +uint16 EnemyInstr_DecTimerAndGoto2(uint16 k, uint16 j); +uint16 EnemyInstr_DecTimerAndGotoRel(uint16 k, uint16 j); +uint16 EnemyInstr_DisableOffScreenProcessing(uint16 k, uint16 j); +uint16 EnemyInstr_EnableOffScreenProcessing(uint16 k, uint16 j); +uint16 EnemyInstr_Goto(uint16 k, uint16 j); +uint16 EnemyInstr_GotoRel(uint16 k, uint16 j); +uint16 EnemyInstr_SetAiPreInstr(uint16 k, uint16 j); +uint16 EnemyInstr_SetTimer(uint16 k, uint16 j); +uint16 EnemyInstr_Skip2bytes(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep(uint16 k, uint16 j); +uint16 EnemyInstr_StopScript(uint16 k, uint16 j); +uint16 EnemyInstr_WaitNframes(uint16 k, uint16 j); +uint16 EnemyWithNormalSpritesIsOffScreen(void); +uint16 GetSamusEnemyDelta_X(uint16 k); +uint16 GetSamusEnemyDelta_Y(uint16 k); +uint16 GrappleBeam_CollDetect_Enemy(void); +uint16 IsSamusWithinEnemy_X(uint16 k, uint16 a); +uint16 IsSamusWithinEnemy_Y(uint16 k, uint16 a); +uint16 Mult32(uint16 a); +uint16 Samus_CheckSolidEnemyColl(void); +uint16 SignExtend8(uint16 a); +uint16 SineMult8bit(void); +uint16 SineMult8bitNegative(uint16 a); +uint16 SpawnEnemy(uint8 db, uint16 k); +uint16 SubtractThenAbs16(uint16 k, uint16 j); +uint16 SuitDamageDivision(uint16 a); +uint8 ClearCarry_13(void); +uint8 CompareDistToSamus_X(uint16 k, uint16 a); +uint8 CompareDistToSamus_Y(uint16 k, uint16 a); +uint8 EnemyBlockCollHorizReact_Slope(void); +uint8 EnemyBlockCollHorizReact_Slope_NonSquare(void); +uint8 EnemyBlockCollHorizReact_Slope_Square(uint16 k, uint16 a); +uint8 EnemyBlockCollReact_Horiz(uint16 k); +uint8 EnemyBlockCollReact_HorizExt(void); +uint8 EnemyBlockCollReact_Spike(void); +uint8 EnemyBlockCollReact_Vert(uint16 k); +uint8 EnemyBlockCollReact_VertExt(void); +uint8 EnemyBlockCollVertReact_Slope(void); +uint8 EnemyBlockCollVertReact_Slope_NonSquare(void); +uint8 EnemyBlockCollVertReact_Slope_Square(uint16 a, uint16 k); +uint8 EnemyFunc_BBBF(uint16 k); +uint8 EnemyFunc_BC76(uint16 k); +uint8 EnemyFunc_BF8A(uint16 k, uint16 a); +uint8 EnemyFunc_C8AD(uint16 k); +uint8 Enemy_MoveDown(uint16 k); +uint8 Enemy_MoveDownInner(uint16 k); +uint8 Enemy_MoveRight_IgnoreSlopes(uint16 k); +uint8 Enemy_MoveRight_IgnoreSlopes_Inner(uint16 k); +uint8 Enemy_MoveRight_ProcessSlopes(uint16 k); +uint8 Enemy_MoveRight_SlopesAsWalls(uint16 k); +uint8 Enemy_SetYpos_Aligned(uint16 j); +uint8 IsEnemyLeavingScreen(uint16 k); +uint8 SetCarry_4(void); +void ClearEnemyDataAndProcessEnemySet(void); +void ConvertAngleToXy(void); +void CreateADudShot(void); +void CreateDudShot(void); +void DebugLoadEnemySetData(void); +void DecrementSamusTimers(void); +void DeleteEnemyAndConnectedEnemies(void); +void DetermineWhichEnemiesToProcess(void); +void DrawOneEnemy(void); +void DrawSamusEnemiesAndProjectiles(void); +void EnemyBombCollHandler(void); +void EnemyBombCollHandler_Multibox(void); +void EnemyCollisionHandler(void); +void EnemyDeathAnimation(uint16 k, uint16 a); +void EnemyFunc_A6B4_UsedBySporeSpawn(void); +void EnemyFunc_B691(void); +void EnemyFunc_B761(void); +void EnemyFunc_B7A1(void); +void EnemyGrappleDeath(void); +void EnemyMain(void); +void EnemyProjectileCollHandler(void); +void EnemyProjectileCollHandler_Multibox(void); +void EnemySamusCollHandler(void); +void EnemySamusCollHandler_Multibox(void); +void Enemy_AddPos_X(uint16 k); +void Enemy_AddPos_Y(uint16 k); +void Enemy_GrappleReact_CancelBeam_A0(void); +void Enemy_GrappleReact_HurtSamus_A0(void); +void Enemy_GrappleReact_KillEnemy_A0(void); +void Enemy_GrappleReact_NoInteract_A0(void); +void Enemy_GrappleReact_SamusLatchesNoInvinc_A0(void); +void Enemy_GrappleReact_SamusLatchesOn_A0(void); +void Enemy_GrappleReact_SamusLatchesParalyze_A0(void); +void Enemy_ItemDrop_BombTorizo(uint16 k); +void Enemy_ItemDrop_Botwoon(uint16 k); +void Enemy_ItemDrop_Crocomire(uint16 k); +void Enemy_ItemDrop_Draygon(uint16 k); +void Enemy_ItemDrop_GoldenTorizo(uint16 k); +void Enemy_ItemDrop_Kraid(uint16 k); +void Enemy_ItemDrop_LowerNorfairSpacePirate(uint16 k); +void Enemy_ItemDrop_Metroid(uint16 k); +void Enemy_ItemDrop_MiniKraid(uint16 k); +void Enemy_ItemDrop_Phantoon(uint16 k); +void Enemy_ItemDrop_Ridley(uint16 k); +void Enemy_ItemDrop_SporeSpawn(uint16 k); +void Enemy_NormalFrozenAI(void); +void Enemy_NormalPowerBombAI_A0(void); +void Enemy_NormalPowerBombAI_SkipDeathAnim_A0(void); +void Enemy_NormalShotAI_A0(void); +void Enemy_NormalShotAI_SkipSomeParts_A0(void); +void Enemy_NormalTouchAI_A0(void); +void Enemy_NormalTouchAI_SkipDeathAnim_A0(void); +void Enemy_SetXpos_Aligned(uint16 j); +void Enemy_SubPos_X(uint16 k); +void Enemy_SubPos_Y(uint16 k); +void Enemy_SwitchToFrozenAi(void); +void EprojProjCollDet(void); +void EprojSamusCollDetect(void); +void HandleEprojCollWithProj(uint16 k, uint16 j); +void HandleEprojCollWithSamus(uint16 k); +void HandleRoomShaking(void); +void InitializeEnemies(void); +void LoadEnemies(void); +void LoadEnemyGfxIndexes(uint16 k, uint16 j); +void LoadEnemyTileData(void); +void Mult32bit(void); +void NormalEnemyFrozenAI(void); +void NormalEnemyPowerBombAi(void); +void NormalEnemyPowerBombAiSkipDeathAnim(void); +void NormalEnemyPowerBombAiSkipDeathAnim_CurEnemy(void); +void NormalEnemyShotAi(void); +void NormalEnemyShotAiSkipDeathAnim(void); +void NormalEnemyShotAiSkipDeathAnim_CurEnemy(void); +void NormalEnemyTouchAi(void); +void NormalEnemyTouchAiSkipDeathAnim(void); +void NormalEnemyTouchAiSkipDeathAnim_CurEnemy(void); +void ProcessEnemyInstructions(void); +void ProcessEnemyPowerBombInteraction(void); +void ProcessEnemyTilesets(void); +void ProcessExtendedTilemap(uint8 db); +void QueueEnemyBG2TilemapTransfers(void); +void RecordEnemySpawnData(uint16 j); +void RinkasDeathAnimation(uint16 a); +void SamusHurtFromGrapple(void); +void SamusLatchesOnWithGrapple(void); +void SamusLatchesOnWithGrappleNoInvinc(void); +void SamusLatchesOnWithGrappleParalyze(void); +void SamusProjectileInteractionHandler(void); +void SetAllEnemiesToShakeFor2Frames(void); +void SpawnEnemyDrops(uint16 a, uint16 k); +void SwitchEnemyAiToMainAi(void); +void TransferEnemyTilesToVramAndInit(void); +void WriteEnemyOams(void); + +// Bank A2 +uint16 BouncingGoofball_Instr_88C5(uint16 k, uint16 j); +uint16 BouncingGoofball_Instr_88C6(uint16 k, uint16 j); +uint16 BouncingGoofball_SamusCloseX(void); +uint16 EnemyInstr_DecTimerAndGoto2_A2(uint16 k, uint16 j); +uint16 EnemyInstr_DisableOffScreenProcessing_A2(uint16 k, uint16 j); +uint16 EnemyInstr_EnableOffScreenProcessing_A2(uint16 k, uint16 j); +uint16 EnemyInstr_Goto_A2(uint16 k, uint16 j); +uint16 EnemyInstr_Rio_Instr_1(uint16 k, uint16 j); +uint16 EnemyInstr_SetTimer_A2(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep_A2(uint16 k, uint16 j); +uint16 Flies_2(uint16 k); +uint16 LavaSeahorse_Instr_E5FB(uint16 k, uint16 j); +uint16 LowerNorfairRio_Instr_C6D2(uint16 k, uint16 j); +uint16 LowerNorfairRio_Instr_C6DD(uint16 k, uint16 j); +uint16 LowerNorfairRio_Instr_C6E8(uint16 k, uint16 j); +uint16 MaridiaBeybladeTurtle_Instr_9381(uint16 k, uint16 j); +uint16 MaridiaBeybladeTurtle_Instr_9412(uint16 k, uint16 j); +uint16 MaridiaBeybladeTurtle_Instr_9447(uint16 k, uint16 j); +uint16 MaridiaBeybladeTurtle_Instr_9451(uint16 k, uint16 j); +uint16 MaridiaBeybladeTurtle_Instr_946B(uint16 k, uint16 j); +uint16 MaridiaBeybladeTurtle_Instr_9485(uint16 k, uint16 j); +uint16 MaridiaBeybladeTurtle_Instr_94A1(uint16 k, uint16 j); +uint16 MaridiaBeybladeTurtle_Instr_94C7(uint16 k, uint16 j); +uint16 MaridiaBeybladeTurtle_Instr_94D1(uint16 k, uint16 j); +uint16 MaridiaLargeSnail_Instr_CB6B(uint16 k, uint16 j); +uint16 MaridiaLargeSnail_Instr_CCB3(uint16 k, uint16 j); +uint16 MaridiaLargeSnail_Instr_CCBE(uint16 k, uint16 j); +uint16 MaridiaLargeSnail_Instr_CCC9(uint16 k, uint16 j); +uint16 MaridiaSpikeyShell_Instr_A56D(uint16 k, uint16 j); +uint16 MaridiaSpikeyShell_Instr_A571(uint16 k, uint16 j); +uint16 MiniCrocomire_Instr_897E(uint16 k, uint16 j); +uint16 MiniCrocomire_Instr_8990(uint16 k, uint16 j); +uint16 MiniCrocomire_Instr_899D(uint16 k, uint16 j); +uint16 NorfairLavajumpingEnemy_Instr_BE8E(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C1C9(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C1D4(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C1DF(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C1EA(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C1F5(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C200(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C20B(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C216(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C221(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C22C(uint16 k, uint16 j); +uint16 NorfairRio_Instr_C237(uint16 k, uint16 j); +uint16 Rinka_2(uint16 k); +uint16 Rinka_Instr_B9A2(uint16 k, uint16 j); +uint16 Rinka_Instr_B9B3(uint16 k, uint16 j); +uint16 Rinka_Instr_B9BD(uint16 k, uint16 j); +uint16 Rinka_Instr_B9C7(uint16 k, uint16 j); +uint16 SpikeShootingPlant_Instr_9F2A(uint16 k, uint16 j); +uint16 SpikeShootingPlant_Instr_A095(uint16 k, uint16 j); +uint16 SpikeShootingPlant_Instr_A0A7(uint16 k, uint16 j); +uint8 Gripper_Func_1(uint16 k); +uint8 Gripper_Func_2(uint16 k); +uint8 MiniCrocomire_Func9(void); +uint8 Rinka_10(void); +uint8 Rinka_9(uint16 k); +void BouncingGoofball_Func1(uint16 k); +void BouncingGoofball_Func2(void); +void BouncingGoofball_Func3(void); +void BouncingGoofball_Init(void); +void BouncingGoofball_Main(void); +void BouncingGoofball_State0(void); +void BouncingGoofball_State1(void); +void Enemy_GrappleReact_CancelBeam_A2(void); +void Enemy_GrappleReact_KillEnemy_A2(void); +void Enemy_GrappleReact_SamusLatchesOn_A2(void); +void Enemy_NormalFrozenAI_A2(void); +void Enemy_NormalPowerBombAI_A2(void); +void Enemy_NormalShotAI_A2(void); +void Enemy_NormalTouchAI_A2(void); +void Flies_1(uint16 k); +void Flies_3(uint16 k); +void Flies_4(uint16 k); +void Flies_5(uint16 k); +void Flies_6(uint16 k); +void Flies_7(uint16 k); +void Flies_Init(void); +void Flies_Main(void); +void Gripper_Func_3(void); +void Gripper_Func_4(void); +void Gripper_Init(void); +void Gripper_Main(void); +void GunshipBottom_Init(void); +void GunshipTop_1(uint16 k); +void GunshipTop_10(uint16 k); +void GunshipTop_11(uint16 k); +void GunshipTop_12(uint16 k); +void GunshipTop_13(uint16 k); +void GunshipTop_14(uint16 k); +void GunshipTop_15(uint16 k); +void GunshipTop_16(uint16 k); +void GunshipTop_17(uint16 k); +void GunshipTop_18(uint16 k); +void GunshipTop_19(uint16 k); +void GunshipTop_2(uint16 k); +void GunshipTop_20(uint16 k); +void GunshipTop_21(uint16 k); +void GunshipTop_3(uint16 k); +void GunshipTop_4(uint16 k); +void GunshipTop_5(uint16 k); +void GunshipTop_6(uint16 k); +void GunshipTop_7(uint16 k); +void GunshipTop_8(uint16 k); +void GunshipTop_9(uint16 k); +void GunshipTop_Init(void); +void GunshipTop_Main(void); +void HirisingSlowfalling_Func_1(uint16 k); +void HirisingSlowfalling_Func_2(uint16 k); +void HirisingSlowfalling_Func_3(uint16 a); +void HirisingSlowfalling_Func_4(void); +void HirisingSlowfalling_Func_5(void); +void HirisingSlowfalling_Func_6(void); +void HirisingSlowfalling_Func_7(void); +void HirisingSlowfalling_Init(void); +void HirisingSlowfalling_Main(void); +void HorizontalShootableShutter_Func_1(uint16 k); +void HorizontalShootableShutter_Func_10(uint16 k); +void HorizontalShootableShutter_Func_11(uint16 k); +void HorizontalShootableShutter_Func_12(void); +void HorizontalShootableShutter_Func_13(void); +void HorizontalShootableShutter_Func_14(void); +void HorizontalShootableShutter_Func_2(void); +void HorizontalShootableShutter_Func_3(void); +void HorizontalShootableShutter_Func_4(void); +void HorizontalShootableShutter_Func_5(void); +void HorizontalShootableShutter_Func_6(void); +void HorizontalShootableShutter_Func_7(uint16 k); +void HorizontalShootableShutter_Func_8(void); +void HorizontalShootableShutter_Func_9(void); +void HorizontalShootableShutter_Init(void); +void HorizontalShootableShutter_Main(void); +void HorizontalShootableShutter_Powerbomb(void); +void HorizontalShootableShutter_Shot(void); +void HorizontalShootableShutter_Touch(void); +void JetPowerRipper_Init(void); +void JetPowerRipper_Main(void); +void JetPowerRipper_Shot(void); +void LavaSeahorse_E7DA(void); +void LavaSeahorse_Func_1(uint16 k); +void LavaSeahorse_Func_2(uint16 k); +void LavaSeahorse_Func_3(uint16 k); +void LavaSeahorse_Func_4(uint16 k); +void LavaSeahorse_Func_5(uint16 k); +void LavaSeahorse_Func_6(void); +void LavaSeahorse_Func_7(void); +void LavaSeahorse_Init(void); +void LavaSeahorse_Main(void); +void LavaSeahorse_Powerbomb(void); +void LavaSeahorse_Shot(void); +void LavaSeahorse_Touch(void); +void LavaquakeRocks_1(void); +void LavaquakeRocks_2(void); +void LavaquakeRocks_3(void); +void LavaquakeRocks_Init(void); +void LavaquakeRocks_Main(void); +void LowerNorfairRio_Func_1(uint16 k); +void LowerNorfairRio_Func_2(uint16 k); +void LowerNorfairRio_Func_3(uint16 k); +void LowerNorfairRio_Func_4(uint16 k); +void LowerNorfairRio_Func_5(uint16 k); +void LowerNorfairRio_Func_6(uint16 k); +void LowerNorfairRio_Func_7(uint16 a); +void LowerNorfairRio_Init(void); +void LowerNorfairRio_Main(void); +void MaridiaBeybladeTurtle_Func1(uint16 k); +void MaridiaBeybladeTurtle_Func10(uint16 k); +void MaridiaBeybladeTurtle_Func11(uint16 k); +void MaridiaBeybladeTurtle_Func2(uint16 k); +void MaridiaBeybladeTurtle_Func21(void); +void MaridiaBeybladeTurtle_Func3(uint16 k); +void MaridiaBeybladeTurtle_Func4(void); +void MaridiaBeybladeTurtle_Func5(uint16 k); +void MaridiaBeybladeTurtle_Func6(uint16 k); +void MaridiaBeybladeTurtle_Func7(uint16 k); +void MaridiaBeybladeTurtle_Func8(uint16 k); +void MaridiaBeybladeTurtle_Func9(uint16 k); +void MaridiaBeybladeTurtle_Init(void); +void MaridiaBeybladeTurtle_Main(void); +void MaridiaBeybladeTurtle_Touch(void); +void MaridiaLargeSnail_Func_1(uint16 k); +void MaridiaLargeSnail_Func_10(uint16 k); +void MaridiaLargeSnail_Func_11(void); +void MaridiaLargeSnail_Func_12(void); +void MaridiaLargeSnail_Func_2(uint16 k); +void MaridiaLargeSnail_Func_3(uint16 k); +void MaridiaLargeSnail_Func_4(void); +void MaridiaLargeSnail_Func_5(void); +void MaridiaLargeSnail_Func_6(void); +void MaridiaLargeSnail_Func_7(uint16 k); +void MaridiaLargeSnail_Func_8(uint16 k); +void MaridiaLargeSnail_Func_9(void); +void MaridiaLargeSnail_Init(void); +void MaridiaLargeSnail_Main(void); +void MaridiaLargeSnail_Shot(void); +void MaridiaLargeSnail_Touch(uint16 k); +void MaridiaSpikeyShell_1(void); +void MaridiaSpikeyShell_2(void); +void MaridiaSpikeyShell_3(void); +void MaridiaSpikeyShell_4(void); +void MaridiaSpikeyShell_5(void); +void MaridiaSpikeyShell_6(void); +void MaridiaSpikeyShell_7(void); +void MaridiaSpikeyShell_8(uint16 k); +void MaridiaSpikeyShell_Init(void); +void MaridiaSpikeyShell_Main(void); +void MaridiaSpikeyShell_Shot(void); +void MiniCrocomire_Func1(void); +void MiniCrocomire_Func2(void); +void MiniCrocomire_Func3(void); +void MiniCrocomire_Func4(void); +void MiniCrocomire_Func7(void); +void MiniCrocomire_Func8(void); +void MiniCrocomire_Init(void); +void MiniCrocomire_Main(void); +void MiniCrocomire_PreInstr5(uint16 k); +void MiniCrocomire_PreInstr6(uint16 k); +void MiniMaridiaBeybladeTurtle_Func1(uint16 k); +void MiniMaridiaBeybladeTurtle_Func2(uint16 k); +void MiniMaridiaBeybladeTurtle_Func3(uint16 k); +void MiniMaridiaBeybladeTurtle_Func4(uint16 k); +void MiniMaridiaBeybladeTurtle_Func5(uint16 k); +void MiniMaridiaBeybladeTurtle_Func6(uint16 k); +void MiniMaridiaBeybladeTurtle_Func7(void); +void MiniMaridiaBeybladeTurtle_Init(void); +void MiniMaridiaBeybladeTurtle_Main(void); +void MiniMaridiaBeybladeTurtle_Shot(void); +void MiniMaridiaBeybladeTurtle_Touch(void); +void NorfairErraticFireball_Init(void); +void NorfairErraticFireball_Main(void); +void NorfairLavajumpingEnemy_Func_1(uint16 k); +void NorfairLavajumpingEnemy_Func_2(uint16 k); +void NorfairLavajumpingEnemy_Func_3(uint16 k); +void NorfairLavajumpingEnemy_Func_4(uint16 k); +void NorfairLavajumpingEnemy_Func_5(uint16 k); +void NorfairLavajumpingEnemy_Func_6(uint16 a); +void NorfairLavajumpingEnemy_Init(void); +void NorfairLavajumpingEnemy_Main(void); +void NorfairRio_Func_1(uint16 k); +void NorfairRio_Func_2(uint16 k); +void NorfairRio_Func_3(uint16 k); +void NorfairRio_Func_4(uint16 k); +void NorfairRio_Func_5(uint16 k); +void NorfairRio_Func_6(uint16 k); +void NorfairRio_Func_7(uint16 a); +void NorfairRio_Init(void); +void NorfairRio_Main(void); +void Rinka_1(uint16 k); +void Rinka_3(uint16 k); +void Rinka_4(uint16 k); +void Rinka_5(uint16 k); +void Rinka_6(uint16 k); +void Rinka_7(uint16 k); +void Rinka_8(uint16 k); +void Rinka_B85B(uint16 k); +void Rinka_B865(uint16 k); +void Rinka_B960(uint16 k); +void Rinka_Frozen(uint16 k); +void Rinka_Init(void); +void Rinka_Init2(uint16 k); +void Rinka_Init3(uint16 k); +void Rinka_Main(void); +void Rinka_Powerbomb(uint16 k); +void Rinka_Shot(void); +void Rinka_Touch(void); +void Rio_1(uint16 k); +void Rio_2(uint16 k); +void Rio_3(uint16 k); +void Rio_4(uint16 k); +void Rio_5(uint16 k); +void Rio_6(uint16 a); +void Rio_Init(void); +void Rio_Main(void); +void Ripper_Func_1(void); +void Ripper_Init(void); +void Ripper_Main(void); +void RisingFallingPlatform_Func_1(uint16 k); +void RisingFallingPlatform_Func_10(void); +void RisingFallingPlatform_Func_11(void); +void RisingFallingPlatform_Func_12(void); +void RisingFallingPlatform_Func_13(void); +void RisingFallingPlatform_Func_2(void); +void RisingFallingPlatform_Func_3(void); +void RisingFallingPlatform_Func_4(void); +void RisingFallingPlatform_Func_5(void); +void RisingFallingPlatform_Func_6(void); +void RisingFallingPlatform_Func_7(uint16 k); +void RisingFallingPlatform_Func_8(void); +void RisingFallingPlatform_Func_9(void); +void RisingFallingPlatform_Init(void); +void RisingFallingPlatform_Main(void); +void RisingFallingPlatform_Powerbomb(void); +void RisingFallingPlatform_Shot(void); +void RisingFallingPlatform_Touch(void); +void ShootableShutter_Init(void); +void ShootableShutter_Shot(void); +void SpikeShootingPlant_2(uint16 k); +void SpikeShootingPlant_3(uint16 k); +void SpikeShootingPlant_4(void); +void SpikeShootingPlant_5(void); +void SpikeShootingPlant_6(void); +void SpikeShootingPlant_7(void); +void SpikeShootingPlant_8(void); +void SpikeShootingPlant_Init(void); +void SpikeShootingPlant_Main(void); +void ThinHoppingBlobs_Func1(uint16 k); +void ThinHoppingBlobs_Func10(void); +void ThinHoppingBlobs_Func11(void); +void ThinHoppingBlobs_Func12(void); +void ThinHoppingBlobs_Func13(void); +void ThinHoppingBlobs_Func14(void); +void ThinHoppingBlobs_Func15(void); +void ThinHoppingBlobs_Func16(void); +void ThinHoppingBlobs_Func3(void); +void ThinHoppingBlobs_Func4(void); +void ThinHoppingBlobs_Func5(void); +void ThinHoppingBlobs_Func6(uint16 k); +void ThinHoppingBlobs_Func7(void); +void ThinHoppingBlobs_Func8(void); +void ThinHoppingBlobs_Func9(void); +void ThinHoppingBlobs_Init(void); +void ThinHoppingBlobs_Main(void); +void TimedShutter_Func_1(uint16 k); +void TimedShutter_Func_10(uint16 k); +void TimedShutter_Func_11(void); +void TimedShutter_Func_12(void); +void TimedShutter_Func_13(void); +void TimedShutter_Func_14(void); +void TimedShutter_Func_15(void); +void TimedShutter_Func_2(uint16 k); +void TimedShutter_Func_3(uint16 k); +void TimedShutter_Func_4(uint16 k); +void TimedShutter_Func_5(uint16 k); +void TimedShutter_Func_6(void); +void TimedShutter_Func_7(void); +void TimedShutter_Func_8(void); +void TimedShutter_Func_9(void); +void TimedShutter_Init(void); +void TimedShutter_Main(void); +void TwinHoppingBlobs_Func2(void); +void sub_A29A6C(uint16 a); + +// Bank A3 +uint16 Bang_Func_4(uint16 a); +uint16 Bang_Instr_1(uint16 k, uint16 j); +uint16 Bang_Instr_2(uint16 k, uint16 j); +uint16 EnemyInstr_DisableOffScreenProcessing_A3(uint16 k, uint16 j); +uint16 EnemyInstr_EnableOffScreenProcessing_A3(uint16 k, uint16 j); +uint16 EnemyInstr_Goto_A3(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep_A3(uint16 k, uint16 j); +uint16 MaridiaFish_Instr_1(uint16 k, uint16 j); +uint16 MaridiaFish_Instr_2(uint16 k, uint16 j); +uint16 MaridiaFish_Instr_3(uint16 k, uint16 j); +uint16 MaridiaRefillCandy_Instr_1(uint16 k, uint16 j); +uint16 MaridiaRefillCandy_Instr_2(uint16 k, uint16 j); +uint16 MaridiaRefillCandy_Instr_3(uint16 k, uint16 j); +uint16 MaridiaSnail_Instr_1(uint16 k, uint16 j); +uint16 MaridiaSnail_Instr_2(uint16 k, uint16 j); +uint16 MaridiaSnail_Instr_3(uint16 k, uint16 j); +uint16 MaridiaSnail_Instr_4(uint16 k, uint16 j); +uint16 MaridiaSnail_Instr_5(uint16 k, uint16 j); +uint16 Metalee_Instr_1(uint16 k, uint16 j); +uint16 Metroid_Instr_1(uint16 k, uint16 j); +uint16 Metroid_Instr_2(uint16 k, uint16 j); +uint16 PlatformThatFallsWithSamus_Instr_1(uint16 k, uint16 j); +uint16 PlatformThatFallsWithSamus_Instr_2(uint16 k, uint16 j); +uint16 PlatformThatFallsWithSamus_Instr_3(uint16 k, uint16 j); +uint16 PlatformThatFallsWithSamus_Instr_4(uint16 k, uint16 j); +uint16 Reflec_Instr_1(uint16 k, uint16 j); +uint16 Sidehopper_Func_1(uint16 k, uint16 j); +uint16 Sidehopper_Func_2(void); +uint16 Sidehopper_Instr_1(uint16 k, uint16 j); +uint16 Skree_Instr_1(uint16 k, uint16 j); +uint16 Waver_Instr_1(uint16 k, uint16 j); +uint16 WreckedShipOrangeZoomer_Func_1(uint16 k, uint16 j); +uint16 Zoomer_Instr_SetPreinstr(uint16 k, uint16 j); +uint8 MaridiaSnail_Func_17(uint16 k); +uint8 MaridiaSnail_Func_18(uint16 k); +uint8 MaridiaSnail_Func_19(uint16 k); +uint8 MaridiaSnail_Func_20(uint16 k); +uint8 MaridiaSnail_Func_21(uint16 k); +void Bang_Func_1(void); +void Bang_Func_10(uint16 k); +void Bang_Func_11(uint16 k); +void Bang_Func_12(void); +void Bang_Func_13(void); +void Bang_Func_14(void); +void Bang_Func_15(void); +void Bang_Func_16(void); +void Bang_Func_17(void); +void Bang_Func_18(void); +void Bang_Func_2(void); +void Bang_Func_3(void); +void Bang_Func_5(void); +void Bang_Func_6(uint16 k); +void Bang_Func_7(uint16 k); +void Bang_Func_8(uint16 k); +void Bang_Func_9(void); +void Bang_Init(void); +void Bang_Main(void); +void Bang_Shot(void); +void BigEyeBugs_Init(void); +void Crab_Func_1(void); +void Crab_Init(void); +void Elevator_Frozen(void); +void Elevator_Func3b(void); +void Elevator_Func_1(void); +void Elevator_Func_2(void); +void Elevator_Func_3(void); +void Elevator_Func_4(void); +void Elevator_Init(void); +void Enemy_GrappleReact_CancelBeam_A3(void); +void Enemy_GrappleReact_KillEnemy_A3(void); +void Enemy_GrappleReact_NoInteract_A3(void); +void Enemy_NormalFrozenAI_A3(void); +void Enemy_NormalPowerBombAI_A3(void); +void Enemy_NormalShotAI_A3(void); +void Enemy_NormalShotAI_SkipSomeParts_A3(void); +void Enemy_NormalTouchAI_A3(void); +void FastMovingSlowSinkingPlatform_Init(void); +void FastMovingSlowSinkingPlatform_Shot(void); +void FireZoomer_E8A5(uint16 k); +void FireZoomer_Func_1(uint16 k); +void FireZoomer_Func_2(uint16 k); +void FireZoomer_Func_3(uint16 k); +void FireZoomer_Init(void); +void Fireflea_Common(void); +void Fireflea_Func_1(uint16 k); +void Fireflea_Func_2(uint16 k); +void Fireflea_Func_3(uint16 k); +void Fireflea_Func_4(uint16 k); +void Fireflea_Func_5(uint16 k); +void Fireflea_Func_6(uint16 k); +void Fireflea_Init(void); +void Fireflea_Main(void); +void Fireflea_Powerbomb(void); +void Fireflea_Shot(void); +void Fireflea_Touch(uint16 k); +void MaridiaFish_Func_1(void); +void MaridiaFish_Func_2(void); +void MaridiaFish_Func_3(void); +void MaridiaFish_Func_4(void); +void MaridiaFish_Init(void); +void MaridiaFish_Main(void); +void MaridiaRefillCandy_Func_1(void); +void MaridiaRefillCandy_Func_2(uint16 k); +void MaridiaRefillCandy_Func_3(uint16 k); +void MaridiaRefillCandy_Func_4(void); +void MaridiaRefillCandy_Func_5(void); +void MaridiaRefillCandy_Func_6(void); +void MaridiaRefillCandy_Init(void); +void MaridiaRefillCandy_Main(void); +void MaridiaSnail_CFB7(uint16 k); +void MaridiaSnail_CFBD(uint16 k); +void MaridiaSnail_CFCE(uint16 k); +void MaridiaSnail_CFD4(uint16 k); +void MaridiaSnail_CFE5(uint16 k); +void MaridiaSnail_CFEB(uint16 k); +void MaridiaSnail_CFFC(uint16 k); +void MaridiaSnail_D002(uint16 k, uint16 j); +void MaridiaSnail_D07E(uint16 k, uint16 j); +void MaridiaSnail_Func_1(uint16 k); +void MaridiaSnail_Func_10(uint16 k, uint16 j); +void MaridiaSnail_Func_11(uint16 k, uint16 j); +void MaridiaSnail_Func_12(uint16 k, uint16 a); +void MaridiaSnail_Func_13(uint16 k, uint16 a); +void MaridiaSnail_Func_14(uint16 k); +void MaridiaSnail_Func_15(uint16 k); +void MaridiaSnail_Func_16(uint16 k); +void MaridiaSnail_Func_2(uint16 k, uint16 j); +void MaridiaSnail_Func_22(uint16 k); +void MaridiaSnail_Func_23(uint16 k); +void MaridiaSnail_Func_3(uint16 k); +void MaridiaSnail_Func_4(uint16 k); +void MaridiaSnail_Func_5(uint16 k); +void MaridiaSnail_Func_6(uint16 k); +void MaridiaSnail_Func_7(uint16 k); +void MaridiaSnail_Func_8(uint16 a); +void MaridiaSnail_Func_9(uint16 k); +void MaridiaSnail_Init(void); +void MaridiaSnail_Main(void); +void MaridiaSnail_Shot(void); +void MaridiaSnail_Touch(void); +void Metalee_Func_1(void); +void Metalee_Func_2(uint16 k); +void Metalee_Func_3(uint16 k); +void Metalee_Func_4(void); +void Metalee_Func_5(void); +void Metalee_Func_6(void); +void Metalee_Init(void); +void Metalee_Main(void); +void Metalee_Shot(void); +void Metroid_Frozen(void); +void Metroid_Func_1(void); +void Metroid_Func_2(void); +void Metroid_Func_3(void); +void Metroid_Func_4(void); +void Metroid_Func_5(uint16 k); +void Metroid_Hurt(void); +void Metroid_Init(void); +void Metroid_Main(void); +void Metroid_Powerbomb(uint16 k); +void Metroid_Shot(void); +void Metroid_Touch(void); +void Mochtroid_Func_1(void); +void Mochtroid_Func_2(void); +void Mochtroid_Func_3(void); +void Mochtroid_Func_4(uint16 k, uint16 a); +void Mochtroid_Init(void); +void Mochtroid_Main(void); +void Mochtroid_Shot(void); +void Mochtroid_Touch(void); +void NorfairSlowFireball_Func_1(void); +void NorfairSlowFireball_Init(void); +void PlatformThatFallsWithSamus_Func_1(void); +void PlatformThatFallsWithSamus_Func_10(void); +void PlatformThatFallsWithSamus_Func_2(void); +void PlatformThatFallsWithSamus_Func_3(void); +void PlatformThatFallsWithSamus_Func_4(void); +void PlatformThatFallsWithSamus_Func_5(void); +void PlatformThatFallsWithSamus_Func_6(void); +void PlatformThatFallsWithSamus_Func_7(void); +void PlatformThatFallsWithSamus_Func_8(void); +void PlatformThatFallsWithSamus_Func_9(void); +void PlatformThatFallsWithSamus_Init(void); +void PlatformThatFallsWithSamus_Main(void); +void PlatformThatFalls_Init(uint16 k, uint16 j); +void Reflec_Func_1(void); +void Reflec_Func_10(void); +void Reflec_Func_11(void); +void Reflec_Func_12(void); +void Reflec_Func_13(void); +void Reflec_Func_2(void); +void Reflec_Func_3(void); +void Reflec_Func_4(void); +void Reflec_Func_5(void); +void Reflec_Func_6(void); +void Reflec_Func_7(void); +void Reflec_Func_8(void); +void Reflec_Func_9(void); +void Reflec_Init(void); +void Reflec_Shot(void); +void Roach_Func_1(void); +void Roach_Func_10(void); +void Roach_Func_11(void); +void Roach_Func_12(void); +void Roach_Func_13(void); +void Roach_Func_14(void); +void Roach_Func_15(void); +void Roach_Func_16(void); +void Roach_Func_17(uint16 k); +void Roach_Func_18(uint16 k); +void Roach_Func_19(void); +void Roach_Func_2(uint16 k); +void Roach_Func_20(void); +void Roach_Func_21(void); +void Roach_Func_22(void); +void Roach_Func_23(void); +void Roach_Func_24(void); +void Roach_Func_25(void); +void Roach_Func_26(void); +void Roach_Func_27(void); +void Roach_Func_28(void); +void Roach_Func_29(uint16 k); +void Roach_Func_3(uint16 k); +void Roach_Func_30(uint16 k); +void Roach_Func_31(uint16 k); +void Roach_Func_32(uint16 k); +void Roach_Func_33(uint16 k); +void Roach_Func_4(uint16 k); +void Roach_Func_5(uint16 k); +void Roach_Func_6(uint16 k); +void Roach_Func_7(uint16 k); +void Roach_Func_8(uint16 k); +void Roach_Func_9(void); +void Roach_Init(void); +void Roach_Main(void); +void Sidehopper_Func_10(void); +void Sidehopper_Func_11(void); +void Sidehopper_Func_12(void); +void Sidehopper_Func_13(void); +void Sidehopper_Func_14(void); +void Sidehopper_Func_15(void); +void Sidehopper_Func_16(void); +void Sidehopper_Func_17(void); +void Sidehopper_Func_18(void); +void Sidehopper_Func_19(void); +void Sidehopper_Func_20(void); +void Sidehopper_Func_21(void); +void Sidehopper_Func_22(void); +void Sidehopper_Func_3(void); +void Sidehopper_Func_4(uint16 k); +void Sidehopper_Func_5(void); +void Sidehopper_Func_6(void); +void Sidehopper_Func_7(void); +void Sidehopper_Func_8(void); +void Sidehopper_Func_9(void); +void Sidehopper_Init(void); +void Sidehopper_Main(void); +void Skree_Func_1(void); +void Skree_Func_2(uint16 k); +void Skree_Func_3(void); +void Skree_Func_4(void); +void Skree_Func_5(void); +void Skree_Init(void); +void Skree_Main(void); +void Skree_Shot(void); +void Slug_Func_1(void); +void Slug_Init(void); +void StoneZoomer_E67A(uint16 k); +void StoneZoomer_Init(void); +void StoneZoomer_Main(void); +void Waver_Func_1(void); +void Waver_Init(void); +void Waver_Main(void); +void WreckedShipOrangeZoomer_Func_2(uint16 k); +void WreckedShipOrangeZoomer_Init(void); +void WreckedShipOrangeZoomer_Main(void); +void sub_A3E168(uint16 k); + +// Bank A4 +uint16 Crocomire_Func_10(uint16 k, uint16 j); +uint16 Crocomire_Func_11(uint16 k, uint16 j); +uint16 Crocomire_Func_12(uint16 k, uint16 j); +uint16 Crocomire_Func_13(uint16 k, uint16 j); +uint16 Crocomire_Func_14(uint16 k, uint16 j); +uint16 Crocomire_Func_15(uint16 k, uint16 j); +uint16 Crocomire_Func_16(uint16 k, uint16 j); +uint16 Crocomire_Func_17(uint16 k, uint16 j); +uint16 Crocomire_Func_18(uint16 k, uint16 j); +uint16 Crocomire_Func_19(uint16 k, uint16 j); +uint16 Crocomire_Func_2(uint16 k, uint16 j); +uint16 Crocomire_Func_20(uint16 k); +uint16 Crocomire_Func_21(uint16 k, uint16 j); +uint16 Crocomire_Func_22(uint16 k, uint16 j); +uint16 Crocomire_Func_23(uint16 k, uint16 j); +uint16 Crocomire_Func_24(uint16 k, uint16 j); +uint16 Crocomire_Func_25(uint16 k, uint16 j); +uint16 Crocomire_Func_26(uint16 k, uint16 j); +uint16 Crocomire_Func_3(uint16 k, uint16 j); +uint16 Crocomire_Func_4(uint16 k, uint16 j); +uint16 Crocomire_Func_5(uint16 k, uint16 j); +uint16 Crocomire_Func_67(void); +uint16 Crocomire_Func_7(uint16 k, uint16 j); +uint16 Crocomire_Func_8(uint16 k, uint16 j); +uint16 Crocomire_Func_87(uint16 j, uint16 a); +uint16 Crocomire_Func_9(uint16 k, uint16 j); +uint16 Crocomire_Instr_1(uint16 k, uint16 j); +uint16 Crocomire_Instr_10(uint16 k, uint16 j); +uint16 Crocomire_Instr_11(uint16 k, uint16 j); +uint16 Crocomire_Instr_12(uint16 k, uint16 j); +uint16 Crocomire_Instr_13(uint16 k, uint16 j); +uint16 Crocomire_Instr_14(uint16 k, uint16 j); +uint16 Crocomire_Instr_15(uint16 k, uint16 j); +uint16 Crocomire_Instr_16(uint16 k, uint16 j); +uint16 Crocomire_Instr_17(uint16 k, uint16 j); +uint16 Crocomire_Instr_18(uint16 k, uint16 j); +uint16 Crocomire_Instr_19(uint16 k, uint16 j); +uint16 Crocomire_Instr_2(uint16 k, uint16 j); +uint16 Crocomire_Instr_20(uint16 k, uint16 j); +uint16 Crocomire_Instr_21(uint16 k, uint16 j); +uint16 Crocomire_Instr_22(uint16 k, uint16 j); +uint16 Crocomire_Instr_23(uint16 k, uint16 j); +uint16 Crocomire_Instr_24(uint16 k, uint16 j); +uint16 Crocomire_Instr_25(uint16 k, uint16 j); +uint16 Crocomire_Instr_26(uint16 k, uint16 j); +uint16 Crocomire_Instr_27(uint16 k, uint16 j); +uint16 Crocomire_Instr_3(uint16 k, uint16 j); +uint16 Crocomire_Instr_4(uint16 k, uint16 j); +uint16 Crocomire_Instr_5(uint16 k, uint16 j); +uint16 Crocomire_Instr_6(uint16 k, uint16 j); +uint16 Crocomire_Instr_7(uint16 k, uint16 j); +uint16 Crocomire_Instr_8(uint16 k, uint16 j); +uint16 Crocomire_Instr_9(uint16 k, uint16 j); +uint16 EnemyInstr_Goto_A4(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep_A4(uint16 k, uint16 j); +void CrocomireTongue_Init(void); +void CrocomireTongue_Main(void); +void Crocomire_8BA4(void); +void Crocomire_8D47(void); +void Crocomire_8EE5(void); +void Crocomire_929E(void); +void Crocomire_92CE(void); +void Crocomire_92D8(void); +void Crocomire_93BE(uint16 k); +void Crocomire_9506(void); +void Crocomire_950F(void); +void Crocomire_9B65(void); +void Crocomire_9B86(void); +void Crocomire_9BB3(void); +void Crocomire_Func_1(void); +void Crocomire_Func_27(uint16 k); +void Crocomire_Func_28(void); +void Crocomire_Func_29(void); +void Crocomire_Func_30(void); +void Crocomire_Func_31(void); +void Crocomire_Func_35(void); +void Crocomire_Func_36(void); +void Crocomire_Func_37(void); +void Crocomire_Func_38(uint16 k); +void Crocomire_Func_43(void); +void Crocomire_Func_49(void); +void Crocomire_Func_50(void); +void Crocomire_Func_51(void); +void Crocomire_Func_52(void); +void Crocomire_Func_53(void); +void Crocomire_Func_54(void); +void Crocomire_Func_55(void); +void Crocomire_Func_56(void); +void Crocomire_Func_57(void); +void Crocomire_Func_58(void); +void Crocomire_Func_59(void); +void Crocomire_Func_60(void); +void Crocomire_Func_61(void); +void Crocomire_Func_62(void); +void Crocomire_Func_63(void); +void Crocomire_Func_64(void); +void Crocomire_Func_65(void); +void Crocomire_Func_66(void); +void Crocomire_Func_68(void); +void Crocomire_Func_69(void); +void Crocomire_Func_70(void); +void Crocomire_Func_71(void); +void Crocomire_Func_72(void); +void Crocomire_Func_73(void); +void Crocomire_Func_88(void); +void Crocomire_Func_89(void); +void Crocomire_Func_90(void); +void Crocomire_Func_91(void); +void Crocomire_Func_92(void); +void Crocomire_Func_93(void); +void Crocomire_Func_94(void); +void Crocomire_Func_95(void); +void Crocomire_Hurt(void); +void Crocomire_Init(void); +void Crocomire_Main(void); +void Crocomire_Powerbomb(void); +void Enemy_GrappleReact_SamusLatchesOn_A4(void); +void Enemy_NormalFrozenAI_A4(void); +void Enemy_NormalPowerBombAI_A4(void); +void Enemy_NormalShotAI_A4(void); +void Enemy_NormalTouchAI_A4(void); +void GetCurEnemyIndex(void); + +// Bank A5 +uint16 Draygon_Instr_1(uint16 k, uint16 j); +uint16 Draygon_Instr_10(uint16 k, uint16 j); +uint16 Draygon_Instr_11(uint16 k, uint16 j); +uint16 Draygon_Instr_12(uint16 k, uint16 j); +uint16 Draygon_Instr_13(uint16 k, uint16 j); +uint16 Draygon_Instr_14(uint16 k, uint16 j); +uint16 Draygon_Instr_15(uint16 k, uint16 j); +uint16 Draygon_Instr_16(uint16 k, uint16 j); +uint16 Draygon_Instr_17(uint16 k, uint16 j); +uint16 Draygon_Instr_18(uint16 k, uint16 j); +uint16 Draygon_Instr_19(uint16 k, uint16 j); +uint16 Draygon_Instr_2(uint16 k, uint16 j); +uint16 Draygon_Instr_20(uint16 k, uint16 j); +uint16 Draygon_Instr_21(uint16 k, uint16 j); +uint16 Draygon_Instr_22(uint16 k, uint16 j); +uint16 Draygon_Instr_23(uint16 k, uint16 j); +uint16 Draygon_Instr_24(uint16 k, uint16 j); +uint16 Draygon_Instr_25(uint16 k, uint16 j); +uint16 Draygon_Instr_26(uint16 k, uint16 j); +uint16 Draygon_Instr_27(uint16 k, uint16 j); +uint16 Draygon_Instr_28(uint16 k, uint16 j); +uint16 Draygon_Instr_29(uint16 k, uint16 j); +uint16 Draygon_Instr_3(uint16 k, uint16 j); +uint16 Draygon_Instr_30(uint16 k, uint16 j); +uint16 Draygon_Instr_4(uint16 k, uint16 j); +uint16 Draygon_Instr_5(uint16 k, uint16 j); +uint16 Draygon_Instr_53(uint16 k, uint16 j); +uint16 Draygon_Instr_54(uint16 k, uint16 j); +uint16 Draygon_Instr_55(uint16 k, uint16 j); +uint16 Draygon_Instr_6(uint16 k, uint16 j); +uint16 Draygon_Instr_7(uint16 k, uint16 j); +uint16 Draygon_Instr_8(uint16 k, uint16 j); +uint16 Draygon_Instr_9(uint16 k, uint16 j); +uint16 EnemyInstr_DecTimerAndGoto2_A5(uint16 k, uint16 j); +uint16 EnemyInstr_Goto_A5(uint16 k, uint16 j); +uint16 EnemyInstr_SetTimer_A5(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep_A5(uint16 k, uint16 j); +uint16 EnemyInstr_StopScript_A5(uint16 k, uint16 j); +uint16 EnemyInstr_WaitNframes_A5(uint16 k, uint16 j); +void CreateADudShot_A5(void); +void Draygon_Func_1(void); +void Draygon_Func_10(void); +void Draygon_Func_11(void); +void Draygon_Func_12(void); +void Draygon_Func_13(void); +void Draygon_Func_14(void); +void Draygon_Func_15(void); +void Draygon_Func_16(void); +void Draygon_Func_17(uint16 k); +void Draygon_Func_18(void); +void Draygon_Func_19(void); +void Draygon_Func_2(void); +void Draygon_Func_20(void); +void Draygon_Func_21(uint16 k); +void Draygon_Func_22(void); +void Draygon_Func_23(void); +void Draygon_Func_24(uint16 k); +void Draygon_Func_25(uint16 k); +void Draygon_Func_26(uint16 k); +void Draygon_Func_27(uint16 k); +void Draygon_Func_28(uint16 k); +void Draygon_Func_29(void); +void Draygon_Func_3(void); +void Draygon_Func_30(void); +void Draygon_Func_31(void); +void Draygon_Func_32(void); +void Draygon_Func_33(void); +void Draygon_Func_34(void); +void Draygon_Func_35(void); +void Draygon_Func_36(void); +void Draygon_Func_37(void); +void Draygon_Func_38(void); +void Draygon_Func_39(void); +void Draygon_Func_4(void); +void Draygon_Func_40(uint16 k); +void Draygon_Func_41(void); +void Draygon_Func_42(void); +void Draygon_Func_43(void); +void Draygon_Func_44(void); +void Draygon_Func_45(void); +void Draygon_Func_46(void); +void Draygon_Func_47(void); +void Draygon_Func_48(uint16 k); +void Draygon_Func_49(uint16 k); +void Draygon_Func_5(void); +void Draygon_Func_50(uint16 j); +void Draygon_Func_51(uint16 j); +void Draygon_Func_52(uint16 j); +void Draygon_Func_6(void); +void Draygon_Func_7(void); +void Draygon_Func_8(void); +void Draygon_Func_9(void); +void Draygon_Hurt(void); +void Draygon_Init(void); +void Draygon_Main(void); +void Draygon_Powerbomb(void); +void Draygon_Shot(void); +void Draygon_Touch(void); +void DraygonsArms_Init(void); +void DraygonsEye_Init(void); +void DraygonsEye_Main(void); +void DraygonsTail_Init(void); +void Enemy_GrappleReact_CancelBeam_A5(void); +void Enemy_GrappleReact_NoInteract_A5(void); +void Enemy_NormalFrozenAI_A5(void); +void Enemy_NormalPowerBombAI_A5(void); +void Enemy_NormalShotAI_A5(void); +void Enemy_NormalTouchAI_A5(void); +void SporeSpawn_Func_1(void); +void SporeSpawn_Func_2(uint16 k); +void SporeSpawn_Func_3(void); +void SporeSpawn_Func_4(void); +void SporeSpawn_Func_5(void); +void SporeSpawn_Func_6(void); +void SporeSpawn_Func_7(uint16 a); +void SporeSpawn_Init(void); +void SporeSpawn_Main(void); +void SporeSpawn_Shot(void); +void SporeSpawn_Touch(void); +void sub_A5960D(void); +void sub_A5E9F5(void); + +// Bank A6 +uint16 BabyMetroid_DBCB_DoubleRet(uint16 a); +uint16 BabyMetroid_Incr2(uint16 k); +uint16 BabyMetroid_Instr_1(uint16 k); +uint16 BabyMetroid_Instr_2(uint16 k); +uint16 BabyMetroid_Instr_3(uint16 k); +uint16 BabyMetroid_Instr_4(uint16 k); +uint16 CeresDoor_Goto(uint16 j); +uint16 CeresDoor_Incr(uint16 j); +uint16 CeresDoor_Instr_1(uint16 k, uint16 j); +uint16 CeresDoor_Instr_2(uint16 k, uint16 j); +uint16 CeresDoor_Instr_3(uint16 k, uint16 j); +uint16 CeresDoor_Instr_4(uint16 k, uint16 j); +uint16 CeresDoor_Instr_5(uint16 k, uint16 j); +uint16 CeresDoor_Instr_6(uint16 k, uint16 j); +uint16 CeresDoor_Instr_7(uint16 k, uint16 j); +uint16 CeresDoor_Instr_8(uint16 k, uint16 j); +uint16 CeresRidley_AC30(uint16 a); +uint16 CeresRidley_Func_30(uint16 a); +uint16 CeresRidley_Func_31(uint16 a); +uint16 CeresSteam_Instr_1(uint16 k, uint16 j); +uint16 CeresSteam_Instr_2(uint16 k, uint16 j); +uint16 CeresSteam_Instr_3(uint16 k, uint16 j); +uint16 CeresSteam_Instr_4(uint16 k, uint16 j); +uint16 CeresSteam_Instr_5(uint16 k, uint16 j); +uint16 EnemyInstr_Goto_A6(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep_A6(uint16 k, uint16 j); +uint16 FakeKraid_Instr_1(uint16 k, uint16 j); +uint16 FakeKraid_Instr_2(uint16 k, uint16 j); +uint16 FakeKraid_Instr_3(uint16 k, uint16 j); +uint16 FakeKraid_Instr_4(uint16 k, uint16 j); +uint16 FakeKraid_Instr_5(uint16 k, uint16 j); +uint16 FireGeyser_Instr_1(uint16 k, uint16 j); +uint16 FireGeyser_Instr_10(uint16 k, uint16 j); +uint16 FireGeyser_Instr_11(uint16 k, uint16 j); +uint16 FireGeyser_Instr_12(uint16 k, uint16 j); +uint16 FireGeyser_Instr_13(uint16 k, uint16 j); +uint16 FireGeyser_Instr_14(uint16 k, uint16 j); +uint16 FireGeyser_Instr_15(uint16 k, uint16 j); +uint16 FireGeyser_Instr_16(uint16 k, uint16 j); +uint16 FireGeyser_Instr_17(uint16 k, uint16 j); +uint16 FireGeyser_Instr_18(uint16 k, uint16 j); +uint16 FireGeyser_Instr_19(uint16 k, uint16 j); +uint16 FireGeyser_Instr_2(uint16 k, uint16 j); +uint16 FireGeyser_Instr_20(uint16 k, uint16 j); +uint16 FireGeyser_Instr_21(uint16 k, uint16 j); +uint16 FireGeyser_Instr_22(uint16 k, uint16 j); +uint16 FireGeyser_Instr_23(uint16 k, uint16 j); +uint16 FireGeyser_Instr_24(uint16 k, uint16 j); +uint16 FireGeyser_Instr_3(uint16 k, uint16 j); +uint16 FireGeyser_Instr_4(uint16 k, uint16 j); +uint16 FireGeyser_Instr_5(uint16 k, uint16 j); +uint16 FireGeyser_Instr_6(uint16 k, uint16 j); +uint16 FireGeyser_Instr_7(uint16 k, uint16 j); +uint16 FireGeyser_Instr_8(uint16 k, uint16 j); +uint16 FireGeyser_Instr_9(uint16 k, uint16 j); +uint16 NuclearWaffle_Func_5(uint16 a); +uint16 NuclearWaffle_Func_6(uint16 a); +uint16 Ridley_E90C(uint16 k, uint16 j, uint16 a); +uint16 Ridley_Func_122(void); +uint16 Ridley_Func_7(void); +uint16 Ridley_Instr_1(uint16 k, uint16 j); +uint16 Ridley_Instr_10(uint16 k, uint16 j); +uint16 Ridley_Instr_11(uint16 k, uint16 j); +uint16 Ridley_Instr_12(uint16 k, uint16 j); +uint16 Ridley_Instr_13(uint16 k, uint16 j); +uint16 Ridley_Instr_14(uint16 k, uint16 j); +uint16 Ridley_Instr_15(uint16 k, uint16 j); +uint16 Ridley_Instr_16(uint16 k, uint16 j); +uint16 Ridley_Instr_2(uint16 k, uint16 j); +uint16 Ridley_Instr_3(uint16 k, uint16 j); +uint16 Ridley_Instr_4(uint16 k, uint16 j); +uint16 Ridley_Instr_5(uint16 k, uint16 j); +uint16 Ridley_Instr_6(uint16 k, uint16 j); +uint16 Ridley_Instr_7(uint16 k, uint16 j); +uint16 Ridley_Instr_8(uint16 k, uint16 j); +uint16 Ridley_Instr_9(uint16 k, uint16 j); +uint16 SpikeyPlatform_Func_5(uint16 k); +uint16 Zebetites_Func_9(void); +uint16 sub_A6E4E9(uint16 j); +uint16 sub_A6E514(uint16 j); +uint8 CeresRidley_Func_12(void); +uint8 CeresRidley_Func_8(uint16 a); +uint8 HandleTypewriterText(void); +uint8 HandleTypewriterText_Ext(uint16 a); +uint8 ProcessEscapeTimerTileTransfers(void); +uint8 Ridley_Func_103(uint16 k, uint16 j); +uint8 Ridley_Func_121(void); +uint8 Ridley_Func_124(void); +uint8 Ridley_Func_17(void); +uint8 Ridley_Func_23(void); +uint8 Ridley_Func_25(void); +uint8 Ridley_Func_26(uint16 k, uint16 j); +uint8 Ridley_Func_40(void); +uint8 Ridley_Func_41(void); +uint8 Ridley_Func_48(void); +uint8 Ridley_Func_68(void); +uint8 Ridley_Func_78(void); +uint8 Ridley_Func_80_DoubleRet(void); +uint8 Ridley_Func_90(void); +uint8 Ridley_Func_97(void); +void Boulder_Func_1(void); +void Boulder_Func_2(void); +void Boulder_Func_3(void); +void Boulder_Func_4(void); +void Boulder_Func_5(void); +void Boulder_Func_6(void); +void Boulder_Func_7(uint16 j); +void Boulder_Func_8(uint16 j); +void Boulder_Func_9(uint16 j); +void Boulder_Init(void); +void Boulder_Main(void); +void CeresDoor_F773(uint16 j); +void CeresDoor_Func_1(uint16 k); +void CeresDoor_Func_2(void); +void CeresDoor_Func_3(void); +void CeresDoor_Func_4(void); +void CeresDoor_Func_5(uint16 k); +void CeresDoor_Func_6(uint16 k); +void CeresDoor_Func_6b(void); +void CeresDoor_Func_7(void); +void CeresDoor_Func_8(void); +void CeresDoor_Init(void); +void CeresDoor_Main(void); +void CeresRidley_A377(void); +void CeresRidley_A7F9(void); +void CeresRidley_A994(void); +void CeresRidley_Func_1(void); +void CeresRidley_Func_10(void); +void CeresRidley_Func_11(void); +void CeresRidley_Func_13(void); +void CeresRidley_Func_14(void); +void CeresRidley_Func_15(void); +void CeresRidley_Func_16(void); +void CeresRidley_Func_17(void); +void CeresRidley_Func_18(void); +void CeresRidley_Func_19(void); +void CeresRidley_Func_2(void); +void CeresRidley_Func_20(void); +void CeresRidley_Func_21(void); +void CeresRidley_Func_22(void); +void CeresRidley_Func_23(void); +void CeresRidley_Func_24(void); +void CeresRidley_Func_25(void); +void CeresRidley_Func_26(void); +void CeresRidley_Func_27(void); +void CeresRidley_Func_28(void); +void CeresRidley_Func_29(void); +void CeresRidley_Func_3(void); +void CeresRidley_Func_32(void); +void CeresRidley_Func_33(void); +void CeresRidley_Func_34(void); +void CeresRidley_Func_35(uint16 a); +void CeresRidley_Func_4(void); +void CeresRidley_Func_5(void); +void CeresRidley_Func_6(void); +void CeresRidley_Func_7(void); +void CeresRidley_Func_9(void); +void CeresRidley_Hurt(void); +void CeresRidley_Init(void); +void CeresRidley_Main(void); +void CeresSteam_Func_1(uint16 k); +void CeresSteam_Init(void); +void CeresSteam_Main(void); +void CeresSteam_Touch(void); +void DrawBabyMetroid_0(void); +void Enemy_GrappleReact_CancelBeam_A6(void); +void Enemy_GrappleReact_NoInteract_A6(void); +void Enemy_NormalFrozenAI_A6(void); +void Enemy_NormalPowerBombAI_A6(void); +void Enemy_NormalShotAI_A6(void); +void Enemy_NormalTouchAI_A6(void); +void FakeKraid_9C50(void); +void FakeKraid_Func_1(uint16 k, uint16 j); +void FakeKraid_Init(void); +void FakeKraid_InstrHelper_45(uint16 k, uint16 j, uint16 a); +void FakeKraid_Main(void); +void FakeKraid_Shot(void); +void FakeKraid_Touch(void); +void FireGeyser_Func_1(void); +void FireGeyser_Func_2(void); +void FireGeyser_Init(void); +void FireGeyser_Main(void); +void HandleCeresRidleyGetawayCutscene(void); +void NuclearWaffle_Func_1(void); +void NuclearWaffle_Func_2(void); +void NuclearWaffle_Func_3(void); +void NuclearWaffle_Func_4(void); +void NuclearWaffle_Func_7(void); +void NuclearWaffle_Init(void); +void NuclearWaffle_Main(void); +void Ridley_A2DC(void); +void Ridley_A2F2(void); +void Ridley_B455(void); +void Ridley_C08E(void); +void Ridley_C09F(void); +void Ridley_C104(void); +void Ridley_C53E(void); +void Ridley_C551(void); +void Ridley_CBC0(void); +void Ridley_CBC7(void); +void Ridley_CBCE(void); +void Ridley_CBD5(void); +void Ridley_CBDC(void); +void Ridley_D495(void); +void Ridley_Func_1(void); +void Ridley_Func_10(void); +void Ridley_Func_100(void); +void Ridley_Func_101(void); +void Ridley_Func_102(void); +void Ridley_Func_104(uint16 k, uint16 j, uint16 a); +void Ridley_Func_104_0(uint16 k, uint16 j); +void Ridley_Func_105(uint16 k); +void Ridley_Func_106(uint16 k, uint16 j); +void Ridley_Func_107(uint16 k); +void Ridley_Func_108(uint16 k); +void Ridley_Func_109(uint16 k); +void Ridley_Func_11(void); +void Ridley_Func_110(uint16 k); +void Ridley_Func_111(void); +void Ridley_Func_112(void); +void Ridley_Func_113(uint16 k); +void Ridley_Func_114(void); +void Ridley_Func_115(void); +void Ridley_Func_116(void); +void Ridley_Func_117(void); +void Ridley_Func_118(void); +void Ridley_Func_119(uint8 carry); +void Ridley_Func_12(void); +void Ridley_Func_120(void); +void Ridley_Func_123(uint16 j); +void Ridley_Func_125(void); +void Ridley_Func_126(void); +void Ridley_Func_127(void); +void Ridley_Func_128(void); +void Ridley_Func_129(void); +void Ridley_Func_13(void); +void Ridley_Func_131(uint16 k); +void Ridley_Func_132(uint16 k, uint16 a); +void Ridley_Func_14(void); +void Ridley_Func_15(void); +void Ridley_Func_16(void); +void Ridley_Func_18(void); +void Ridley_Func_19(void); +void Ridley_Func_2(void); +void Ridley_Func_20(void); +void Ridley_Func_21(void); +void Ridley_Func_22(void); +void Ridley_Func_24(void); +void Ridley_Func_27(void); +void Ridley_Func_28(void); +void Ridley_Func_29(void); +void Ridley_Func_3(void); +void Ridley_Func_30(void); +void Ridley_Func_31(void); +void Ridley_Func_32(void); +void Ridley_Func_33(void); +void Ridley_Func_33b(void); +void Ridley_Func_34(void); +void Ridley_Func_35(void); +void Ridley_Func_36(void); +void Ridley_Func_37(void); +void Ridley_Func_38(void); +void Ridley_Func_39(void); +void Ridley_Func_3b(void); +void Ridley_Func_4(void); +void Ridley_Func_42(void); +void Ridley_Func_43(void); +void Ridley_Func_44(void); +void Ridley_Func_45(void); +void Ridley_Func_46(void); +void Ridley_Func_47(void); +void Ridley_Func_49(void); +void Ridley_Func_5(void); +void Ridley_Func_50(void); +void Ridley_Func_51(void); +void Ridley_Func_52(void); +void Ridley_Func_53(void); +void Ridley_Func_54(void); +void Ridley_Func_55(void); +void Ridley_Func_56(void); +void Ridley_Func_57(void); +void Ridley_Func_58(void); +void Ridley_Func_59(void); +void Ridley_Func_6(void); +void Ridley_Func_60(void); +void Ridley_Func_61(void); +void Ridley_Func_62(void); +void Ridley_Func_63(void); +void Ridley_Func_64(void); +void Ridley_Func_65(void); +void Ridley_Func_66(void); +void Ridley_Func_67(void); +void Ridley_Func_69(void); +void Ridley_Func_70(void); +void Ridley_Func_71(void); +void Ridley_Func_72(void); +void Ridley_Func_73(void); +void Ridley_Func_74(void); +void Ridley_Func_75(void); +void Ridley_Func_77(void); +void Ridley_Func_79(void); +void Ridley_Func_8(void); +void Ridley_Func_81(void); +void Ridley_Func_82(void); +void Ridley_Func_83(void); +void Ridley_Func_84(void); +void Ridley_Func_85(void); +void Ridley_Func_86(void); +void Ridley_Func_87(void); +void Ridley_Func_88(uint16 k); +void Ridley_Func_89(uint16 a); +void Ridley_Func_9(void); +void Ridley_Func_91(void); +void Ridley_Func_92(void); +void Ridley_Func_93(uint16 j, uint16 k); +void Ridley_Func_94(void); +void Ridley_Func_95(void); +void Ridley_Func_96(void); +void Ridley_Func_98(void); +void Ridley_Func_99(uint16 a); +void Ridley_Func_D3DC(uint16 a); +void Ridley_Hurt(void); +void Ridley_Main(void); +void Ridley_Powerbomb(void); +void Ridley_Shot(void); +void RidleysExplosion_Func_1(uint16 k); +void RidleysExplosion_Func_2(void); +void RidleysExplosion_Init(void); +void RidleysExplosion_Main(void); +void SetupZebesEscapeTypewriter(void); +void SpikeyPlatform2ndEnemy_Init(void); +void SpikeyPlatform2ndEnemy_Main(void); +void SpikeyPlatform_Func_1(void); +void SpikeyPlatform_Func_2(void); +void SpikeyPlatform_Func_3(uint16 k); +void SpikeyPlatform_Func_4(void); +void SpikeyPlatform_Init(void); +void SpikeyPlatform_Main(void); +void Zebetites_Func_1(uint16 k); +void Zebetites_Func_2(uint16 k); +void Zebetites_Func_3(void); +void Zebetites_Func_4(void); +void Zebetites_Func_5(void); +void Zebetites_Func_6(void); +void Zebetites_Func_7(uint16 j, uint8 carry); +void Zebetites_Func_8(void); +void Zebetites_Init(void); +void Zebetites_Main(void); +void Zebetites_Shot(void); +void Zebetites_Touch(void); +void sub_A69C0B(void); +void sub_A6DB2A(void); +void sub_A6DBC2(uint16 j); +void sub_A6DC13(uint16 j); +void sub_A6DF59(void); +void sub_A6DF60(void); + +// Bank A7 +PairU16 Phantoon_SetColorBasedOnHp_FindEntry(uint16 k); +uint16 EnemyInstr_Call_A7(uint16 k, uint16 j); +uint16 EnemyInstr_DecTimerAndGoto2_A7(uint16 k, uint16 j); +uint16 EnemyInstr_Goto_A7(uint16 k, uint16 j); +uint16 EnemyInstr_SetTimer_A7(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep_A7(uint16 k, uint16 j); +uint16 Kraid_CheckIfDead(void); +uint16 Kraid_ExecuteInstr(void); +uint16 Kraid_Instr_1(uint16 k, uint16 j); +uint16 Kraid_Instr_9(uint16 k, uint16 j); +uint16 Kraid_Instr_DecYpos(uint16 k, uint16 j); +uint16 Kraid_Instr_IncrYpos_Shake(uint16 k, uint16 j); +uint16 Kraid_Instr_MoveHimRight(uint16 k, uint16 j); +uint16 Kraid_Instr_PlaySound_0x76(uint16 k, uint16 j); +uint16 Kraid_Instr_XposMinus3(uint16 k, uint16 j); +uint16 Kraid_Instr_XposMinus3b(uint16 k, uint16 j); +uint16 Kraid_Instr_XposPlus3(uint16 k, uint16 j); +uint16 Kraid_ProcessKraidInstr(void); +uint16 Phantoon_CalculateNthTransitionColorComponentFromXtoY(uint16 a, uint16 k, uint16 j); +uint16 Phantoon_Func_10_CalculateNthTransitionColorFromXtoY(uint16 a, uint16 k, uint16 j); +uint8 Etecoon_Func_2(uint16 k); +uint8 Etecoon_Func_3(uint16 k); +uint8 Phantoon_Func_3(void); +uint8 Phantoon_Func_8(void); +uint8 Phantoon_Func_9(void); +uint8 Phantoon_SetColorBasedOnHp(void); +void Dachora_Func_1(uint16 j, uint16 k); +void Dachora_Func_10(uint16 k); +void Dachora_Func_11(uint16 k); +void Dachora_Func_12(uint16 k); +void Dachora_Func_2(uint16 k); +void Dachora_Func_3(uint16 k); +void Dachora_Func_4(uint16 k); +void Dachora_Func_5(uint16 k); +void Dachora_Func_6(uint16 k); +void Dachora_Func_7(uint16 k); +void Dachora_Func_8(uint16 k); +void Dachora_Func_9(uint16 k); +void Dachora_Init(void); +void Dachora_Main(void); +void Enemy_GrappleReact_CancelBeam_A7(void); +void Enemy_GrappleReact_NoInteract_A7(void); +void Enemy_NormalFrozenAI_A7(void); +void Enemy_NormalPowerBombAI_SkipDeathAnim_A7(void); +void Enemy_NormalShotAI_A7(void); +void Etecoon_Func_1(uint16 k); +void Etecoon_Func_10(uint16 k); +void Etecoon_Func_11(uint16 k); +void Etecoon_Func_12(uint16 k); +void Etecoon_Func_13(uint16 j); +void Etecoon_Func_14(uint16 j); +void Etecoon_Func_15(uint16 j); +void Etecoon_Func_16(uint16 k); +void Etecoon_Func_17(uint16 k); +void Etecoon_Func_18(uint16 k); +void Etecoon_Func_19(uint16 k); +void Etecoon_Func_20(uint16 k); +void Etecoon_Func_21(uint16 k); +void Etecoon_Func_22(uint16 k); +void Etecoon_Func_23(uint16 k); +void Etecoon_Func_24(uint16 k); +void Etecoon_Func_25(uint16 k); +void Etecoon_Func_26(uint16 k); +void Etecoon_Func_4(uint16 k); +void Etecoon_Func_5(uint16 k); +void Etecoon_Func_6(uint16 k); +void Etecoon_Func_7(uint16 k); +void Etecoon_Func_8(uint16 k); +void Etecoon_Func_9(uint16 k); +void Etecoon_Init(void); +void Etecoon_Main(void); +void KraidEnemy_DecrementEnemyFunctionTimer(void); +void KraidEnemy_HandleFunctionTimer(uint16 k); +void KraidEnemy_ProcessInstrEnemyTimer(uint16 k); +void KraidFingernailInit(uint16 k); +void KraidFingernail_WaitForLintXpos(uint16 k); +void KraidFoot_FirstPhase_Thinking(uint16 k); +void KraidInstr_PlayDyingSfx(void); +void KraidInstr_PlayRoarSfx(void); +void KraidLintCommon_Main(uint16 k); +void KraidLint_ChargeLint(uint16 k); +void KraidLint_FireLint(uint16 k); +void KraidLint_ProduceLint(uint16 k); +void Kraid_AlignEnemyToKraid(uint16 k); +void Kraid_Arm_Shot(uint16 j); +void Kraid_ClearSomeSpikes(void); +void Kraid_CrumbleLeftPlatform_Left(void); +void Kraid_CrumbleLeftPlatform_Middle(void); +void Kraid_CrumbleLeftPlatform_Right(void); +void Kraid_CrumbleRightPlatform_Left(void); +void Kraid_CrumbleRightPlatform_Middle(void); +void Kraid_CrumbleRightPlatform_Right(void); +void Kraid_Death_Fadeout(void); +void Kraid_Death_Init(void); +void Kraid_Death_SinkThroughFloor(void); +void Kraid_Death_UpdateBG2TilemapBottomHalf(void); +void Kraid_Death_UpdateBG2TilemapTopHalf(void); +void Kraid_DrawRoomBg(void); +void Kraid_EnemyTouch_Lint(uint16 k); +void Kraid_Enemy_Touch(void); +void Kraid_FadeInBg_ClearBg2TilemapBottomHalf(void); +void Kraid_FadeInBg_ClearBg2TilemapTopHalf(void); +void Kraid_FadeInBg_FadeInBp6(void); +void Kraid_FadeInBg_LoadBg3Tiles1of4(void); +void Kraid_FadeInBg_LoadBg3Tiles2of4(void); +void Kraid_FadeInBg_LoadBg3Tiles3of4(void); +void Kraid_FadeInBg_LoadBg3Tiles4of4(void); +void Kraid_FadeInBg_SetEnemyDead_KraidWasAlive(void); +void Kraid_FadeInBg_SetEnemyDead_KraidWasDead(void); +void Kraid_Func_1(void); +void Kraid_GetsBig_BreakCeilingPlatforms(void); +void Kraid_GetsBig_DrawRoomBg(void); +void Kraid_GetsBig_FadeInRoomBg(void); +void Kraid_GetsBig_FinishUpdateBg2Tilemap(void); +void Kraid_GetsBig_ReleaseCamera(void); +void Kraid_GetsBig_SetBG2TilemapPrioBits(void); +void Kraid_GetsBig_Thinking(void); +void Kraid_GetsBig_Thinking_Setup(void); +void Kraid_HandleFirstPhase(void); +void Kraid_HandleSinking(void); +void Kraid_HealthBasedPaletteHandling(void); +void Kraid_HurtFlash_Handling(void); +void Kraid_Init(void); +void Kraid_InitEyeGlowing(void); +void Kraid_Lints_Enable(uint16 k, uint16 a); +void Kraid_Main(void); +void Kraid_Main_AttackWithMouthOpen(void); +void Kraid_Mainloop_Thinking(void); +void Kraid_Mainloop_Thinking_Setup(void); +void Kraid_Palette_Handling(void); +void Kraid_PlaySoundEveryHalfSecond(void); +void Kraid_RaiseKraidThroughFloor(uint16 k); +void Kraid_Raise_Handler(void); +void Kraid_Raise_LoadTilemapBottomAndShake(void); +void Kraid_Raise_SpawnRandomEarthquakeProjs16(void); +void Kraid_Raise_SpawnRandomEarthquakeProjs8(void); +void Kraid_RestrictSamusXtoFirstScreen(uint16 k); +void Kraid_RestrictSamusXtoFirstScreen_2(void); +void Kraid_SetEnemyPropsToDead(void); +void Kraid_SetLintYAndRandomThinkTimer(void); +void Kraid_SetWalkingBackwards(uint16 j, uint16 a); +void Kraid_SetWalkingForwards(uint16 j, uint16 a); +void Kraid_SetupGfxWithTilePrioClear(void); +void Kraid_Shot(void); +void Kraid_Shot_Body(void); +void Kraid_Shot_GlowHisEye(void); +void Kraid_Shot_Mouth(void); +void Kraid_Shot_MouthIsOpen(void); +void Kraid_Shot_UnglowEye(void); +void Kraid_SpawnExplosionEproj(uint16 k); +void Kraid_SpawnPlmToClearCeiling(void); +void Kraid_SpawnRandomQuakeProjs(void); +void Kraid_Touch(void); +void Kraid_Touch_ArmFoot(void); +void Kraid_TransferTopHalfToVram(void); +void Kraid_UnpauseHook_IsSinking(void); +void Kraid_UpdateBG2TilemapBottomHalf(void); +void Kraid_UpdateBg2TilemapTopHalf(void); +void KraidsArm_Init(void); +void KraidsArm_Main(void); +void KraidsArm_Touch(void); +void KraidsBadFingernail_Init(void); +void KraidsBadFingernail_Main(void); +void KraidsBadFingernail_Touch(void); +void KraidsBottomLint_Init(void); +void KraidsBottomLint_Main(void); +void KraidsFingernail_Fire(uint16 k); +void KraidsFingernail_Init(void); +void KraidsFoot_FirstPhase_LungeForward(void); +void KraidsFoot_FirstPhase_RetreatFromLunge(void); +void KraidsFoot_Init(void); +void KraidsFoot_Main(void); +void KraidsFoot_PrepareToLungeForward(void); +void KraidsFoot_SecondPhaseSetup_WalkToStartPt(void); +void KraidsFoot_SecondPhase_Init(void); +void KraidsFoot_SecondPhase_Thinking(void); +void KraidsFoot_SecondPhase_WalkForward(void); +void KraidsFoot_SecondPhase_WalkingBackwards(void); +void KraidsGoodFingernail_Init(void); +void KraidsGoodFingernail_Main(void); +void KraidsGoodFingernail_Touch(void); +void KraidsMiddleLint_Init(void); +void KraidsMiddleLint_Main(void); +void KraidsTopLint_Init(void); +void KraidsTopLint_Main(void); +void PauseHook_Kraid(void); +void Phantoon2_Init(void); +void Phantoon_AdjustSpeedAndMoveInFigure8(void); +void Phantoon_AdjustSpeedLeftSideClockwise(void); +void Phantoon_AdjustSpeedRightSideClockwise(void); +void Phantoon_AlmostDead(uint16 k); +void Phantoon_BecomeSolidAfterRainingFireballs(uint16 k); +void Phantoon_BecomesSolidAndBodyVuln(uint16 k); +void Phantoon_BeginSwoopingPattern(uint16 k); +void Phantoon_ChangeEyeSpriteBasedOnSamusDist(void); +void Phantoon_CompleteSwoopAfterFatalShot(uint16 k); +void Phantoon_Dead(uint16 k); +void Phantoon_DyingFadeOut(uint16 k); +void Phantoon_DyingPhantoonExplosions(uint16 k); +void Phantoon_DyingPhantoonFadeInOut(uint16 k); +void Phantoon_Enraged(uint16 k); +void Phantoon_EyeFollowsSamusUntilTimerRunsOut(uint16 k); +void Phantoon_FadeIn(uint16 a); +void Phantoon_FadeInBeforeFigure8(uint16 k); +void Phantoon_FadeInDuringFireballRain(uint16 k); +void Phantoon_FadeInEnragedPhantoon(uint16 k); +void Phantoon_FadeOut(uint16 a); +void Phantoon_FadeOutBeforeEnrage(uint16 k); +void Phantoon_FadeOutBeforeFirstFireballRain(uint16 k); +void Phantoon_FadeOutDuringFireballRain(uint16 k); +void Phantoon_FadeoutAfterEnrage(uint16 k); +void Phantoon_FadeoutWithSwoop(uint16 k); +void Phantoon_FollowSamusWithEyeDuringFireballRain(uint16 k); +void Phantoon_Func_1(void); +void Phantoon_Func_2(uint16 k); +void Phantoon_Func_4(uint16 k); +void Phantoon_Func_5(uint16 k); +void Phantoon_Func_6(uint16 k, uint16 a); +void Phantoon_Func_7(uint16 k); +void Phantoon_Hurt(void); +void Phantoon_Init(void); +void Phantoon_IsSwooping(uint16 k); +void Phantoon_Main(void); +void Phantoon_MoveEnragedPhantoonToTopCenter(uint16 k); +void Phantoon_MoveInFigure8_LeftSideClockwise(uint16 j); +void Phantoon_MoveInFigure8_RightSideClockwise(uint16 j); +void Phantoon_MoveInSwoopingPattern(uint16 k); +void Phantoon_MoveLeftOrRightAndPickEyeOpenPatt(uint16 k); +void Phantoon_MovePhantoonInFigure8ThenOpenEye(uint16 k); +void Phantoon_PickPatternForRound1(uint16 k); +void Phantoon_PickPatternForRound2(void); +void Phantoon_Shot(void); +void Phantoon_Spawn8FireballsInCircleAtStart(uint16 k); +void Phantoon_SpawnFireballsBeforeFight(uint16 k); +void Phantoon_SpawnRainingFireballs(uint16 k); +void Phantoon_StartDeathSequence(uint16 k); +void Phantoon_StartTrackingSamusAndInitEyeTimer(void); +void Phantoon_Touch(void); +void Phantoon_WaitAfterFadeOut(uint16 k); +void Phantoon_WaitBetweenSpawningAndSpinningFireballs(uint16 k); +void Phantoon_WavyDyingPhantoonAndCry(uint16 k); +void Phantoon_WavyFadeIn(uint16 k); +void UnpauseHook_Kraid_IsAlive(void); +void UnpauseHook_Kraid_IsDead(void); +void sub_A7A92A(void); + +// Bank A8 +uint16 Beetom_Func_2(void); +uint16 Beetom_Instr_1(uint16 k, uint16 j); +uint16 EnemyInstr_DecTimerAndGoto2_A8(uint16 k, uint16 j); +uint16 EnemyInstr_DisableOffScreenProcessing_A8(uint16 k, uint16 j); +uint16 EnemyInstr_EnableOffScreenProcessing_A8(uint16 k, uint16 j); +uint16 EnemyInstr_Goto_A8(uint16 k, uint16 j); +uint16 EnemyInstr_SetTimer_A8(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep_A8(uint16 k, uint16 j); +uint16 Fune_Func_3(void); +uint16 Fune_Instr_1(uint16 k, uint16 j); +uint16 Fune_Instr_2(uint16 k, uint16 j); +uint16 Fune_Instr_3(uint16 k, uint16 j); +uint16 Fune_Instr_4(uint16 k, uint16 j); +uint16 Fune_Instr_5(uint16 k, uint16 j); +uint16 Fune_Instr_6(uint16 k, uint16 j); +uint16 Fune_Instr_7(uint16 k, uint16 j); +uint16 KiHunter_Instr_1(uint16 k, uint16 j); +uint16 KiHunter_Instr_2(uint16 k, uint16 j); +uint16 KiHunter_Instr_3(uint16 k, uint16 j); +uint16 KiHunter_Instr_4(uint16 k, uint16 j); +uint16 KiHunter_Instr_5(uint16 k, uint16 j); +uint16 MiniDraygon_Instr_1(uint16 k, uint16 j); +uint16 MiniDraygon_Instr_2(uint16 k, uint16 j); +uint16 MiniDraygon_Instr_3(uint16 k, uint16 j); +uint16 MiniDraygon_Instr_4(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_1(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_10(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_11(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_12(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_13(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_14(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_15(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_16(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_2(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_3(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_4(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_5(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_6(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_7(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_8(uint16 k, uint16 j); +uint16 NorfairLavaMan_Instr_9(uint16 k, uint16 j); +uint16 WalkingLavaSeahorse_Func_2(uint16 k); +uint16 WalkingLavaSeahorse_Instr_1(uint16 k, uint16 j); +uint16 WalkingLavaSeahorse_Instr_2(uint16 k, uint16 j); +uint16 WalkingLavaSeahorse_Instr_3(uint16 k, uint16 j); +uint16 WalkingLavaSeahorse_Instr_4(uint16 k, uint16 j); +uint16 WalkingLavaSeahorse_Instr_5(uint16 k, uint16 j); +uint16 WalkingLavaSeahorse_Instr_6(uint16 k, uint16 j); +uint16 WreckedShipGhost_Func_8(void); +uint16 WreckedShipRobot_CommonInstr(uint16 k, uint16 j); +uint16 WreckedShipRobot_D10C(uint16 k, uint16 j); +uint16 WreckedShipRobot_D147(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_1(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_10(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_11(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_12(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_13(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_14(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_15(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_16(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_17(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_18(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_2(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_3(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_4(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_5(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_6(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_7(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_8(uint16 k, uint16 j); +uint16 WreckedShipRobot_Instr_9(uint16 k, uint16 j); +uint16 WreckedShipSpark_Instr_1(uint16 k, uint16 j); +uint16 WreckedShipSpark_Instr_2(uint16 k, uint16 j); +uint16 YappingMaw_Func_16(uint16 a); +uint16 YappingMaw_Func_17(uint16 a); +uint16 YappingMaw_Instr_1(uint16 k, uint16 j); +uint16 YappingMaw_Instr_2(uint16 k, uint16 j); +uint16 YappingMaw_Instr_3(uint16 k, uint16 j); +uint16 YappingMaw_Instr_4(uint16 k, uint16 j); +uint16 YappingMaw_Instr_5(uint16 k, uint16 j); +uint16 YappingMaw_Instr_6(uint16 k, uint16 j); +uint16 YappingMaw_Instr_7(uint16 k, uint16 j); +void Beetom_Func_1(void); +void Beetom_Func_10(void); +void Beetom_Func_11(void); +void Beetom_Func_12(void); +void Beetom_Func_13(void); +void Beetom_Func_14(void); +void Beetom_Func_15(void); +void Beetom_Func_16(void); +void Beetom_Func_17(void); +void Beetom_Func_18(void); +void Beetom_Func_19(void); +void Beetom_Func_20(void); +void Beetom_Func_21(void); +void Beetom_Func_22(uint16 k); +void Beetom_Func_23(uint16 k); +void Beetom_Func_24(void); +void Beetom_Func_25(void); +void Beetom_Func_26(uint16 k); +void Beetom_Func_27(uint16 k); +void Beetom_Func_28(void); +void Beetom_Func_29(void); +void Beetom_Func_3(void); +void Beetom_Func_30(uint16 k); +void Beetom_Func_31(uint16 k); +void Beetom_Func_32(void); +void Beetom_Func_33(void); +void Beetom_Func_34(void); +void Beetom_Func_35(void); +void Beetom_Func_36(void); +void Beetom_Func_37(uint16 k); +void Beetom_Func_4(void); +void Beetom_Func_5(void); +void Beetom_Func_6(void); +void Beetom_Func_7(void); +void Beetom_Func_8(void); +void Beetom_Func_9(void); +void Beetom_Init(void); +void Beetom_Main(void); +void Beetom_Shot(void); +void Beetom_Touch(void); +void BlueBrinstarFaceBlock_Func_1(void); +void BlueBrinstarFaceBlock_Init(void); +void BlueBrinstarFaceBlock_Main(void); +void BlueBrinstarFaceBlock_Shot(void); +void Enemy_GrappleReact_CancelBeam_A8(void); +void Enemy_GrappleReact_HurtSamus_A8(void); +void Enemy_GrappleReact_KillEnemy_A8(void); +void Enemy_GrappleReact_NoInteract_A8(void); +void Enemy_GrappleReact_SamusLatchesNoInvinc_A8(void); +void Enemy_NormalFrozenAI_A8(void); +void Enemy_NormalPowerBombAI_A8(void); +void Enemy_NormalShotAI_A8(void); +void Enemy_NormalTouchAI_A8(void); +void EvirProjectile_Init(void); +void EvirProjectile_Main(void); +void Fune_Func_1(void); +void Fune_Func_2(void); +void Fune_Func_4(void); +void Fune_Init(void); +void Fune_Main(void); +void Kago_Func_1(uint16 k); +void Kago_Init(void); +void Kago_Main(void); +void Kago_Shot(void); +void KiHunterWings_Init(void); +void KiHunterWings_Main(void); +void KiHunter_Func_1(uint16 k); +void KiHunter_Func_10(uint16 k); +void KiHunter_Func_11(void); +void KiHunter_Func_12(void); +void KiHunter_Func_13(void); +void KiHunter_Func_14(void); +void KiHunter_Func_15(uint16 k); +void KiHunter_Func_16(uint16 k); +void KiHunter_Func_17(void); +void KiHunter_Func_2(uint16 k); +void KiHunter_Func_3(uint16 k); +void KiHunter_Func_4(uint16 k); +void KiHunter_Func_5(uint16 k); +void KiHunter_Func_6(uint16 k); +void KiHunter_Func_7(uint16 k); +void KiHunter_Func_8(uint16 k); +void KiHunter_Func_9(uint16 k); +void KiHunter_Init(void); +void KiHunter_Main(void); +void KiHunter_Shot(void); +void MaridiaFloater_Func_1(uint16 k); +void MaridiaFloater_Func_10(uint16 k); +void MaridiaFloater_Func_11(uint16 k); +void MaridiaFloater_Func_12(uint16 k); +void MaridiaFloater_Func_13(uint16 k); +void MaridiaFloater_Func_2(uint16 k); +void MaridiaFloater_Func_3(uint16 k); +void MaridiaFloater_Func_4(uint16 k); +void MaridiaFloater_Func_5(uint16 k); +void MaridiaFloater_Func_6(uint16 k); +void MaridiaFloater_Func_7(uint16 k); +void MaridiaFloater_Func_8(uint16 k); +void MaridiaFloater_Func_9(uint16 k); +void MaridiaFloater_Init(void); +void MaridiaFloater_Main(void); +void MaridiaFloater_Powerbomb(void); +void MaridiaFloater_Shot(void); +void MaridiaFloater_Touch(void); +void MaridiaPuffer_Func_1(void); +void MaridiaPuffer_Func_10(void); +void MaridiaPuffer_Func_11(void); +void MaridiaPuffer_Func_2(void); +void MaridiaPuffer_Func_3(void); +void MaridiaPuffer_Func_4(void); +void MaridiaPuffer_Func_5(void); +void MaridiaPuffer_Func_6(void); +void MaridiaPuffer_Func_7(void); +void MaridiaPuffer_Func_8(uint16 k); +void MaridiaPuffer_Func_9(uint16 k); +void MaridiaPuffer_Init(void); +void MaridiaPuffer_Main(void); +void MaridiaPuffer_Shot(void); +void MiniDraygon_Func_1(void); +void MiniDraygon_Func_10(void); +void MiniDraygon_Func_11(void); +void MiniDraygon_Func_12(void); +void MiniDraygon_Func_13(void); +void MiniDraygon_Func_2(void); +void MiniDraygon_Func_3(void); +void MiniDraygon_Func_4(void); +void MiniDraygon_Func_5(void); +void MiniDraygon_Func_6(void); +void MiniDraygon_Func_7(void); +void MiniDraygon_Func_8(void); +void MiniDraygon_Func_9(void); +void MiniDraygon_Init(void); +void MiniDraygon_Main(void); +void MiniDraygon_Powerbomb(void); +void MiniDraygon_Shot(void); +void MiniDraygon_Touch(void); +void MorphBallEye_Func_1(uint16 k); +void MorphBallEye_Func_2(uint16 k); +void MorphBallEye_Func_3(uint16 k); +void MorphBallEye_Func_4(uint16 k); +void MorphBallEye_Init(void); +void MorphBallEye_Main(void); +void NorfairLavaMan_Common(void); +void NorfairLavaMan_Func_1(void); +void NorfairLavaMan_Func_10(uint16 k); +void NorfairLavaMan_Func_11(uint16 k); +void NorfairLavaMan_Func_12(uint16 k); +void NorfairLavaMan_Func_13(void); +void NorfairLavaMan_Func_14(uint16 k); +void NorfairLavaMan_Func_15(uint16 k); +void NorfairLavaMan_Func_16(uint16 k); +void NorfairLavaMan_Func_17(uint16 k); +void NorfairLavaMan_Func_18(uint16 k); +void NorfairLavaMan_Func_19(uint16 k); +void NorfairLavaMan_Func_2(void); +void NorfairLavaMan_Func_20(void); +void NorfairLavaMan_Func_3(void); +void NorfairLavaMan_Func_4(void); +void NorfairLavaMan_Func_5(uint16 k); +void NorfairLavaMan_Func_6(void); +void NorfairLavaMan_Func_7(uint16 k); +void NorfairLavaMan_Func_8(uint16 k); +void NorfairLavaMan_Func_9(uint16 k); +void NorfairLavaMan_Init(void); +void NorfairLavaMan_Main(void); +void NorfairLavaMan_Powerbomb(void); +void NorfairLavaMan_Shot(void); +void NorfairLavaMan_Touch(void); +void WalkingLavaSeahorse_DF20(uint16 a); +void WalkingLavaSeahorse_Func_1(uint16 k); +void WalkingLavaSeahorse_Func_10(void); +void WalkingLavaSeahorse_Func_3(uint16 k); +void WalkingLavaSeahorse_Func_4(uint16 k); +void WalkingLavaSeahorse_Func_5(uint16 k); +void WalkingLavaSeahorse_Func_6(uint16 k); +void WalkingLavaSeahorse_Func_7(uint16 k); +void WalkingLavaSeahorse_Func_8(uint16 k); +void WalkingLavaSeahorse_Func_9(uint16 k); +void WalkingLavaSeahorse_Init(void); +void WalkingLavaSeahorse_Main(void); +void WreckedShipGhost_Func_1(uint16 k); +void WreckedShipGhost_Func_2(uint16 k); +void WreckedShipGhost_Func_3(uint16 k); +void WreckedShipGhost_Func_4(uint16 k); +void WreckedShipGhost_Func_5(uint16 k); +void WreckedShipGhost_Func_6(uint16 k); +void WreckedShipGhost_Func_7(uint16 k); +void WreckedShipGhost_Init(void); +void WreckedShipGhost_Main(void); +void WreckedShipOrbs_Func_1(void); +void WreckedShipOrbs_Func_2(void); +void WreckedShipOrbs_Func_3(void); +void WreckedShipOrbs_Func_4(void); +void WreckedShipOrbs_Func_5(void); +void WreckedShipOrbs_Func_6(void); +void WreckedShipOrbs_Func_7(void); +void WreckedShipOrbs_Func_8(void); +void WreckedShipOrbs_Init(void); +void WreckedShipOrbs_Main(void); +void WreckedShipRobotDeactivated_Init(void); +void WreckedShipRobotDeactivated_Shot(void); +void WreckedShipRobotDeactivated_Touch(void); +void WreckedShipRobot_Func_1(void); +void WreckedShipRobot_Func_2(uint16 k); +void WreckedShipRobot_Init(void); +void WreckedShipRobot_Main(void); +void WreckedShipRobot_Shot(void); +void WreckedShipSpark_Func_1(uint16 k); +void WreckedShipSpark_Func_2(uint16 k); +void WreckedShipSpark_Func_3(uint16 k); +void WreckedShipSpark_Func_4(uint16 k); +void WreckedShipSpark_Init(void); +void WreckedShipSpark_Main(void); +void WreckedShipSpark_Shot(void); +void YappingMaw_Frozen(void); +void YappingMaw_Func_1(void); +void YappingMaw_Func_10(void); +void YappingMaw_Func_11(void); +void YappingMaw_Func_12(void); +void YappingMaw_Func_13(void); +void YappingMaw_Func_14(void); +void YappingMaw_Func_15(void); +void YappingMaw_Func_18(uint16 j); +void YappingMaw_Func_19(void); +void YappingMaw_Func_2(void); +void YappingMaw_Func_3(void); +void YappingMaw_Func_4(void); +void YappingMaw_Func_5(void); +void YappingMaw_Func_6(void); +void YappingMaw_Func_7(void); +void YappingMaw_Func_8(void); +void YappingMaw_Func_9(uint16 k); +void YappingMaw_Init(void); +void YappingMaw_Main(void); +void YappingMaw_Shot(void); +void YappingMaw_Touch(void); +void sub_A8AF32(void); +void sub_A8B193(uint16 k); +void sub_A8B291(uint16 k); +void sub_A8DDDE(uint16 k); +void sub_A8F6DC(uint16 k, uint16 j); + +// Bank A9 +uint16 ComputeCosMult(uint16 a); +uint16 ComputeSinMult(uint16 a); +uint16 EnemyInstr_Sleep_A9(uint16 k, uint16 j); +uint16 HandleRoomPaletteInstructionList(uint16 a); +uint16 MotherBrain_DetermineShotReactionType(void); +uint16 MotherBrain_Func_1_DoubleRetTmp(void); +uint16 MotherBrain_Instr_AimRingsAtSamus(uint16 k); +uint16 MotherBrain_Instr_AimRingsAtShitroid(uint16 k); +uint16 MotherBrain_Instr_DisableNeckMovement(uint16 k); +uint16 MotherBrain_Instr_Down2Right15(uint16 k, uint16 j); +uint16 MotherBrain_Instr_Down4Right6(uint16 k, uint16 j); +uint16 MotherBrain_Instr_EnableNeckMovementGoto(uint16 k); +uint16 MotherBrain_Instr_Goto(uint16 k); +uint16 MotherBrain_Instr_Goto2(uint16 k); +uint16 MotherBrain_Instr_GotoEitherOr(uint16 k); +uint16 MotherBrain_Instr_IncrBeamAttackPhase(uint16 k, uint16 j); +uint16 MotherBrain_Instr_IncrShitroidAttackCtr(uint16 k); +uint16 MotherBrain_Instr_MaybeGoto(uint16 k); +uint16 MotherBrain_Instr_MaybeGoto2(uint16 k); +uint16 MotherBrain_Instr_MoveBodyUp10Left4(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveBodyUp12Right2(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveBodyUp16Left4(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveDown1(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveDown10Right2(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveDown12Left4(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveDown16Right2(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveDown1Left3(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveDown2Right1(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveDown4Right2(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveLeft2(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveRight2(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveUp1(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveUp1Right3_Sfx(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveUp2Left15_Sfx(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveUp2Right1(uint16 k, uint16 j); +uint16 MotherBrain_Instr_MoveUp4Left6(uint16 k, uint16 j); +uint16 MotherBrain_Instr_QueueSfx2(uint16 k); +uint16 MotherBrain_Instr_QueueSfx3(uint16 k); +uint16 MotherBrain_Instr_QueueShitroidAttackSfx(uint16 k); +uint16 MotherBrain_Instr_SetMainShakeTimer50(uint16 k); +uint16 MotherBrain_Instr_SetPose_Crouched(uint16 k, uint16 j); +uint16 MotherBrain_Instr_SetPose_CrouchedTrans(uint16 k, uint16 j); +uint16 MotherBrain_Instr_SetPose_DeathBeamMode(uint16 k, uint16 j); +uint16 MotherBrain_Instr_SetPose_LeaningDown(uint16 k, uint16 j); +uint16 MotherBrain_Instr_SetPose_Standing(uint16 k, uint16 j); +uint16 MotherBrain_Instr_SetPose_Walking(uint16 k, uint16 j); +uint16 MotherBrain_Instr_SetShitroidAttackCtr0(uint16 k); +uint16 MotherBrain_Instr_SetupFxForRainbowBeam(uint16 k); +uint16 MotherBrain_Instr_SpawnBlueRingEproj(uint16 k); +uint16 MotherBrain_Instr_SpawnBombEproj(uint16 k); +uint16 MotherBrain_Instr_SpawnDeathBeamEproj(uint16 k, uint16 j); +uint16 MotherBrain_Instr_SpawnDroolEproj(uint16 k); +uint16 MotherBrain_Instr_SpawnEprojToOffset(uint16 k, uint16 j); +uint16 MotherBrain_Instr_SpawnLaserEproj(uint16 k); +uint16 MotherBrain_Instr_SpawnPurpleBreath(uint16 k); +uint16 MotherBrain_Instr_SpawnRainbowEproj(uint16 k); +uint16 MotherBrain_Instr_Up2Left1_Sfx(uint16 k, uint16 j); +uint16 MotherBrain_Instr_Up2Left1_Sfx2(uint16 k, uint16 j); +uint16 MotherBrain_Instr_Up4Left2(uint16 k, uint16 j); +uint16 Shitroid_HandleCrySoundEffect(uint16 k, uint16 a); +uint16 Shitroid_Instr_1(uint16 k, uint16 j); +uint16 Shitroid_Instr_2(uint16 k, uint16 j); +uint16 Shitroid_Instr_3(uint16 k, uint16 j); +uint16 Shitroid_Instr_4(uint16 k, uint16 j); +uint16 Shitroid_Instr_5(uint16 k, uint16 j); +uint16 Shitroid_Instr_6(uint16 k, uint16 j); +uint16 sub_A9C46C(uint16 a, uint16 j); +uint16 sub_A9ECD0(uint16 k, uint16 j); +uint8 DeadMonsters_Func_3(uint16 k); +uint8 DeadTorizo_Func_0(void); +uint8 MotherBrain_MakeHerCrouch(void); +uint8 MotherBrain_MakeHerLeanDown(void); +uint8 MotherBrain_MakeHerStandUp(void); +uint8 MotherBrain_MakeWalkBackwards(uint16 a, uint16 j); +uint8 MotherBrain_MakeWalkForwards(uint16 j, uint16 a); +uint8 MotherBrain_MoveSamusForFallingAfterBeam(void); +uint8 MotherBrain_MoveSamusHorizTowardsWall(uint16 a); +uint8 MotherBrain_MoveSamusTowardsWallDueToBeam(void); +uint8 MotherBrain_MoveSamusVerticallyTowardsCeilingFloor(uint16 a); +uint8 MotherBrain_Phase2_DecideAttackStrategy_DoubleRet(void); +uint8 MotherBrain_SamusCollDetectPart(uint16 k); +uint8 MotherBrain_WalkBackwardsSlowlyAndRetractHead(uint16 a); +uint8 ProcessCorpseRotting(uint16 k); +uint8 ProcessSpriteTilesTransfers(uint8 db, uint16 k); +uint8 Samus_HealDueToShitroid(void); +uint8 ShitroidInCutscene_FadeShitroidToBlack(uint16 k); +uint8 Shitroid_AccelerateTowardsPoint(uint16 k, uint16 a); +uint8 Shitroid_CheckIfOnScreen(uint16 k); +uint8 Shitroid_Func_1(uint16 k, uint16 j); +uint8 Shitroid_Func_2(uint16 k); +uint8 Shitroid_Func_27(uint16 k); +void CopyMoveCorpseRottingRotEntry(uint16 a); +void CorpseRottingRotEntryFinishedHook(void); +void DeadMonsters_Func_1(uint16 k); +void DeadMonsters_Func_2(uint16 k); +void DeadMonsters_Func_4(uint16 k, uint16 a); +void DeadMonsters_Func_5(uint16 k); +void DeadMonsters_PreRotDelay_Common(uint16 k, uint16 j); +void DeadMonsters_WaitForSamusColl(uint16 k, uint16 j); +void DeadRipper_Init(void); +void DeadRipper_Powerbomb(void); +void DeadRipper_PreRotDelay(uint16 k); +void DeadRipper_Rotting(uint16 k); +void DeadRipper_Shot(void); +void DeadRipper_WaitForSamusColl(uint16 k); +void DeadSidehopper_Activated(uint16 k); +void DeadSidehopper_Alive_WaitForActivate(uint16 k); +void DeadSidehopper_DD31(void); +void DeadSidehopper_DD34(uint16 a); +void DeadSidehopper_Init(void); +void DeadSidehopper_Init_0(void); +void DeadSidehopper_Init_1(void); +void DeadSidehopper_Main(void); +void DeadSidehopper_Powerbomb(void); +void DeadSidehopper_PreRotDelay(uint16 k); +void DeadSidehopper_Rotting(uint16 k); +void DeadSidehopper_Shot(void); +void DeadSidehopper_Touch(void); +void DeadSidehopper_WaitForSamusColl(uint16 k); +void DeadSkree_Init(void); +void DeadSkree_Powerbomb(void); +void DeadSkree_PreRotDelay(uint16 k); +void DeadSkree_Rotting(uint16 k); +void DeadSkree_Shot(void); +void DeadSkree_WaitForSamusColl(uint16 k); +void DeadTorizo_CopyLineOfSandHeapTileData(uint16 a); +void DeadTorizo_CorpseRottingFinished(void); +void DeadTorizo_Func_1(void); +void DeadTorizo_Init(void); +void DeadTorizo_Main(void); +void DeadTorizo_MainGfxHook(void); +void DeadTorizo_Powerbomb(void); +void DeadTorizo_PreRotDelay(void); +void DeadTorizo_Rotting(void); +void DeadTorizo_Shot(void); +void DeadTorizo_WaitForSamusColl(uint16 k); +void DeadZoomer_Init(void); +void DeadZoomer_Powerbomb(void); +void DeadZoomer_PreRotDelay(uint16 k); +void DeadZoomer_Rotting(uint16 k); +void DeadZoomer_Shot(void); +void DeadZoomer_WaitForSamusColl(uint16 k); +void Enemy_GrappleReact_CancelBeam_A9(void); +void Enemy_IncreaseYpos(uint16 k, uint16 a); +void Enemy_NormalFrozenAI_A9(void); +void Enemy_SetInstrList(uint16 k, uint16 a); +void HandleSamusRainbowPaletteAnimation(uint16 k); +void InitializeCorpseRottingDataTable(uint16 k, uint16 a); +void InitializeEnemyCorpseRotting(uint16 k, uint16 j); +void MotherBomb_FiringDeathBeam(void); +void MotherBomb_FiringDeathBeam_0(void); +void MotherBomb_FiringDeathBeam_1(void); +void MotherBomb_FiringDeathBeam_2(void); +void MotherBomb_FiringDeathBeam_3(void); +void MotherBomb_FiringLaser_FinishAttack(void); +void MotherBomb_FiringLaser_PositionHead(void); +void MotherBomb_FiringLaser_PositionHeadSlowlyFire(void); +void MotherBomb_FiringRainbowBeam_0(void); +void MotherBomb_FiringRainbowBeam_10_FinishFiringRainbow(void); +void MotherBomb_FiringRainbowBeam_11_LetSamusFall(void); +void MotherBomb_FiringRainbowBeam_12_WaitForSamusHitGround(void); +void MotherBomb_FiringRainbowBeam_13_LowerHead(void); +void MotherBomb_FiringRainbowBeam_14_DecideNextAction(void); +void MotherBomb_FiringRainbowBeam_1_StartCharge(void); +void MotherBomb_FiringRainbowBeam_2_RetractNeck(void); +void MotherBomb_FiringRainbowBeam_3_Wait(void); +void MotherBomb_FiringRainbowBeam_4_ExtendNeckDown(void); +void MotherBomb_FiringRainbowBeam_5_StartFiring(void); +void MotherBomb_FiringRainbowBeam_6_MoveSamusToWall(void); +void MotherBomb_FiringRainbowBeam_7_DelayFrame(void); +void MotherBomb_FiringRainbowBeam_8_StartDrainSamus(void); +void MotherBomb_FiringRainbowBeam_9_DrainingSamus(void); +void MotherBrainBody_0_Wait(void); +void MotherBrainBody_10_ClearCeilingTubeColumn7(void); +void MotherBrainBody_11_SpawnTopMiddleRightFalling(void); +void MotherBrainBody_12_ClearCeilingTubeColumn8(void); +void MotherBrainBody_13_SpawnTubeFallingEnemy3(void); +void MotherBrainBody_14_ClearBottomMiddleRightTube(void); +void MotherBrainBody_15_SpawnTubeFallingEnemy4(void); +void MotherBrainBody_16_ClearBottomMiddleTubes(void); +void MotherBrainBody_1_ClearBottomLeftTube(void); +void MotherBrainBody_2_SpawnTopRightTubeFalling(void); +void MotherBrainBody_2ndphase_16_ShakeHeadMenacingly(void); +void MotherBrainBody_2ndphase_17_BringHeadBackUp(void); +void MotherBrainBody_2ndphase_18_FinishStretching(void); +void MotherBrainBody_3_ClearCeilingBlock9(void); +void MotherBrainBody_4_ClearCeilingBlock6(void); +void MotherBrainBody_4_SpawnTopLeftTubeFalling(void); +void MotherBrainBody_5_SpawnTubeFallingEnemy1(void); +void MotherBrainBody_6_ClearBottomRightTube(void); +void MotherBrainBody_7_SpawnTubeFallingEnemy2(void); +void MotherBrainBody_8_ClearBottomMiddleLeftTube(void); +void MotherBrainBody_9_SpawnTopMiddleLeftFalling(void); +void MotherBrainBody_FakeDeath_Ascent_0_DrawBG1Row23(void); +void MotherBrainBody_FakeDeath_Ascent_10_LoadLegTiles(void); +void MotherBrainBody_FakeDeath_Ascent_11_ContinuePause(void); +void MotherBrainBody_FakeDeath_Ascent_12_StartMusic(void); +void MotherBrainBody_FakeDeath_Ascent_13_Raise(void); +void MotherBrainBody_FakeDeath_Ascent_14_WaitForUncouching(void); +void MotherBrainBody_FakeDeath_Ascent_15_TransitionFromGrey(void); +void MotherBrainBody_FakeDeath_Ascent_1_DrawBG1Row45(void); +void MotherBrainBody_FakeDeath_Ascent_2_DrawBG1Row67(void); +void MotherBrainBody_FakeDeath_Ascent_3_DrawBG1Row89(void); +void MotherBrainBody_FakeDeath_Ascent_4_DrawBG1RowAB(void); +void MotherBrainBody_FakeDeath_Ascent_5_DrawBG1RowCD(void); +void MotherBrainBody_FakeDeath_Ascent_6_SetupPhase2Gfx(void); +void MotherBrainBody_FakeDeath_Ascent_7_SetupPhase2Brain(void); +void MotherBrainBody_FakeDeath_Ascent_8_Pause(void); +void MotherBrainBody_FakeDeath_Ascent_9_PrepareRise(void); +void MotherBrainBody_FakeDeath_Descent_0_Pause(void); +void MotherBrainBody_FakeDeath_Descent_1(void); +void MotherBrainBody_FakeDeath_Descent_2(void); +void MotherBrainBody_FakeDeath_Descent_3(void); +void MotherBrainBody_FakeDeath_Descent_4(void); +void MotherBrainBody_FakeDeath_Descent_5(void); +void MotherBrainBody_FakeDeath_Descent_6(void); +void MotherBrain_AddSpritemapToOam(uint16 j); +void MotherBrain_AimBeam(void); +void MotherBrain_AimBeamAndIncrWidth(void); +void MotherBrain_B7CB(void); +void MotherBrain_BodyRainbowBeamPalAnimIndex0(void); +void MotherBrain_Body_Phase2_Thinking(void); +void MotherBrain_Body_Phase2_TryAttack(void); +void MotherBrain_CalculateRainbowBeamHdma(void); +void MotherBrain_CalculateRainbowBeamHdma_(void); +void MotherBrain_CorpseRottingCopyFunc(uint16 j, uint16 k); +void MotherBrain_CorpseRottingFinished(void); +void MotherBrain_CorpseRottingInitFunc(void); +void MotherBrain_CorpseRottingMoveFunc(uint16 j, uint16 k); +void MotherBrain_DrainedByShitroid_0(void); +void MotherBrain_DrainedByShitroid_1(void); +void MotherBrain_DrainedByShitroid_2(void); +void MotherBrain_DrainedByShitroid_3(void); +void MotherBrain_DrainedByShitroid_4(void); +void MotherBrain_DrainedByShitroid_5(void); +void MotherBrain_DrainedByShitroid_6(void); +void MotherBrain_DrainedByShitroid_7(void); +void MotherBrain_DrawBrain(void); +void MotherBrain_DrawBrainNeck_EnemyGfxDrawHook(void); +void MotherBrain_DrawNeck(void); +void MotherBrain_DrawNeckSegment(void); +void MotherBrain_ExplodeEscapeDoor(void); +void MotherBrain_FiringBomb_Crouch(void); +void MotherBrain_FiringBomb_DecideOnCrouching(void); +void MotherBrain_FiringBomb_DecideOnWalking(void); +void MotherBrain_FiringBomb_Finish(void); +void MotherBrain_FiringBomb_Fired(void); +void MotherBrain_FiringBomb_Standup(void); +void MotherBrain_FiringBomb_WalkingBackwards(void); +void MotherBrain_FootstepEffect(void); +void MotherBrain_GenerateEscapeDoorExploding(void); +void MotherBrain_GenerateExplosions(uint16 a); +void MotherBrain_GenerateMixedExplosions(void); +void MotherBrain_GenerateSmokyExplosions(void); +void MotherBrain_HandleBrainPal(void); +void MotherBrain_HandleFakeDeathExplosions(void); +void MotherBrain_HandleNeck(void); +void MotherBrain_HandleNeckLower(void); +void MotherBrain_HandleNeckLower_0(void); +void MotherBrain_HandleNeckLower_2_BobDown(void); +void MotherBrain_HandleNeckLower_4_BobUp(void); +void MotherBrain_HandleNeckLower_6_Lower(void); +void MotherBrain_HandleNeckLower_8_Raise(void); +void MotherBrain_HandleNeckUpper(void); +void MotherBrain_HandlePalette(void); +void MotherBrain_HandleRainbowBeamExplosions(void); +void MotherBrain_HandleRainbowBeamPalette(void); +void MotherBrain_HandleWalking(void); +void MotherBrain_HurtSamus(void); +void MotherBrain_Instr_AimRings(void); +void MotherBrain_MaybeStandupOrLeanDown(void); +void MotherBrain_MoveBodyDown(uint16 a); +void MotherBrain_MoveBodyDownScrollLeft(uint16 k, uint16 a); +void MotherBrain_MoveSamusTowardsMiddleOfWall(void); +void MotherBrain_PainfulWalkBackwards(void); +void MotherBrain_PainfulWalkForwards(void); +void MotherBrain_PainfulWalkingBackwards(void); +void MotherBrain_PainfulWalkingForwards(void); +void MotherBrain_Pal_BeginScreenFlash(void); +void MotherBrain_Pal_EndScreenFlash(void); +void MotherBrain_Pal_HandleRoomPal(void); +void MotherBrain_Pal_ProcessInvincibility(void); +void MotherBrain_Pal_WriteRoomPal(uint16 j); +void MotherBrain_Phase23_ShotReaction(void); +void MotherBrain_Phase2Cut_0(void); +void MotherBrain_Phase2Cut_1(void); +void MotherBrain_Phase2Cut_2(void); +void MotherBrain_Phase2Cut_3(void); +void MotherBrain_Phase2Cut_4(void); +void MotherBrain_Phase2Cut_5(void); +void MotherBrain_Phase2_Attack_Cooldown(void); +void MotherBrain_Phase2_Attack_End(void); +void MotherBrain_Phase2_ExecuteFinalkShitroid(void); +void MotherBrain_Phase2_MurderShitroid_1(void); +void MotherBrain_Phase2_MurderShitroid_2(void); +void MotherBrain_Phase2_PrepareForFinalShitroid(void); +void MotherBrain_Phase2_Revive_0(void); +void MotherBrain_Phase2_Revive_1(void); +void MotherBrain_Phase2_Revive_2(void); +void MotherBrain_Phase2_Revive_3(void); +void MotherBrain_Phase2_Revive_4(void); +void MotherBrain_Phase2_Revive_5(void); +void MotherBrain_Phase2_Revive_6(void); +void MotherBrain_Phase2_Revive_7(void); +void MotherBrain_Phase2_Revive_8(void); +void MotherBrain_Phase3_BeamShotReaction(void); +void MotherBrain_Phase3_Death_0(void); +void MotherBrain_Phase3_Death_1(void); +void MotherBrain_Phase3_Death_10(void); +void MotherBrain_Phase3_Death_11(void); +void MotherBrain_Phase3_Death_12(void); +void MotherBrain_Phase3_Death_13(void); +void MotherBrain_Phase3_Death_14_20framedelay(void); +void MotherBrain_Phase3_Death_15_LoadEscapeTimerTiles(void); +void MotherBrain_Phase3_Death_16_StartEscape(void); +void MotherBrain_Phase3_Death_17_SpawnTimeBomb(void); +void MotherBrain_Phase3_Death_18_TypesZebesText(void); +void MotherBrain_Phase3_Death_19_EscapeDoorExploding(void); +void MotherBrain_Phase3_Death_2(void); +void MotherBrain_Phase3_Death_20_BlowUpEscapeDoor(void); +void MotherBrain_Phase3_Death_21_KeepEarthquakeGoing(void); +void MotherBrain_Phase3_Death_3(void); +void MotherBrain_Phase3_Death_4(void); +void MotherBrain_Phase3_Death_5(void); +void MotherBrain_Phase3_Death_6(void); +void MotherBrain_Phase3_Death_7(void); +void MotherBrain_Phase3_Death_8(void); +void MotherBrain_Phase3_Death_9(void); +void MotherBrain_Phase3_Fighting_Cooldown(void); +void MotherBrain_Phase3_Fighting_Main(void); +void MotherBrain_Phase3_NeckHandler(void); +void MotherBrain_Phase3_Neck_HyperBeamRecoil(void); +void MotherBrain_Phase3_Neck_Normal(void); +void MotherBrain_Phase3_Neck_RecoilRecovery(void); +void MotherBrain_Phase3_Neck_SetupHyperBeamRecoil(void); +void MotherBrain_Phase3_Neck_SetupRecoilRecovery(void); +void MotherBrain_Phase3_Recover_MakeDistance(void); +void MotherBrain_Phase3_Recover_SetupForFight(void); +void MotherBrain_Phase3_WalkHandler(void); +void MotherBrain_Phase3_Walk_RetreatQuickly(void); +void MotherBrain_Phase3_Walk_RetreatSlowly(void); +void MotherBrain_Phase3_Walk_TryToInchForward(void); +void MotherBrain_PlayRainbowBeamSfx(void); +void MotherBrain_RetractHead(void); +void MotherBrain_SamusCollDetect(void); +void MotherBrain_SetBodyInstrs(uint16 a); +void MotherBrain_SetBrainInstrs(uint16 a); +void MotherBrain_SetBrainUnusedInstrs(uint16 a); +void MotherBrain_SetPainfulWalkingTimer(void); +void MotherBrain_SetToTryToInchForward(uint16 a); +void MotherBrain_SetupBrainNormalPal(void); +void MotherBrain_SetupBrainPalForLaser(void); +void MotherBrain_SetupNeckForFakeAscent(void); +void MotherBrain_SpawnDustCloudsForAscent(void); +void MotherBrain_SpawnShitroidInCutscene(void); +void MotherBrain_WriteDefaultPalette(void); +void MotherBrain_WritePalette(uint16 j); +void MotherBrain_WritePhase2DeathPalette(void); +void MotherBrainsBody_FirstPhase_DoubleRet(void); +void MotherBrainsBody_Hurt(void); +void MotherBrainsBody_Init(void); +void MotherBrainsBody_Powerbomb(void); +void MotherBrainsBody_Shot(void); +void MotherBrainsBody_UnpauseHook(void); +void MotherBrainsBrain_GfxDrawHook(void); +void MotherBrainsBrain_Hurt(void); +void MotherBrainsBrain_Init(void); +void MotherBrainsBrain_SetupBrainAndNeckToDraw(void); +void MotherBrainsBrain_SetupBrainToDraw(void); +void MotherBrainsBrain_Shot(void); +void MotherBrainsBrain_Touch(void); +void MotherBrainsTubesFalling_Explode(uint16 k); +void MotherBrainsTubesFalling_Falling(uint16 k); +void MotherBrainsTubesFalling_HandleSmoke(uint16 k); +void MotherBrainsTubesFalling_Init(void); +void MotherBrainsTubesFalling_Main(uint16 k); +void MotherBrainsTubesFalling_Main_NonMain(uint16 k); +void MotherBrainsTubesFalling_SpawnSmoke(uint16 k); +void MotherBrainsTubesFalling_WaitToFall(uint16 k); +void MoveEnemyWithVelocity(void); +void ProcessCorpseRottingVramTransfers(uint16 k); +void Ripper_CorpseRottingCopyFunc_0(uint16 j, uint16 k); +void Ripper_CorpseRottingCopyFunc_2(uint16 j, uint16 k); +void Ripper_CorpseRottingInitFunc_0(void); +void Ripper_CorpseRottingInitFunc_2(void); +void Ripper_CorpseRottingMoveFunc_0(uint16 j, uint16 k); +void Ripper_CorpseRottingMoveFunc_2(uint16 j, uint16 k); +void SamusRainbowPaletteFunc_ActivateWhenEnemyLow(uint16 k); +void SamusRainbowPaletteFunc_GraduallySlowDown(void); +void Samus_DamageDueToRainbowBeam(void); +void Samus_DamageDueToShitroid(void); +void Samus_DecrementAmmoDueToRainbowBeam(void); +void Samus_PlayGainingLosingHealthSfx(void); +void ShitroidInCutscene_AccelerateDownwards(uint16 k); +void ShitroidInCutscene_ActivateRainbowBeam(uint16 k); +void ShitroidInCutscene_BrainTurnsToCorpse(uint16 k); +void ShitroidInCutscene_CurveTowardsBrain(uint16 k); +void ShitroidInCutscene_DashOntoScreen(uint16 k); +void ShitroidInCutscene_DeathSequence(uint16 k); +void ShitroidInCutscene_FinalCharge(uint16 k); +void ShitroidInCutscene_FinishCutscene(uint16 k); +void ShitroidInCutscene_Flashing(uint16 k); +void ShitroidInCutscene_FlyOffScreen(uint16 k); +void ShitroidInCutscene_GetIntoFace(uint16 k); +void ShitroidInCutscene_HandleCry(void); +void ShitroidInCutscene_HandleEnemyBlinking(uint16 k); +void ShitroidInCutscene_HandleHealthBasedPalette(uint16 k); +void ShitroidInCutscene_HandleShitroidDeathExplosions(uint16 k); +void ShitroidInCutscene_HealSamusToFullHealth(uint16 k); +void ShitroidInCutscene_IdleUntilToNoHealth(uint16 k); +void ShitroidInCutscene_Init(void); +void ShitroidInCutscene_InitiateFinalCharge(uint16 k); +void ShitroidInCutscene_LatchOntoBrain(uint16 k); +void ShitroidInCutscene_LatchOntoSamus(uint16 k); +void ShitroidInCutscene_LetGoAndSpawnDust(uint16 k); +void ShitroidInCutscene_LetSamusRainbowMore(uint16 k); +void ShitroidInCutscene_Main(void); +void ShitroidInCutscene_MoveToFinalChargeStart(uint16 k); +void ShitroidInCutscene_MoveToSamus(uint16 k); +void ShitroidInCutscene_MoveUpToCeiling(uint16 k); +void ShitroidInCutscene_PlaySamusTheme(uint16 k); +void ShitroidInCutscene_PrepareSamusHyperbeam(uint16 k); +void ShitroidInCutscene_ReleaseSamus(uint16 k); +void ShitroidInCutscene_SetMotherBrainToStumbleBack(uint16 k); +void ShitroidInCutscene_Shake(uint16 k); +void ShitroidInCutscene_ShitroidFinalBelow(uint16 k); +void ShitroidInCutscene_SpawnOneDustCloudAt(uint16 a); +void ShitroidInCutscene_SpawnThreeDustClouds(void); +void ShitroidInCutscene_StareDownMotherBrain(uint16 k); +void ShitroidInCutscene_StopDraining(uint16 k); +void ShitroidInCutscene_Touch(void); +void ShitroidInCutscene_UnloadShitroid(uint16 k); +void ShitroidInCutscene_UpdateSpeedAndAngle(uint16 k); +void Shitroid_AccelerateTowardsX(uint16 k); +void Shitroid_AccelerateTowardsY(uint16 k); +void Shitroid_F3C4(uint16 k); +void Shitroid_Func_10(uint16 k); +void Shitroid_Func_11(uint16 k); +void Shitroid_Func_12(uint16 k); +void Shitroid_Func_13(uint16 k); +void Shitroid_Func_14(uint16 k); +void Shitroid_Func_15(uint16 k); +void Shitroid_Func_16(uint16 k); +void Shitroid_Func_17(uint16 k); +void Shitroid_Func_18(uint16 k); +void Shitroid_Func_19(uint16 k); +void Shitroid_Func_20(void); +void Shitroid_Func_21(void); +void Shitroid_Func_22(uint16 k); +void Shitroid_Func_23(void); +void Shitroid_Func_24(uint16 k); +void Shitroid_Func_25(uint16 k); +void Shitroid_Func_26(uint16 k); +void Shitroid_Func_3(uint16 k); +void Shitroid_Func_4(void); +void Shitroid_Func_5(uint16 k); +void Shitroid_Func_6(uint16 k); +void Shitroid_Func_7(uint16 k); +void Shitroid_Func_8(uint16 k); +void Shitroid_Func_9(uint16 k); +void Shitroid_Func_GraduallyAccelerateTowards0x400(uint16 k, uint16 j); +void Shitroid_GraduallyAccelerateHoriz(uint16 k); +void Shitroid_GraduallyAccelerateTowards0x10(uint16 k, uint16 j); +void Shitroid_GraduallyAccelerateTowards0x4(uint16 k, uint16 j); +void Shitroid_GraduallyAccelerateTowards0x8(uint16 k, uint16 j); +void Shitroid_GraduallyAccelerateTowardsPt(uint16 k, uint16 j); +void Shitroid_HandleCutscenePalette(void); +void Shitroid_HandleCutscenePalette_Common(void); +void Shitroid_HandleCutscenePalette_LowHealth(void); +void Shitroid_HandleNormalPalette(void); +void Shitroid_Init(void); +void Shitroid_Main(void); +void Shitroid_Powerbomb(void); +void Shitroid_Shot(void); +void Shitroid_Touch(void); +void Sidehopper_CorpseRottingCopyFunc_0(uint16 j, uint16 k); +void Sidehopper_CorpseRottingCopyFunc_2(uint16 j, uint16 k); +void Sidehopper_CorpseRottingInitFunc_0(void); +void Sidehopper_CorpseRottingInitFunc_2(void); +void Sidehopper_CorpseRottingMoveFunc_0(uint16 j, uint16 k); +void Sidehopper_CorpseRottingMoveFunc_2(uint16 j, uint16 k); +void Skree_CorpseRottingCopyFunc_0(uint16 j, uint16 k); +void Skree_CorpseRottingCopyFunc_2(uint16 j, uint16 k); +void Skree_CorpseRottingCopyFunc_4(uint16 j, uint16 k); +void Skree_CorpseRottingInitFunc_0(void); +void Skree_CorpseRottingInitFunc_2(void); +void Skree_CorpseRottingInitFunc_4(void); +void Skree_CorpseRottingMoveFunc_0(uint16 j, uint16 k); +void Skree_CorpseRottingMoveFunc_2(uint16 j, uint16 k); +void Skree_CorpseRottingMoveFunc_4(uint16 j, uint16 k); +void Torizo_CorpseRottingCopyFunc(uint16 j, uint16 k); +void Torizo_CorpseRottingInitFunc(void); +void Torizo_CorpseRottingMoveFunc(uint16 j, uint16 k); +void WriteColorsToPalette(uint16 k, uint8 db, uint16 j, uint16 a); +void WriteColorsToTargetPalette(uint8 db, uint16 k, uint16 j, uint16 a); +void Zoomer_CorpseRottingCopyFunc_0(uint16 j, uint16 k); +void Zoomer_CorpseRottingCopyFunc_2(uint16 j, uint16 k); +void Zoomer_CorpseRottingCopyFunc_4(uint16 j, uint16 k); +void Zoomer_CorpseRottingInitFunc_0(void); +void Zoomer_CorpseRottingInitFunc_2(void); +void Zoomer_CorpseRottingInitFunc_4(void); +void Zoomer_CorpseRottingMoveFunc_0(uint16 j, uint16 k); +void Zoomer_CorpseRottingMoveFunc_2(uint16 j, uint16 k); +void Zoomer_CorpseRottingMoveFunc_4(uint16 j, uint16 k); + +// Bank AA +uint16 EnemyInstr_CopyToVram_AA(uint16 k, uint16 j); +uint16 EnemyInstr_DecTimerAndGoto2_AA(uint16 k, uint16 j); +uint16 EnemyInstr_Goto_AA(uint16 k, uint16 j); +uint16 EnemyInstr_SetTimer_AA(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep_AA(uint16 k, uint16 j); +uint16 EnemyInstr_StopScript_AA(uint16 k, uint16 j); +uint16 EnemyInstr_WaitNframes_AA(uint16 k, uint16 j); +uint16 Enemy_ClearAiPreInstr_AA(uint16 k, uint16 j); +uint16 Enemy_SetAiPreInstr_AA(uint16 k, uint16 j); +uint16 Shaktool_D956(uint16 k, uint16 j, uint16 a); +uint16 Shaktool_Instr_1(uint16 k, uint16 j); +uint16 Shaktool_Instr_10(uint16 k, uint16 j); +uint16 Shaktool_Instr_11(uint16 k, uint16 j); +uint16 Shaktool_Instr_12(uint16 k, uint16 j); +uint16 Shaktool_Instr_13(uint16 k, uint16 j); +uint16 Shaktool_Instr_14(uint16 k, uint16 j); +uint16 Shaktool_Instr_2(uint16 k, uint16 j); +uint16 Shaktool_Instr_3(uint16 k, uint16 j); +uint16 Shaktool_Instr_4(uint16 k, uint16 j); +uint16 Shaktool_Instr_5(uint16 k, uint16 j); +uint16 Shaktool_Instr_6(uint16 k, uint16 j); +uint16 Shaktool_Instr_7(uint16 k, uint16 j); +uint16 Shaktool_Instr_8(uint16 k, uint16 j); +uint16 Shaktool_Instr_9(uint16 k, uint16 j); +uint16 Torizo_Func_12(uint16 k); +uint16 Torizo_Instr_1(uint16 k, uint16 j); +uint16 Torizo_Instr_10(uint16 k, uint16 j); +uint16 Torizo_Instr_11(uint16 k, uint16 j); +uint16 Torizo_Instr_12(uint16 k, uint16 j); +uint16 Torizo_Instr_13(uint16 k, uint16 j); +uint16 Torizo_Instr_14(uint16 k, uint16 j); +uint16 Torizo_Instr_15(uint16 k, uint16 j); +uint16 Torizo_Instr_16(uint16 k, uint16 j); +uint16 Torizo_Instr_17(uint16 k, uint16 j); +uint16 Torizo_Instr_18(uint16 k, uint16 j); +uint16 Torizo_Instr_19(uint16 k, uint16 j); +uint16 Torizo_Instr_2(uint16 k, uint16 j); +uint16 Torizo_Instr_20(uint16 k, uint16 j); +uint16 Torizo_Instr_21(uint16 k, uint16 j); +uint16 Torizo_Instr_22(uint16 k, uint16 j); +uint16 Torizo_Instr_23(uint16 k, uint16 j); +uint16 Torizo_Instr_24(uint16 k, uint16 j); +uint16 Torizo_Instr_25(uint16 k, uint16 j); +uint16 Torizo_Instr_26(uint16 k, uint16 j); +uint16 Torizo_Instr_27(uint16 k, uint16 j); +uint16 Torizo_Instr_28(uint16 k, uint16 j); +uint16 Torizo_Instr_29(uint16 k, uint16 j); +uint16 Torizo_Instr_3(uint16 k, uint16 j); +uint16 Torizo_Instr_30(uint16 k, uint16 j); +uint16 Torizo_Instr_31(uint16 k, uint16 j); +uint16 Torizo_Instr_32(uint16 k, uint16 j); +uint16 Torizo_Instr_33(uint16 k, uint16 j); +uint16 Torizo_Instr_34(uint16 k, uint16 j); +uint16 Torizo_Instr_35(uint16 k, uint16 j); +uint16 Torizo_Instr_36(uint16 k, uint16 j); +uint16 Torizo_Instr_37(uint16 k, uint16 j); +uint16 Torizo_Instr_38(uint16 k, uint16 j); +uint16 Torizo_Instr_39(uint16 k, uint16 j); +uint16 Torizo_Instr_4(uint16 k, uint16 j); +uint16 Torizo_Instr_40(uint16 k, uint16 j); +uint16 Torizo_Instr_41(uint16 k, uint16 j); +uint16 Torizo_Instr_42(uint16 k, uint16 j); +uint16 Torizo_Instr_43(uint16 k, uint16 j); +uint16 Torizo_Instr_44(uint16 k, uint16 j); +uint16 Torizo_Instr_45(uint16 k, uint16 j); +uint16 Torizo_Instr_46(uint16 k, uint16 j); +uint16 Torizo_Instr_47(uint16 k, uint16 j); +uint16 Torizo_Instr_48(uint16 k, uint16 j); +uint16 Torizo_Instr_49(uint16 k, uint16 j); +uint16 Torizo_Instr_5(uint16 k, uint16 j); +uint16 Torizo_Instr_50(uint16 k, uint16 j); +uint16 Torizo_Instr_51(uint16 k, uint16 j); +uint16 Torizo_Instr_52(uint16 k, uint16 j); +uint16 Torizo_Instr_53(uint16 k, uint16 j); +uint16 Torizo_Instr_54(uint16 k, uint16 j); +uint16 Torizo_Instr_55(uint16 k, uint16 j); +uint16 Torizo_Instr_56(uint16 k, uint16 j); +uint16 Torizo_Instr_57(uint16 k, uint16 j); +uint16 Torizo_Instr_58(uint16 k, uint16 j); +uint16 Torizo_Instr_59(uint16 k, uint16 j); +uint16 Torizo_Instr_6(uint16 k, uint16 j); +uint16 Torizo_Instr_60(uint16 k, uint16 j); +uint16 Torizo_Instr_61(uint16 k, uint16 j); +uint16 Torizo_Instr_62(uint16 k, uint16 j); +uint16 Torizo_Instr_63(uint16 k, uint16 j); +uint16 Torizo_Instr_7(uint16 k, uint16 j); +uint16 Torizo_Instr_8(uint16 k, uint16 j); +uint16 Torizo_Instr_9(uint16 k, uint16 j); +void ChozoStatue_Init(void); +void ChozoStatue_Main(void); +void Enemy_GrappleReact_CancelBeam_AA(void); +void Enemy_NormalFrozenAI_AA(void); +void GoldTorizo_Hurt(void); +void GoldTorizo_Main(void); +void GoldTorizo_Shot(void); +void GoldTorizo_Touch(void); +void N00bTubeCracks_Init(void); +void Shaktool_DAE5(uint16 k); +void Shaktool_DB0E(uint16 k, uint16 a); +void Shaktool_DB27(uint16 k, uint16 a); +void Shaktool_DB40(uint16 k, uint16 a); +void Shaktool_DB59(uint16 k); +void Shaktool_DC07(uint16 k); +void Shaktool_DC2A(uint16 k); +void Shaktool_DC6F(uint16 k); +void Shaktool_DCAC(uint16 k); +void Shaktool_DCD7(uint16 k); +void Shaktool_DD25(uint16 k); +void Shaktool_Hurt(void); +void Shaktool_Init(void); +void Shaktool_PreInstr_0(uint16 k); +void Shaktool_Shot(void); +void Shaktool_Touch(void); +void Torizo_C20A(uint16 k); +void Torizo_C22D(uint16 k); +void Torizo_C250(void); +void Torizo_C268(void); +void Torizo_C280(void); +void Torizo_C298(void); +void Torizo_C2B0(void); +void Torizo_C620(uint16 k); +void Torizo_C643(uint16 k); +void Torizo_D5E6(uint16 k); +void Torizo_D5ED(uint16 k); +void Torizo_D5F1(uint16 k); +void Torizo_D658(void); +void Torizo_D6A6(void); +void Torizo_D6D1(uint16 k, uint16 j); +void Torizo_D6F7(uint16 k, uint16 j); +void Torizo_Func_1(uint16 k); +void Torizo_Func_10(uint16 k); +void Torizo_Func_11(uint16 k); +void Torizo_Func_2(uint16 k); +void Torizo_Func_3(uint16 k); +void Torizo_Func_4(uint16 k); +void Torizo_Func_5(uint16 k); +void Torizo_Func_6(uint16 k); +void Torizo_Func_7(uint16 k); +void Torizo_Func_8(void); +void Torizo_Func_9(uint16 k); +void Torizo_Hurt(void); +void Torizo_Init(void); +void Torizo_Main(void); +void Torizo_Shot(void); +void TourianEntranceStatue_Init(void); +void sub_AAE445(uint16 k); +void sub_AAE784(void); + +// Bank AD +uint8 MotherBrain_EEF6(uint16 a); +uint8 MotherBrain_FadeFromGray_Drained(uint16 a); +uint8 MotherBrain_FadeFromGray_FakeDeath(uint16 a); +uint8 MotherBrain_FadePalToBlack(uint16 a); +uint8 MotherBrain_FadeToGray_Drained(uint16 a); +uint8 MotherBrain_FadeToGray_FakeDeath(uint16 a); +uint8 MotherBrain_FadeToGray_RealDeath(uint16 a); +uint8 MotherBrain_Phase3_TurnLightsBackOn(uint16 a); +void EnableEarthquakeAframes(uint16 a); +void HandleMotherBrainBodyFlickering(void); +void MotherBrain_CalcHdma(void); +void MotherBrain_CalcHdma_BeamAimedRight(void); +void MotherBrain_CalcHdma_BeamAimedRight2(void); +void MotherBrain_CalcHdma_BeamAimedUp(void); +void MotherBrain_CalcHdma_Down(void); +void MotherBrain_CalcHdma_Down_Down(void); +void MotherBrain_CalcHdma_Down_DownLeft(void); +void MotherBrain_CalcHdma_Down_DownRight(void); +void MotherBrain_CalcHdma_Up_Up(void); +void MotherBrain_CalcHdma_Up_UpLeft(void); +void MotherBrain_CalcHdma_Up_UpRight(void); +void MotherBrain_HealthBasedPaletteHandling(void); +void MotherBrain_SealWall(void); +void TurnOffLightsForShitroidDeath(void); + +// Bank B2 +uint16 EnemyInstr_DecTimerAndGoto2_B2(uint16 k, uint16 j); +uint16 EnemyInstr_Goto_B2(uint16 k, uint16 j); +uint16 EnemyInstr_SetTimer_B2(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep_B2(uint16 k, uint16 j); +uint16 EnemyInstr_WaitNframes_B2(uint16 k, uint16 j); +uint16 SpacePirates_Func_10(void); +uint16 SpacePirates_Func_8(void); +uint16 SpacePirates_Func_9(void); +uint16 SpacePirates_Instr_11(uint16 k, uint16 j); +uint16 SpacePirates_Instr_12(uint16 k, uint16 j); +uint16 SpacePirates_Instr_13(uint16 k, uint16 j); +uint16 SpacePirates_Instr_14(uint16 k, uint16 j); +uint16 SpacePirates_Instr_15(uint16 k, uint16 j); +uint16 SpacePirates_Instr_16(uint16 k, uint16 j); +uint16 SpacePirates_Instr_17(uint16 k, uint16 j); +uint16 SpacePirates_Instr_18(uint16 k, uint16 j); +uint16 SpacePirates_Instr_19(uint16 k, uint16 j); +uint16 SpacePirates_Instr_20(uint16 k, uint16 j); +uint16 SpacePirates_Instr_21(uint16 k, uint16 j); +uint16 SpacePirates_Instr_FireLaserL(uint16 k, uint16 j); +uint16 SpacePirates_Instr_FireLaserR(uint16 k, uint16 j); +uint16 SpacePirates_Instr_MovePixelsDownAndChangeDirFaceLeft(uint16 k, uint16 j); +uint16 SpacePirates_Instr_MovePixelsDownAndChangeDirFaceRight(uint16 k, uint16 j); +uint16 SpacePirates_Instr_PlaySfx(uint16 k, uint16 j); +uint16 SpacePirates_Instr_PrepareWallJumpL(uint16 k, uint16 j); +uint16 SpacePirates_Instr_PrepareWallJumpR(uint16 k, uint16 j); +uint16 SpacePirates_Instr_RandomNewDirFaceL(uint16 k, uint16 j); +uint16 SpacePirates_Instr_RandomNewDirFaceR(uint16 k, uint16 j); +uint16 SpacePirates_Instr_SetEnemyFunc(uint16 k, uint16 j); +void Enemy_GrappleReact_CancelBeam_B2(void); +void Enemy_NormalFrozenAI_B2(void); +void NinjaSpacePirates_Init(void); +void NinjaSpacePirates_Main(void); +void SpacePirates_F985(uint16 k); +void SpacePirates_F9C1(uint16 k); +void SpacePirates_FA15(uint16 k); +void SpacePirates_FA59(uint16 k); +void SpacePirates_FA95(uint16 k); +void SpacePirates_FAE9(uint16 k); +void SpacePirates_FB11(uint16 k); +void SpacePirates_Func_1(uint16 k); +void SpacePirates_Func_11(uint16 k); +void SpacePirates_Func_12(uint16 k); +void SpacePirates_Func_13(uint16 k); +void SpacePirates_Func_14(uint16 k); +void SpacePirates_Func_15(uint16 k); +void SpacePirates_Func_16(void); +void SpacePirates_Func_2(uint16 k); +void SpacePirates_Func_3(uint16 k); +void SpacePirates_Func_4(uint16 k); +void SpacePirates_Func_5(uint16 k); +void SpacePirates_Func_6(uint16 k); +void SpacePirates_Func_7(uint16 k); +void WalkingSpacePirates_8789(void); +void WalkingSpacePirates_87C8(void); +void WalkingSpacePirates_883E(void); +void WalkingSpacePirates_FD44(void); +void WalkingSpacePirates_FDCE(void); +void WalkingSpacePirates_FE4B(void); +void WalkingSpacePirates_Init(void); +void WalkingSpacePirates_Main(void); +void WalkingSpacePirates_Powerbomb(void); +void WalkingSpacePirates_Shot(void); +void WalkingSpacePirates_Touch(void); +void WallSpacePirates_Init(void); +void WallSpacePirates_Main(void); +void sub_B2F554(void); +void sub_B2F5B3(void); + +// Bank B3 +uint16 Botwoon_Instr_1(uint16 k, uint16 j); +uint16 Botwoon_Instr_10(uint16 k, uint16 j); +uint16 Botwoon_Instr_2(uint16 k, uint16 j); +uint16 Botwoon_Instr_3(uint16 k, uint16 j); +uint16 Botwoon_Instr_4(uint16 k, uint16 j); +uint16 Botwoon_Instr_5(uint16 k, uint16 j); +uint16 Botwoon_Instr_6(uint16 k, uint16 j); +uint16 Botwoon_Instr_7(uint16 k, uint16 j); +uint16 Botwoon_Instr_8(uint16 k, uint16 j); +uint16 Botwoon_Instr_9(uint16 k, uint16 j); +uint16 Botwoon_Instr_QueueSpitSfx(uint16 k, uint16 j); +uint16 Botwoon_Instr_SetSpitting(uint16 k, uint16 j); +uint16 EnemyInstr_DecTimerAndGoto2_B3(uint16 k, uint16 j); +uint16 EnemyInstr_Goto_B3(uint16 k, uint16 j); +uint16 EnemyInstr_SetTimer_B3(uint16 k, uint16 j); +uint16 EnemyInstr_Sleep_B3(uint16 k, uint16 j); +uint16 Enemy_ClearAiPreInstr_B3(uint16 k, uint16 j); +uint16 Enemy_SetAiPreInstr_B3(uint16 k, uint16 j); +uint16 EscapeDachora_Instr_1(uint16 k, uint16 j); +uint16 EscapeDachora_Instr_2(uint16 k, uint16 j); +uint16 EscapeDachora_Instr_3(uint16 k, uint16 j); +uint16 EscapeDachora_Instr_4(uint16 k, uint16 j); +uint16 EscapeEtecoon_Instr_1(uint16 k, uint16 j); +uint16 EscapeEtecoon_Instr_2(uint16 k, uint16 j); +void Botwoon_Func_1(uint16 k); +void Botwoon_Func_10(uint16 k); +void Botwoon_Func_11(uint16 k); +void Botwoon_Func_12(void); +void Botwoon_Func_13(void); +void Botwoon_Func_14(void); +void Botwoon_Func_15(void); +void Botwoon_Func_16(void); +void Botwoon_Func_17(uint16 k); +void Botwoon_Func_18(uint16 k); +void Botwoon_Func_19(void); +void Botwoon_Func_2(void); +void Botwoon_Func_20(uint16 k); +void Botwoon_Func_21(void); +void Botwoon_Func_22(void); +void Botwoon_Func_23(void); +void Botwoon_Func_24(void); +void Botwoon_Func_25(void); +void Botwoon_Func_26(uint16 k); +void Botwoon_Func_27(uint16 k); +void Botwoon_Func_28(uint16 k); +void Botwoon_Func_29(uint16 k); +void Botwoon_Func_3(void); +void Botwoon_Func_30(uint16 k); +void Botwoon_Func_31(uint16 k); +void Botwoon_Func_32(void); +void Botwoon_Func_33(void); +void Botwoon_Func_4(void); +void Botwoon_Func_5(void); +void Botwoon_Func_6(void); +void Botwoon_Func_7(void); +void Botwoon_Func_8(void); +void Botwoon_Func_9(void); +void Botwoon_HealthBasedPalHandling(void); +void Botwoon_Init(void); +void Botwoon_Main(void); +void Botwoon_Powerbomb(void); +void Botwoon_QueueExplosionSfx(void); +void Botwoon_Shot(void); +void Botwoon_Touch(void); +void BrinstarPipeBug_Func_1(void); +void BrinstarPipeBug_Init(void); +void BrinstarPipeBug_Main(void); +void BrinstarPipeBug_PreInstr_1(uint16 k); +void BrinstarPipeBug_PreInstr_2(uint16 k); +void BrinstarPipeBug_PreInstr_3(uint16 k); +void BrinstarPipeBug_PreInstr_4(uint16 k); +void BrinstarPipeBug_PreInstr_5(uint16 k); +void BrinstarYellowPipeBug_Func_1(void); +void BrinstarYellowPipeBug_Func_10(uint16 k); +void BrinstarYellowPipeBug_Func_2(uint16 k); +void BrinstarYellowPipeBug_Func_3(void); +void BrinstarYellowPipeBug_Func_4(uint16 k); +void BrinstarYellowPipeBug_Func_5(void); +void BrinstarYellowPipeBug_Func_6(uint16 k); +void BrinstarYellowPipeBug_Func_7(void); +void BrinstarYellowPipeBug_Func_8(void); +void BrinstarYellowPipeBug_Func_9(uint16 k); +void BrinstarYellowPipeBug_Init(void); +void BrinstarYellowPipeBug_Main(void); +void Enemy_GrappleReact_CancelBeam_B3(void); +void Enemy_GrappleReact_KillEnemy_B3(void); +void Enemy_GrappleReact_NoInteract_B3(void); +void Enemy_NormalFrozenAI_B3(void); +void Enemy_NormalPowerBombAI_SkipDeathAnim_B3(void); +void Enemy_NormalShotAI_B3(void); +void Enemy_NormalShotAI_SkipSomeParts_B3(void); +void Enemy_NormalTouchAI_B3(void); +void Enemy_NormalTouchAI_SkipDeathAnim_B3(void); +void EscapeDachora_Init(void); +void EscapeEtecoon_E65C(uint16 k); +void EscapeEtecoon_E670(uint16 k); +void EscapeEtecoon_E680(uint16 k); +void EscapeEtecoon_Init(void); +void EscapeEtecoon_Main(void); +void NorfairPipeBug_8BA8(void); +void NorfairPipeBug_Func_1(void); +void NorfairPipeBug_Func_10(void); +void NorfairPipeBug_Func_11(void); +void NorfairPipeBug_Func_12(void); +void NorfairPipeBug_Func_2(void); +void NorfairPipeBug_Func_3(uint16 k); +void NorfairPipeBug_Func_4(void); +void NorfairPipeBug_Func_5(uint16 k); +void NorfairPipeBug_Func_6(void); +void NorfairPipeBug_Func_7(void); +void NorfairPipeBug_Func_8(void); +void NorfairPipeBug_Func_9(void); +void NorfairPipeBug_Init(void); +void NorfairPipeBug_Main(void); +void UnusedSpinningTurtleEye_Init(void); +void UnusedSpinningTurtleEye_Main(void); +void sub_B38E56(void); + +// Bank B4 +void ClearSpriteObjects(void); +void CreateSpriteAtPos(void); +void DrawSpriteObjects(void); +void HandleSpriteObjects(void); +void SpriteObject_Instr_Goto(void); +void SpriteObject_Instr_RepeatLast(void); +void SpriteObject_Instr_Terminate(void); +void VerifySRAM(void); +void DecompressToMem_IpArg(const void* p); + +#define fnDrawTimer 0x809F6C +#define fnnullsub_1 0x818AB7 +#define fnnullsub_27 0x818B21 +#define fnnullsub_56 0x8192DB +#define fnDemoRoom_ChargeBeamRoomScroll21 0x82891A +#define fnnullsub_291 0x828924 +#define fnDemoRoom_SetBG2TilemapBase 0x828925 +#define fnDemoRoom_SetKraidFunctionTimer 0x82892B +#define fnDemoRoom_SetBrinstarBossBits 0x828932 +#define fnnullsub_8 0x828B0D +#define fnOptionsPreInstr_nullsub_57 0x828C10 +#define fnOptionsInstr_Destroy 0x828C5A +#define fnOptionsInstr_8C64 0x828C64 +#define fnOptionsInstr_SetPreInstr 0x828C6E +#define fnOptionsInstr_8C79 0x828C79 +#define fnOptionsInstr_Goto 0x828C82 +#define fnOptionsInstr_8C89 0x828C89 +#define fnOptionsInstr_8C93 0x828C93 +#define fnBabyMetroidPlaySfx0x23 0x82BC0C +#define fnBabyMetroidPlaySfx0x26 0x82BC15 +#define fnBabyMetroidPlaySfx0x27 0x82BC1E +#define fnDoorTransitionFunction_HandleElevator 0x82E17D +#define fnDoorTransitionFunction_Wait48frames 0x82E19F +#define fnDoorTransitionFunction_WaitForSoundsToFinish 0x82E29E +#define fnDoorTransitionFunction_FadeOutScreen 0x82E2DB +#define fnDoorTransitionFunction_LoadDoorHeaderEtc 0x82E2F7 +#define fnDoorTransitionFunction_ScrollScreenToAlignment 0x82E310 +#define fnDoorTransitionFunction_FixDoorsMovingUp 0x82E353 +#define fnDoorTransitionFunction_SetupNewRoom 0x82E36E +#define fnDoorTransitionFunction_SetupScrolling 0x82E38E +#define fnDoorTransitionFunction_PlaceSamusLoadTiles 0x82E3C0 +#define fnDoorTransitionFunction_LoadMoreThings_Async 0x82E4A9 +#define fnDoorTransition_C_HandleAnimTiles 0x82E659 +#define fnDoorTransition_WaitForMusicToClear 0x82E664 +#define fnDoorTransition_HandleTransition 0x82E6A2 +#define fnDoorTransition_FadeInScreenAndFinish 0x82E737 +#define fnsub_82F296 0x82F296 +#define fnOptionsPreInstr_F2A9 0x82F2A9 +#define fnsub_82F34B 0x82F34B +#define fnsub_82F353 0x82F353 +#define fnsub_82F35B 0x82F35B +#define fnsub_82F363 0x82F363 +#define fnOptionsPreInstr_F376 0x82F376 +#define fnOptionsPreInstr_F3A0 0x82F3A0 +#define fnOptionsPreInstr_F3E2 0x82F3E2 +#define fnsub_82F419 0x82F419 +#define fnOptionsPreInstr_F42C 0x82F42C +#define fnPlmPreInstr_nullsub_60 0x848469 +#define fnPlmPreInstr_Empty2 0x8484E6 +#define fnPlmPreInstr_Empty3 0x84853D +#define fnPlmInstr_Sleep 0x8486B4 +#define fnPlmInstr_Delete 0x8486BC +#define fnPlmInstr_PreInstr 0x8486C1 +#define fnPlmInstr_ClearPreInstr 0x8486CA +#define fnPlmPreInstr_Empty 0x8486D0 +#define fnPlmInstr_CallFunction 0x84870B +#define fnPlmInstr_Goto 0x848724 +#define fnPlmInstr_DecrementAndBranchNonzero 0x84873F +#define fnPlmInstr_SetTimer 0x84874E +#define fnPlmInstr_LoadItemPlmGfx 0x848764 +#define fnPlmInstr_CopyFromRamToVram 0x8487E5 +#define fnPlmInstr_GotoIfBossBitSet 0x84880E +#define fnPlmInstr_GotoIfEventSet 0x84882D +#define fnPlmInstr_SetEvent 0x84883E +#define fnPlmInstr_GotoIfChozoSet 0x848848 +#define fnPlmInstr_SetRoomChozoBit 0x848865 +#define fnPlmInstr_GotoIfItemBitSet 0x84887C +#define fnPlmInstr_SetItemBit 0x848899 +#define fnPlmInstr_PickupBeamAndShowMessage 0x8488B0 +#define fnPlmInstr_PickupEquipmentAndShowMessage 0x8488F3 +#define fnPlmInstr_PickupEquipmentAddGrappleShowMessage 0x84891A +#define fnPlmInstr_PickupEquipmentAddXrayShowMessage 0x848941 +#define fnPlmInstr_CollectHealthEnergyTank 0x848968 +#define fnPlmInstr_CollectHealthReserveTank 0x848986 +#define fnPlmInstr_CollectAmmoMissileTank 0x8489A9 +#define fnPlmInstr_CollectAmmoSuperMissileTank 0x8489D2 +#define fnPlmInstr_CollectAmmoPowerBombTank 0x8489FB +#define fnPlmInstr_SetLinkReg 0x848A24 +#define fnPlmInstr_Call 0x848A2E +#define fnPlmInstr_Return 0x848A3A +#define fnPlmInstr_GotoIfDoorBitSet 0x848A72 +#define fnPlmInstr_IncrementDoorHitCounterAndJGE 0x848A91 +#define fnPlmInstr_IncrementArgumentAndJGE 0x848ACD +#define fnPlmInstr_SetBTS 0x848AF1 +#define fnPlmInstr_DrawPlmBlock 0x848B05 +#define fnPlmInstr_DrawPlmBlock_ 0x848B17 +#define fnPlmInstr_ProcessAirScrollUpdate 0x848B55 +#define fnPlmInstr_ProcessSolidScrollUpdate 0x848B93 +#define fnPlmInstr_QueueMusic 0x848BD1 +#define fnPlmInstr_ClearMusicQueueAndQueueTrack 0x848BDD +#define fnPlmInstr_QueueSfx1_Max6 0x848C07 +#define fnPlmInstr_QueueSfx2_Max6 0x848C10 +#define fnPlmInstr_QueueSfx3_Max6 0x848C19 +#define fnPlmInstr_QueueSfx1_Max15 0x848C22 +#define fnPlmInstr_QueueSfx2_Max15 0x848C2B +#define fnPlmInstr_QueueSfx3_Max15 0x848C34 +#define fnPlmInstr_QueueSfx1_Max3 0x848C3D +#define fnPlmInstr_QueueSfx2_Max3 0x848C46 +#define fnPlmInstr_QueueSfx_Max3 0x848C4F +#define fnPlmInstr_QueueSfx1_Max9 0x848C58 +#define fnPlmInstr_QueueSfx2_Max9 0x848C61 +#define fnPlmInstr_QueueSfx3_Max9 0x848C6A +#define fnPlmInstr_QueueSfx1_Max1 0x848C73 +#define fnPlmInstr_QueueSfx2_Max1 0x848C7C +#define fnPlmInstr_QueueSfx3_Max1 0x848C85 +#define fnPlmInstr_ActivateMapStation 0x848C8F +#define fnPlmInstr_ActivateEnergyStation 0x848CAF +#define fnPlmInstr_ActivateMissileStation 0x848CD0 +#define fnPlmInstr_ActivateSaveStationAndGotoIfNo 0x848CF1 +#define fnPlmInstr_GotoIfSamusNear 0x848D41 +#define fnPlmInstr_MovePlmDownOneBlock 0x84AB00 +#define fnnullsub_67 0x84AB27 +#define fnPlmSetup_CrumbleBotwoonWall 0x84AB28 +#define fnPlmInstr_Scroll_0_1_Blue 0x84AB51 +#define fnPlmInstr_MovePlmDownOneBlock_0 0x84AB59 +#define fnPlmInstr_ABD6 0x84ABD6 +#define fnPlmPreInstr_PositionSamusAndInvincible 0x84AC89 +#define fnPlmInstr_DealDamage_2 0x84AC9D +#define fnPlmInstr_GiveInvincibility 0x84ACB1 +#define fnPlmInstr_Draw0x38FramesOfRightTreadmill 0x84AD43 +#define fnPlmInstr_Draw0x38FramesOfLeftTreadmill 0x84AD58 +#define fnPlmInstr_GotoIfSamusHealthFull 0x84AE35 +#define fnPlmInstr_GotoIfMissilesFull 0x84AEBF +#define fnPlmInstr_PlaceSamusOnSaveStation 0x84B00E +#define fnPlmInstr_DisplayGameSavedMessageBox 0x84B024 +#define fnPlmInstr_EnableMovementAndSetSaveStationUsed 0x84B030 +#define fnPlmSetup_SetrupWreckedShipEntrance 0x84B04A +#define fnPlmSetup_BTS_Brinstar_0x80_Floorplant 0x84B0DC +#define fnPlmSetup_BTS_Brinstar_0x81_Ceilingplant 0x84B113 +#define fnPlmSetup_B6D3_MapStation 0x84B18B +#define fnPlmSetup_Bts47_MapStationRightAccess 0x84B1C8 +#define fnPlmSetup_Bts4_MapStationLeftAccess 0x84B1F0 +#define fnPlmSetup_PlmB6DF_EnergyStation 0x84B21D +#define fnPlmSetup_PlmB6EB_EnergyStation 0x84B245 +#define fnPlmSetup_B6E3_EnergyStationRightAccess 0x84B26D +#define fnPlmSetup_B6E7_EnergyStationLeftAccess 0x84B29D +#define fnPlmSetup_B6EF_MissileStationRightAccess 0x84B2D0 +#define fnPlmSetup_B6F3_MissileStationLeftAccess 0x84B300 +#define fnPlmSetup_B638_Rightwards_Extension 0x84B33A +#define fnPlmSetup_B63F_Leftwards_Extension 0x84B345 +#define fnPlmSetup_B643_Downwards_Extension 0x84B350 +#define fnPlmSetup_B647_Upwards_Extension 0x84B35B +#define fnPlmSetup_B703_ScrollPLM 0x84B371 +#define fnPlmSetup_B707_SolidScrollPLM 0x84B382 +#define fnPlmSetup_B6FF_ScrollBlockTouch 0x84B393 +#define fnPlmSetup_DeactivatePlm 0x84B3C1 +#define fnnullsub_290 0x84B3CF +#define fnPlmSetup_ReturnCarryClear 0x84B3D0 +#define fnPlmSetup_ReturnCarrySet 0x84B3D2 +#define fnPlmSetup_D094_EnemyBreakableBlock 0x84B3D4 +#define fnUNUSED_sub_84B3E3 0x84B3E3 +#define fnPlmSetup_B70F_IcePhysics 0x84B3EB +#define fnPlmSetup_QuicksandSurface 0x84B408 +#define fnPlmSetup_B71F_SubmergingQuicksand 0x84B497 +#define fnPlmSetup_B723_SandfallsSlow 0x84B4A8 +#define fnPlmSetup_B727_SandFallsFast 0x84B4B6 +#define fnPlmSetup_QuicksandSurfaceB 0x84B4C4 +#define fnPlmSetup_B737_SubmergingQuicksand 0x84B541 +#define fnPlmSetup_B73B_B73F_SandFalls 0x84B54F +#define fnPlmSetup_ClearShitroidInvisibleWall 0x84B551 +#define fnPlmSetup_B767_ClearShitroidInvisibleWall 0x84B56F +#define fnPlmSetup_B76B_SaveStationTrigger 0x84B590 +#define fnPlmSetup_B76F_SaveStation 0x84B5EE +#define fnPlmSetup_MotherBrainRoomEscapeDoor 0x84B5F8 +#define fnPlmSetup_B7EB_EnableSoundsIn32Frames 0x84B7C3 +#define fnPlmPreInstr_B7EB_DecTimerEnableSoundsDeletePlm 0x84B7DD +#define fnPlmPreInstr_WakeAndLavaIfBoosterCollected 0x84B7EF +#define fnPlmPreInstr_WakePLMAndStartFxMotionSamusFarLeft 0x84B82A +#define fnPlmPreInstr_AdvanceLavaSamusMovesLeft 0x84B846 +#define fnPlmSetup_SpeedBoosterEscape 0x84B89C +#define fnPlmPreInstr_ShaktoolsRoom 0x84B8B0 +#define fnPlmSetup_ShaktoolsRoom 0x84B8DC +#define fnnullsub_68 0x84B8EF +#define fnPlmPreInstr_OldTourianEscapeShaftEscape 0x84B927 +#define fnPlmPreInstr_EscapeRoomBeforeOldTourianEscapeShaft 0x84B948 +#define fnPlmSetup_B974 0x84B96C +#define fnPlmSetup_B9C1_CrittersEscapeBlock 0x84B978 +#define fnPlmSetup_B9ED_CrittersEscapeBlock 0x84B9C5 +#define fnsub_84B9F1 0x84B9F1 +#define fnPlmInstr_JumpIfSamusHasNoBombs 0x84BA6F +#define fnnullsub_84BAFA 0x84BAFA +#define fnPlmSetup_BB30_CrateriaMainstreetEscape 0x84BB09 +#define fnPlmInstr_MovePlmRight4Blocks 0x84BB25 +#define fnPlmPreInstr_WakePlmIfTriggered 0x84BB52 +#define fnnullsub_359 0x84BB6A +#define fnPlmPreInstr_WakePlmIfTriggeredOrSamusBelowPlm 0x84BB6B +#define fnPlmPreInstr_Empty5 0x84BBA3 +#define fnPlmPreInstr_WakePlmIfTriggeredOrSamusAbovePlm 0x84BBA4 +#define fnPlmInstr_ClearTrigger 0x84BBDD +#define fnPlmInstr_SpawnEnemyProjectile 0x84BBE1 +#define fnPlmInstr_WakeEnemyProjectileAtPlmPos 0x84BBF0 +#define fnPlmPreInstr_GoToLinkInstrIfShot 0x84BD0F +#define fnPlmPreInstr_GoToLinkInstrIfShotWithPowerBomb 0x84BD26 +#define fnPlmPreInstr_GoToLinkInstrIfShotWithAnyMissile 0x84BD50 +#define fnPlmPreInstr_GoToLinkInstrIfShotWithSuperMissile 0x84BD88 +#define fnPlmPreInstr_GoToLinkInstruction 0x84BDB2 +#define fnPlmPreInstr_GotoLinkIfBoss1Dead 0x84BDD4 +#define fnPlmPreInstr_GotoLinkIfMiniBossDead 0x84BDE3 +#define fnPlmPreInstr_GotoLinkIfTorizoDead 0x84BDF2 +#define fnPlmPreInstr_GotoLinkIfEnemyDeathQuotaOk 0x84BE01 +#define fnPlmPreInstr_PlayDudSound 0x84BE1C +#define fnPlmPreInstr_GotoLinkIfTourianStatueFinishedProcessing 0x84BE1F +#define fnPlmPreInstr_GotoLinkIfCrittersEscaped 0x84BE30 +#define fnPlmInstr_SetGreyDoorPreInstr 0x84BE3F +#define fnPlmSetup_C806_LeftGreenGateTrigger 0x84C54D +#define fnPlmSetup_C80A_RightGreenGateTrigger 0x84C56C +#define fnPlmSetup_C80E_LeftRedGateTrigger 0x84C58B +#define fnPlmSetup_C812_RightRedGateTrigger 0x84C5AF +#define fnPlmSetup_C81E_LeftYellowGateTrigger 0x84C5D3 +#define fnPlmSetup_C822_RightYellowGateTrigger 0x84C5F1 +#define fnPlmSetup_C816_LeftBlueGateTrigger 0x84C610 +#define fnPlmSetup_C81A_RightBlueGateTrigger 0x84C627 +#define fnPlmSetup_C82A_DownwardsClosedGate 0x84C6BE +#define fnPlmSetup_C832_UpwardsClosedGate 0x84C6CB +#define fnPlmSetup_C826_DownwardsOpenGate 0x84C6D8 +#define fnPlmSetup_C82E_UpwardsOpenGate 0x84C6DC +#define fnPlmSetup_C836_DownwardsGateShootblock 0x84C6E0 +#define fnPlmSetup_C73A_UpwardsGateShootblock 0x84C73A +#define fnPlmSetup_C794_GreyDoor 0x84C794 +#define fnPlmSetup_Door_Colored 0x84C7B1 +#define fnPlmSetup_Door_Blue 0x84C7BB +#define fnPlmSetup_Door_Strange 0x84C7E2 +#define fnPlmInstr_SetBtsTo1 0x84CD93 +#define fnPlmSetup_D028_D02C_Unused 0x84CDC2 +#define fnPlmSetup_RespawningSpeedBoostBlock 0x84CDEA +#define fnPlmSetup_RespawningCrumbleBlock 0x84CE37 +#define fnPlmSetup_RespawningShotBlock 0x84CE6B +#define fnPlmSetup_RespawningBombBlock 0x84CE83 +#define fnPlmSetup_RespawningBombBlock2 0x84CEDA +#define fnPlmSetup_RespawningPowerBombBlock 0x84CF2E +#define fnPlmSetup_D08C_SuperMissileBlockRespawning 0x84CF67 +#define fnPlmSetup_D08C_CrumbleBlock 0x84CFA0 +#define fnPlmSetup_D0DC_BreakableGrappleBlock 0x84CFB5 +#define fnPlmSetup_D0D8_SetVFlag 0x84CFCD +#define fnPlmSetup_D0D8_ClearVflag 0x84CFD1 +#define fnPlmSetup_D0E8_GiveSamusDamage 0x84CFD5 +#define fnPlmSetup_D113_LowerNorfairChozoRoomPlug 0x84D108 +#define fnPlmSetup_D127 0x84D117 +#define fnPlmSetup_D138 0x84D12B +#define fnPlmInstr_FxBaseYPos_0x2D2 0x84D155 +#define fnPlmPreInstr_DeletePlmAndSpawnTriggerIfBlockDestroyed 0x84D15C +#define fnnullsub_69 0x84D18E +#define fnPlmSetup_D6DA_LowerNorfairChozoHandTrigger 0x84D18F +#define fnPlmPreInstr_IncrementRoomArgIfShotBySuperMissile 0x84D1E6 +#define fnPlmInstr_GotoIfRoomArgLess 0x84D2F9 +#define fnPlmInstr_SpawnFourMotherBrainGlass 0x84D30B +#define fnPlmPreInstr_WakePlmIfSamusHasBombs 0x84D33B +#define fnnullsub_351 0x84D356 +#define fnPlmInstr_SpawnTorizoStatueBreaking 0x84D357 +#define fnPlmInstr_QueueSong1MusicTrack 0x84D3C7 +#define fnPlmInstr_TransferWreckedShipChozoSpikesToSlopes 0x84D3D7 +#define fnPlmInstr_TransferWreckedShipSlopesToChozoSpikes 0x84D3F4 +#define fnPlmPreInstr_WakeOnKeyPress 0x84D4BF +#define fnPlmInstr_EnableWaterPhysics 0x84D525 +#define fnPlmInstr_SpawnN00bTubeCrackEnemyProjectile 0x84D52C +#define fnPlmInstr_DiagonalEarthquake 0x84D536 +#define fnPlmInstr_Spawn10shardsAnd6n00bs 0x84D543 +#define fnPlmInstr_DisableSamusControls 0x84D5E6 +#define fnPlmInstr_EnableSamusControls 0x84D5EE +#define fnPlmSetup_MotherBrainGlass 0x84D5F6 +#define fnPlmSetup_DeletePlmIfAreaTorizoDead 0x84D606 +#define fnPlmSetup_MakeBllockChozoHandTrigger 0x84D616 +#define fnPlmSetup_D6F2_WreckedShipChozoHandTrigger 0x84D620 +#define fnPlmSetup_D700_MakePlmAirBlock_Unused 0x84D67F +#define fnPlmSetup_D704_AlteranateLowerNorfairChozoHand_Unused 0x84D689 +#define fnPlmSetup_D708_LowerNorfairChozoBlockUnused 0x84D693 +#define fnPlmSetup_D70C_NoobTube 0x84D6CC +#define fnnullsub_71 0x84D6F6 +#define fnnullsub_72 0x84D6F7 +#define fnPlmPreInstr_WakePlmIfRoomArgumentDoorIsSet 0x84D753 +#define fnPlmInstr_ShootEyeDoorProjectileWithProjectileArg 0x84D77A +#define fnPlmInstr_SpawnEyeDoorSweatEnemyProjectile 0x84D790 +#define fnPlmInstr_SpawnTwoEyeDoorSmoke 0x84D79F +#define fnPlmInstr_SpawnEyeDoorSmokeProjectile 0x84D7B6 +#define fnPlmInstr_MoveUpAndMakeBlueDoorFacingRight 0x84D7C3 +#define fnPlmInstr_MoveUpAndMakeBlueDoorFacingLeft 0x84D7DA +#define fnPlmSetup_EyeDoorEye 0x84DA8C +#define fnPlmSetup_EyeDoor 0x84DAB9 +#define fnnullsub_73 0x84DAD5 +#define fnnullsub_74 0x84DAD6 +#define fnnullsub_75 0x84DAD7 +#define fnnullsub_76 0x84DAD8 +#define fnnullsub_77 0x84DAD9 +#define fnnullsub_78 0x84DADA +#define fnnullsub_79 0x84DADB +#define fnnullsub_80 0x84DADC +#define fnnullsub_81 0x84DADD +#define fnPlmPreInstr_SetMetroidsClearState_Ev0x10 0x84DADE +#define fnPlmPreInstr_SetMetroidsClearState_Ev0x11 0x84DAEE +#define fnPlmPreInstr_SetMetroidsClearState_Ev0x12 0x84DAFE +#define fnPlmPreInstr_SetMetroidsClearState_Ev0x13 0x84DB0E +#define fnPlmSetup_SetMetroidRequiredClearState 0x84DB1E +#define fnPlmPreInstr_GotoLinkIfShotWithSuperMissile 0x84DB64 +#define fnPlmInstr_DamageDraygonTurret 0x84DB8E +#define fnPlmInstr_DamageDraygonTurretFacingDownRight 0x84DBB8 +#define fnPlmInstr_DamageDraygonTurretFacingUpRight 0x84DBF7 +#define fnPlmInstr_DamageDraygonTurret2 0x84DC36 +#define fnPlmInstr_DamageDraygonTurretFacingDownLeft 0x84DC60 +#define fnPlmInstr_DamageDraygonTurretFacingUpLeft 0x84DC9F +#define fnPlmSetup_DraygonCannonFacingRight 0x84DE94 +#define fnPlmSetup_DraygonCannonFacingDiagonalRight 0x84DEB9 +#define fnPlmSetup_DraygonCannonFacingLeft 0x84DEF0 +#define fnPlmSetup_DraygonCannonFacingDiagonalLeft 0x84DF15 +#define fnPlmSetup_DraygonCannon 0x84DF4C +#define fnPlmPreInstr_GotoLinkIfTriggered 0x84DF89 +#define fnPlmPreInstr_nullsub_301 0x84DFA8 +#define fnPlmPreInstr_WakeIfTriggered 0x84DFE6 +#define fnPlmInstr_DrawItemFrame0 0x84E04F +#define fnPlmInstr_DrawItemFrame1 0x84E067 +#define fnPlmInstr_DrawItemFrame_Common 0x84E07F +#define fnPlmInstr_ClearChargeBeamCounter 0x84E29D +#define fnPlmInstr_E63B 0x84E63B +#define fnsub_84EE4D 0x84EE4D +#define fnsub_84EE52 0x84EE52 +#define fnsub_84EE57 0x84EE57 +#define fnsub_84EE5C 0x84EE5C +#define fnsub_84EE64 0x84EE64 +#define fnsub_84EE77 0x84EE77 +#define fnsub_84EE7C 0x84EE7C +#define fnsub_84EE81 0x84EE81 +#define fnsub_84EE86 0x84EE86 +#define fnsub_84EE8E 0x84EE8E +#define fnsub_84EEAB 0x84EEAB +#define fnWriteLargeMessageBoxTilemap 0x85825A +#define fnWriteSmallMessageBoxTilemap 0x858289 +#define fnDrawShootButtonAndSetupPpuForLargeMessageBox 0x8583C5 +#define fnDrawRunButtonAndSetupPpuForLargeMessageBox 0x8583CC +#define fnSetupPpuForSmallMessageBox 0x858436 +#define fnSetupPpuForLargeMessageBox 0x858441 +#define fnEprojInstr_Delete 0x868154 +#define fnEprojInstr_Sleep 0x868159 +#define fnEprojInstr_SetPreInstr_ 0x868161 +#define fnEprojInstr_ClearPreInstr 0x86816A +#define fnEprojPreInstr_nullsub_297 0x868170 +#define fnEprojInstr_CallFunc 0x868171 +#define fnEprojInstr_Goto 0x8681AB +#define fnEprojInstr_GotoRel 0x8681B0 +#define fnEprojInstr_DecTimerAndGotoIfNonZero 0x8681C6 +#define fnEprojInstr_DecTimerAndGotoRelIfNonZero 0x8681CE +#define fnEprojInstr_SetTimer 0x8681D5 +#define fnnullsub_82 0x8681DE +#define fnEprojInstr_MoveRandomlyWithinRadius 0x8681DF +#define fnEprojInstr_SetProjectileProperties 0x868230 +#define fnEprojInstr_ClearProjectileProperties 0x86823C +#define fnEprojInstr_EnableCollisionWithSamusProj 0x868248 +#define fnEprojInstr_DisableCollisionWithSamusProj 0x868252 +#define fnEprojInstr_DisableCollisionWithSamus 0x86825C +#define fnEprojInstr_EnableCollisionWithSamus 0x868266 +#define fnEprojInstr_SetToNotDieOnContact 0x868270 +#define fnEprojInstr_SetToDieOnContact 0x86827A +#define fnEprojInstr_SetLowPriority 0x868284 +#define fnEprojInstr_SetHighPriority 0x86828E +#define fnEprojInstr_SetXyRadius 0x868298 +#define fnEprojInstr_SetXyRadiusZero 0x8682A1 +#define fnEprojInstr_CalculateDirectionTowardsSamus 0x8682A5 +#define fnEprojInstr_WriteColorsToPalette 0x8682D5 +#define fnEprojInstr_QueueMusic 0x8682FD +#define fnEprojInstr_QueueSfx1_Max6 0x868309 +#define fnEprojInstr_QueueSfx2_Max6 0x868312 +#define fnEprojInstr_QueueSfx3_Max6 0x86831B +#define fnEprojInstr_QueueSfx1_Max15 0x868324 +#define fnEprojInstr_QueueSfx2_Max15 0x86832D +#define fnEprojInstr_QueueSfx3_Max15 0x868336 +#define fnEprojInstr_QueueSfx1_Max3 0x86833F +#define fnEprojInstr_QueueSfx2_Max3 0x868348 +#define fnEprojInstr_QueueSfx3_Max3 0x868351 +#define fnEprojInstr_QueueSfx1_Max9 0x86835A +#define fnEprojInstr_QueueSfx2_Max9 0x868363 +#define fnEprojInstr_QueueSfx3_Max9 0x86836C +#define fnEprojInstr_QueueSfx1_Max1 0x868375 +#define fnEprojInstr_QueueSfx2_Max1 0x86837E +#define fnEprojInstr_QueueSfx3_Max1 0x868387 +#define fnEprojPreInstr_nullsub_83 0x8684FB +#define fnEnemyProj_Init_0x8aaf 0x868A39 +#define fnEnemyProj_PreInit_0x8aaf 0x868A7D +#define fnEnemyProj_Init_0x8bc2_SkreeDownRight 0x868ACD +#define fnEnemyProj_Init_0x8bd0_SkreeUpRight 0x868AF1 +#define fnEnemyProj_Init_0x8bde_SkreeDownLeft 0x868B15 +#define fnEnemyProj_Init_0x8bec_SkreeUpLeft 0x868B39 +#define fnEnemyProj_PreInstr_SkreeParticle 0x868B5D +#define fnEnemyProjInstr_SetPreInstrA 0x868CF6 +#define fnEprojInit_DraygonsGunk 0x868D04 +#define fnEprojInit_DraygonsWallTurretProjs 0x868D40 +#define fnnullsub_84 0x868D54 +#define fnEprojInstr_868D55 0x868D55 +#define fnEprojInstr_868D99 0x868D99 +#define fnEprojPreInstr_8DCA 0x868DCA +#define fnEprojPreInstr_DraygonsTurret_8DFF 0x868DFF +#define fnEprojPreInstr_DraygonsGunk_8E0F 0x868E0F +#define fnEprojInit_8E6C 0x868E7A +#define fnEprojPreInstr_8E6C 0x868E99 +#define fnEprojInit_CrocomireProjectile 0x869023 +#define fnEprojPreInstr_CrocomireProjectile 0x86906B +#define fnsub_8690B3 0x8690B3 +#define fnEprojInit_CrocomireSpikeWallPieces 0x8690CF +#define fnEprojPreInstr_CrocomireSpikeWallPieces 0x869115 +#define fnEprojInstr_9270 0x869270 +#define fnEprojInit_CrocomireBridgeCrumbling 0x869286 +#define fnEprojPreInstr_CrocomireBridgeCrumbling 0x8692BA +#define fnEprojInit_9634 0x86934D +#define fnEprojPreInstr_9634 0x869392 +#define fnEprojInit_9642_RidleysFireball 0x8693CA +#define fnEprojPreInstr_9642_RidleysFireball 0x86940E +#define fnEprojInstr_DisableCollisionsWithSamus 0x869475 +#define fnEprojInit_9660_FireballExplosion 0x86947F +#define fnEprojInit_9688 0x8694A0 +#define fnEprojInit_9696 0x8694B4 +#define fnEprojInit_966C 0x8694C8 +#define fnEprojInit_967A 0x8694DC +#define fnnullsub_85 0x86950C +#define fnEprojPreInstr_966C 0x86950D +#define fnEprojPreInstr_9688 0x869522 +#define fnEprojPreInstr_96A4 0x869537 +#define fnEprojPreInstr_96C0 0x869540 +#define fnEprojPreInstr_96CE 0x869549 +#define fnEprojInstr_95BA 0x8695BA +#define fnEprojInstr_95ED 0x8695ED +#define fnEprojInstr_9620 0x869620 +#define fnEprojInit_9734_CeresFallingDebris 0x8696DC +#define fnEprojPreInstr_9734_CeresFallingDebris 0x869701 +#define fnEprojInstr_980E 0x86980E +#define fnEprojInit_PhantoonDestroyableFireballs 0x869824 +#define fnEprojInit_PhantoonStartingFireballs 0x86993A +#define fnEprojPreInstr_PhantoonStartingFireballs 0x869981 +#define fnEprojPreInstr_PhantoonStartingFireballs2 0x8699BF +#define fnEprojPreInstr_PhantoonStartingFireballs3 0x869A01 +#define fnnullsub_86 0x869A44 +#define fnEprojPreInstr_PhantoonDestroyableFireballs 0x869A45 +#define fnEprojPreInstr_PhantoonDestroyableFireballs_2 0x869A94 +#define fnEprojPreInstr_PhantoonDestroyableFireballs_3 0x869ADA +#define fnEprojPreInstr_PhantoonStartingFireballsB 0x869B29 +#define fnEprojPreInstr_PhantoonStartingFireballsB_2 0x869B41 +#define fnEprojInit_RocksKraidSpits 0x869CA3 +#define fnEprojInit_RocksFallingKraidCeiling 0x869CD8 +#define fnEprojInit_RocksWhenKraidRises 0x869D0C +#define fnEprojPreInstr_KraidRocks 0x869D56 +#define fnEprojPreInstr_RocksFallingKraidCeiling 0x869D89 +#define fnsub_869DA5 0x869DA5 +#define fnEprojInit_MiniKraidSpit 0x869DEC +#define fnEprojPreInit_MiniKraidSpit 0x869E1E +#define fnEprojInit_MiniKraidSpikesLeft 0x869E46 +#define fnEprojInit_MiniKraidSpikesRight 0x869E4B +#define fnEprojInit_MiniKraidSpikes 0x869E4E +#define fnEprojPreInstr_MiniKraidSpikes 0x869E83 +#define fnEprojInit_WalkingLavaSeahorseFireball 0x869EB2 +#define fnEprojPreInstr_WalkingLavaSeahorseFireball 0x869EFF +#define fnEprojInit_PirateMotherBrainLaser 0x86A009 +#define fnEprojInstr_SetPreInstrAndRun 0x86A050 +#define fnnullsub_87 0x86A05B +#define fnEprojPreInstr_PirateMotherBrainLaser_MoveLeft 0x86A05C +#define fnEprojPreInstr_PirateMotherBrainLaser_MoveRight 0x86A07A +#define fnEprojInit_PirateClaw 0x86A098 +#define fnEprojPreInstr_PirateClawThrownLeft 0x86A0D1 +#define fnEprojPreInstr_PirateClawThrownRight 0x86A124 +#define fnEprojInit_A379 0x86A2A1 +#define fnEprojInit_CeresElevatorPad 0x86A2EE +#define fnEprojInit_CeresElevatorPlatform 0x86A31B +#define fnnullsub_88 0x86A327 +#define fnEprojPreInstr_CeresElevatorPad 0x86A328 +#define fnEprojPreInstr_CeresElevatorPlatform 0x86A364 +#define fnEprojPreInstr_PrePhantomRoom 0x86A3A3 +#define fnEprojInstr_A3BE 0x86A3BE +#define fnEprojInstr_GotoWithProbability25 0x86A456 +#define fnEprojInit_BombTorizoLowHealthDrool 0x86A5D3 +#define fnEprojInit_BombTorizoLowHealthInitialDrool 0x86A65D +#define fnEprojInit_A977 0x86A6C7 +#define fnEprojInit_BombTorizoExplosiveSwipe 0x86A6F6 +#define fnEprojInit_BombTorizoStatueBreaking 0x86A764 +#define fnEprojInit_BombTorizoLowHealthExplode 0x86A81B +#define fnEprojInit_BombTorizoDeathExplosion 0x86A871 +#define fnsub_86A887 0x86A887 +#define fnEprojPreInstr_A977 0x86A8EF +#define fnnullsub_352 0x86A918 +#define fnnullsub_89 0x86A919 +#define fnEprojInit_AB07 0x86AA3D +#define fnEprojPreInstr_AB07 0x86AA8C +#define fnEprojInstr_SpawnEnemyDrops 0x86AB8A +#define fnEprojInit_BombTorizosChozoOrbs 0x86ABEB +#define fnEprojInit_GoldenTorizosChozoOrbs 0x86AC7C +#define fnEprojPreInstr_BombTorizosChozoOrbs 0x86ACAD +#define fnEprojPreInstr_GoldenTorizosChozoOrbs 0x86ACFA +#define fnEprojInstr_GotoDependingOnXDirection 0x86AD92 +#define fnEprojInit_TorizoSonicBoom 0x86AE15 +#define fnEprojPreInstr_TorizoSonicBoom 0x86AE6C +#define fnEprojInit_WreckedShipChozoSpikeFootsteps 0x86AEFC +#define fnEprojInstr_ResetXYpos1 0x86AF36 +#define fnEprojInit_TourianStatueDustClouds 0x86AF43 +#define fnEprojInit_TourianLandingDustCloudsRightFoot 0x86AF50 +#define fnEprojInstr_MoveY_Minus4 0x86AF92 +#define fnEprojInit_TorizoLandingDustCloudLeftFoot 0x86AFCD +#define fnEprojInit_GoldenTorizoEgg 0x86B001 +#define fnEprojPreInstr_GoldenTorizoEgg 0x86B043 +#define fnsub_86B0B9 0x86B0B9 +#define fnsub_86B0DD 0x86B0DD +#define fnsub_86B13E 0x86B13E +#define fnEprojInit_GoldenTorizoSuperMissile 0x86B1CE +#define fnEprojPreInstr_GoldenTorizoSuperMissile 0x86B20D +#define fnEprojPreInstr_B237 0x86B237 +#define fnEprojInit_GoldenTorizoEyeBeam 0x86B328 +#define fnEprojPreInstr_GoldenTorizoEyeBeam 0x86B38A +#define fnEprojInstr_GotoIfFunc1 0x86B3B8 +#define fnEprojInstr_ResetXYpos2 0x86B436 +#define fnEprojInit_TourianEscapeShaftFakeWallExplode 0x86B49D +#define fnnullsub_90 0x86B4B0 +#define fnEprojInit_LavaSeahorseFireball 0x86B4EF +#define fnsub_86B535 0x86B535 +#define fnEprojInit_EyeDoorProjectile 0x86B62D +#define fnEprojInit_EyeDoorSweat 0x86B683 +#define fnEprojPreInstr_EyeDoorProjectile 0x86B6B9 +#define fnEprojPreInstr_EyeDoorSweat 0x86B714 +#define fnEprojInstr_SpawnTourianStatueUnlockingParticle 0x86B7EA +#define fnEprojInstr_Earthquake 0x86B7F5 +#define fnEprojInstr_SpawnTourianStatueUnlockingParticleTail 0x86B818 +#define fnEprojInstr_AddToYpos 0x86B841 +#define fnEprojInit_TourianStatueUnlockingParticleWaterSplash 0x86B87A +#define fnEprojInit_TourianStatueEyeGlow 0x86B88E +#define fnEprojInit_TourianStatueUnlockingParticle 0x86B8B5 +#define fnEprojIni_TourianStatueUnlockingParticleTail 0x86B8E8 +#define fnEprojInit_TourianStatueSoul 0x86B8F8 +#define fnEprojInit_TourianStatueBaseDecoration 0x86B93E +#define fnEprojInit_TourianStatueRidley 0x86B951 +#define fnEprojInit_TourianStatuePhantoon 0x86B964 +#define fnEprojPreInstr_TourianStatueUnlockingParticleWaterSplash 0x86B977 +#define fnEprojPreInstr_TourianStatueUnlockingParticle 0x86B982 +#define fnEprojPreInstr_TourianStatueSoul 0x86B9FD +#define fnEprojPreInstr_TourianStatueStuff 0x86BA37 +#define fnEprojPreInstr_BA42 0x86BA42 +#define fnEprojInstr_BB24 0x86BB24 +#define fnsub_86BB30 0x86BB30 +#define fnnullsub_91 0x86BB4F +#define fnEprojInit_NuclearWaffleBody 0x86BB92 +#define fnnullsub_92 0x86BBC6 +#define fnEprojInit_NorfairLavaquakeRocks 0x86BBDB +#define fnEprojPreInstr_NorfairLavaquakeRocks 0x86BC0F +#define fnEproj_NorfairLavaquakeRocks_Func1 0x86BC16 +#define fnEproj_NorfairLavaquakeRocks_Func2 0x86BC8F +#define fnEprojPreInstr_NorfairLavaquakeRocks_Inner 0x86BD1E +#define fnEprojPreInstr_NorfairLavaquakeRocks_Inner2 0x86BD2A +#define fnEprojInit_ShaktoolAttackMiddleBackCircle 0x86BD9C +#define fnEprojInit_BDA2 0x86BDA2 +#define fnEprojInit_ShaktoolAttackFrontCircle 0x86BE03 +#define fnEprojPreInstr_BE12 0x86BE12 +#define fnEprojInit_MotherBrainRoomTurrets 0x86BE4F +#define fnEprojInit_MotherBrainRoomTurretBullets 0x86BF59 +#define fnEprojPreInstr_MotherBrainRoomTurrets 0x86BFDF +#define fnEprojPreInstr_MotherBrainRoomTurretBullets 0x86C0E0 +#define fnEprojInstr_SwitchJump 0x86C173 +#define fnEprojInstr_UserPalette0 0x86C1B4 +#define fnEproj_MotherBrainsBlueRingLasers 0x86C2F3 +#define fnEproj_MoveToBlueRingSpawnPosition 0x86C335 +#define fnEprojInit_MotherBrainBomb 0x86C482 +#define fnEprojPreInstr_MotherBrainBomb 0x86C4C8 +#define fnsub_86C605 0x86C605 +#define fnEprojInit_MotherBrainDeathBeemFired 0x86C684 +#define fnnullsub_366 0x86C76D +#define fnSpawnMotherBrainDeathBeam 0x86C7FB +#define fnEprojInit_MotherBrainRainbowBeam 0x86C80A +#define fnEprojPreInstr_MotherBrainRainbowBeam 0x86C814 +#define fnEprojInit_MotherBrainsDrool 0x86C843 +#define fnEprojPreInstr_C84D 0x86C84D +#define fnEprojInit_MotherBrainsDrool_Falling 0x86C886 +#define fnEprojInstr_Add12ToY 0x86C8D0 +#define fnEprojInit_MotherBrainsDeathExplosion 0x86C8F5 +#define fnEprojPreInit_MotherBrainsDeathExplosion_0 0x86C914 +#define fnEprojInit_MotherBrainsRainbowBeamExplosion 0x86C92F +#define fnEprojPreInstr_MotherBrainsRainbowBeamExplosion 0x86C94C +#define fnEprojInit_MotherBrainEscapeDoorParticles 0x86C961 +#define fnEprojPreInstr_MotherBrainsExplodedDoorParticles 0x86C9D2 +#define fnEprojInit_MotherBrainPurpleBreathBig 0x86CA6A +#define fnEprojInit_MotherBrainPurpleBreathSmall 0x86CA83 +#define fnnullsub_94 0x86CAA3 +#define fnEprojInstr_MotherBrainPurpleBreathIsActive 0x86CAEE +#define fnEprojInit_TimeBombSetJapaneseText 0x86CAF6 +#define fnEprojPreInstr_TimeBombSetJapaneseText 0x86CAFA +#define fnEprojInit_MotherBrainTubeFalling 0x86CBC9 +#define fnEprojPreInstr_MotherBrainTubeFalling 0x86CBE7 +#define fnMotherBrainTubeFallingFunc_GenerateExplosion 0x86CBEA +#define fnMotherBrainTubeFallingFunc_Falling 0x86CC08 +#define fnEprojInit_MotherBrainGlassShatteringShard 0x86CDC5 +#define fnEprojInit_MotherBrainGlassShatteringSparkle 0x86CE6D +#define fnEprojPreInstr_MotherBrainGlassShatteringShard 0x86CE9B +#define fnEprojInit_KiHunterAcidSpitLeft 0x86CF90 +#define fnEprojInit_KiHunterAcidSpitRight 0x86CFA6 +#define fnsub_86CFD5 0x86CFD5 +#define fnsub_86CFE6 0x86CFE6 +#define fnnullsub_95 0x86CFF7 +#define fnsub_86CFF8 0x86CFF8 +#define fnEprojInit_KagosBugs 0x86D088 +#define fnEprojPreInstr_KagosBugs_Func1 0x86D0B3 +#define fnEprojPreInstr_KagosBugs 0x86D0CA +#define fnnullsub_302 0x86D0EB +#define fnEprojPreInstr_D0EC 0x86D0EC +#define fnEprojPreInstr_D128 0x86D128 +#define fnEprojInstr_D15C 0x86D15C +#define fnEprojInstr_D1B6 0x86D1B6 +#define fnEprojInstr_D1C7 0x86D1C7 +#define fnEprojInstr_D1CE 0x86D1CE +#define fnEprojPreInstr_KagosBugs_Func2 0x86D1E4 +#define fnEprojInit_MaridiaFloatersSpikes 0x86D23A +#define fnEprojPreInstr_MaridiaFloatersSpikes 0x86D263 +#define fnEprojInit_WreckedShipRobotLaserDown 0x86D30C +#define fnEprojInit_WreckedShipRobotLaserHorizontal 0x86D32E +#define fnEprojInit_WreckedShipRobotLaserUp 0x86D341 +#define fnEprojPreInstr_WreckedShipRobotLaser 0x86D3BF +#define fnEprojInstr_AssignNewN00bTubeShardVelocity 0x86D5E1 +#define fnEprojInstr_SetN00bTubeShardX 0x86D5F2 +#define fnEprojInstr_D62A 0x86D62A +#define fnEprojInstr_SetXvelRandom 0x86D69A +#define fnEprojInit_N00bTubeCrack 0x86D6A5 +#define fnEprojInit_N00bTubeShards 0x86D6C9 +#define fnEprojInit_N00bTubeReleasedAirBubbles 0x86D774 +#define fnsub_86D7BF 0x86D7BF +#define fnsub_86D7DE 0x86D7DE +#define fnEprojPreInstr_N00bTubeShards 0x86D7FD +#define fnsub_86D83D 0x86D83D +#define fnsub_86D89F 0x86D89F +#define fnsub_86D8DF 0x86D8DF +#define fnsub_86D992 0x86D992 +#define fnEprojPreInstr_SpikeShootingPlantSpikes 0x86D9DB +#define fnEprojPreInstr_SpikeShootingPlantSpikes_MoveY1 0x86D9E6 +#define fnEprojPreInstr_SpikeShootingPlantSpikes_MoveY2 0x86DA10 +#define fnEprojPreInstr_SpikeShootingPlantSpikes_MoveX1 0x86DA3A +#define fnEprojPreInstr_SpikeShootingPlantSpikes_MoveX2 0x86DA64 +#define fnEprojPreInstr_SpikeShootingPlantSpikes_0_MoveX1 0x86DA8E +#define fnEprojPreInstr_SpikeShootingPlantSpikes_2_MoveX2 0x86DA93 +#define fnEprojPreInstr_SpikeShootingPlantSpikes_1_MoveY1 0x86DA98 +#define fnEprojPreInstr_SpikeShootingPlantSpikes_4_MoveY2 0x86DA9D +#define fnEprojPreInstr_SpikeShootingPlantSpikes_6_MoveX1Y1 0x86DAA2 +#define fnEprojPreInstr_SpikeShootingPlantSpikes_8_MoveX1Y2 0x86DAAA +#define fnEprojPreInstr_SpikeShootingPlantSpikes_7_MoveX2Y1 0x86DAB2 +#define fnEprojPreInstr_SpikeShootingPlantSpikes_9_MoveX2Y2 0x86DABA +#define fnEprojInit_DBF2 0x86DB18 +#define fnEprojPreInstr_DBF2 0x86DB5B +#define fnEprojPreInstr_DBF2_MoveX1 0x86DB62 +#define fnEprojPreInstr_DBF2_MoveX2 0x86DB8C +#define fnEprojPreInstr_DBF2_Func1 0x86DBB6 +#define fnEprojInstr_DC5A 0x86DC5A +#define fnEprojInstr_SpawnEnemyDrops_0 0x86DC61 +#define fnEprojInstr_SpawnSporesEproj 0x86DC77 +#define fnEprojInit_Spores 0x86DC8D +#define fnEprojInit_SporeSpawnStalk 0x86DCA3 +#define fnEprojInit_SporeSpawners 0x86DCD4 +#define fnEprojPreInstr_Spores 0x86DCEE +#define fnnullsub_96 0x86DD44 +#define fnEprojPreInstr_SporeSpawners 0x86DD46 +#define fnEprojInit_NamiFuneFireball 0x86DED6 +#define fnEprojPreInstr_NamiFuneFireball 0x86DF39 +#define fnEprojInit_NamiFuneFireball_MoveX1 0x86DF40 +#define fnEprojInit_NamiFuneFireball_MoveX2 0x86DF6A +#define fnEprojInstr_DFEA 0x86DFEA +#define fnEprojInit_LavaThrownByLavaman 0x86E000 +#define fnsub_86E049 0x86E049 +#define fnEproj_LavaThrownByLavaman_MoveX1 0x86E050 +#define fnEproj_LavaThrownByLavaman_MoveX2 0x86E07A +#define fnEprojInst_DustCloudOrExplosion 0x86E468 +#define fnEprojInit_EyeDoorSmoke 0x86E4A6 +#define fnEprojPreInstr_DustCloudOrExplosion 0x86E4FE +#define fnEprojPreInstr_nullsub_98 0x86E508 +#define fnEprojInstr_SetYVel 0x86E533 +#define fnEprojInit_SpawnedShotGate 0x86E5D0 +#define fnEprojInit_ClosedDownwardsShotGate 0x86E5D5 +#define fnEprojInit_ClosedUpwardsShotGate 0x86E5DA +#define fnEprojPreInstr_nullsub_99 0x86E604 +#define fnEprojPreInstr_E605 0x86E605 +#define fnEprojInit_SaveStationElectricity 0x86E6AD +#define fnnullsub_100 0x86E6D1 +#define fnEprojInit_BotwoonsBody 0x86EA31 +#define fnEprojPreInstr_BotwoonsBody 0x86EA80 +#define fnEproj_BotwoonsBody_Main 0x86EA98 +#define fnEproj_BotwonsBodyFunction_Dying 0x86EAF4 +#define fnEproj_BotwonsBodyFunction_Dying2 0x86EB04 +#define fnEproj_BotwonsBodyFunction_DyingFalling 0x86EB1F +#define fnnullsub_101 0x86EB93 +#define fnEprojInit_BotwoonsSpit 0x86EBC6 +#define fnEprojPreInstr_BotwoonsSpit 0x86EC05 +#define fnEprojInit_YappingMawsBody 0x86EC62 +#define fnEprojPreInstr_Empty2 0x86EC94 +#define fnEprojInstr_ECE3 0x86ECE3 +#define fnEprojInstr_ED17 0x86ED17 +#define fnEprojInstr_QueueSfx2_9 0x86EE8B +#define fnEprojInstr_QueueSfx2_24 0x86EE97 +#define fnEprojInstr_QueueSfx2_B 0x86EEA3 +#define fnEprojInstr_EEAF 0x86EEAF +#define fnEprojInstr_HandleRespawningEnemy 0x86EF10 +#define fnEprojInit_F337 0x86EF29 +#define fnEprojInit_EnemyDeathExplosion 0x86EF89 +#define fnEprojPreInstr_Empty 0x86EFDF +#define fnEprojPreInstr_Pickup 0x86EFE0 +#define fnEprojInit_Sparks 0x86F391 +#define fnEprojPreInstr_Sparks 0x86F3F0 +#define fnAnimtilesInstr_Delete 0x8780B2 +#define fnAnimtilesInstr_Goto 0x8780B7 +#define fnAnimtilesInstr_GotoRel 0x8780BC +#define fnAnimtilesInstr_DecrementTimerAndGoto 0x8780D4 +#define fnAnimtilesInstr_DecrementTimerAndGotoRel 0x8780DC +#define fnAnimtilesInstr_SetTimer 0x8780E3 +#define fnAnimtilesInstr_QueueMusic 0x8780F0 +#define fnAnimtilesInstr_QueueSfx1 0x8780FC +#define fnAnimtilesInstr_QueueSfx2 0x878108 +#define fnAnimtilesInstr_QueueSfx3 0x878114 +#define fnAnimtilesInstr_GotoIfBossBitSet 0x878120 +#define fnAnimtilesInstr_SetBossBit 0x878133 +#define fnAnimtilesInstr_GotoIfEventHappened 0x87813F +#define fnAnimtilesInstr_SetEventHappened 0x878150 +#define fnAnimtilesInstr_WaitUntilAreaBossDead_DoubleRet 0x8781BA +#define fnAnimtilesInstr_GotoIfBossBitSetInArea 0x878303 +#define fnAnimtilesInstr_SpawnTourianStatueEyeGlow 0x878320 +#define fnAnimtilesInstr_SpawnTourianStatueSoul 0x87832F +#define fnAnimtilesInstr_GotoIfTourianStatueBusy 0x87833E +#define fnAnimtilesInstr_TourianStatueSetState 0x878349 +#define fnAnimtilesInstr_TourianStatueClearState 0x878352 +#define fnAnimtilesInstr_Clear3PaletteColors 0x87835B +#define fnAnimtilesInstr_SpawnPalfxObj 0x878372 +#define fnAnimtilesInstr_Write8PaletteColors 0x87837F +#define fnLayerBlendingHandler 0x888000 +#define fnnullsub_9 0x888074 +#define fnnullsub_10 0x8880B7 +#define fnnullsub_11 0x88810C +#define fnPauseHook_Empty 0x8883E1 +#define fnnullsub_293 0x8884B8 +#define fnHdmaobjInstr_Delete 0x888569 +#define fnHdmaobjInstr_SetPreInstr 0x888570 +#define fnHdmaobjInstr_ClearPreInstr 0x888584 +#define fnHdmaobjInstr_CallFarFunc 0x8885B4 +#define fnHdmaobjInstr_Goto 0x8885EC +#define fnHdmaobjInstr_GotoRel 0x8885F1 +#define fnHdmaobjInstr_DecrementAndGoto 0x888607 +#define fnHdmaobjInstr_DecrementAndGotoRel 0x88860F +#define fnHdmaobjInstr_SetTimer 0x888616 +#define fnHdmaobjInstr_SetHdmaControl 0x888622 +#define fnHdmaobjInstr_SetHdmaTarget 0x888637 +#define fnHdmaobjInstr_SetHdmaTablePtr 0x88864C +#define fnHdmaobjInstr_SetHdmaTableBank 0x888655 +#define fnHdmaobjInstr_SetIndirectHdmaDataBank 0x88866A +#define fnHdmaobjInstr_Skip 0x88867F +#define fnHdmaobjInstr_Sleep 0x888682 +#define fnHdmaobjPreInstr_Xray 0x8886EF +#define fnHdmaobjPreInstr_XrayFunc0_NoBeam 0x888732 +#define fnnullsub_2 0x888753 +#define fnHdmaobjPreInstr_XrayFunc1_BeamWidening 0x888754 +#define fnHdmaobjPreInstr_XrayFunc2_FullBeam 0x8887AB +#define fnHdmaobjPreInstr_XrayFunc3_DeactivateBeam 0x888934 +#define fnHdmaobjPreInstr_XrayFunc4_DeactivateBeam 0x8889BA +#define fnHdmaobjPreInstr_XrayFunc5_DeactivateBeam 0x888A08 +#define fnHdmaobj_PreExplodeWhite 0x888B14 +#define fnHdmaobj_PreExplodeYellow 0x888B32 +#define fnHdmaobj_ExplodeYellow 0x888B39 +#define fnHdmaobj_ExplodeWhite 0x888B47 +#define fnHdmaobj_CleanUpTryCrystalFlash 0x888B4E +#define fnHdmaobjPreInstr_PowerBombExplode_SetWindowConf 0x888B8F +#define fnHdmaobjPreInstr_PowerBombExplode_Stage5_Afterglow 0x888B98 +#define fnHdmaobjPreInstr_PowerBombExplode_ExplosionYellow 0x888DE9 +#define fnHdmaobjPreInstr_PowerBombExplode_ExplosionWhite 0x888EB2 +#define fnHdmaobjPreInstr_PowerBombExplode_PreExplosionWhite 0x8890DF +#define fnHdmaobjPreInstr_PowerBombExplode_PreExplosionYellow 0x8891A8 +#define fnCrystalFlashSetupPart1 0x88A2E4 +#define fnCrystalFlashSetupPart2 0x88A309 +#define fnCrystalFlashCleanup 0x88A317 +#define fnHdmaobjPreInstr_CrystalFlash_CustomLayerBlend 0x88A339 +#define fnHdmaobjPreInstr_CrystalFlash_Stage2_AfterGlow 0x88A35D +#define fnHdmaobjPreInstr_CrystalFlash_Stage1_Explosion 0x88A552 +#define fnHdmaobjPreInstr_FxType22_BG3Yscroll 0x88A643 +#define fnHdmaobjInstr_SetFlagB 0x88A66C +#define fnHdmaobjPreInstr_BG3Xscroll 0x88A673 +#define fnHdmaobjPreInstr_SkyLandBG2Xscroll 0x88ADB2 +#define fnHdmaobjPreInstr_SkyLandBG2Xscroll2 0x88ADBA +#define fnHdmaobjPreInstr_SkyLandBG2XscrollInner 0x88ADC2 +#define fnRoomCode_ScrollingSkyLand 0x88AF8D +#define fnHdmaobjPreInstr_FirefleaBG3XScroll 0x88B0BC +#define fnFxRisingFunction_LavaAcid 0x88B343 +#define fnFxRisingFunction_LavaAcid_WaitToRise 0x88B367 +#define fnFxRisingFunction_LavaAcid_Raising 0x88B382 +#define fnHdmaobjInstr_B3A9 0x88B3A9 +#define fnHdmaobjPreInstr_LavaAcidBG3YScroll 0x88B3B0 +#define fnHdmaobjInstr_SetFlagB_Copy 0x88B4CE +#define fnHdmaobjPreInstr_LavaAcidBG2YScroll 0x88B4D5 +#define fnFxRisingFunction_C428_WaterNormal 0x88C428 +#define fnFxRisingFunction_WaterWaitToRise 0x88C44C +#define fnFxRisingFunction_WaterRising 0x88C458 +#define fnHdmaobjInstr_SetFlagB_Copy2 0x88C467 +#define fnHdmaobjPreInstr_WaterBG3XScroll 0x88C48E +#define fnHdmaobjInstr_SetFlagB_Copy3 0x88C582 +#define fnHdmaobjPreInstr_WaterBG2XScroll 0x88C589 +#define fnHdmaobjPreInstr_WaterBG2XScroll_Func2 0x88C5E4 +#define fnHdmaobjPreInstr_WaterBG2XScroll_Func1 0x88C636 +#define fnsub_88D916 0x88D916 +#define fnHdmaobjInstr_SetVideoMode1 0x88D949 +#define fnHdmaobjInstr_1938_RandomNumber 0x88D981 +#define fnHdmaobjPreInstr_RainBg3Scroll 0x88D9A1 +#define fnHdmaobjPreInstr_SporesBG3Xscroll 0x88DA47 +#define fnnullsub_112 0x88DB2E +#define fnHdmaobjPreInstr_FogBG3Scroll 0x88DB36 +#define fnHdmaobjPreInstr_CheckLotsOfEventsHappened 0x88DBD7 +#define fnHdmaobjPreInstr_DC23 0x88DC23 +#define fnHdmaobjPreInstr_DC69 0x88DC69 +#define fnHdmaobjPreInstr_DCBA 0x88DCBA +#define fnHdmaobjInstr_GotoIfEventHappened 0x88DCCB +#define fnHdmaobjPreInstr_BombTorizoHazeColorMathBgColor 0x88DD43 +#define fnHdmaobjPreInstr_HazeColorMathSubscreen_CeresRidleyAlive 0x88DE10 +#define fnHdmaobjPreInstr_HazeColorMathSubscreen_CeresRidleyDead 0x88DE15 +#define fnHdmaobjPreInstr_HazeColorMathSubscreen_FadingIn 0x88DE2D +#define fnHdmaobjPreInstr_HazeColorMathSubscreen_FadedIn 0x88DE74 +#define fnHdmaobjPreInstr_HazeColorMathSubscreen_FadingOut 0x88DE96 +#define fnnullsub_113 0x88DF91 +#define fnnullsub_114 0x88DF92 +#define fnHdmaobjPreInstr_DF94 0x88DF94 +#define fnHdmaobjPreInstr_VariaSuitPickup 0x88E026 +#define fnHdmaobjPreInstr_GravitySuitPickup 0x88E05C +#define fnHdmaobjPreInstr_E449 0x88E449 +#define fnHdmaobjInstr_E4BD 0x88E4BD +#define fnHdmaobjPreInstr_E567 0x88E567 +#define fnnullsub_357 0x88E726 +#define fnInitializeRainbowBeam 0x88E767 +#define fnHdmaobjPreInstr_E7BC 0x88E7BC +#define fnHdmaobjInstr_InitMorphBallEyeBeamHdma 0x88E917 +#define fnHdmaobjPreInstr_E9E6 0x88E9E6 +#define fnHdmaobjPreInstr_EA3C 0x88EA3C +#define fnHdmaobjPreInstr_EACB 0x88EACB +#define fnHdmaobjInsr_ConfigTitleSequenceGradientHDMA 0x88EB9F +#define fnHdmaobjPreInstr_Backdrop_TitleSequenceGradient 0x88EBB0 +#define fnHdmaobjPreInstr_ColorMathControlB_TitleGradient 0x88EBD2 +#define fnHdmaobjPreInstr_IntroCutsceneCrossfade 0x88EC1D +#define fnHdmaobjInstr_EC9F_ClearVars 0x88EC9F +#define fnHdmaobjPreInstr_ECB6 0x88ECB6 +#define fnRoomCode_CeresElevatorShaft 0x89ACC3 +#define fnnullsub_5 0x8B8697 +#define fnProcessCinematicBgObject 0x8B8839 +#define fnProcessCinematicBgObject_Nothing 0x8B8849 +#define fnProcessCinematicBgObject_DrawChar 0x8B884D +#define fnProcessCinematicBgObject_DrawToTextTilemap 0x8B88B7 +#define fnProcessCinematicBgObject_DrawToBgTilemap 0x8B88FD +#define fnProcessCinematicBgObject_Unk1 0x8B896B +#define fnProcessCinematicBgObject_Unk2 0x8B89CF +#define fnCinematicFunction_Intro_Func20 0x8B8D23 +#define fnCinematicFunction_nullsub_116 0x8B93D9 +#define fnCinematicSprInstr_Delete 0x8B9438 +#define fnCinematicSprInstr_Sleep 0x8B9442 +#define fnCinematicSprInstr_SetPreInstr 0x8B944C +#define fnCinematicSprInstr_ClearPreInstr 0x8B9457 +#define fnCinematicFunction_nullsub_298 0x8B945F +#define fnCinematicSprInstr_GotoRel 0x8B94A2 +#define fnCinematicSprInstr_Goto 0x8B94BC +#define fnCinematicSprInstr_DecTimerGoto 0x8B94C3 +#define fnCinematicSprInstr_DecTimerGotoRel 0x8B94CD +#define fnCinematicSprInstr_SetTimer 0x8B94D6 +#define fnMode7Instr_Delete 0x8B956B +#define fnMode7Instr_SetPreInstr 0x8B9572 +#define fnMode7Instr_ClearPreInstr 0x8B957D +#define fnMode7Instr_Goto 0x8B9586 +#define fnMode7Instr_DecTimerAndGoto 0x8B958D +#define fnMode7Instr_SetTimer 0x8B9597 +#define fnEnableCinematicBgTilemapUpdates 0x8B95B8 +#define fnCinematicBgInstr_Delete 0x8B9698 +#define fnCinematicBgInstr_Goto 0x8B971E +#define fnIntroObject_Delete 0x8B99FE +#define fnIntroObject_Goto 0x8B9A06 +#define fnIntroObject_DecTimerGoto 0x8B9A0D +#define fnIntroObject_SetTimer 0x8B9A17 +#define fnCinematicFunctionNone 0x8B9A47 +#define fnCinematicSpriteInit_7 0x8B9B1A +#define fnCinematicSpriteInit_8 0x8B9B2D +#define fnCinematicSpriteInit_9 0x8B9B40 +#define fnCinematicFunctionOpening 0x8B9B68 +#define fnCinematicSpriteInit_0 0x8B9CBC +#define fnsub_8B9CCF 0x8B9CCF +#define fnCinematicSprInstr_9CE1 0x8B9CE1 +#define fnCinematicFunc_Func2 0x8B9D17 +#define fnCinematicSpriteInit_1 0x8B9D4A +#define fnCinematicSprInstr_9D5D 0x8B9D5D +#define fnCinematicFunc_Func4 0x8B9D90 +#define fnCinematicSpriteInit_2 0x8B9DC3 +#define fnCinematicSprInstr_9DD6 0x8B9DD6 +#define fnCinematicFunc_Func5 0x8B9E12 +#define fnCinematicSpriteInit_3 0x8B9E45 +#define fnCinematicSprInstr_Func8 0x8B9E58 +#define fnCinematicFunc_Func7 0x8B9E8B +#define fnCinematicSpriteInit_4 0x8B9EB3 +#define fnCinematicSprInstr_Func9 0x8B9ECD +#define fnCinematicSpriteInit_5 0x8B9ED6 +#define fnCinematicSprInstr_sub_8B9EF0 0x8B9EF0 +#define fnCinematicSpriteInit_6 0x8B9EFF +#define fnCinematicSprInstr_9F19 0x8B9F19 +#define fnnullsub_117 0x8B9F28 +#define fnCinematicFunc_Func1 0x8B9F29 +#define fnCinematicFunc_Func10 0x8B9F52 +#define fnCinematicFunc_Func9 0x8B9FAE +#define fnPlayBabyMetroidCry1 0x8BA25B +#define fnPlayBabyMetroidCry2 0x8BA263 +#define fnPlayBabyMetroidCry3 0x8BA26B +#define fnCinematicSetPal1 0x8BA273 +#define fnCinematicSetPal2 0x8BA284 +#define fnCinematicSetPal3 0x8BA295 +#define fnCinematicSetPal4 0x8BA2A6 +#define fnnullsub_120 0x8BA38F +#define fnnullsub_121 0x8BA390 +#define fnCinematicFunc_Nothing 0x8BA391 +#define fnCinematicFunction_Intro_Initial 0x8BA395 +#define fnCinematicFunction_Intro_FadeIn 0x8BA5A7 +#define fnCinematicFunction_Intro_DrawInitJpn 0x8BA5BD +#define fnCinematicFunction_Intro_LastMetroidCaptivity 0x8BA5F8 +#define fnCinematicFunc_Intro_QueueGalaxyIsAtPeace 0x8BA613 +#define fnCinematicFunc_Intro_WaitForQueueWait4secs 0x8BA639 +#define fnCinematicFunc_Intro_FadeOut 0x8BA64C +#define fnCinematicFunc_Intro_WaitForFadeOut 0x8BA663 +#define fnCinematicFunc_Intro_SetupTextPage2 0x8BA66F +#define fnCinematicFunc_Intro_WaitFadeinShowText 0x8BA82B +#define fnCinematicFunc_Intro_WaitForFadeinSleep 0x8BA84A +#define fnSetSomeStuffForSpriteObject_2 0x8BA8C1 +#define fnnullsub_122 0x8BA8D4 +#define fnSetSomeStuffForSpriteObject_3 0x8BA8D5 +#define fnSetSomeStuffForSpriteObject_4_MetroidEgg 0x8BA8E8 +#define fnCinematicSprPreInstr_A903 0x8BA903 +#define fnCinematicSprInstr_SpawnMetroidEggParticles 0x8BA918 +#define fnSetSomeStuffForSpriteObject_6 0x8BA958 +#define fnSetSomeStuffForSpriteObject_7 0x8BA994 +#define fnSetSomeStuffForSpriteObject_8 0x8BAA9A +#define fnSetSomeStuffForSpriteObject_9 0x8BAAB3 +#define fnSetSomeStuffForSpriteObject_10 0x8BAD55 +#define fnSetSomeStuffForSpriteObject_11 0x8BAD68 +#define fnSetSomeStuffForSpriteObject_12 0x8BAD93 +#define fnSetSomeStuffForSpriteObject_13 0x8BADA6 +#define fnCinematicBgInstr_SetSomeStuffForSpriteObject_14 0x8BADD4 +#define fnSetSomeStuffForSpriteObject_17 0x8BAE07 +#define fnSetSomeStuffForSpriteObject_18 0x8BAE1A +#define fnCinematicBgInstr_HandleCreateJpnText_Page1 0x8BAE43 +#define fnCinematicBgInstr_SpawnMarkerWaitInput_Page1 0x8BAE5B +#define fnCinematicBgInstr_HandleCreateJpnText_Page2 0x8BAE79 +#define fnCinematicBgInstr_SpawnMarkerWaitInput_Page2 0x8BAE91 +#define fnCinematicFunction_Intro_WaitInputSetupMotherBrainFight 0x8BAEB8 +#define fnCinematicFunction_Intro_WaitInputSetupBabyMetroid 0x8BAF6C +#define fnCinematicBgInstr_HandleCreateJpnText_Page3 0x8BB074 +#define fnCinematicBgInstr_SpawnMarkerWaitInput_Page3 0x8BB08C +#define fnCinematicBgInstr_HandleCreateJpnText_Page4 0x8BB0B3 +#define fnCinematicBgInstr_SpawnMarkerWaitInput_Page4 0x8BB0CB +#define fnCinematicFunction_Intro_Func11 0x8BB0F2 +#define fnCinematicFunction_Intro_Func12 0x8BB123 +#define fnCinematicFunction_Intro_Func13 0x8BB151 +#define fnCinematicBgInstr_HandleCreateJpnText_Page5 0x8BB19B +#define fnCinematicBgInstr_SpawnMarkerWaitInput_Page5 0x8BB1B3 +#define fnCinematicFunction_Intro_Func15 0x8BB1DA +#define fnCinematicFunction_Intro_Func15b 0x8BB207 +#define fnCinematicBgInstr_Func16 0x8BB228 +#define fnCinematicBgInstr_Func17 0x8BB240 +#define fnCinematicFunction_Intro_XfadeGameplayFade 0x8BB250 +#define fnCinematicFunction_Intro_XfadeScientistFade 0x8BB2D2 +#define fnCinematicSprInstr_StartIntroPage2 0x8BB336 +#define fnCinematicSprInstr_StartIntroPage3 0x8BB33E +#define fnCinematicSprInstr_StartIntroPage4 0x8BB346 +#define fnCinematicSprInstr_StartIntroPage5 0x8BB34E +#define fnCinematicFunction_Intro_Page2 0x8BB35F +#define fnCinematicFunction_Intro_Page3 0x8BB370 +#define fnCinematicFunction_Intro_Page4 0x8BB381 +#define fnCinematicFunction_Intro_Page5 0x8BB392 +#define fnCinematicFunction_Intro_Fadestuff 0x8BB3F4 +#define fnCinematicFunction_Intro_Fadestuff2 0x8BB458 +#define fnCinematicBgPreInstr_SamusBlink 0x8BB4BC +#define fnCinematicFunction_Intro_Func19 0x8BB4DC +#define fnCinematicFunction_Intro_Func18 0x8BB4EB +#define fnEnableCinematicBgTilemapUpdates_ 0x8BB519 +#define fnsub_8BB51E 0x8BB51E +#define fnEnableCinematicBgTilemapUpdates__0 0x8BB54F +#define fnCinematicFunction_Intro_Func21 0x8BB554 +#define fnCinematicFunction_Intro_Func22 0x8BB585 +#define fnCinematicFunction_Intro_ThenWaitInputSetupBabyMetroid 0x8BB5B8 +#define fnCinematicFunction_Intro_Func23 0x8BB5C3 +#define fnCinematicFunction_Intro_Func24 0x8BB5EE +#define fnCinematicFunction_Intro_Func25 0x8BB61B +#define fnCinematicFunction_Intro_Func26 0x8BB626 +#define fnCinematicFunction_Intro_Func27 0x8BB657 +#define fnCinematicFunction_Intro_Func28 0x8BB68A +#define fnCinematicFunction_Intro_Func29 0x8BB695 +#define fnCinematicFunction_Intro_Func30 0x8BB6C0 +#define fnCinematicFunction_Intro_Func31 0x8BB6ED +#define fnCinematicFunction_Intro_Func32 0x8BB6F8 +#define fnEnableCinematicBgTilemapUpdates__ 0x8BB70B +#define fnnullsub_26 0x8BB710 +#define fnCinematicFunction_Intro_Func34 0x8BB72F +#define fnCinematicFunction_Intro_Func35 0x8BB773 +#define fnCinematicFunction_Intro_Func36 0x8BB786 +#define fnCinematicFunction_Intro_Func39 0x8BB80F +#define fnCinematicSprPreInstr_B82E 0x8BB82E +#define fnCinematicFunction_Intro_Func42 0x8BB896 +#define fnCinematicSprInstr_Func43 0x8BB8C5 +#define fnCinematicFunction_Intro_Func44 0x8BB8D8 +#define fnCinematicFunction_Intro_Func45 0x8BB93B +#define fnCinematicFunction_Intro_Func46 0x8BB98D +#define fnCinematicFunction_Intro_Func47 0x8BB9D4 +#define fnCinematicFunction_Intro_Func48 0x8BBA0F +#define fnCinematicSprInstr_SpawnIntroRinkas01 0x8BBA21 +#define fnCinematicSprInstr_SpawnIntroRinkas23 0x8BBA36 +#define fnCinematicFunction_Intro_Func49 0x8BBA4B +#define fnCinematicFunction_Intro_Func50 0x8BBA5E +#define fnCinematicFunction_Intro_Func51 0x8BBA73 +#define fnCinematicFunction_Intro_Func52 0x8BBB0D +#define fnCinematicFunction_Intro_Func53 0x8BBB24 +#define fnCinematicFunction_Intro_Func54 0x8BBCA0 +#define fnCinematicFunction_Intro_Func55 0x8BBDE4 +#define fnCinematicFunction_Intro_Func56 0x8BBDF9 +#define fnCinematicFunction_Intro_Func57 0x8BBE7E +#define fnCinematicFunction_Intro_Func58 0x8BBEB5 +#define fnCinematicFunction_Intro_Func59 0x8BBF22 +#define fnCinematicFunction_Intro_Func60 0x8BBF35 +#define fnCinematicFunction_Intro_Func61 0x8BBF4C +#define fnCinematicFunction_Intro_Func62 0x8BBF5F +#define fnCinematicFunction_Intro_Func63 0x8BBF76 +#define fnCinematicFunction_Intro_Func64 0x8BBF89 +#define fnCinematicFunction_Intro_Func65 0x8BBFA0 +#define fnCinematicFunction_Intro_Func66 0x8BBFC6 +#define fnCinematicSprPreInstr_nullsub_300 0x8BBFD9 +#define fnCinematicFunction_Intro_Func67 0x8BBFDA +#define fnCinematicFunction_Intro_Func68 0x8BC083 +#define fnCinematicCommonInstr_Func69 0x8BC096 +#define fnCinematicCommonInstr_Func70 0x8BC0A2 +#define fnCinematicFunction_Intro_Func71 0x8BC0B2 +#define fnCinematicFunction_Intro_Func72 0x8BC0C5 +#define fnCinematicFunction_Intro_Func73 0x8BC100 +#define fnCinematicFunctionBlackoutFromCeres 0x8BC11B +#define fnCinematicFunction_Intro_Func74 0x8BC2E4 +#define fnCinematicFunction_Intro_Func75 0x8BC2F1 +#define fnCinematicFunction_Intro_Func76 0x8BC345 +#define fnCinematicSprInstr_SpawnCeresExplosions1 0x8BC404 +#define fnCinematicFunction_Intro_Func78 0x8BC434 +#define fnCinematicSprPreInstr_C489 0x8BC489 +#define fnCinematicFunction_Intro_Func80 0x8BC4B9 +#define fnCinematicSprInstr_SpawnCeresExplosions3 0x8BC50C +#define fnCinematicFunction_Intro_Func81 0x8BC533 +#define fnCinematicFunction_Intro_Func82 0x8BC582 +#define fnCinematicFunction_Intro_Func83 0x8BC5A9 +#define fnCinematicFunction_Intro_Func77 0x8BC5CA +#define fnCinematicFunction_Intro_Func84 0x8BC610 +#define fnCinematicFunction_Intro_Func85 0x8BC627 +#define fnCinematicFunction_Intro_Func86 0x8BC699 +#define fnCinematicFunction_Intro_Func87 0x8BC79C +#define fnCinematicFunction_Intro_Func88 0x8BC7CA +#define fnCinematicFunction_Intro_Func89 0x8BC83B +#define fnCinematicFunction_Intro_Func90 0x8BC84E +#define fnCinematicFunction_Intro_Func91 0x8BC85D +#define fnCinematicFunction_Intro_Func92 0x8BC897 +#define fnCinematicFunction_Intro_Func93 0x8BC8AA +#define fnCinematicFunction_Intro_Func94 0x8BC8B9 +#define fnCinematicFunction_Intro_Func96 0x8BC8F9 +#define fnCinematicFunction_Intro_Func97 0x8BC908 +#define fnCinematicFunction_Intro_Func98 0x8BC942 +#define fnCinematicFunction_Intro_Func99 0x8BC956 +#define fnCinematicFunction_Intro_Func100 0x8BC96A +#define fnCinematicFunction_Intro_Func101 0x8BC97E +#define fnCinematicFunction_Intro_Func102 0x8BC992 +#define fnCinematicSprInstr_C9A5 0x8BC9A5 +#define fnCinematicSprInstr_C9AF 0x8BC9AF +#define fnCinematicSprInstr_C9BD 0x8BC9BD +#define fnCinematicSprInstr_C9C7 0x8BC9C7 +#define fnCinematicFunction_Intro_Func104 0x8BC9E6 +#define fnCinematicFunction_Intro_Func105 0x8BC9F9 +#define fnCinematicFunction_Intro_Func106 0x8BCA36 +#define fnCinematicFunction_Intro_Func107 0x8BCA85 +#define fnCinematicFunction_Intro_Func108 0x8BCAD0 +#define fnnullsub_124 0x8BCADE +#define fnCinematicFunction_Intro_Func95 0x8BCADF +#define fnCinematicFunctionEscapeFromCebes 0x8BD480 +#define fnCinematicFunction_Intro_Func109 0x8BD6D7 +#define fnCinematicFunction_Intro_Func110 0x8BD6F2 +#define fnCinematicFunction_Intro_Func111 0x8BD701 +#define fnCinematicFunction_Intro_Func112 0x8BD731 +#define fnCinematicFunction_Intro_Func113 0x8BD7F8 +#define fnCinematicFunction_Intro_Func114 0x8BD807 +#define fnCinematicFunction_Intro_Func115 0x8BD837 +#define fnCinematicFunction_Intro_Func116 0x8BDA02 +#define fnCinematicFunction_Intro_Func117 0x8BDA1A +#define fnCinematicFunction_Intro_Func118 0x8BDAD3 +#define fnnullsub_125 0x8BDB9D +#define fnCinematicFunction_Intro_Func119 0x8BDB9E +#define fnCinematicFunction_Intro_Func120 0x8BDBC4 +#define fnCinematicFunction_Intro_Func121 0x8BDCA5 +#define fnCinematicFunction_Intro_Func123 0x8BDD42 +#define fnCinematicFunction_Intro_Func124 0x8BDDCD +#define fnnullsub_126 0x8BDE63 +#define fnCinematicFunction_Intro_Func125 0x8BDE64 +#define fnCinematicFunction_Intro_Func126 0x8BDE80 +#define fnCinematicFunction_Intro_Func129 0x8BE0F4 +#define fnCinematicFunction_Intro_Func130 0x8BE110 +#define fnCinematicFunction_Intro_Func131 0x8BE158 +#define fnCinematicFunction_Intro_Func132 0x8BE190 +#define fnCinematicFunction_Intro_Func134 0x8BE1D2 +#define fnCinematicFunction_Intro_Func136 0x8BE265 +#define fnCinematicFunction_Intro_Func135 0x8BE293 +#define fnCinematicFunction_Intro_Func137 0x8BE2DD +#define fnCinematicFunction_Intro_Func138 0x8BE314 +#define fnCinematicFunction_Intro_Func145 0x8BE342 +#define fnCinematicFunction_Intro_Func139 0x8BE3AE +#define fnCinematicFunction_Intro_Func141 0x8BE48A +#define fnCinematicFunction_Intro_Func143 0x8BE504 +#define fnCinematicFunction_Intro_Func144 0x8BE58A +#define fnCalcItemPercentageCount 0x8BE627 +#define fnCinematicFunction_Intro_Func146 0x8BE769 +#define fnCinematicFunction_Intro_Func147 0x8BE780 +#define fnCinematicFunction_Intro_Func148 0x8BE797 +#define fnnullsub_127 0x8BE7BA +#define fnCinematicFunction_Intro_Func150 0x8BEF99 +#define fnCinematicFunction_Intro_Func151 0x8BEFB2 +#define fnCinematicFunction_Intro_Func152 0x8BEFEA +#define fnCinematicFunction_Intro_Func153 0x8BEFFD +#define fnCinematicFunction_Intro_Func154 0x8BF005 +#define fnCinematicFunction_Intro_Func155 0x8BF018 +#define fnCinematicFunction_Intro_Func156 0x8BF02B +#define fnCinematicFunction_Intro_Func157 0x8BF03E +#define fnCinematicFunction_Intro_Func159 0x8BF05E +#define fnCinematicFunction_Intro_Func161 0x8BF06D +#define fnCinematicFunction_Intro_Func162 0x8BF07C +#define fnCinematicFunction_Intro_Func163 0x8BF085 +#define fnCinematicFunction_Intro_Func164 0x8BF094 +#define fnCinematicFunction_Intro_Func165 0x8BF0B2 +#define fnCinematicFunction_Intro_Func166 0x8BF0E1 +#define fnCinematicFunction_Intro_Func167 0x8BF0E9 +#define fnCinematicFunction_Intro_Func168 0x8BF0F1 +#define fnCinematicFunction_Intro_Func169 0x8BF0F9 +#define fnCinematicFunction_Intro_Func170 0x8BF11E +#define fnCinematicFunction_Intro_Func171 0x8BF143 +#define fnCinematicFunction_Intro_Func172 0x8BF156 +#define fnCinematicFunction_Intro_Func173 0x8BF169 +#define fnCinematicFunction_Intro_Func174 0x8BF17C +#define fnCinematicFunction_Intro_Func175 0x8BF18F +#define fnCinematicFunction_Intro_Func176 0x8BF1A8 +#define fnCinematicFunction_Intro_Func177 0x8BF1C1 +#define fnCinematicFunction_Intro_Func178 0x8BF1D4 +#define fnCinematicFunction_Intro_Func179 0x8BF1E7 +#define fnCinematicFunction_Intro_Func180 0x8BF227 +#define fnCinematicSprInstr_Func181 0x8BF25E +#define fnCinematicSprInstr_Func182 0x8BF284 +#define fnCinematicSprInstr_Func183 0x8BF295 +#define fnCinematicFunction_Intro_Func184 0x8BF2A5 +#define fnCinematicSprInstr_Func185 0x8BF2B7 +#define fnCinematicSprInstr_Func186 0x8BF2FA +#define fnCinematicSprInstr_Func187 0x8BF32B +#define fnCinematicSprPreInstr_F35A 0x8BF35A +#define fnCinematicFunction_Intro_Func189 0x8BF375 +#define fnCinematicFunction_Intro_Func189b 0x8BF39B +#define fnCinematicSprInstr_Func190 0x8BF3B0 +#define fnCinematicFunction_Intro_Func191 0x8BF3B9 +#define fnCinematicSprInstr_Func192 0x8BF3CE +#define fnCinematicSprInstr_Func193 0x8BF41B +#define fnCinematicSprInstr_Func194 0x8BF424 +#define fnCinematicSprInstr_Func195 0x8BF42D +#define fnCinematicSprInstr_Func196 0x8BF436 +#define fnCinematicSprInstr_Func197 0x8BF43F +#define fnCinematicSprInstr_Func198 0x8BF448 +#define fnCinematicFunction_Intro_Func199 0x8BF455 +#define fnCinematicFunction_Intro_Func200 0x8BF464 +#define fnCinematicFunction_Intro_Func201 0x8BF478 +#define fnCinematicFunction_Intro_Func202 0x8BF487 +#define fnCinematicFunction_Intro_Func203 0x8BF49B +#define fnCinematicFunction_Intro_Func204 0x8BF4AA +#define fnCinematicFunction_Intro_Func205 0x8BF4D1 +#define fnCinematicFunction_Intro_Func206 0x8BF4E0 +#define fnCinematicFunction_Intro_Func207 0x8BF507 +#define fnnullsub_128 0x8BF51C +#define fnCinematicSprInstr_Func208 0x8BF51D +#define fnCinematicSprPreInstr_F528 0x8BF528 +#define fnCinematicSprInstr_Func211 0x8BF554 +#define fnCinematicSprPreInstr_F57F 0x8BF57F +#define fnCinematicSprInstr_Func213 0x8BF597 +#define fnCinematicSprInstr_Func214 0x8BF5BA +#define fnCinematicFunction_Intro_Func215 0x8BF5DD +#define fnCinematicSprInstr_Func217 0x8BF604 +#define fnCinematicSprInstr_Func218 0x8BF651 +#define fnCinematicFunction_Intro_Func219 0x8BF6FE +#define fnPalPreInstr_nullsub_129 0x8DC526 +#define fnPalInstr_Finish 0x8DC595 +#define fnPalInstr_ColorPlus2 0x8DC599 +#define fnPalInstr_ColorPlus3 0x8DC5A2 +#define fnPalInstr_ColorPlus4 0x8DC5AB +#define fnPalInstr_ColorPlus8 0x8DC5B4 +#define fnPalInstr_ColorPlus9 0x8DC5BD +#define fnPalInstr_ColorPlus15 0x8DC5C6 +#define fnPalInstr_Delete 0x8DC5CF +#define fnPalInstr_SetPreInstr 0x8DC5D4 +#define fnPalInstr_ClearPreInstr 0x8DC5DD +#define fnPalInstr_Goto 0x8DC61E +#define fnPalInstr_GotoRel 0x8DC623 +#define fnPalInstr_DecTimerGoto 0x8DC639 +#define fnPalInstr_DecTimerGotoRel 0x8DC641 +#define fnPalInstr_SetTimer 0x8DC648 +#define fnPalInstr_SetColorIndex 0x8DC655 +#define fnPalInstr_QueueMusic 0x8DC65E +#define fnPalInstr_QueueSfx1 0x8DC66A +#define fnPalInstr_QueueSfx2 0x8DC673 +#define fnPalInstr_QueueSfx3 0x8DC67C +#define fnnullsub_131 0x8DC685 +#define fnPalInit_E1BC 0x8DE204 +#define fnPalPreInstr_E1BC 0x8DE20B +#define fnPalPreInstr_CheckEnemy0Health 0x8DE2E0 +#define fnPalPreInstr_SamusInHeat 0x8DE379 +#define fnPalInit_F761_Norfair1 0x8DE440 +#define fnPalInstr_SetTimerIfBossBit 0x8DEB2A +#define fnPalPreInstr_SwitchIfYpos 0x8DEC59 +#define fnPalPreInstr_SwitchIfYpos2 0x8DED84 +#define fnPalPreInstr_DeletePalfxIfMinibossDead 0x8DEEC5 +#define fnPalInstr_SetPalfxIndex 0x8DF1C6 +#define fnPalPreInstr_F621 0x8DF621 +#define fnPalInit_F779_Brinstar8 0x8DF730 +#define fnRoomSetup_AfterSavingAnimals 0x8F9194 +#define fnRoomSetup_AutoDestroyWallAfterEscape 0x8F91A9 +#define fnRoomSetup_TurnWallIntoShotblocks 0x8F91B2 +#define fnnullsub_132 0x8F91BB +#define fnnullsub_133 0x8F91BC +#define fnRoomSetup_ShakeDuringEscape 0x8F91BD +#define fnRoomSetup_ScrollingSkyLand 0x8F91C9 +#define fnRoomSetup_ScrollingSkyOcean 0x8F91CE +#define fnnullsub_134 0x8F91D3 +#define fnnullsub_135 0x8F91D4 +#define fnnullsub_136 0x8F91D5 +#define fnnullsub_137 0x8F91D6 +#define fnRoomSetup_RunStatueUnlockAnims 0x8F91D7 +#define fnnullsub_138 0x8F91F4 +#define fnnullsub_139 0x8F91F5 +#define fnnullsub_140 0x8F91F6 +#define fnnullsub_141 0x8F91F7 +#define fnDoorCode_StartWreckedShipTreadmillWest 0x8FB971 +#define fnDoorCode_Scroll6_Green 0x8FB981 +#define fnDoorCode_Scroll0_Blue 0x8FB98C +#define fnDoorCode_Scroll13_Blue 0x8FB997 +#define fnDoorCode_Scroll_4Blue_8Green 0x8FB9A2 +#define fnDoorCode_Scroll_8toB_Red 0x8FB9B3 +#define fnDoorCode_Scroll_LotsRed 0x8FB9CA +#define fnDoorCode_Scroll_1_4_Green 0x8FB9F1 +#define fnDoorCode_Scroll_2_Blue 0x8FBA00 +#define fnDoorCode_Scroll_17_Blue 0x8FBA0B +#define fnDoorCode_Scroll_4_Blue 0x8FBA16 +#define fnDoorCode_Scroll_6_Green 0x8FBA21 +#define fnDoorCode_Scroll_3_Green 0x8FBA2C +#define fnDoorCode_SetScroll_0 0x8FBD07 +#define fnDoorCode_SetScroll_1 0x8FBD16 +#define fnDoorCode_SetScroll_2 0x8FBD25 +#define fnDoorCode_SetScroll_3 0x8FBD30 +#define fnDoorCode_SetScroll_4 0x8FBD3F +#define fnDoorCode_SetScroll_5 0x8FBD50 +#define fnDoorCode_SetScroll_6 0x8FBD5B +#define fnDoorCode_SetScroll_7 0x8FBD6C +#define fnDoorCode_SetScroll_8 0x8FBD77 +#define fnDoorCode_SetScroll_9 0x8FBD8A +#define fnDoorCode_SetScroll_10 0x8FBD95 +#define fnDoorCode_SetScroll_11 0x8FBDA0 +#define fnDoorCode_SetScroll_12 0x8FBDAF +#define fnDoorCode_SetScroll_13 0x8FBDC0 +#define fnDoorCode_SetScroll_14 0x8FBDD1 +#define fnDoorCode_SetScroll_15 0x8FBDE2 +#define fnDoorCode_SetScroll_16 0x8FBDF1 +#define fnDoorCode_SetScroll_17 0x8FBE00 +#define fnDoorCode_SetScroll_18 0x8FBE0B +#define fnDoorCode_SetScroll_19 0x8FBE1A +#define fnDoorCode_SetScroll_20 0x8FBE25 +#define fnDoorCode_SetScroll_21 0x8FBE36 +#define fnDoorCode_SetScroll_22 0x8FBF9E +#define fnDoorCode_SetScroll_23 0x8FBFBB +#define fnDoorCode_SetScroll_24 0x8FBFDA +#define fnDoorCode_SetScroll_25 0x8FBFE9 +#define fnDoorCode_SetScroll_26 0x8FBFFA +#define fnDoorCode_SetScroll_28 0x8FC016 +#define fnDoorCode_SetScroll_29 0x8FC025 +#define fnDoorCode_SetScroll_30 0x8FC03A +#define fnDoorCode_SetScroll_31 0x8FC04B +#define fnDoorCode_SetScroll_32 0x8FC056 +#define fnDoorCode_SetScroll_33 0x8FC067 +#define fnDoorCode_SetScroll_34 0x8FC078 +#define fnDoorCode_SetScroll_35 0x8FC089 +#define fnDoorCode_SetScroll_36 0x8FC0A2 +#define fnDoorCode_SetScroll_37 0x8FC0AD +#define fnDoorCode_SetScroll_38 0x8FC0C2 +#define fnDoorCode_SetScroll_39 0x8FC0D3 +#define fnDoorCode_SetScroll_40 0x8FC0DE +#define fnDoorCode_SetScroll_41 0x8FC0EF +#define fnDoorCode_SetScroll_42 0x8FC0FA +#define fnDoorCode_SetScroll_43 0x8FC10B +#define fnRoomCode_ScrollingSkyLand_ 0x8FC116 +#define fnRoomCode_ScrollingSkyOcean_ 0x8FC11B +#define fnRoomCode_ScrollingSkyLand_Shakes 0x8FC120 +#define fnRoomCode_ExplodeShakes 0x8FC124 +#define fnRoomCode_GenRandomExplodes_4th 0x8FC183 +#define fnRoomCode_GenRandomExplodes 0x8FC1A9 +#define fnRoomCode_ScrollRightDachora 0x8FC1E6 +#define fnnullsub_142 0x8FC8C7 +#define fnRoomCode_8FC8C8 0x8FC8C8 +#define fnnullsub_143 0x8FC8D0 +#define fnnullsub_144 0x8FC8D1 +#define fnnullsub_145 0x8FC8D2 +#define fnRoomCode_SetupShaktoolRoomPlm 0x8FC8D3 +#define fnnullsub_146 0x8FC8DC +#define fnRoomCode_SetPauseCodeForDraygon 0x8FC8DD +#define fnPauseHook_DraygonRoom 0x8FC8F6 +#define fnUnpauseHook_DraygonRoom 0x8FC8FC +#define fnRoomCode_SetCollectedMap 0x8FC90A +#define fnnullsub_147 0x8FC91E +#define fnRoomCode_SetZebesTimebombEvent 0x8FC91F +#define fnRoomCode_SetLightHorizRoomShake 0x8FC933 +#define fnRoomCode_SetMediumHorizRoomShake 0x8FC946 +#define fnRoomCode_Escape4_SetMediumHorizRoomShake 0x8FC953 +#define fnRoomCode_SetCeresDoorSolid 0x8FC96E +#define fnRoomCode_CeresColorMathHdma 0x8FC976 +#define fnRoomCode_CeresColorMathHdma_BgBase 0x8FC97B +#define fnDoorCode_StartWreckedSkipTreadmill_East 0x8FE1D8 +#define fnDoorCode_SetScroll_44 0x8FE1E8 +#define fnDoorCode_SetScroll_45 0x8FE1F3 +#define fnDoorCode_SetScroll_46 0x8FE1FE +#define fnDoorCode_SetScroll_47 0x8FE20F +#define fnDoorCode_SetScroll_48 0x8FE21A +#define fnDoorCode_SetScroll_49 0x8FE229 +#define fnDoorCode_SetupElevatubeFromSouth 0x8FE26C +#define fnDoorCode_SetupElevatubeFromNorth 0x8FE291 +#define fnRoomCode_Elevatube 0x8FE2B6 +#define fnDoorCode_ResetElevatubeNorthExit 0x8FE301 +#define fnDoorCode_ResetElevatubeSouthExit 0x8FE309 +#define fnDoorCode_SetScroll_50 0x8FE318 +#define fnDoorCode_SetScroll_53 0x8FE345 +#define fnDoorCode_SetScroll_54 0x8FE356 +#define fnDoorCode_SetScroll_55 0x8FE367 +#define fnDoorCode_SetScroll_56 0x8FE378 +#define fnDoorCode_SetScroll_57 0x8FE38D +#define fnDoorCode_SetScroll_58 0x8FE398 +#define fnDoorCode_SetScroll_59 0x8FE3A3 +#define fnDoorCode_SetScroll_61 0x8FE3B9 +#define fnDoorCode_SetScroll_62 0x8FE3C8 +#define fnDoorCode_SetScroll_63 0x8FE3D9 +#define fnDoorCode_SetScroll_64 0x8FE4C0 +#define fnDoorCode_SetScroll_65 0x8FE4CF +#define fnDoorCode_CeresElevatorShaft 0x8FE4E0 +#define fnDoorCode_CeresElevatorShaft_2 0x8FE513 +#define fnRoomCode_CeresElevatorShaft_ 0x8FE51F +#define fnnullsub_148 0x8FE524 +#define fnRoomCode_SpawnCeresFallingDebris 0x8FE525 +#define fnRoomCode_HandleCeresRidleyGetaway 0x8FE571 +#define fnRoomCode_ShakeScreenHorizDiag 0x8FE57C +#define fnRoomCode_GenRandomExplodes_4th_ 0x8FE5A0 +#define fnRoomCode_ShakeScreenHorizDiagStrong 0x8FE5A4 +#define fnRoomDefStateSelect_Finish 0x8FE5E6 +#define fnRoomDefStateSelect_TourianBoss01 0x8FE5FF +#define fnRoomDefStateSelect_IsEventSet 0x8FE612 +#define fnRoomDefStateSelect_IsBossDead 0x8FE629 +#define fnRoomDefStateSelect_MorphBallMissiles 0x8FE652 +#define fnRoomDefStateSelect_PowerBombs 0x8FE669 +#define fnRoomCode_CrocomireShaking 0x8FE8CD +#define fnRoomCode_RidleyRoomShaking 0x8FE950 +#define fnnullsub_12 0x908077 +#define fnSamus_Draw 0x9085E2 +#define fnnullsub_3 0x9092E9 +#define fnSamus_MoveHandler_ReleaseFromGrapple 0x90946E +#define fnSamus_HandleMovement_DrainedCrouching 0x9094CB +#define fnSamus_ScrollFinishedHook_SporeSpawnFight 0x909589 +#define fnSamus_MovementHandler_Normal 0x90A337 +#define fnnullsub_13 0x90A671 +#define fnProjPreInstr_Beam_NoWaveBeam 0x90AEF3 +#define fnProjPreInstr_Dir0459 0x90AF4A +#define fnProjPreInstr_Dir1368 0x90AF52 +#define fnProjPreInstr_Dir27 0x90AF60 +#define fnProjPreInstr_Missile 0x90AF68 +#define fnProjPreInstr_Missile_Func0459 0x90AFC7 +#define fnProjPreInstr_Missile_Func1368 0x90AFCF +#define fnProjPreInstr_Missile_Func27 0x90AFDD +#define fnProjPreInstr_SuperMissile 0x90AFE5 +#define fnProjPreInstr_SuperMissile_Func0459 0x90B047 +#define fnProjPreInstr_SuperMissile_Func1368 0x90B052 +#define fnProjPreInstr_SuperMissile_Func27 0x90B06A +#define fnProjPreInstr_Func1 0x90B075 +#define fnProjPreInstr_Bomb 0x90B099 +#define fnProjPreInstr_PowerBomb 0x90B0AE +#define fnProjPreInstr_WavePlasmaEtc 0x90B0C3 +#define fnProjPreInstr_BeamOrIceWave 0x90B0E4 +#define fnProjPreInstr_Wave_Shared 0x90B103 +#define fnProjPreInstr_WavePlasmaEtc_0459 0x90B13B +#define fnProjPreInstr_WavePlasmaEtc_1368 0x90B143 +#define fnProjPreInstr_WavePlasmaEtc_27 0x90B151 +#define fnProjPreInstr_HyperBeam 0x90B159 +#define fnProjPreInstr_Empty 0x90B169 +#define fnProjInstr_MoveLeftProjectileTrailDown 0x90B525 +#define fnProjInstr_MoveRightProjectileTrailDown 0x90B587 +#define fnProjInstr_MoveLeftProjectileTrailUp 0x90B5B3 +#define fnProjPreInstr_IceSba 0x90CF09 +#define fnProjPreInstr_IceSba2 0x90CF7A +#define fnSamus_MoveHandlerShinesparkWindup 0x90D068 +#define fnSamus_MoveHandlerVerticalShinespark 0x90D0AB +#define fnSamus_MoveHandler_Shinespark_Diag 0x90D0D7 +#define fnSamus_MoveHandler_Shinespark_Horiz 0x90D106 +#define fnSamus_MoveHandler_ShinesparkCrash 0x90D346 +#define fnSamus_MoveHandler_ShinesparkCrash_0 0x90D383 +#define fnSamus_MoveHandler_ShinesparkCrash_1 0x90D396 +#define fnSamus_MoveHandler_ShinesparkCrash_2 0x90D3CC +#define fnSamus_MoveHandler_ShinesparkCrashEchoCircle 0x90D3F3 +#define fnSamus_MoveHandler_ShinesparkCrashFinish 0x90D40D +#define fnProjPreInstr_SpeedEcho 0x90D4D2 +#define fnSamusMoveHandler_CrystalFlashStart 0x90D678 +#define fnSamusMoveHandler_CrystalFlashMain 0x90D6CE +#define fnkSamusMoveHandler_CrystalFlashFinish 0x90D75B +#define fnProjPreInstr_PlasmaSba 0x90D793 +#define fnProjPreInstr_PlasmaSbaFunc_0 0x90D7E1 +#define fnProjPreInstr_PlasmaSbaFunc_1 0x90D7FA +#define fnProjPreInstr_PlasmaSbaFunc_2 0x90D813 +#define fnProjPreInstr_SpreadBomb 0x90D8F7 +#define fnProjPreInstr_WaveSba 0x90DA08 +#define fnProjPreInstr_SpazerSba 0x90DB06 +#define fnProjPreInstr_SpazerSba_FuncA_0 0x90DB57 +#define fnProjPreInstr_SpazerSba_FuncA_1 0x90DB66 +#define fnProjPreInstr_SpazerSba_FuncA_2 0x90DB75 +#define fnProjPreInstr_SpazerSba_FuncA_3 0x90DB84 +#define fnProjPreInstr_SpazerSba_FuncB_0 0x90DB93 +#define fnProjPreInstr_SpazerSba_FuncB_1 0x90DBCF +#define fnProjPreInstr_SpazerSba_FuncB_2 0x90DC30 +#define fnProjPreInstr_EndOfSpazerSba 0x90DC9C +#define fnSamus_MoveHandler_Knockback 0x90DF38 +#define fnSamus_MoveHandler_Knockback_0 0x90DF50 +#define fnSamus_MoveHandler_Knockback_Up 0x90DF53 +#define fnSamus_MoveHandler_Knockback_3 0x90DF5D +#define fnSamus_MoveHandler_Knockback_Down 0x90DF64 +#define fnSamus_MoveHandler_BombJumpStart 0x90E025 +#define fnSamus_MoveHandler_BombJumpMain 0x90E032 +#define fnSamus_MoveHandler_BombJumpFunc1 0x90E07D +#define fnSamus_Func1 0x90E09B +#define fnSamus_Func2 0x90E0C5 +#define fnSamus_Func3 0x90E0E6 +#define fnDrawTimer_ 0x90E114 +#define fnSamus_PushOutOfRidleysWay 0x90E12E +#define fnSamus_Func4 0x90E1C8 +#define fnSamus_GrabbedByDraygonFrameHandler 0x90E2A1 +#define fnnullsub_151 0x90E37E +#define fnSamus_Func7 0x90E3A3 +#define fnSamus_Func9 0x90E41B +#define fnSamus_FrameHandlerAlfa_Func11 0x90E695 +#define fnSamus_FrameHandlerAlfa_Func12 0x90E6C9 +#define fnSamus_FrameHandlerAlfa_Func13 0x90E713 +#define fnSamus_FrameHandlerBeta_Func17 0x90E725 +#define fnHandleDemoRecorder_3 0x90E7D2 +#define fnSamus_FrameHandlerBeta_Func14 0x90E7F5 +#define fnSamus_Func15 0x90E833 +#define fnSamus_Func16 0x90E86A +#define fnSamus_Func18 0x90E8AA +#define fnEmptyFunction 0x90E8CD +#define fnj_HandleDemoRecorder_2 0x90E8D6 +#define fnj_HandleDemoRecorder_2_0 0x90E8D9 +#define fnSetContactDamageIndexAndUpdateMinimap 0x90E8DC +#define fnSamus_Func19 0x90E8EC +#define fnSamus_LowHealthCheck 0x90E902 +#define fnnullsub_152 0x90E90E +#define fnSamus_InputHandler_E913 0x90E913 +#define fnSamus_Func20_ 0x90E918 +#define fnSamus_InputHandler_E91D 0x90E91D +#define fnHandleAutoJumpHack 0x90E926 +#define fnSamusMovementType_Xray 0x90E94F +#define fnSamusDrawHandler_Default 0x90EB52 +#define fnsub_90EB86 0x90EB86 +#define fnnullsub_156 0x90EBF2 +#define fnSamus_DrawHandler_EndOfShinespark 0x90EBF3 +#define fnSamusDisplayHandler_UsingElevator 0x90EC14 +#define fnSamusDisplayHandler_SamusReceivedFatal 0x90EC1D +#define fnProjPreInstr_UnknownProj8027 0x90EFD3 +#define fnSamus_Func25_ShineSpark 0x90F04B +#define fnSamus_MoveHandler_F072 0x90F072 +#define fnnullsub_7 0x90F52F +#define fnSamus_InputHandler 0x918000 +#define fnDemoPreInstr_nullsub_162 0x9183BF +#define fnDemoInstr_Finish 0x918427 +#define fnDemoInstr_SetPreInstr 0x918434 +#define fnDemoInstr_ClearPreInstr 0x91843F +#define fnDemoInstr_Goto 0x918448 +#define fnDemoInstr_DecTimerAndGoto 0x91844F +#define fnDemoInstr_SetTimer 0x918459 +#define fnDemoInstr_Func2 0x9185FC +#define fnDemoPreInstr_864F 0x91864F +#define fnDemoPreInstr_866A 0x91866A +#define fnDemoInstr_Disable 0x918682 +#define fnDemoInstr_Func3 0x918739 +#define fnDemoPreInstr_CheckLeaveDemo 0x918A9B +#define fnDemoPreInstr_8AB0 0x918AB0 +#define fnXray_SetupStage1_FreezeTimeBackup 0x91CAF9 +#define fnXray_SetupStage2_ReadBg1_2ndScreen 0x91CB1C +#define fnXray_SetupStage3_ReadBg1_1stScreen 0x91CB57 +#define fnXray_SetupStage4 0x91CB8E +#define fnXray_Func6 0x91CE79 +#define fnXray_Func6B 0x91CEBB +#define fnXray_Func7 0x91CF36 +#define fnXray_Func9 0x91CF4E +#define fnXray_Func10 0x91CF62 +#define fnXray_Func11 0x91CF6F +#define fnXray_SetupStage5 0x91D0D3 +#define fnXray_SetupStage6 0x91D173 +#define fnXray_SetupStage7 0x91D1A0 +#define fnHdmaobjPreInstr_XraySetup 0x91D27F +#define fnXray_SetupStage8_SetBackdropColor 0x91D2BC +#define fnVariaSuitPickup 0x91D4E4 +#define fnGravitySuitPickup 0x91D5BA +#define fnInitializeSuitPickupHdma 0x91D692 +#define fnnullsub_17 0x91E732 +#define fnnullsub_21 0x91ECD8 +#define fnnullsub_22 0x91ECD9 +#define fnnullsub_19 0x91EF39 +#define fnnullsub_23 0x91EFDE +#define fnnullsub_24 0x91FC07 +#define fnnullsub_25 0x91FCAE +#define fnSamus_Func20 0x91FCAF +#define fnProj93Instr_Delete 0x93822F +#define fnProj93Instr_Goto 0x938239 +#define fnProj93Instr_GotoIfLess 0x938240 +#define fnGrappleInstr_Goto 0x94B0F4 +#define fnnullsub_6 0x9BB8D4 +#define fnGrappleNext_SwingClockwise 0x9BB9D9 +#define fnGrappleNext_SwingAntiClockwise 0x9BB9E2 +#define fnGrappleNext_StandAimRight 0x9BB9EA +#define fnGrappleNext_StandAimDownRight 0x9BB9F3 +#define fnGrappleNext_StandAimDownLeft 0x9BB9FC +#define fnGrappleNext_StandAimLeft 0x9BBA05 +#define fnGrappleNext_CrouchAimRight 0x9BBA0E +#define fnGrappleNext_CrouchAimDownRight 0x9BBA17 +#define fnGrappleNext_CrouchAimDownLeft 0x9BBA20 +#define fnGrappleNext_CrouchAimLeft 0x9BBA29 +#define fnGrappleBeamFunc_BB64 0x9BBB64 +#define fnGrappleBeamFunc_BC1F 0x9BBC1F +#define fnGrappleBeamFunc_BCFF 0x9BBCFF +#define fnGrappleBeamFunc_BD44 0x9BBD44 +#define fnGrappleBeamFunc_BD95 0x9BBD95 +#define fnGrappleBeamFunc_BE98 0x9BBE98 +#define fnGrappleBeamFunc_BEEB 0x9BBEEB +#define fnGrappleBeamFunc_BF1B 0x9BBF1B +#define fnGrappleBeamFunc_Inactive 0x9BC4F0 +#define fnGrappleBeamFunc_FireGoToCancel 0x9BC51E +#define fnGrappleBeamFunc_Firing 0x9BC703 +#define fnUNUSED_sub_9BC759 0x9BC759 +#define fnGrappleBeamFunc_ConnectedLockedInPlace 0x9BC77E +#define fnGrappleBeamFunc_Connected_Swinging 0x9BC79D +#define fnGrappleBeamFunc_Wallgrab 0x9BC814 +#define fnGrappleBeamFunc_C832 0x9BC832 +#define fnGrappleBeamFunc_Cancel 0x9BC856 +#define fnGrappleBeam_Func2 0x9BC8C5 +#define fnGrappleBeamFunc_C9CE 0x9BC9CE +#define fnGrappleBeamFunc_ReleaseFromSwing 0x9BCB8B +#define fnEnemy_GrappleReact_NoInteract_A0 0xA08000 +#define fnEnemy_GrappleReact_SamusLatchesOn_A0 0xA08005 +#define fnEnemy_GrappleReact_KillEnemy_A0 0xA0800A +#define fnEnemy_GrappleReact_CancelBeam_A0 0xA0800F +#define fnEnemy_GrappleReact_SamusLatchesNoInvinc_A0 0xA08014 +#define fnEnemy_GrappleReact_SamusLatchesParalyze_A0 0xA08019 +#define fnEnemy_GrappleReact_HurtSamus_A0 0xA0801E +#define fnEnemy_NormalTouchAI_A0 0xA08023 +#define fnEnemy_NormalShotAI_A0 0xA0802D +#define fnEnemy_NormalPowerBombAI_A0 0xA08037 +#define fnEnemy_NormalFrozenAI 0xA08041 +#define fnCreateADudShot 0xA08046 +#define fnnullsub_169 0xA0804B +#define fnnullsub_170 0xA0804C +#define fnnullsub_171 0xA0807B +#define fnEnemyInstr_StopScript 0xA0807C +#define fnEnemyInstr_Call 0xA0808A +#define fnEnemyInstr_Goto 0xA080ED +#define fnEnemyInstr_DecTimerAndGoto 0xA08108 +#define fnEnemyInstr_DecTimerAndGoto2 0xA08110 +#define fnEnemyInstr_SetTimer 0xA08123 +#define fnEnemyInstr_Sleep 0xA0812F +#define fnEnemyInstr_WaitNframes 0xA0813A +#define fnEnemyInstr_CopyToVram 0xA0814B +#define fnEnemyInstr_EnableOffScreenProcessing 0xA08173 +#define fnEnemyInstr_DisableOffScreenProcessing 0xA0817D +#define fnnullsub_4 0xA09784 +#define fnEnemy_GrappleReact_SamusLatchesOn_A2 0xA28005 +#define fnEnemy_GrappleReact_KillEnemy_A2 0xA2800A +#define fnEnemy_GrappleReact_CancelBeam_A2 0xA2800F +#define fnEnemy_NormalTouchAI_A2 0xA28023 +#define fnEnemy_NormalShotAI_A2 0xA2802D +#define fnEnemy_NormalPowerBombAI_A2 0xA28037 +#define fnEnemy_NormalFrozenAI_A2 0xA28041 +#define fnnullsub_170_A2 0xA2804C +#define fnnullsub_171_A2 0xA2807B +#define fnEnemyInstr_Goto_A2 0xA280ED +#define fnEnemyInstr_DecTimerAndGoto2_A2 0xA28110 +#define fnEnemyInstr_SetTimer_A2 0xA28123 +#define fnEnemyInstr_Sleep_A2 0xA2812F +#define fnEnemyInstr_EnableOffScreenProcessing_A2 0xA28173 +#define fnEnemyInstr_DisableOffScreenProcessing_A2 0xA2817D +#define fnBouncingGoofball_Init 0xA2871C +#define fnBouncingGoofball_Main 0xA2879C +#define fnBouncingGoofball_Instr_88C5 0xA288C5 +#define fnBouncingGoofball_Instr_88C6 0xA288C6 +#define fnMiniCrocomire_Instr_897E 0xA2897E +#define fnMiniCrocomire_Instr_8990 0xA28990 +#define fnMiniCrocomire_Instr_899D 0xA2899D +#define fnMiniCrocomire_Init 0xA289AD +#define fnMiniCrocomire_Main 0xA289F0 +#define fnMiniCrocomire_PreInstr5 0xA28A43 +#define fnMiniCrocomire_PreInstr6 0xA28A5C +#define fnnullsub_175 0xA28A75 +#define fnMaridiaBeybladeTurtle_Init 0xA28D6C +#define fnMiniMaridiaBeybladeTurtle_Init 0xA28D9D +#define fnMaridiaBeybladeTurtle_Main 0xA28DD2 +#define fnMaridiaBeybladeTurtle_Func1 0xA28DD8 +#define fnnullsub_360 0xA28E09 +#define fnMaridiaBeybladeTurtle_Func2 0xA28E0A +#define fnMaridiaBeybladeTurtle_Func3 0xA28EE0 +#define fnMaridiaBeybladeTurtle_Func5 0xA28F3F +#define fnMaridiaBeybladeTurtle_Func7 0xA28F8D +#define fnMaridiaBeybladeTurtle_Func8 0xA28FEB +#define fnMaridiaBeybladeTurtle_Func9 0xA29083 +#define fnMaridiaBeybladeTurtle_Func10 0xA290CC +#define fnMaridiaBeybladeTurtle_Func11 0xA290E1 +#define fnMiniMaridiaBeybladeTurtle_Main 0xA2912E +#define fnMiniMaridiaBeybladeTurtle_Func1 0xA29142 +#define fnMiniMaridiaBeybladeTurtle_Func2 0xA2916E +#define fnMiniMaridiaBeybladeTurtle_Func3 0xA29198 +#define fnMiniMaridiaBeybladeTurtle_Func4 0xA291F8 +#define fnMiniMaridiaBeybladeTurtle_Func6 0xA29239 +#define fnMiniMaridiaBeybladeTurtle_Func7 0xA2925E +#define fnMaridiaBeybladeTurtle_Touch 0xA29281 +#define fnMiniMaridiaBeybladeTurtle_Touch 0xA2929F +#define fnMiniMaridiaBeybladeTurtle_Shot 0xA2930F +#define fnMaridiaBeybladeTurtle_Instr_9381 0xA29381 +#define fnMaridiaBeybladeTurtle_Instr_9412 0xA29412 +#define fnMaridiaBeybladeTurtle_Instr_9447 0xA29447 +#define fnMaridiaBeybladeTurtle_Instr_9451 0xA29451 +#define fnMaridiaBeybladeTurtle_Instr_946B 0xA2946B +#define fnMaridiaBeybladeTurtle_Instr_9485 0xA29485 +#define fnMaridiaBeybladeTurtle_Instr_94A1 0xA294A1 +#define fnMaridiaBeybladeTurtle_Instr_94C7 0xA294C7 +#define fnMaridiaBeybladeTurtle_Instr_94D1 0xA294D1 +#define fnThinHoppingBlobs_Init 0xA29A3F +#define fnThinHoppingBlobs_Main 0xA29A7D +#define fnThinHoppingBlobs_Func1 0xA29A84 +#define fnThinHoppingBlobs_Func6 0xA29B65 +#define fnThinHoppingBlobs_Func7 0xA29B81 +#define fnThinHoppingBlobs_Func11 0xA29D0B +#define fnThinHoppingBlobs_Func12 0xA29D2B +#define fnThinHoppingBlobs_Func13 0xA29D4B +#define fnThinHoppingBlobs_Func14 0xA29D6B +#define fnThinHoppingBlobs_Func15 0xA29D98 +#define fnThinHoppingBlobs_Func16 0xA29DCD +#define fnSpikeShootingPlant_Instr_9F2A 0xA29F2A +#define fnSpikeShootingPlant_Init 0xA29F48 +#define fnSpikeShootingPlant_Main 0xA29FB3 +#define fnSpikeShootingPlant_2 0xA29FBA +#define fnSpikeShootingPlant_3 0xA29FEC +#define fnnullsub_182 0xA2A01B +#define fnSpikeShootingPlant_Instr_A095 0xA2A095 +#define fnSpikeShootingPlant_Instr_A0A7 0xA2A0A7 +#define fnMaridiaSpikeyShell_Init 0xA2A3F9 +#define fnMaridiaSpikeyShell_Main 0xA2A47E +#define fnMaridiaSpikeyShell_Instr_A56D 0xA2A56D +#define fnMaridiaSpikeyShell_Instr_A571 0xA2A571 +#define fnMaridiaSpikeyShell_Shot 0xA2A579 +#define fnGunshipTop_Init 0xA2A644 +#define fnGunshipBottom_Init 0xA2A6D2 +#define fnGunshipTop_Main 0xA2A759 +#define fnGunshipTop_1 0xA2A784 +#define fnnullsub_187 0xA2A7D7 +#define fnGunshipTop_2 0xA2A7D8 +#define fnGunshipTop_3 0xA2A80C +#define fnGunshipTop_4 0xA2A8D0 +#define fnGunshipTop_5 0xA2A942 +#define fnGunshipTop_6 0xA2A950 +#define fnGunshipTop_7 0xA2A987 +#define fnGunshipTop_8 0xA2A9BD +#define fnGunshipTop_9 0xA2AA4F +#define fnGunshipTop_10 0xA2AA5D +#define fnGunshipTop_11 0xA2AA94 +#define fnGunshipTop_12 0xA2AAA2 +#define fnGunshipTop_13 0xA2AB1F +#define fnGunshipTop_14 0xA2AB60 +#define fnGunshipTop_15 0xA2AB6E +#define fnGunshipTop_16 0xA2ABA5 +#define fnGunshipTop_17 0xA2ABC7 +#define fnGunshipTop_18 0xA2AC1B +#define fnGunshipTop_19 0xA2ACD7 +#define fnGunshipTop_20 0xA2AD0E +#define fnGunshipTop_21 0xA2AD2D +#define fnFlies_Init 0xA2B06B +#define fnFlies_Main 0xA2B11F +#define fnFlies_4 0xA2B14E +#define fnFlies_5 0xA2B17C +#define fnFlies_6 0xA2B1AA +#define fnFlies_7 0xA2B1D2 +#define fnNorfairErraticFireball_Init 0xA2B3E0 +#define fnNorfairErraticFireball_Main 0xA2B40F +#define fnLavaquakeRocks_Init 0xA2B570 +#define fnLavaquakeRocks_Main 0xA2B58F +#define fnLavaquakeRocks_1 0xA2B596 +#define fnLavaquakeRocks_2 0xA2B5B2 +#define fnLavaquakeRocks_3 0xA2B5EA +#define fnRinka_Init 0xA2B602 +#define fnRinka_Main 0xA2B7C4 +#define fnRinka_3 0xA2B7DF +#define fnRinka_4 0xA2B844 +#define fnRinka_5 0xA2B852 +#define fnRinka_B85B 0xA2B85B +#define fnRinka_Frozen 0xA2B929 +#define fnRinka_Touch 0xA2B947 +#define fnRinka_Shot 0xA2B94D +#define fnRinka_Powerbomb 0xA2B953 +#define fnRinka_Instr_B9B3 0xA2B9B3 +#define fnRinka_Instr_B9BD 0xA2B9BD +#define fnRinka_Instr_B9C7 0xA2B9C7 +#define fnEnemyInstr_Rio_Instr_1 0xA2BBC3 +#define fnRio_Init 0xA2BBCD +#define fnRio_Main 0xA2BBE3 +#define fnRio_1 0xA2BBED +#define fnRio_2 0xA2BC32 +#define fnRio_3 0xA2BC48 +#define fnRio_4 0xA2BCB7 +#define fnRio_5 0xA2BCFF +#define fnNorfairLavajumpingEnemy_Instr_BE8E 0xA2BE8E +#define fnNorfairLavajumpingEnemy_Init 0xA2BE99 +#define fnNorfairLavajumpingEnemy_Main 0xA2BED2 +#define fnNorfairLavajumpingEnemy_Func_1 0xA2BEDC +#define fnNorfairLavajumpingEnemy_Func_2 0xA2BF1A +#define fnNorfairLavajumpingEnemy_Func_3 0xA2BF3E +#define fnNorfairLavajumpingEnemy_Func_4 0xA2BF7C +#define fnNorfairLavajumpingEnemy_Func_5 0xA2BFBC +#define fnNorfairRio_Instr_C1C9 0xA2C1C9 +#define fnNorfairRio_Instr_C1D4 0xA2C1D4 +#define fnNorfairRio_Instr_C1DF 0xA2C1DF +#define fnNorfairRio_Instr_C1EA 0xA2C1EA +#define fnNorfairRio_Instr_C1F5 0xA2C1F5 +#define fnNorfairRio_Instr_C200 0xA2C200 +#define fnNorfairRio_Instr_C20B 0xA2C20B +#define fnNorfairRio_Instr_C216 0xA2C216 +#define fnNorfairRio_Instr_C221 0xA2C221 +#define fnNorfairRio_Instr_C22C 0xA2C22C +#define fnNorfairRio_Instr_C237 0xA2C237 +#define fnNorfairRio_Init 0xA2C242 +#define fnNorfairRio_Main 0xA2C277 +#define fnNorfairRio_Func_1 0xA2C281 +#define fnNorfairRio_Func_2 0xA2C2E7 +#define fnNorfairRio_Func_3 0xA2C33F +#define fnNorfairRio_Func_4 0xA2C361 +#define fnNorfairRio_Func_5 0xA2C3B1 +#define fnNorfairRio_Func_6 0xA2C406 +#define fnLowerNorfairRio_Instr_C6D2 0xA2C6D2 +#define fnLowerNorfairRio_Instr_C6DD 0xA2C6DD +#define fnLowerNorfairRio_Instr_C6E8 0xA2C6E8 +#define fnLowerNorfairRio_Init 0xA2C6F3 +#define fnLowerNorfairRio_Main 0xA2C724 +#define fnLowerNorfairRio_Func_1 0xA2C72E +#define fnLowerNorfairRio_Func_2 0xA2C771 +#define fnLowerNorfairRio_Func_3 0xA2C7BB +#define fnLowerNorfairRio_Func_4 0xA2C7D6 +#define fnLowerNorfairRio_Func_5 0xA2C82D +#define fnLowerNorfairRio_Func_6 0xA2C888 +#define fnMaridiaLargeSnail_Instr_CB6B 0xA2CB6B +#define fnMaridiaLargeSnail_Instr_CCB3 0xA2CCB3 +#define fnMaridiaLargeSnail_Instr_CCBE 0xA2CCBE +#define fnMaridiaLargeSnail_Instr_CCC9 0xA2CCC9 +#define fnMaridiaLargeSnail_Init 0xA2CCD4 +#define fnMaridiaLargeSnail_Main 0xA2CD13 +#define fnMaridiaLargeSnail_Func_1 0xA2CD23 +#define fnMaridiaLargeSnail_Func_4 0xA2CDE6 +#define fnMaridiaLargeSnail_Func_5 0xA2CE2B +#define fnMaridiaLargeSnail_Func_6 0xA2CF40 +#define fnMaridiaLargeSnail_Func_7 0xA2CF66 +#define fnMaridiaLargeSnail_Func_8 0xA2CFA9 +#define fnMaridiaLargeSnail_Func_12 0xA2D388 +#define fnMaridiaLargeSnail_Touch 0xA2D38C +#define fnMaridiaLargeSnail_Shot 0xA2D3B4 +#define fnHirisingSlowfalling_Init 0xA2DF76 +#define fnHirisingSlowfalling_Main 0xA2E02E +#define fnHirisingSlowfalling_Func_4 0xA2E035 +#define fnHirisingSlowfalling_Func_5 0xA2E04F +#define fnHirisingSlowfalling_Func_6 0xA2E06A +#define fnHirisingSlowfalling_Func_7 0xA2E0CD +#define fnGripper_Init 0xA2E1D3 +#define fnGripper_Main 0xA2E221 +#define fnJetPowerRipper_Init 0xA2E318 +#define fnJetPowerRipper_Main 0xA2E353 +#define fnJetPowerRipper_Shot 0xA2E3A9 +#define fnRipper_Init 0xA2E49F +#define fnRipper_Main 0xA2E4DA +#define fnLavaSeahorse_Instr_E5FB 0xA2E5FB +#define fnLavaSeahorse_Init 0xA2E606 +#define fnLavaSeahorse_Main 0xA2E64E +#define fnLavaSeahorse_Func_1 0xA2E654 +#define fnLavaSeahorse_Func_2 0xA2E6AD +#define fnLavaSeahorse_Func_3 0xA2E6F1 +#define fnLavaSeahorse_Func_4 0xA2E734 +#define fnLavaSeahorse_Func_5 0xA2E749 +#define fnnullsub_196 0xA2E781 +#define fnLavaSeahorse_Touch 0xA2E7C8 +#define fnLavaSeahorse_Shot 0xA2E7CE +#define fnLavaSeahorse_Powerbomb 0xA2E7D4 +#define fnTimedShutter_Init 0xA2E9DA +#define fnTimedShutter_Main 0xA2EAB6 +#define fnTimedShutter_Func_1 0xA2EABD +#define fnTimedShutter_Func_2 0xA2EAD1 +#define fnTimedShutter_Func_3 0xA2EAE7 +#define fnTimedShutter_Func_4 0xA2EAFD +#define fnTimedShutter_Func_5 0xA2EB11 +#define fnTimedShutter_Func_10 0xA2EC13 +#define fnRisingFallingPlatform_Init 0xA2EE05 +#define fnShootableShutter_Init 0xA2EE12 +#define fnRisingFallingPlatform_Func_1 0xA2EE1F +#define fnRisingFallingPlatform_Main 0xA2EED1 +#define fnRisingFallingPlatform_Func_2 0xA2EF09 +#define fnRisingFallingPlatform_Func_4 0xA2EF28 +#define fnRisingFallingPlatform_Func_9 0xA2EF68 +#define fnRisingFallingPlatform_Func_10 0xA2EFD4 +#define fnRisingFallingPlatform_Func_11 0xA2F040 +#define fnRisingFallingPlatform_Func_12 0xA2F072 +#define fnRisingFallingPlatform_Func_13 0xA2F099 +#define fnRisingFallingPlatform_Touch 0xA2F09D +#define fnRisingFallingPlatform_Shot 0xA2F0A2 +#define fnShootableShutter_Shot 0xA2F0AA +#define fnRisingFallingPlatform_Powerbomb 0xA2F0B6 +#define fnHorizontalShootableShutter_Init 0xA2F111 +#define fnHorizontalShootableShutter_Func_1 0xA2F11E +#define fnHorizontalShootableShutter_Main 0xA2F1DE +#define fnHorizontalShootableShutter_Func_2 0xA2F224 +#define fnHorizontalShootableShutter_Func_4 0xA2F243 +#define fnHorizontalShootableShutter_Func_8 0xA2F272 +#define fnHorizontalShootableShutter_Func_9 0xA2F2E4 +#define fnHorizontalShootableShutter_Func_12 0xA2F38C +#define fnHorizontalShootableShutter_Func_13 0xA2F3B0 +#define fnHorizontalShootableShutter_Func_14 0xA2F3D4 +#define fnHorizontalShootableShutter_Touch 0xA2F3D8 +#define fnHorizontalShootableShutter_Shot 0xA2F40E +#define fnHorizontalShootableShutter_Powerbomb 0xA2F41A +#define fnEnemy_GrappleReact_NoInteract_A3 0xA38000 +#define fnEnemy_GrappleReact_KillEnemy_A3 0xA3800A +#define fnEnemy_GrappleReact_CancelBeam_A3 0xA3800F +#define fnEnemy_NormalTouchAI_A3 0xA38023 +#define fnEnemy_NormalShotAI_A3 0xA3802D +#define fnEnemy_NormalPowerBombAI_A3 0xA38037 +#define fnEnemy_NormalFrozenAI_A3 0xA38041 +#define fnnullsub_170_A3 0xA3804C +#define fnEnemyInstr_Goto_A3 0xA380ED +#define fnEnemyInstr_Sleep_A3 0xA3812F +#define fnEnemyInstr_EnableOffScreenProcessing_A3 0xA38173 +#define fnEnemyInstr_DisableOffScreenProcessing_A3 0xA3817D +#define fnWaver_Instr_1 0xA386E3 +#define fnWaver_Init 0xA386ED +#define fnWaver_Main 0xA3874C +#define fnMetalee_Instr_1 0xA38956 +#define fnMetalee_Init 0xA38960 +#define fnMetalee_Main 0xA38979 +#define fnMetalee_Func_1 0xA38987 +#define fnMetalee_Func_3 0xA389D4 +#define fnMetalee_Func_4 0xA389F3 +#define fnMetalee_Func_5 0xA38A5C +#define fnMetalee_Shot 0xA38B0F +#define fnFireflea_Init 0xA38D2D +#define fnFireflea_Main 0xA38DEE +#define fnFireflea_Touch 0xA38E6B +#define fnFireflea_Powerbomb 0xA38E83 +#define fnFireflea_Shot 0xA38E89 +#define fnMaridiaFish_Instr_3 0xA39096 +#define fnMaridiaFish_Instr_1 0xA390A0 +#define fnMaridiaFish_Instr_2 0xA390AA +#define fnMaridiaFish_Init 0xA390B5 +#define fnMaridiaFish_Main 0xA3912B +#define fnMaridiaFish_Func_1 0xA39132 +#define fnMaridiaFish_Func_2 0xA391AB +#define fnMaridiaFish_Func_3 0xA39224 +#define fnMaridiaFish_Func_4 0xA39256 +#define fnElevator_Init 0xA394E6 +#define fnElevator_Frozen 0xA3952A +#define fnCrab_Init 0xA396E3 +#define fnSlug_Init 0xA3993B +#define fnPlatformThatFallsWithSamus_Instr_3 0xA39C6B +#define fnPlatformThatFallsWithSamus_Instr_4 0xA39C76 +#define fnPlatformThatFallsWithSamus_Instr_1 0xA39C81 +#define fnPlatformThatFallsWithSamus_Instr_2 0xA39C8C +#define fnPlatformThatFallsWithSamus_Init 0xA39C9F +#define fnFastMovingSlowSinkingPlatform_Init 0xA39CBA +#define fnPlatformThatFallsWithSamus_Main 0xA39D16 +#define fnnullsub_32 0xA39F07 +#define fnFastMovingSlowSinkingPlatform_Shot 0xA39F08 +#define fnRoach_Func_1 0xA3A12F +#define fnRoach_Init 0xA3A14D +#define fnRoach_Func_2 0xA3A183 +#define fnRoach_Main 0xA3A2D0 +#define fnRoach_Func_9 0xA3A2D7 +#define fnRoach_Func_10 0xA3A301 +#define fnRoach_Func_11 0xA3A30B +#define fnRoach_Func_12 0xA3A315 +#define fnRoach_Func_13 0xA3A325 +#define fnRoach_Func_14 0xA3A33B +#define fnRoach_Func_15 0xA3A34B +#define fnRoach_Func_16 0xA3A380 +#define fnRoach_Func_19 0xA3A407 +#define fnRoach_Func_20 0xA3A40E +#define fnRoach_Func_21 0xA3A440 +#define fnRoach_Func_22 0xA3A447 +#define fnRoach_Func_23 0xA3A44E +#define fnRoach_Func_24 0xA3A462 +#define fnRoach_Func_25 0xA3A476 +#define fnRoach_Func_26 0xA3A4B6 +#define fnRoach_Func_27 0xA3A4F0 +#define fnMochtroid_Init 0xA3A77D +#define fnMochtroid_Main 0xA3A790 +#define fnMochtroid_Touch 0xA3A953 +#define fnMochtroid_Shot 0xA3A9A8 +#define fnSidehopper_Func_1 0xA3AA68 +#define fnSidehopper_Instr_1 0xA3AAFE +#define fnSidehopper_Init 0xA3AB09 +#define fnSidehopper_Main 0xA3ABCF +#define fnSidehopper_Func_4 0xA3ABD6 +#define fnSidehopper_Func_5 0xA3ABE6 +#define fnSidehopper_Func_6 0xA3AC13 +#define fnSidehopper_Func_7 0xA3AC40 +#define fnSidehopper_Func_8 0xA3AC56 +#define fnSidehopper_Func_9 0xA3AC6C +#define fnSidehopper_Func_10 0xA3AC8F +#define fnSidehopper_Func_11 0xA3ACA8 +#define fnSidehopper_Func_12 0xA3ACCB +#define fnSidehopper_Func_13 0xA3ACE4 +#define fnSidehopper_Func_14 0xA3AD0E +#define fnSidehopper_Func_15 0xA3AD20 +#define fnSidehopper_Func_16 0xA3AD32 +#define fnSidehopper_Func_17 0xA3AD44 +#define fnSidehopper_Func_18 0xA3AD56 +#define fnMaridiaRefillCandy_Instr_1 0xA3B429 +#define fnMaridiaRefillCandy_Instr_2 0xA3B434 +#define fnMaridiaRefillCandy_Instr_3 0xA3B43F +#define fnMaridiaRefillCandy_Init 0xA3B44A +#define fnMaridiaRefillCandy_Main 0xA3B47C +#define fnMaridiaRefillCandy_Func_1 0xA3B482 +#define fnMaridiaRefillCandy_Func_2 0xA3B4A8 +#define fnMaridiaRefillCandy_Func_3 0xA3B4D6 +#define fnNorfairSlowFireball_Init 0xA3B66F +#define fnBang_Instr_1 0xA3BA78 +#define fnBang_Instr_2 0xA3BAA8 +#define fnBang_Init 0xA3BAB3 +#define fnBang_Main 0xA3BB25 +#define fnBang_Func_1 0xA3BB2B +#define fnBang_Func_6 0xA3BCA5 +#define fnBang_Func_7 0xA3BCC1 +#define fnBang_Func_8 0xA3BCC5 +#define fnBang_Func_10 0xA3BD1C +#define fnBang_Func_11 0xA3BD2C +#define fnBang_Shot 0xA3BEFD +#define fnSkree_Instr_1 0xA3C6A4 +#define fnSkree_Init 0xA3C6AE +#define fnSkree_Main 0xA3C6C7 +#define fnSkree_Func_1 0xA3C6D5 +#define fnSkree_Func_2 0xA3C6F7 +#define fnSkree_Func_3 0xA3C716 +#define fnSkree_Func_4 0xA3C77F +#define fnSkree_Shot 0xA3C7F5 +#define fnMaridiaSnail_Instr_1 0xA3CC36 +#define fnMaridiaSnail_Instr_2 0xA3CC3F +#define fnMaridiaSnail_Instr_4 0xA3CC48 +#define fnMaridiaSnail_Instr_3 0xA3CC5F +#define fnMaridiaSnail_Instr_5 0xA3CC78 +#define fnMaridiaSnail_Func_1 0xA3CC92 +#define fnMaridiaSnail_Init 0xA3CDE2 +#define fnMaridiaSnail_Main 0xA3CE64 +#define fnnullsub_215 0xA3CF5F +#define fnMaridiaSnail_Func_7 0xA3CF60 +#define fnMaridiaSnail_Func_9 0xA3CFA6 +#define fnMaridiaSnail_CFB7 0xA3CFB7 +#define fnMaridiaSnail_CFBD 0xA3CFBD +#define fnMaridiaSnail_CFCE 0xA3CFCE +#define fnMaridiaSnail_CFD4 0xA3CFD4 +#define fnMaridiaSnail_CFE5 0xA3CFE5 +#define fnMaridiaSnail_CFEB 0xA3CFEB +#define fnMaridiaSnail_CFFC 0xA3CFFC +#define fnMaridiaSnail_Func_15 0xA3D1B3 +#define fnMaridiaSnail_Touch 0xA3D3B0 +#define fnMaridiaSnail_Shot 0xA3D469 +#define fnReflec_Func_1 0xA3DB0C +#define fnReflec_Instr_1 0xA3DBC8 +#define fnReflec_Init 0xA3DBD3 +#define fnnullsub_33 0xA3DC1B +#define fnReflec_Shot 0xA3DC1C +#define fnWreckedShipOrangeZoomer_Func_1 0xA3DFC2 +#define fnWreckedShipOrangeZoomer_Init 0xA3E043 +#define fnnullsub_343 0xA3E08A +#define fnWreckedShipOrangeZoomer_Main 0xA3E08B +#define fnsub_A3E168 0xA3E168 +#define fnBigEyeBugs_Init 0xA3E2D4 +#define fnFireZoomer_Init 0xA3E59C +#define fnZoomer_Instr_SetPreinstr 0xA3E660 +#define fnStoneZoomer_Init 0xA3E669 +#define fnnullsub_304 0xA3E6C1 +#define fnStoneZoomer_Main 0xA3E6C2 +#define fnFireZoomer_Func_1 0xA3E6C8 +#define fnFireZoomer_Func_2 0xA3E785 +#define fnFireZoomer_Func_3 0xA3E7F2 +#define fnMetroid_Init 0xA3EA4F +#define fnMetroid_Instr_2 0xA3EAA5 +#define fnMetroid_Instr_1 0xA3EAB1 +#define fnMetroid_Frozen 0xA3EAE6 +#define fnMetroid_Hurt 0xA3EB33 +#define fnMetroid_Main 0xA3EB98 +#define fnMetroid_Touch 0xA3EDEB +#define fnMetroid_Shot 0xA3EF07 +#define fnMetroid_Powerbomb 0xA3F042 +#define fnEnemy_GrappleReact_SamusLatchesOn_A4 0xA48005 +#define fnEnemy_NormalTouchAI_A4 0xA48023 +#define fnEnemy_NormalShotAI_A4 0xA4802D +#define fnEnemy_NormalPowerBombAI_A4 0xA48037 +#define fnEnemy_NormalFrozenAI_A4 0xA48041 +#define fnnullsub_170_A4 0xA4804C +#define fnEnemyInstr_Goto_A4 0xA480ED +#define fnEnemyInstr_Sleep_A4 0xA4812F +#define fnCrocomire_Hurt 0xA48687 +#define fnCrocomire_Instr_1 0xA486A6 +#define fnCrocomire_Instr_14 0xA48752 +#define fnCrocomire_Func_9 0xA487CA +#define fnCrocomire_Init 0xA48A5A +#define fnCrocomire_Main 0xA48C04 +#define fnCrocomire_Instr_11 0xA48CFB +#define fnCrocomire_Instr_7 0xA48D07 +#define fnCrocomire_Instr_19 0xA48D13 +#define fnCrocomire_Instr_2 0xA48FC7 +#define fnCrocomire_Instr_4 0xA48FDF +#define fnCrocomire_Instr_3 0xA48FFA +#define fnCrocomire_Instr_15 0xA48FFF +#define fnCrocomire_Instr_16 0xA4901D +#define fnCrocomire_Instr_13 0xA4905B +#define fnCrocomire_Instr_18 0xA4907F +#define fnCrocomire_Instr_12 0xA4908F +#define fnCrocomire_Instr_17 0xA49094 +#define fnnullsub_309 0xA4943C +#define fnCrocomire_Instr_8 0xA49A9B +#define fnCrocomire_Instr_6 0xA49AA0 +#define fnCrocomire_Instr_9 0xA49AA5 +#define fnCrocomire_Instr_5 0xA49AAA +#define fnCrocomire_Instr_20 0xA49AAF +#define fnCrocomire_Instr_21 0xA49AB4 +#define fnCrocomire_Instr_22 0xA49AB9 +#define fnCrocomire_Instr_23 0xA49ABE +#define fnCrocomire_Instr_24 0xA49AC3 +#define fnCrocomire_Instr_10 0xA49AC8 +#define fnCrocomire_Instr_25 0xA49ACD +#define fnCrocomire_Instr_26 0xA49AD2 +#define fnCrocomire_Instr_27 0xA49AD7 +#define fnCrocomire_Func_92 0xA4B93D +#define fnnullsub_34 0xA4B950 +#define fnCrocomire_Func_93 0xA4B951 +#define fnCrocomire_Func_94 0xA4B968 +#define fnCrocomire_Powerbomb 0xA4B992 +#define fnCrocomire_Func_95 0xA4BA05 +#define fnCrocomire_Func_1 0xA4BAB4 +#define fnCrocomireTongue_Init 0xA4F67A +#define fnCrocomireTongue_Main 0xA4F6BB +#define fnEnemy_GrappleReact_NoInteract_A5 0xA58000 +#define fnEnemy_GrappleReact_CancelBeam_A5 0xA5800F +#define fnEnemy_NormalTouchAI_A5 0xA58023 +#define fnEnemy_NormalShotAI_A5 0xA5802D +#define fnEnemy_NormalPowerBombAI_A5 0xA58037 +#define fnEnemy_NormalFrozenAI_A5 0xA58041 +#define fnCreateADudShot_A5 0xA58046 +#define fnnullsub_169_A5 0xA5804B +#define fnnullsub_170_A5 0xA5804C +#define fnEnemyInstr_StopScript_A5 0xA5807C +#define fnEnemyInstr_Goto_A5 0xA580ED +#define fnEnemyInstr_DecTimerAndGoto2_A5 0xA58110 +#define fnEnemyInstr_SetTimer_A5 0xA58123 +#define fnEnemyInstr_Sleep_A5 0xA5812F +#define fnEnemyInstr_WaitNframes_A5 0xA5813A +#define fnDraygon_Init 0xA58687 +#define fnDraygon_Main 0xA586FC +#define fnDraygon_Func_1 0xA5871B +#define fnDraygon_Func_2 0xA5878B +#define fnDraygon_Func_3 0xA587AA +#define fnDraygon_Func_4 0xA587F4 +#define fnDraygon_Func_6 0xA588B1 +#define fnDraygon_Func_8 0xA58922 +#define fnDraygon_Func_9 0xA58951 +#define fnDraygon_Func_10 0xA589B3 +#define fnDraygon_Func_11 0xA58A00 +#define fnDraygon_Func_12 0xA58A50 +#define fnDraygon_Func_13 0xA58A90 +#define fnDraygon_Func_14 0xA58B0A +#define fnDraygon_Func_15 0xA58B52 +#define fnDraygon_Func_16 0xA58BAE +#define fnDraygon_Func_17 0xA58C33 +#define fnDraygon_Func_18 0xA58C8E +#define fnDraygon_Func_19 0xA58CD4 +#define fnDraygon_Func_20 0xA58D30 +#define fnDraygon_Func_21 0xA58DB2 +#define fnDraygon_Func_22 0xA58E19 +#define fnDraygon_Func_23 0xA58F10 +#define fnDraygon_Func_24 0xA58F1E +#define fnDraygon_Func_25 0xA58FD6 +#define fnDraygon_Func_26 0xA590D4 +#define fnDraygon_Func_27 0xA59105 +#define fnDraygon_Func_28 0xA59124 +#define fnDraygon_Func_29 0xA59128 +#define fnDraygon_Func_30 0xA59154 +#define fnDraygon_Func_31 0xA59185 +#define fnDraygon_Func_32 0xA59294 +#define fnDraygon_Func_33 0xA592AB +#define fnDraygon_Func_36 0xA59342 +#define fnDraygon_Instr_1 0xA594DD +#define fnDraygon_Hurt 0xA5954D +#define fnDraygon_Touch 0xA595EA +#define fnDraygon_Shot 0xA595F0 +#define fnDraygon_Powerbomb 0xA59607 +#define fnDraygon_Instr_13 0xA59736 +#define fnDraygon_Instr_8 0xA5973F +#define fnDraygon_Instr_7 0xA59752 +#define fnDraygon_Instr_6 0xA59765 +#define fnDraygon_Instr_9 0xA59778 +#define fnDraygon_Instr_2 0xA59895 +#define fnDraygon_Instr_11 0xA598D3 +#define fnDraygon_Instr_5 0xA598EF +#define fnDraygon_Instr_15 0xA59B9A +#define fnDraygon_Instr_17 0xA59C8A +#define fnDraygon_Instr_14 0xA59E0A +#define fnDraygon_Instr_16 0xA59F57 +#define fnDraygon_Instr_10 0xA59F60 +#define fnDraygon_Instr_4 0xA59F6E +#define fnDraygon_Instr_12 0xA59F7C +#define fnDraygon_Instr_18 0xA59FAE +#define fnDraygonsEye_Init 0xA5C46B +#define fnDraygon_Instr_3 0xA5C47B +#define fnDraygonsEye_Main 0xA5C486 +#define fnDraygon_Func_48 0xA5C48D +#define fnDraygon_Func_49 0xA5C513 +#define fnDraygonsTail_Init 0xA5C599 +#define fnnullsub_37 0xA5C5AA +#define fnDraygonsArms_Init 0xA5C5AD +#define fnnullsub_38 0xA5C5C4 +#define fnDraygon_Instr_25 0xA5E75F +#define fnDraygon_Instr_24 0xA5E771 +#define fnDraygon_Instr_21 0xA5E82D +#define fnDraygon_Instr_22 0xA5E872 +#define fnDraygon_Instr_27 0xA5E87C +#define fnDraygon_Instr_23 0xA5E895 +#define fnDraygon_Instr_30 0xA5E8B1 +#define fnDraygon_Instr_20 0xA5E8BA +#define fnDraygon_Instr_29 0xA5E8CA +#define fnDraygon_Instr_19 0xA5E91C +#define fnDraygon_Instr_28 0xA5E96E +#define fnDraygon_Instr_26 0xA5E9B1 +#define fnSporeSpawn_Init 0xA5EA2A +#define fnSporeSpawn_Main 0xA5EB13 +#define fnnullsub_223 0xA5EB1A +#define fnSporeSpawn_Func_1 0xA5EB1B +#define fnSporeSpawn_Func_2 0xA5EB52 +#define fnSporeSpawn_Func_3 0xA5EB9B +#define fnSporeSpawn_Func_4 0xA5EBEE +#define fnSporeSpawn_Shot 0xA5ED5A +#define fnSporeSpawn_Touch 0xA5EDEC +#define fnnullsub_39 0xA5EDF2 +#define fnEnemy_GrappleReact_NoInteract_A6 0xA68000 +#define fnEnemy_GrappleReact_CancelBeam_A6 0xA6800F +#define fnEnemy_NormalTouchAI_A6 0xA68023 +#define fnEnemy_NormalShotAI_A6 0xA6802D +#define fnEnemy_NormalPowerBombAI_A6 0xA68037 +#define fnEnemy_NormalFrozenAI_A6 0xA68041 +#define fnnullsub_170_A6 0xA6804C +#define fnEnemyInstr_Goto_A6 0xA680ED +#define fnEnemyInstr_Sleep_A6 0xA6812F +#define fnBoulder_Init 0xA686F5 +#define fnBoulder_Main 0xA68793 +#define fnBoulder_Func_1 0xA6879A +#define fnBoulder_Func_2 0xA687ED +#define fnBoulder_Func_3 0xA68832 +#define fnBoulder_Func_4 0xA6888B +#define fnBoulder_Func_5 0xA68942 +#define fnBoulder_Func_6 0xA689FC +#define fnSpikeyPlatform_Init 0xA68B2F +#define fnSpikeyPlatform2ndEnemy_Init 0xA68B85 +#define fnSpikeyPlatform2ndEnemy_Main 0xA68B99 +#define fnSpikeyPlatform_Main 0xA68BAD +#define fnSpikeyPlatform_Func_1 0xA68BB4 +#define fnSpikeyPlatform_Func_2 0xA68BDC +#define fnSpikeyPlatform_Func_3 0xA68C4A +#define fnSpikeyPlatform_Func_4 0xA68C5D +#define fnFireGeyser_Instr_1 0xA68DAF +#define fnFireGeyser_Instr_2 0xA68E13 +#define fnFireGeyser_Instr_3 0xA68E2D +#define fnFireGeyser_Instr_4 0xA68E41 +#define fnFireGeyser_Instr_5 0xA68E55 +#define fnFireGeyser_Instr_6 0xA68E69 +#define fnFireGeyser_Instr_7 0xA68E7D +#define fnFireGeyser_Instr_8 0xA68E91 +#define fnFireGeyser_Instr_9 0xA68EA5 +#define fnFireGeyser_Instr_10 0xA68EB9 +#define fnFireGeyser_Instr_11 0xA68ECD +#define fnFireGeyser_Instr_12 0xA68EE1 +#define fnFireGeyser_Instr_13 0xA68EF5 +#define fnFireGeyser_Instr_14 0xA68F09 +#define fnFireGeyser_Instr_15 0xA68F1D +#define fnFireGeyser_Instr_16 0xA68F31 +#define fnFireGeyser_Instr_17 0xA68F45 +#define fnFireGeyser_Instr_18 0xA68F59 +#define fnFireGeyser_Instr_19 0xA68F6D +#define fnFireGeyser_Instr_20 0xA68F81 +#define fnFireGeyser_Instr_21 0xA68F95 +#define fnFireGeyser_Instr_22 0xA68FA9 +#define fnFireGeyser_Instr_23 0xA68FBD +#define fnFireGeyser_Instr_24 0xA68FD1 +#define fnFireGeyser_Init 0xA68FFC +#define fnFireGeyser_Main 0xA69023 +#define fnFireGeyser_Func_1 0xA6902F +#define fnFireGeyser_Func_2 0xA69062 +#define fnNuclearWaffle_Init 0xA694C4 +#define fnNuclearWaffle_Main 0xA6960E +#define fnNuclearWaffle_Func_1 0xA69615 +#define fnNuclearWaffle_Func_2 0xA69682 +#define fnFakeKraid_Init 0xA69A58 +#define fnFakeKraid_Main 0xA69AC2 +#define fnFakeKraid_Instr_2 0xA69B26 +#define fnFakeKraid_Instr_1 0xA69B74 +#define fnFakeKraid_Instr_3 0xA69BB2 +#define fnFakeKraid_Instr_4 0xA69BC4 +#define fnFakeKraid_Instr_5 0xA69C02 +#define fnFakeKraid_Touch 0xA69C22 +#define fnFakeKraid_Shot 0xA69C39 +#define fnCeresRidley_Init 0xA6A0F5 +#define fnCeresRidley_Main 0xA6A288 +#define fnCeresRidley_Func_1 0xA6A2BD +#define fnCeresRidley_Hurt 0xA6A2D3 +#define fnRidley_A2F2 0xA6A2F2 +#define fnCeresRidley_Func_2 0xA6A354 +#define fnCeresRidley_Func_3 0xA6A35B +#define fnCeresRidley_A377 0xA6A377 +#define fnCeresRidley_Func_4 0xA6A389 +#define fnCeresRidley_Func_5 0xA6A3DF +#define fnCeresRidley_Func_6 0xA6A455 +#define fnCeresRidley_Func_7 0xA6A478 +#define fnCeresRidley_Func_9 0xA6A6AF +#define fnCeresRidley_Func_10 0xA6A6C8 +#define fnCeresRidley_Func_11 0xA6A6E8 +#define fnCeresRidley_Func_13 0xA6A782 +#define fnCeresRidley_A7F9 0xA6A7F9 +#define fnCeresRidley_Func_14 0xA6A83C +#define fnCeresRidley_Func_15 0xA6A84E +#define fnCeresRidley_Func_16 0xA6A88D +#define fnCeresRidley_Func_17 0xA6A8A4 +#define fnCeresRidley_Func_18 0xA6A8D4 +#define fnCeresRidley_Func_19 0xA6A8F8 +#define fnCeresRidley_Func_20 0xA6A923 +#define fnCeresRidley_Func_21 0xA6A947 +#define fnCeresRidley_Func_22 0xA6A971 +#define fnCeresRidley_Func_23 0xA6A9A0 +#define fnCeresRidley_Func_24 0xA6AA11 +#define fnnullsub_233 0xA6AA4F +#define fnCeresRidley_Func_26 0xA6AA50 +#define fnRidley_Main 0xA6B227 +#define fnRidley_Func_1 0xA6B26F +#define fnRidley_Func_2 0xA6B28A +#define fnRidley_Hurt 0xA6B297 +#define fnRidley_Func_3 0xA6B2F3 +#define fnRidley_Func_3b 0xA6B321 +#define fnRidley_Func_4 0xA6B335 +#define fnRidley_Func_5 0xA6B3EC +#define fnRidley_Func_6 0xA6B3F8 +#define fnRidley_Func_8 0xA6B441 +#define fnRidley_B455 0xA6B455 +#define fnRidley_Func_9 0xA6B493 +#define fnRidley_Func_10 0xA6B4D1 +#define fnRidley_Func_11 0xA6B516 +#define fnRidley_Func_12 0xA6B554 +#define fnRidley_Func_13 0xA6B594 +#define fnRidley_Func_14 0xA6B5C4 +#define fnRidley_Func_15 0xA6B5E5 +#define fnRidley_Func_16 0xA6B613 +#define fnRidley_Func_19 0xA6B6A7 +#define fnRidley_Func_20 0xA6B6DD +#define fnRidley_Func_21 0xA6B70E +#define fnRidley_Func_22 0xA6B7B9 +#define fnRidley_Func_33 0xA6BAB7 +#define fnRidley_Func_33b 0xA6BB8F +#define fnRidley_Func_34 0xA6BBC4 +#define fnRidley_Func_35 0xA6BBF1 +#define fnRidley_Func_36 0xA6BC2E +#define fnRidley_Func_43 0xA6BD4E +#define fnRidley_Func_44 0xA6BD9A +#define fnRidley_Func_45 0xA6BDBC +#define fnRidley_Func_46 0xA6BDF2 +#define fnRidley_Func_47 0xA6BE03 +#define fnRidley_Func_50 0xA6BE9C +#define fnRidley_Func_51 0xA6BEB3 +#define fnRidley_Func_52 0xA6BECA +#define fnRidley_Func_53 0xA6BEDC +#define fnnullsub_348 0xA6BF19 +#define fnBabyMetroid_Instr_2 0xA6BFC9 +#define fnBabyMetroid_Instr_3 0xA6BFE1 +#define fnBabyMetroid_Instr_1 0xA6BFF2 +#define fnBabyMetroid_Instr_4 0xA6BFF8 +#define fnRidley_Func_54 0xA6C04E +#define fnRidley_Func_63 0xA6C538 +#define fnRidley_C53E 0xA6C53E +#define fnRidley_C551 0xA6C551 +#define fnRidley_Func_64 0xA6C588 +#define fnRidley_Func_65 0xA6C5A8 +#define fnRidley_Func_66 0xA6C5C8 +#define fnRidley_Func_67 0xA6C5DA +#define fnnullsub_349 0xA6C600 +#define fnRidleysExplosion_Init 0xA6C696 +#define fnRidleysExplosion_Main 0xA6C8D4 +#define fnRidley_Func_79 0xA6CC39 +#define fnRidley_Func_81 0xA6CCBD +#define fnRidley_Func_83 0xA6CD24 +#define fnRidley_Func_84 0xA6CDAA +#define fnsub_A6DF59 0xA6DF59 +#define fnRidley_Shot 0xA6DF8A +#define fnRidley_Powerbomb 0xA6DFB2 +#define fnRidley_Instr_5 0xA6E4BE +#define fnRidley_Instr_6 0xA6E4CA +#define fnRidley_Instr_10 0xA6E4D2 +#define fnRidley_Instr_4 0xA6E4EE +#define fnRidley_Instr_3 0xA6E4F8 +#define fnRidley_Instr_2 0xA6E501 +#define fnRidley_Instr_1 0xA6E517 +#define fnRidley_Instr_14 0xA6E51F +#define fnRidley_Instr_9 0xA6E71C +#define fnRidley_Instr_7 0xA6E727 +#define fnRidley_Instr_8 0xA6E72F +#define fnRidley_Instr_11 0xA6E84D +#define fnRidley_Instr_12 0xA6E904 +#define fnRidley_Instr_13 0xA6E909 +#define fnRidley_Instr_15 0xA6E969 +#define fnRidley_Instr_16 0xA6E976 +#define fnCeresSteam_Init 0xA6EFB1 +#define fnnullsub_350 0xA6EFF4 +#define fnCeresSteam_Main 0xA6F00D +#define fnCeresSteam_Func_1 0xA6F019 +#define fnCeresSteam_Touch 0xA6F03F +#define fnCeresSteam_Instr_1 0xA6F11D +#define fnCeresSteam_Instr_2 0xA6F127 +#define fnCeresSteam_Instr_3 0xA6F135 +#define fnCeresDoor_Instr_6 0xA6F63E +#define fnCeresDoor_Instr_4 0xA6F66A +#define fnCeresDoor_Instr_8 0xA6F678 +#define fnCeresSteam_Instr_4 0xA6F68B +#define fnCeresDoor_Instr_1 0xA6F695 +#define fnCeresDoor_Instr_3 0xA6F69F +#define fnCeresSteam_Instr_5 0xA6F6A6 +#define fnCeresDoor_Instr_5 0xA6F6B0 +#define fnCeresDoor_Instr_2 0xA6F6B3 +#define fnCeresDoor_Instr_7 0xA6F6BD +#define fnCeresDoor_Init 0xA6F6C5 +#define fnCeresDoor_Main 0xA6F765 +#define fnCeresDoor_Func_2 0xA6F76B +#define fnCeresDoor_Func_3 0xA6F770 +#define fnCeresDoor_Func_4 0xA6F7A5 +#define fnCeresDoor_Func_5 0xA6F7BD +#define fnCeresDoor_Func_6 0xA6F7DC +#define fnCeresDoor_Func_7 0xA6F850 +#define fnnullsub_41 0xA6F920 +#define fnZebetites_Init 0xA6FB72 +#define fnZebetites_Main 0xA6FC33 +#define fnZebetites_Func_1 0xA6FC41 +#define fnZebetites_Func_2 0xA6FC5B +#define fnZebetites_Func_3 0xA6FC67 +#define fnZebetites_Touch 0xA6FDA7 +#define fnZebetites_Shot 0xA6FDAC +#define fnEnemy_GrappleReact_NoInteract_A7 0xA78000 +#define fnEnemy_GrappleReact_CancelBeam_A7 0xA7800F +#define fnEnemy_NormalShotAI_A7 0xA7802D +#define fnEnemy_NormalPowerBombAI_A7 0xA78037 +#define fnEnemy_NormalPowerBombAI_SkipDeathAnim_A7 0xA7803C +#define fnEnemy_NormalFrozenAI_A7 0xA78041 +#define fnnullsub_170_A7 0xA7804C +#define fnEnemyInstr_Call_A7 0xA7808A +#define fnEnemyInstr_Goto_A7 0xA780ED +#define fnEnemyInstr_DecTimerAndGoto2_A7 0xA78110 +#define fnEnemyInstr_SetTimer_A7 0xA78123 +#define fnEnemyInstr_Sleep_A7 0xA7812F +#define fnKraid_Instr_9 0xA78A8F +#define fnKraid_Touch_ArmFoot 0xA7948B +#define fnnullsub_44 0xA7948F +#define fnKraidsArm_Touch 0xA79490 +#define fnKraid_Touch 0xA7949F +#define fnKraid_Shot 0xA794B1 +#define fnnullsub_43 0xA794B5 +#define fnKraid_Arm_Shot 0xA794B6 +#define fnKraid_Init 0xA7A959 +#define fnKraidsArm_Init 0xA7AB43 +#define fnKraidsTopLint_Init 0xA7AB68 +#define fnKraidsMiddleLint_Init 0xA7AB9C +#define fnKraidsBottomLint_Init 0xA7ABCA +#define fnKraidsFoot_Init 0xA7ABF8 +#define fnKraid_Main 0xA7AC21 +#define fnKraid_GetsBig_BreakCeilingPlatforms 0xA7AC4D +#define fnKraid_GetsBig_SetBG2TilemapPrioBits 0xA7AD3A +#define fnKraid_GetsBig_FinishUpdateBg2Tilemap 0xA7AD61 +#define fnKraid_GetsBig_DrawRoomBg 0xA7AD8E +#define fnKraid_GetsBig_FadeInRoomBg 0xA7AE23 +#define fnKraid_Mainloop_Thinking 0xA7AEA4 +#define fnKraid_GetsBig_Thinking 0xA7AEC4 +#define fnKraid_Shot_MouthIsOpen 0xA7AEE4 +#define fnKraidInstr_PlayRoarSfx 0xA7AF94 +#define fnKraidInstr_PlayDyingSfx 0xA7AF9F +#define fnKraid_Shot_Mouth 0xA7AFAA +#define fnKraid_Instr_1 0xA7B633 +#define fnKraid_Instr_DecYpos 0xA7B636 +#define fnKraid_Instr_IncrYpos_Shake 0xA7B63C +#define fnKraid_Instr_PlaySound_0x76 0xA7B64E +#define fnKraid_Instr_XposMinus3 0xA7B65A +#define fnKraid_Instr_XposMinus3b 0xA7B667 +#define fnKraid_Instr_XposPlus3 0xA7B674 +#define fnKraid_Instr_MoveHimRight 0xA7B683 +#define fnKraid_InitEyeGlowing 0xA7B6BF +#define fnKraid_Shot_GlowHisEye 0xA7B6D7 +#define fnKraid_Shot_UnglowEye 0xA7B73D +#define fnKraidsArm_Main 0xA7B7BD +#define fnKraidsTopLint_Main 0xA7B801 +#define fnKraidsMiddleLint_Main 0xA7B80D +#define fnKraidsBottomLint_Main 0xA7B819 +#define fnnullsub_347 0xA7B831 +#define fnKraidLint_ProduceLint 0xA7B832 +#define fnKraidLint_ChargeLint 0xA7B868 +#define fnKraidLint_FireLint 0xA7B89B +#define fnKraidFingernail_WaitForLintXpos 0xA7B907 +#define fnKraid_AlignEnemyToKraid 0xA7B923 +#define fnKraidEnemy_HandleFunctionTimer 0xA7B92D +#define fnKraidEnemy_DecrementEnemyFunctionTimer 0xA7B93F +#define fnKraidFoot_FirstPhase_Thinking 0xA7B960 +#define fnKraidEnemy_ProcessInstrEnemyTimer 0xA7B965 +#define fnKraidsFoot_Main 0xA7B9F6 +#define fnnullsub_234 0xA7BA2D +#define fnKraidsFoot_SecondPhase_Thinking 0xA7BA2E +#define fnKraidsFoot_SecondPhase_WalkingBackwards 0xA7BB45 +#define fnKraidsFoot_SecondPhaseSetup_WalkToStartPt 0xA7BB6E +#define fnKraidsFoot_SecondPhase_Init 0xA7BBA4 +#define fnKraidsFoot_SecondPhase_WalkForward 0xA7BBAE +#define fnKraid_Main_AttackWithMouthOpen 0xA7BBEA +#define fnKraidsGoodFingernail_Touch 0xA7BCCF +#define fnKraidsBadFingernail_Touch 0xA7BCDE +#define fnKraidsGoodFingernail_Init 0xA7BCEF +#define fnKraidsBadFingernail_Init 0xA7BD2D +#define fnKraidsGoodFingernail_Main 0xA7BD32 +#define fnKraidsBadFingernail_Main 0xA7BD49 +#define fnKraidsFingernail_Init 0xA7BD60 +#define fnKraidsFingernail_Fire 0xA7BE8E +#define fnKraidsFoot_PrepareToLungeForward 0xA7BF2D +#define fnKraidsFoot_FirstPhase_LungeForward 0xA7BF5D +#define fnKraidsFoot_FirstPhase_RetreatFromLunge 0xA7BFAB +#define fnKraid_GetsBig_ReleaseCamera 0xA7C0A1 +#define fnUnpauseHook_Kraid_IsDead 0xA7C1FB +#define fnUnpauseHook_Kraid_IsAlive 0xA7C24E +#define fnKraid_UnpauseHook_IsSinking 0xA7C2A0 +#define fnPauseHook_Kraid 0xA7C325 +#define fnKraid_Death_Init 0xA7C360 +#define fnKraid_Death_Fadeout 0xA7C3F9 +#define fnKraid_Death_UpdateBG2TilemapTopHalf 0xA7C4A4 +#define fnKraid_Death_UpdateBG2TilemapBottomHalf 0xA7C4C8 +#define fnKraid_Death_SinkThroughFloor 0xA7C537 +#define fnKraid_CrumbleLeftPlatform_Left 0xA7C691 +#define fnnullsub_356 0xA7C6A6 +#define fnKraid_CrumbleRightPlatform_Middle 0xA7C6A7 +#define fnKraid_CrumbleRightPlatform_Left 0xA7C6BD +#define fnKraid_CrumbleLeftPlatform_Right 0xA7C6D3 +#define fnKraid_CrumbleLeftPlatform_Middle 0xA7C6E9 +#define fnKraid_CrumbleRightPlatform_Right 0xA7C6FF +#define fnKraid_FadeInBg_ClearBg2TilemapTopHalf 0xA7C715 +#define fnKraid_FadeInBg_ClearBg2TilemapBottomHalf 0xA7C751 +#define fnKraid_FadeInBg_LoadBg3Tiles1of4 0xA7C777 +#define fnKraid_FadeInBg_LoadBg3Tiles2of4 0xA7C7A3 +#define fnKraid_FadeInBg_LoadBg3Tiles3of4 0xA7C7C9 +#define fnKraid_FadeInBg_LoadBg3Tiles4of4 0xA7C7EF +#define fnKraid_FadeInBg_FadeInBp6 0xA7C815 +#define fnKraid_FadeInBg_SetEnemyDead_KraidWasAlive 0xA7C843 +#define fnKraid_FadeInBg_SetEnemyDead_KraidWasDead 0xA7C851 +#define fnKraid_RestrictSamusXtoFirstScreen 0xA7C865 +#define fnKraid_RaiseKraidThroughFloor 0xA7C86B +#define fnKraid_Raise_LoadTilemapBottomAndShake 0xA7C89A +#define fnKraid_Raise_SpawnRandomEarthquakeProjs16 0xA7C8E0 +#define fnKraid_Raise_SpawnRandomEarthquakeProjs8 0xA7C902 +#define fnKraid_Raise_Handler 0xA7C924 +#define fnPhantoon_Init 0xA7CDF3 +#define fnPhantoon2_Init 0xA7CE55 +#define fnPhantoon_Main 0xA7CEA6 +#define fnPhantoon_Func_1 0xA7CEED +#define fnPhantoon_Func_4 0xA7CF5E +#define fnPhantoon_StartTrackingSamusAndInitEyeTimer 0xA7D03F +#define fnPhantoon_PickPatternForRound2 0xA7D076 +#define fnPhantoon_FadeOut 0xA7D464 +#define fnPhantoon_FadeIn 0xA7D486 +#define fnnullsub_237 0xA7D4A8 +#define fnPhantoon_Spawn8FireballsInCircleAtStart 0xA7D4A9 +#define fnPhantoon_WaitBetweenSpawningAndSpinningFireballs 0xA7D4EE +#define fnPhantoon_SpawnFireballsBeforeFight 0xA7D508 +#define fnPhantoon_WavyFadeIn 0xA7D54A +#define fnPhantoon_PickPatternForRound1 0xA7D596 +#define fnPhantoon_MovePhantoonInFigure8ThenOpenEye 0xA7D5E7 +#define fnPhantoon_EyeFollowsSamusUntilTimerRunsOut 0xA7D60D +#define fnPhantoon_BecomesSolidAndBodyVuln 0xA7D65C +#define fnPhantoon_IsSwooping 0xA7D678 +#define fnPhantoon_FadeoutWithSwoop 0xA7D6B9 +#define fnPhantoon_WaitAfterFadeOut 0xA7D6D4 +#define fnPhantoon_MoveLeftOrRightAndPickEyeOpenPatt 0xA7D6E2 +#define fnPhantoon_FadeInBeforeFigure8 0xA7D72D +#define fnPhantoon_BecomeSolidAfterRainingFireballs 0xA7D73F +#define fnPhantoon_FadeInDuringFireballRain 0xA7D767 +#define fnPhantoon_FollowSamusWithEyeDuringFireballRain 0xA7D788 +#define fnPhantoon_FadeOutDuringFireballRain 0xA7D7D5 +#define fnPhantoon_SpawnRainingFireballs 0xA7D7F7 +#define fnPhantoon_FadeOutBeforeFirstFireballRain 0xA7D82A +#define fnPhantoon_FadeOutBeforeEnrage 0xA7D85C +#define fnPhantoon_MoveEnragedPhantoonToTopCenter 0xA7D874 +#define fnPhantoon_FadeInEnragedPhantoon 0xA7D891 +#define fnPhantoon_Enraged 0xA7D8AC +#define fnPhantoon_FadeoutAfterEnrage 0xA7D916 +#define fnPhantoon_CompleteSwoopAfterFatalShot 0xA7D92E +#define fnPhantoon_DyingPhantoonFadeInOut 0xA7D948 +#define fnPhantoon_DyingPhantoonExplosions 0xA7D98B +#define fnPhantoon_WavyDyingPhantoonAndCry 0xA7DA51 +#define fnPhantoon_DyingFadeOut 0xA7DA86 +#define fnPhantoon_AlmostDead 0xA7DAD7 +#define fnPhantoon_Dead 0xA7DB3D +#define fnPhantoon_Hurt 0xA7DD3F +#define fnPhantoon_Touch 0xA7DD95 +#define fnnullsub_358 0xA7DD9A +#define fnPhantoon_Shot 0xA7DD9B +#define fnnullsub_45 0xA7E011 +#define fnEtecoon_Init 0xA7E912 +#define fnEtecoon_Main 0xA7E940 +#define fnEtecoon_Func_1 0xA7E958 +#define fnEtecoon_Func_2 0xA7E974 +#define fnEtecoon_Func_4 0xA7E9AF +#define fnEtecoon_Func_5 0xA7EA00 +#define fnEtecoon_Func_6 0xA7EA37 +#define fnEtecoon_Func_7 0xA7EAB5 +#define fnEtecoon_Func_8 0xA7EB02 +#define fnEtecoon_Func_9 0xA7EB2C +#define fnEtecoon_Func_10 0xA7EB50 +#define fnEtecoon_Func_11 0xA7EBCD +#define fnEtecoon_Func_12 0xA7EC1B +#define fnEtecoon_Func_16 0xA7EC97 +#define fnEtecoon_Func_17 0xA7ECBB +#define fnEtecoon_Func_18 0xA7ECDF +#define fnEtecoon_Func_19 0xA7ED09 +#define fnEtecoon_Func_20 0xA7ED2A +#define fnEtecoon_Func_21 0xA7ED54 +#define fnEtecoon_Func_22 0xA7ED75 +#define fnEtecoon_Func_23 0xA7EDC7 +#define fnEtecoon_Func_24 0xA7EE3E +#define fnEtecoon_Func_25 0xA7EE9A +#define fnEtecoon_Func_26 0xA7EEB8 +#define fnDachora_Init 0xA7F4DD +#define fnDachora_Main 0xA7F52E +#define fnDachora_Func_1 0xA7F535 +#define fnDachora_Func_2 0xA7F570 +#define fnDachora_Func_3 0xA7F5BC +#define fnDachora_Func_4 0xA7F5ED +#define fnDachora_Func_5 0xA7F65E +#define fnDachora_Func_7 0xA7F78F +#define fnDachora_Func_8 0xA7F806 +#define fnDachora_Func_11 0xA7F935 +#define fnDachora_Func_12 0xA7F98C +#define fnEnemy_GrappleReact_NoInteract_A8 0xA88000 +#define fnEnemy_GrappleReact_KillEnemy_A8 0xA8800A +#define fnEnemy_GrappleReact_CancelBeam_A8 0xA8800F +#define fnEnemy_GrappleReact_SamusLatchesNoInvinc_A8 0xA88014 +#define fnEnemy_GrappleReact_HurtSamus_A8 0xA8801E +#define fnEnemy_NormalTouchAI_A8 0xA88023 +#define fnEnemy_NormalShotAI_A8 0xA8802D +#define fnEnemy_NormalPowerBombAI_A8 0xA88037 +#define fnEnemy_NormalFrozenAI_A8 0xA88041 +#define fnnullsub_170_A8 0xA8804C +#define fnEnemyInstr_Goto_A8 0xA880ED +#define fnEnemyInstr_DecTimerAndGoto2_A8 0xA88110 +#define fnEnemyInstr_SetTimer_A8 0xA88123 +#define fnEnemyInstr_Sleep_A8 0xA8812F +#define fnEnemyInstr_EnableOffScreenProcessing_A8 0xA88173 +#define fnEnemyInstr_DisableOffScreenProcessing_A8 0xA8817D +#define fnMiniDraygon_Instr_2 0xA8878F +#define fnMiniDraygon_Instr_1 0xA8879B +#define fnMiniDraygon_Instr_3 0xA887B6 +#define fnMiniDraygon_Instr_4 0xA887CB +#define fnMiniDraygon_Init 0xA887E0 +#define fnMiniDraygon_Func_1 0xA88838 +#define fnEvirProjectile_Init 0xA888B0 +#define fnMiniDraygon_Main 0xA8891B +#define fnMiniDraygon_Func_4 0xA88922 +#define fnEvirProjectile_Main 0xA8899E +#define fnMiniDraygon_Func_8 0xA88A34 +#define fnMiniDraygon_Func_9 0xA88A3B +#define fnMiniDraygon_Func_10 0xA88A78 +#define fnMiniDraygon_Touch 0xA88B06 +#define fnMiniDraygon_Powerbomb 0xA88B0C +#define fnMiniDraygon_Shot 0xA88B12 +#define fnMorphBallEye_Init 0xA89058 +#define fnMorphBallEye_Main 0xA890E2 +#define fnMorphBallEye_Func_1 0xA890F1 +#define fnMorphBallEye_Func_2 0xA8912E +#define fnMorphBallEye_Func_3 0xA89160 +#define fnMorphBallEye_Func_4 0xA891CE +#define fnnullsub_244 0xA891DC +#define fnFune_Instr_2 0xA89625 +#define fnFune_Instr_6 0xA89631 +#define fnFune_Instr_7 0xA8964A +#define fnFune_Instr_1 0xA89663 +#define fnFune_Instr_4 0xA8967C +#define fnFune_Instr_3 0xA89695 +#define fnFune_Instr_5 0xA896B4 +#define fnFune_Init 0xA896E3 +#define fnFune_Main 0xA89730 +#define fnFune_Func_1 0xA89737 +#define fnFune_Func_2 0xA8975C +#define fnnullsub_247 0xA8978E +#define fnnullsub_248 0xA8978F +#define fnWreckedShipGhost_Init 0xA89AEE +#define fnWreckedShipGhost_Main 0xA89B3C +#define fnWreckedShipGhost_Func_1 0xA89B42 +#define fnWreckedShipGhost_Func_2 0xA89BAD +#define fnWreckedShipGhost_Func_4 0xA89C69 +#define fnWreckedShipGhost_Func_5 0xA89C8A +#define fnWreckedShipGhost_Func_6 0xA89D13 +#define fnWreckedShipGhost_Func_7 0xA89D36 +#define fnYappingMaw_Instr_2 0xA8A0C7 +#define fnYappingMaw_Instr_4 0xA8A0D9 +#define fnYappingMaw_Instr_5 0xA8A0EB +#define fnYappingMaw_Instr_7 0xA8A0FD +#define fnYappingMaw_Instr_3 0xA8A10F +#define fnYappingMaw_Instr_6 0xA8A121 +#define fnYappingMaw_Instr_1 0xA8A133 +#define fnYappingMaw_Init 0xA8A148 +#define fnYappingMaw_Main 0xA8A211 +#define fnYappingMaw_Func_1 0xA8A235 +#define fnYappingMaw_Func_2 0xA8A28C +#define fnYappingMaw_Func_8 0xA8A445 +#define fnYappingMaw_Func_11 0xA8A68A +#define fnYappingMaw_Touch 0xA8A799 +#define fnYappingMaw_Shot 0xA8A7BD +#define fnYappingMaw_Frozen 0xA8A835 +#define fnKago_Init 0xA8AB46 +#define fnKago_Main 0xA8AB75 +#define fnKago_Func_1 0xA8AB7B +#define fnnullsub_306 0xA8AB81 +#define fnKago_Shot 0xA8AB83 +#define fnNorfairLavaMan_Instr_1 0xA8AE12 +#define fnNorfairLavaMan_Instr_8 0xA8AE26 +#define fnNorfairLavaMan_Instr_14 0xA8AE30 +#define fnNorfairLavaMan_Instr_2 0xA8AE3A +#define fnNorfairLavaMan_Instr_7 0xA8AE45 +#define fnNorfairLavaMan_Instr_10 0xA8AE50 +#define fnNorfairLavaMan_Instr_12 0xA8AE5A +#define fnNorfairLavaMan_Instr_9 0xA8AE64 +#define fnNorfairLavaMan_Instr_11 0xA8AE88 +#define fnNorfairLavaMan_Instr_13 0xA8AE96 +#define fnNorfairLavaMan_Instr_5 0xA8AEBA +#define fnNorfairLavaMan_Instr_15 0xA8AECA +#define fnNorfairLavaMan_Instr_4 0xA8AEE4 +#define fnNorfairLavaMan_Instr_16 0xA8AEFE +#define fnNorfairLavaMan_Instr_6 0xA8AF18 +#define fnNorfairLavaMan_Instr_3 0xA8AF44 +#define fnNorfairLavaMan_Init 0xA8AF8B +#define fnNorfairLavaMan_Func_1 0xA8AF9D +#define fnNorfairLavaMan_Func_6 0xA8B0B2 +#define fnNorfairLavaMan_Main 0xA8B10A +#define fnNorfairLavaMan_Func_7 0xA8B11A +#define fnNorfairLavaMan_Func_8 0xA8B175 +#define fnsub_A8B193 0xA8B193 +#define fnNorfairLavaMan_Func_9 0xA8B1B8 +#define fnNorfairLavaMan_Func_10 0xA8B1DD +#define fnNorfairLavaMan_Func_11 0xA8B204 +#define fnsub_A8B291 0xA8B291 +#define fnNorfairLavaMan_Func_13 0xA8B295 +#define fnNorfairLavaMan_Func_15 0xA8B30D +#define fnNorfairLavaMan_Func_16 0xA8B31F +#define fnNorfairLavaMan_Func_17 0xA8B356 +#define fnNorfairLavaMan_Func_18 0xA8B3A7 +#define fnNorfairLavaMan_Powerbomb 0xA8B400 +#define fnNorfairLavaMan_Touch 0xA8B406 +#define fnNorfairLavaMan_Shot 0xA8B40C +#define fnBeetom_Instr_1 0xA8B75E +#define fnBeetom_Func_1 0xA8B762 +#define fnBeetom_Init 0xA8B776 +#define fnBeetom_Func_2 0xA8B7EF +#define fnBeetom_Main 0xA8B80D +#define fnBeetom_Func_3 0xA8B814 +#define fnBeetom_Func_4 0xA8B82F +#define fnBeetom_Func_5 0xA8B84F +#define fnBeetom_Func_6 0xA8B85F +#define fnBeetom_Func_7 0xA8B873 +#define fnBeetom_Func_8 0xA8B887 +#define fnBeetom_Func_9 0xA8B8A9 +#define fnBeetom_Func_10 0xA8B8CB +#define fnBeetom_Func_11 0xA8B8ED +#define fnBeetom_Func_12 0xA8B90F +#define fnBeetom_Func_13 0xA8B952 +#define fnBeetom_Func_14 0xA8B966 +#define fnBeetom_Func_15 0xA8B97A +#define fnBeetom_Func_16 0xA8B9A2 +#define fnBeetom_Func_17 0xA8B9B2 +#define fnBeetom_Func_18 0xA8B9C1 +#define fnBeetom_Func_19 0xA8BA24 +#define fnBeetom_Func_20 0xA8BA84 +#define fnBeetom_Func_21 0xA8BAB7 +#define fnBeetom_Func_24 0xA8BB55 +#define fnBeetom_Func_25 0xA8BB88 +#define fnBeetom_Func_28 0xA8BC26 +#define fnBeetom_Func_29 0xA8BC5A +#define fnBeetom_Func_32 0xA8BCF8 +#define fnBeetom_Func_33 0xA8BD42 +#define fnBeetom_Func_35 0xA8BD9D +#define fnBeetom_Func_36 0xA8BDC5 +#define fnBeetom_Touch 0xA8BE2E +#define fnBeetom_Shot 0xA8BEAC +#define fnMaridiaFloater_Init 0xA8C1C9 +#define fnMaridiaFloater_Main 0xA8C21C +#define fnMaridiaFloater_Func_1 0xA8C223 +#define fnMaridiaFloater_Func_3 0xA8C283 +#define fnMaridiaFloater_Func_4 0xA8C2A6 +#define fnMaridiaFloater_Func_5 0xA8C2CF +#define fnMaridiaFloater_Func_6 0xA8C36B +#define fnMaridiaFloater_Func_7 0xA8C3E1 +#define fnMaridiaFloater_Func_8 0xA8C469 +#define fnMaridiaFloater_Func_9 0xA8C4DC +#define fnMaridiaFloater_Func_10 0xA8C500 +#define fnMaridiaFloater_Func_11 0xA8C51D +#define fnnullsub_256 0xA8C568 +#define fnMaridiaFloater_Func_12 0xA8C569 +#define fnMaridiaFloater_Func_13 0xA8C59F +#define fnMaridiaFloater_Touch 0xA8C5BE +#define fnMaridiaFloater_Shot 0xA8C5EF +#define fnMaridiaFloater_Powerbomb 0xA8C63F +#define fnWreckedShipRobot_Init 0xA8CB77 +#define fnWreckedShipRobotDeactivated_Init 0xA8CBCC +#define fnWreckedShipRobot_Main 0xA8CC36 +#define fnnullsub_342 0xA8CC66 +#define fnWreckedShipRobot_Func_1 0xA8CC67 +#define fnWreckedShipRobot_Instr_4 0xA8CD09 +#define fnWreckedShipRobot_Instr_9 0xA8CDA4 +#define fnWreckedShipRobot_Instr_6 0xA8CDEA +#define fnWreckedShipRobot_Instr_8 0xA8CE85 +#define fnWreckedShipRobot_Instr_7 0xA8CECB +#define fnWreckedShipRobot_Instr_15 0xA8CECF +#define fnWreckedShipRobot_Instr_18 0xA8CF6A +#define fnWreckedShipRobot_Instr_16 0xA8CFB0 +#define fnWreckedShipRobot_Instr_17 0xA8D04B +#define fnWreckedShipRobot_Instr_3 0xA8D091 +#define fnWreckedShipRobot_Instr_10 0xA8D0C2 +#define fnWreckedShipRobot_Instr_14 0xA8D0C6 +#define fnWreckedShipRobot_Instr_2 0xA8D0D2 +#define fnWreckedShipRobot_Instr_13 0xA8D100 +#define fnWreckedShipRobot_Instr_1 0xA8D107 +#define fnWreckedShipRobot_Instr_12 0xA8D131 +#define fnWreckedShipRobot_Instr_5 0xA8D13D +#define fnWreckedShipRobot_Instr_11 0xA8D16B +#define fnWreckedShipRobotDeactivated_Touch 0xA8D174 +#define fnWreckedShipRobotDeactivated_Shot 0xA8D18D +#define fnWreckedShipRobot_Shot 0xA8D192 +#define fnMaridiaPuffer_Init 0xA8D8C9 +#define fnMaridiaPuffer_Main 0xA8D90B +#define fnMaridiaPuffer_Func_1 0xA8D92B +#define fnMaridiaPuffer_Func_2 0xA8D940 +#define fnMaridiaPuffer_Func_3 0xA8D963 +#define fnMaridiaPuffer_Func_4 0xA8D97C +#define fnMaridiaPuffer_Shot 0xA8DB14 +#define fnWalkingLavaSeahorse_Init 0xA8DCCD +#define fnWalkingLavaSeahorse_Main 0xA8DD6B +#define fnWalkingLavaSeahorse_Func_3 0xA8DD71 +#define fnWalkingLavaSeahorse_Func_4 0xA8DDC6 +#define fnWalkingLavaSeahorse_Func_6 0xA8DE05 +#define fnWalkingLavaSeahorse_Func_7 0xA8DE4B +#define fnnullsub_257 0xA8DECC +#define fnWalkingLavaSeahorse_Func_8 0xA8DECD +#define fnWalkingLavaSeahorse_Func_9 0xA8DEEC +#define fnWalkingLavaSeahorse_Instr_4 0xA8DF1C +#define fnWalkingLavaSeahorse_Instr_3 0xA8DF33 +#define fnWalkingLavaSeahorse_Instr_5 0xA8DF39 +#define fnWalkingLavaSeahorse_Instr_6 0xA8DF3F +#define fnWalkingLavaSeahorse_Instr_2 0xA8DF63 +#define fnWalkingLavaSeahorse_Instr_1 0xA8DF71 +#define fnWreckedShipOrbs_Init 0xA8E388 +#define fnWreckedShipOrbs_Main 0xA8E3C3 +#define fnWreckedShipOrbs_Func_3 0xA8E405 +#define fnWreckedShipOrbs_Func_4 0xA8E424 +#define fnWreckedShipOrbs_Func_5 0xA8E443 +#define fnWreckedShipOrbs_Func_6 0xA8E462 +#define fnWreckedShipSpark_Instr_2 0xA8E61D +#define fnWreckedShipSpark_Instr_1 0xA8E62A +#define fnWreckedShipSpark_Init 0xA8E637 +#define fnWreckedShipSpark_Main 0xA8E68E +#define fnnullsub_259 0xA8E694 +#define fnWreckedShipSpark_Func_1 0xA8E695 +#define fnWreckedShipSpark_Func_2 0xA8E6B7 +#define fnWreckedShipSpark_Func_3 0xA8E6DC +#define fnWreckedShipSpark_Shot 0xA8E70E +#define fnBlueBrinstarFaceBlock_Init 0xA8E82E +#define fnBlueBrinstarFaceBlock_Func_1 0xA8E86E +#define fnBlueBrinstarFaceBlock_Main 0xA8E8AE +#define fnBlueBrinstarFaceBlock_Shot 0xA8E91D +#define fnKiHunter_Init 0xA8F188 +#define fnKiHunterWings_Init 0xA8F214 +#define fnKiHunter_Main 0xA8F25C +#define fnKiHunterWings_Main 0xA8F262 +#define fnKiHunter_Func_1 0xA8F268 +#define fnKiHunter_Func_2 0xA8F3B8 +#define fnKiHunter_Func_3 0xA8F4ED +#define fnKiHunter_Instr_1 0xA8F526 +#define fnKiHunter_Func_4 0xA8F55A +#define fnKiHunter_Func_5 0xA8F58B +#define fnnullsub_346 0xA8F5E3 +#define fnKiHunter_Instr_2 0xA8F5E4 +#define fnKiHunter_Func_6 0xA8F5F0 +#define fnKiHunter_Instr_3 0xA8F67F +#define fnKiHunter_Func_7 0xA8F68B +#define fnKiHunter_Func_8 0xA8F6B3 +#define fnKiHunter_Instr_4 0xA8F6D2 +#define fnKiHunter_Instr_5 0xA8F6D8 +#define fnKiHunter_Func_9 0xA8F6F3 +#define fnKiHunter_Shot 0xA8F701 +#define fnKiHunter_Func_10 0xA8F7CF +#define fnKiHunter_Func_11 0xA8F7DB +#define fnKiHunter_Func_14 0xA8F8AD +#define fnEnemy_GrappleReact_CancelBeam_A9 0xA9800F +#define fnEnemy_NormalPowerBombAI_A9 0xA98037 +#define fnEnemy_NormalFrozenAI_A9 0xA98041 +#define fnnullsub_170_A9 0xA9804C +#define fnEnemyInstr_Sleep_A9 0xA9812F +#define fnMotherBrainsBody_Init 0xA98687 +#define fnMotherBrainsBrain_Init 0xA98705 +#define fnMotherBrainsBody_Hurt 0xA9873E +#define fnMotherBrainsBody_UnpauseHook 0xA98763 +#define fnnullsub_264 0xA98786 +#define fnMotherBrainsBody_Powerbomb 0xA98787 +#define fnMotherBrainsBrain_Hurt 0xA9878B +#define fnMotherBrainsBrain_SetupBrainAndNeckToDraw 0xA987A2 +#define fnMotherBrain_DrawBrainNeck_EnemyGfxDrawHook 0xA987C9 +#define fnMotherBrainsBrain_SetupBrainToDraw 0xA987D0 +#define fnMotherBrainsBrain_GfxDrawHook 0xA987DD +#define fnMotherBrainsBody_FirstPhase_DoubleRet 0xA987E1 +#define fnMotherBrainBody_FakeDeath_Descent_0_Pause 0xA9881D +#define fnMotherBrainBody_FakeDeath_Descent_1 0xA98829 +#define fnMotherBrainBody_FakeDeath_Descent_2 0xA9884D +#define fnMotherBrainBody_FakeDeath_Descent_3 0xA9886C +#define fnMotherBrainBody_FakeDeath_Descent_4 0xA98884 +#define fnMotherBrainBody_FakeDeath_Descent_5 0xA988B2 +#define fnMotherBrainBody_FakeDeath_Descent_6 0xA988D3 +#define fnMotherBrainBody_0_Wait 0xA98949 +#define fnMotherBrainBody_1_ClearBottomLeftTube 0xA9896E +#define fnMotherBrainBody_2_SpawnTopRightTubeFalling 0xA98983 +#define fnMotherBrainBody_3_ClearCeilingBlock9 0xA989A0 +#define fnMotherBrainBody_4_SpawnTopLeftTubeFalling 0xA989B5 +#define fnMotherBrainBody_4_ClearCeilingBlock6 0xA989D2 +#define fnMotherBrainBody_5_SpawnTubeFallingEnemy1 0xA989E7 +#define fnMotherBrainBody_6_ClearBottomRightTube 0xA989FA +#define fnMotherBrainBody_7_SpawnTubeFallingEnemy2 0xA98A0F +#define fnMotherBrainBody_8_ClearBottomMiddleLeftTube 0xA98A22 +#define fnMotherBrainBody_9_SpawnTopMiddleLeftFalling 0xA98A37 +#define fnMotherBrainBody_10_ClearCeilingTubeColumn7 0xA98A54 +#define fnMotherBrainBody_11_SpawnTopMiddleRightFalling 0xA98A69 +#define fnMotherBrainBody_12_ClearCeilingTubeColumn8 0xA98A86 +#define fnMotherBrainBody_13_SpawnTubeFallingEnemy3 0xA98A9B +#define fnMotherBrainBody_14_ClearBottomMiddleRightTube 0xA98AAE +#define fnMotherBrainBody_15_SpawnTubeFallingEnemy4 0xA98AC3 +#define fnMotherBrainBody_16_ClearBottomMiddleTubes 0xA98AD6 +#define fnnullsub_365 0xA98AE4 +#define fnMotherBrainsTubesFalling_Init 0xA98B35 +#define fnMotherBrainsTubesFalling_Main 0xA98B85 +#define fnMotherBrainsTubesFalling_Main_NonMain 0xA98B88 +#define fnMotherBrainsTubesFalling_WaitToFall 0xA98BCB +#define fnMotherBrainsTubesFalling_Falling 0xA98BD6 +#define fnMotherBrainBody_FakeDeath_Ascent_0_DrawBG1Row23 0xA98C87 +#define fnMotherBrainBody_FakeDeath_Ascent_1_DrawBG1Row45 0xA98C9E +#define fnMotherBrainBody_FakeDeath_Ascent_2_DrawBG1Row67 0xA98CB5 +#define fnMotherBrainBody_FakeDeath_Ascent_3_DrawBG1Row89 0xA98CCC +#define fnMotherBrainBody_FakeDeath_Ascent_4_DrawBG1RowAB 0xA98CE3 +#define fnMotherBrainBody_FakeDeath_Ascent_5_DrawBG1RowCD 0xA98CFA +#define fnMotherBrainBody_FakeDeath_Ascent_6_SetupPhase2Gfx 0xA98D11 +#define fnMotherBrainBody_FakeDeath_Ascent_7_SetupPhase2Brain 0xA98D49 +#define fnMotherBrainBody_FakeDeath_Ascent_8_Pause 0xA98D79 +#define fnMotherBrainBody_FakeDeath_Ascent_9_PrepareRise 0xA98D8B +#define fnMotherBrainBody_FakeDeath_Ascent_10_LoadLegTiles 0xA98DB4 +#define fnMotherBrainBody_FakeDeath_Ascent_11_ContinuePause 0xA98DC3 +#define fnMotherBrainBody_FakeDeath_Ascent_12_StartMusic 0xA98DEC +#define fnMotherBrainBody_FakeDeath_Ascent_13_Raise 0xA98E4D +#define fnMotherBrainBody_FakeDeath_Ascent_14_WaitForUncouching 0xA98E95 +#define fnMotherBrainBody_FakeDeath_Ascent_15_TransitionFromGrey 0xA98EAA +#define fnMotherBrainBody_2ndphase_16_ShakeHeadMenacingly 0xA98EF5 +#define fnMotherBrainBody_2ndphase_17_BringHeadBackUp 0xA98F14 +#define fnMotherBrainBody_2ndphase_18_FinishStretching 0xA98F33 +#define fnMotherBrain_DrawBrain 0xA99357 +#define fnMotherBrain_Instr_MoveBodyUp10Left4 0xA995B6 +#define fnMotherBrain_Instr_MoveBodyUp16Left4 0xA995C0 +#define fnMotherBrain_Instr_MoveBodyUp12Right2 0xA995CA +#define fnMotherBrain_Instr_MoveDown12Left4 0xA995DE +#define fnMotherBrain_Instr_MoveDown16Right2 0xA995E8 +#define fnMotherBrain_Instr_MoveDown10Right2 0xA995F2 +#define fnMotherBrain_Instr_MoveUp2Right1 0xA995FC +#define fnMotherBrain_Instr_MoveRight2 0xA9960C +#define fnMotherBrain_Instr_MoveUp1 0xA9961C +#define fnMotherBrain_Instr_MoveUp1Right3_Sfx 0xA99622 +#define fnMotherBrain_Instr_Down2Right15 0xA99638 +#define fnMotherBrain_Instr_Down4Right6 0xA99648 +#define fnMotherBrain_Instr_Up4Left2 0xA99658 +#define fnMotherBrain_Instr_Up2Left1_Sfx 0xA99668 +#define fnMotherBrain_Instr_Up2Left1_Sfx2 0xA9967E +#define fnMotherBrain_Instr_MoveLeft2 0xA99694 +#define fnMotherBrain_Instr_MoveDown1 0xA996A4 +#define fnMotherBrain_Instr_MoveDown1Left3 0xA996AA +#define fnMotherBrain_Instr_MoveUp2Left15_Sfx 0xA996BA +#define fnMotherBrain_Instr_MoveUp4Left6 0xA996D0 +#define fnMotherBrain_Instr_MoveDown4Right2 0xA996E0 +#define fnMotherBrain_Instr_MoveDown2Right1 0xA996F0 +#define fnMotherBrain_Instr_SetPose_Standing 0xA99700 +#define fnMotherBrain_Instr_SetPose_Walking 0xA99708 +#define fnMotherBrain_Instr_SetPose_Crouched 0xA99710 +#define fnMotherBrain_Instr_SetPose_CrouchedTrans 0xA99718 +#define fnMotherBrain_Instr_SetPose_DeathBeamMode 0xA99720 +#define fnMotherBrain_Instr_SetPose_LeaningDown 0xA99728 +#define fnMotherBrain_Instr_SpawnEprojToOffset 0xA99AC8 +#define fnMotherBrain_Instr_SpawnDeathBeamEproj 0xA99AEF +#define fnMotherBrain_Instr_IncrBeamAttackPhase 0xA99B05 +#define fnMotherBrain_Instr_Goto 0xA99B0F +#define fnMotherBrain_Instr_EnableNeckMovementGoto 0xA99B14 +#define fnMotherBrain_Instr_DisableNeckMovement 0xA99B20 +#define fnMotherBrain_Instr_QueueSfx2 0xA99B28 +#define fnMotherBrain_Instr_QueueSfx3 0xA99B32 +#define fnMotherBrain_Instr_SpawnDroolEproj 0xA99B3C +#define fnMotherBrain_Instr_SpawnPurpleBreath 0xA99B6D +#define fnMotherBrain_Instr_SetMainShakeTimer50 0xA99B77 +#define fnMotherBrain_Instr_GotoEitherOr 0xA99C65 +#define fnMotherBrain_Instr_MaybeGoto 0xA99CAD +#define fnMotherBrain_Instr_MaybeGoto2 0xA99D0D +#define fnMotherBrain_Instr_Goto2 0xA99D21 +#define fnMotherBrain_Instr_QueueShitroidAttackSfx 0xA99DF7 +#define fnMotherBrain_Instr_SpawnBlueRingEproj 0xA99E29 +#define fnMotherBrain_Instr_AimRingsAtShitroid 0xA99E37 +#define fnMotherBrain_Instr_AimRingsAtSamus 0xA99E5B +#define fnMotherBrain_Instr_AimRings 0xA99E77 +#define fnMotherBrain_Instr_IncrShitroidAttackCtr 0xA99EA3 +#define fnMotherBrain_Instr_SetShitroidAttackCtr0 0xA99EB5 +#define fnMotherBrain_Instr_SpawnBombEproj 0xA99EBD +#define fnMotherBrain_Instr_SpawnLaserEproj 0xA99F46 +#define fnMotherBrain_Instr_SpawnRainbowEproj 0xA99F84 +#define fnMotherBrain_Instr_SetupFxForRainbowBeam 0xA99F8E +#define fnMotherBrain_Phase3_Death_0 0xA9AEE1 +#define fnMotherBrain_Phase3_Death_1 0xA9AF12 +#define fnMotherBrain_Phase3_Death_2 0xA9AF21 +#define fnMotherBrain_Phase3_Death_3 0xA9AF54 +#define fnMotherBrain_Phase3_Death_4 0xA9AF9D +#define fnMotherBrain_Phase3_Death_5 0xA9AFB6 +#define fnMotherBrain_Phase3_Death_6 0xA9B013 +#define fnMotherBrain_Phase3_Death_7 0xA9B115 +#define fnMotherBrain_Phase3_Death_8 0xA9B12D +#define fnMotherBrain_Phase3_Death_9 0xA9B15E +#define fnMotherBrain_Phase3_Death_10 0xA9B173 +#define fnMotherBrain_Phase3_Death_11 0xA9B189 +#define fnMotherBrain_Phase3_Death_12 0xA9B1B8 +#define fnMotherBrain_Phase3_Death_13 0xA9B1D5 +#define fnMotherBrain_Phase3_Death_14_20framedelay 0xA9B211 +#define fnMotherBrain_CorpseRottingFinished 0xA9B223 +#define fnMotherBrain_Phase3_Death_15_LoadEscapeTimerTiles 0xA9B258 +#define fnMotherBrain_Phase3_Death_16_StartEscape 0xA9B26D +#define fnMotherBrain_Phase3_Death_17_SpawnTimeBomb 0xA9B2D1 +#define fnMotherBrain_Phase3_Death_18_TypesZebesText 0xA9B2E3 +#define fnMotherBrain_Phase3_Death_19_EscapeDoorExploding 0xA9B2F9 +#define fnMotherBrain_Phase3_Death_20_BlowUpEscapeDoor 0xA9B32A +#define fnMotherBrain_Phase3_Death_21_KeepEarthquakeGoing 0xA9B33C +#define fnMotherBrainsBody_Shot 0xA9B503 +#define fnMotherBrainsBrain_Shot 0xA9B507 +#define fnnullsub_47 0xA9B5C5 +#define fnMotherBrainsBrain_Touch 0xA9B5C6 +#define fnMotherBrain_Body_Phase2_Thinking 0xA9B605 +#define fnMotherBrain_Body_Phase2_TryAttack 0xA9B64B +#define fnMotherBrain_FiringBomb_DecideOnWalking 0xA9B781 +#define fnMotherBrain_FiringBomb_WalkingBackwards 0xA9B7AC +#define fnMotherBrain_FiringBomb_Crouch 0xA9B7C6 +#define fnMotherBrain_FiringBomb_Fired 0xA9B7E8 +#define fnMotherBrain_FiringBomb_Standup 0xA9B7F8 +#define fnMotherBomb_FiringLaser_PositionHead 0xA9B80E +#define fnMotherBomb_FiringLaser_PositionHeadSlowlyFire 0xA9B839 +#define fnMotherBomb_FiringLaser_FinishAttack 0xA9B863 +#define fnMotherBomb_FiringDeathBeam 0xA9B87D +#define fnMotherBomb_FiringRainbowBeam_0 0xA9B8EB +#define fnMotherBomb_FiringRainbowBeam_1_StartCharge 0xA9B91A +#define fnMotherBomb_FiringRainbowBeam_2_RetractNeck 0xA9B92B +#define fnMotherBomb_FiringRainbowBeam_3_Wait 0xA9B93F +#define fnMotherBomb_FiringRainbowBeam_4_ExtendNeckDown 0xA9B951 +#define fnMotherBomb_FiringRainbowBeam_5_StartFiring 0xA9B975 +#define fnMotherBomb_FiringRainbowBeam_6_MoveSamusToWall 0xA9B9E5 +#define fnMotherBomb_FiringRainbowBeam_7_DelayFrame 0xA9BA00 +#define fnMotherBomb_FiringRainbowBeam_8_StartDrainSamus 0xA9BA27 +#define fnMotherBomb_FiringRainbowBeam_9_DrainingSamus 0xA9BA3C +#define fnMotherBomb_FiringRainbowBeam_10_FinishFiringRainbow 0xA9BA5E +#define fnMotherBomb_FiringRainbowBeam_11_LetSamusFall 0xA9BAC4 +#define fnMotherBomb_FiringRainbowBeam_12_WaitForSamusHitGround 0xA9BAD1 +#define fnMotherBomb_FiringRainbowBeam_13_LowerHead 0xA9BADD +#define fnMotherBomb_FiringRainbowBeam_14_DecideNextAction 0xA9BB06 +#define fnMotherBrain_Phase2Cut_0 0xA9BD45 +#define fnMotherBrain_Phase2Cut_1 0xA9BD98 +#define fnMotherBrain_Phase2Cut_2 0xA9BDA9 +#define fnMotherBrain_Phase2Cut_3 0xA9BDC1 +#define fnMotherBrain_Phase2Cut_4 0xA9BDD2 +#define fnMotherBrain_Phase2Cut_5 0xA9BDED +#define fnnullsub_364 0xA9BE1A +#define fnMotherBrain_DrainedByShitroid_0 0xA9BE38 +#define fnMotherBrain_DrainedByShitroid_1 0xA9BE5D +#define fnMotherBrain_DrainedByShitroid_2 0xA9BE96 +#define fnMotherBrain_DrainedByShitroid_3 0xA9BF0E +#define fnMotherBrain_DrainedByShitroid_4 0xA9BF41 +#define fnMotherBrain_DrainedByShitroid_5 0xA9BF56 +#define fnMotherBrain_DrainedByShitroid_6 0xA9BF7D +#define fnMotherBrain_DrainedByShitroid_7 0xA9BF95 +#define fnMotherBrain_PainfulWalkForwards 0xA9BFD0 +#define fnMotherBrain_PainfulWalkingForwards 0xA9BFE8 +#define fnMotherBrain_PainfulWalkBackwards 0xA9C004 +#define fnMotherBrain_PainfulWalkingBackwards 0xA9C01C +#define fnMotherBrain_Phase2_Revive_0 0xA9C059 +#define fnMotherBrain_Phase2_Revive_1 0xA9C066 +#define fnMotherBrain_Phase2_Revive_2 0xA9C082 +#define fnMotherBrain_Phase2_Revive_3 0xA9C08F +#define fnMotherBrain_Phase2_Revive_4 0xA9C0BA +#define fnMotherBrain_Phase2_Revive_5 0xA9C0E4 +#define fnMotherBrain_Phase2_Revive_6 0xA9C0FB +#define fnMotherBrain_Phase2_Revive_7 0xA9C11E +#define fnMotherBrain_Phase2_Revive_8 0xA9C147 +#define fnMotherBrain_Phase2_MurderShitroid_1 0xA9C15C +#define fnMotherBrain_Phase2_MurderShitroid_2 0xA9C182 +#define fnnullsub_367 0xA9C18D +#define fnMotherBrain_Phase2_PrepareForFinalShitroid 0xA9C18E +#define fnMotherBrain_Phase2_ExecuteFinalkShitroid 0xA9C19A +#define fnnullsub_363 0xA9C1A6 +#define fnMotherBrain_Phase3_Recover_MakeDistance 0xA9C1CF +#define fnMotherBrain_Phase3_Recover_SetupForFight 0xA9C1F0 +#define fnMotherBrain_Phase3_Fighting_Main 0xA9C209 +#define fnMotherBrain_Phase3_Fighting_Cooldown 0xA9C24E +#define fnMotherBrain_Phase3_Walk_TryToInchForward 0xA9C26A +#define fnMotherBrain_Phase3_Walk_RetreatQuickly 0xA9C2B3 +#define fnMotherBrain_Phase3_Walk_RetreatSlowly 0xA9C2D2 +#define fnMotherBrain_Phase3_Neck_Normal 0xA9C330 +#define fnnullsub_369 0xA9C353 +#define fnMotherBrain_Phase3_Neck_SetupRecoilRecovery 0xA9C354 +#define fnMotherBrain_Phase3_Neck_RecoilRecovery 0xA9C37B +#define fnMotherBrain_Phase3_Neck_SetupHyperBeamRecoil 0xA9C395 +#define fnMotherBrain_Phase3_Neck_HyperBeamRecoil 0xA9C3CD +#define fnShitroidInCutscene_Init 0xA9C710 +#define fnShitroidInCutscene_Main 0xA9C779 +#define fnShitroidInCutscene_DashOntoScreen 0xA9C7CC +#define fnShitroidInCutscene_CurveTowardsBrain 0xA9C7EC +#define fnShitroidInCutscene_GetIntoFace 0xA9C811 +#define fnShitroidInCutscene_LatchOntoBrain 0xA9C851 +#define fnShitroidInCutscene_SetMotherBrainToStumbleBack 0xA9C879 +#define fnShitroidInCutscene_ActivateRainbowBeam 0xA9C889 +#define fnShitroidInCutscene_BrainTurnsToCorpse 0xA9C8E2 +#define fnShitroidInCutscene_StopDraining 0xA9C915 +#define fnShitroidInCutscene_LetGoAndSpawnDust 0xA9C94B +#define fnShitroidInCutscene_MoveUpToCeiling 0xA9C959 +#define fnShitroidInCutscene_MoveToSamus 0xA9C9C3 +#define fnShitroidInCutscene_LatchOntoSamus 0xA9CA66 +#define fnShitroidInCutscene_HealSamusToFullHealth 0xA9CA7A +#define fnnullsub_368 0xA9CABC +#define fnShitroidInCutscene_IdleUntilToNoHealth 0xA9CABD +#define fnShitroidInCutscene_ReleaseSamus 0xA9CB13 +#define fnShitroidInCutscene_StareDownMotherBrain 0xA9CB2D +#define fnShitroidInCutscene_FlyOffScreen 0xA9CB56 +#define fnShitroidInCutscene_MoveToFinalChargeStart 0xA9CB7B +#define fnShitroidInCutscene_InitiateFinalCharge 0xA9CBB3 +#define fnShitroidInCutscene_FinalCharge 0xA9CBD8 +#define fnShitroidInCutscene_ShitroidFinalBelow 0xA9CC3E +#define fnShitroidInCutscene_PlaySamusTheme 0xA9CC60 +#define fnShitroidInCutscene_PrepareSamusHyperbeam 0xA9CC7F +#define fnnullsub_338 0xA9CC98 +#define fnShitroidInCutscene_DeathSequence 0xA9CC99 +#define fnShitroidInCutscene_UnloadShitroid 0xA9CCC0 +#define fnShitroidInCutscene_LetSamusRainbowMore 0xA9CCDE +#define fnShitroidInCutscene_FinishCutscene 0xA9CCF0 +#define fnSamusRainbowPaletteFunc_ActivateWhenEnemyLow 0xA9CD30 +#define fnSamusRainbowPaletteFunc_GraduallySlowDown 0xA9CD4B +#define fnShitroidInCutscene_Touch 0xA9CF03 +#define fnShitroid_Instr_1 0xA9CFB4 +#define fnShitroid_Instr_2 0xA9CFCA +#define fnDeadTorizo_Init 0xA9D308 +#define fnDeadTorizo_Main 0xA9D368 +#define fnDeadTorizo_MainGfxHook 0xA9D39A +#define fnDeadTorizo_WaitForSamusColl 0xA9D3AD +#define fnnullsub_361 0xA9D3C7 +#define fnDeadTorizo_PreRotDelay 0xA9D3C8 +#define fnDeadTorizo_Rotting 0xA9D3E6 +#define fnDeadTorizo_Powerbomb 0xA9D42A +#define fnDeadTorizo_Shot 0xA9D433 +#define fnDeadTorizo_CorpseRottingFinished 0xA9D5BD +#define fnDeadSidehopper_Init 0xA9D7B6 +#define fnDeadZoomer_Init 0xA9D849 +#define fnDeadRipper_Init 0xA9D876 +#define fnDeadSkree_Init 0xA9D89F +#define fnDeadSidehopper_Powerbomb 0xA9D8CC +#define fnDeadSidehopper_Main 0xA9D8DB +#define fnDeadSidehopper_Alive_WaitForActivate 0xA9D8E2 +#define fnDeadSidehopper_Activated 0xA9D8F1 +#define fnnullsub_362 0xA9D90F +#define fnDeadMonsters_Func_1 0xA9D910 +#define fnDeadMonsters_Func_2 0xA9D91D +#define fnDeadMonsters_Func_5 0xA9DA08 +#define fnnullsub_268 0xA9DA63 +#define fnDeadSidehopper_WaitForSamusColl 0xA9DA64 +#define fnDeadZoomer_WaitForSamusColl 0xA9DA69 +#define fnDeadSkree_WaitForSamusColl 0xA9DA6E +#define fnDeadRipper_WaitForSamusColl 0xA9DA73 +#define fnDeadSidehopper_PreRotDelay 0xA9DA8F +#define fnDeadZoomer_PreRotDelay 0xA9DA94 +#define fnDeadRipper_PreRotDelay 0xA9DA99 +#define fnDeadSkree_PreRotDelay 0xA9DA9E +#define fnDeadSidehopper_Rotting 0xA9DABA +#define fnDeadZoomer_Rotting 0xA9DAD0 +#define fnDeadRipper_Rotting 0xA9DAE6 +#define fnDeadSkree_Rotting 0xA9DAFC +#define fnCorpseRottingRotEntryFinishedHook 0xA9DC08 +#define fnDeadZoomer_Powerbomb 0xA9DCED +#define fnDeadZoomer_Shot 0xA9DCF8 +#define fnDeadRipper_Powerbomb 0xA9DCFD +#define fnDeadRipper_Shot 0xA9DD08 +#define fnDeadSkree_Powerbomb 0xA9DD0D +#define fnDeadSkree_Shot 0xA9DD18 +#define fnDeadSidehopper_Shot 0xA9DD1D +#define fnDeadSidehopper_Touch 0xA9DD44 +#define fnTorizo_CorpseRottingInitFunc 0xA9DE18 +#define fnSidehopper_CorpseRottingInitFunc_0 0xA9DEC1 +#define fnSidehopper_CorpseRottingInitFunc_2 0xA9DF08 +#define fnZoomer_CorpseRottingInitFunc_0 0xA9DF4F +#define fnZoomer_CorpseRottingInitFunc_2 0xA9DF6C +#define fnZoomer_CorpseRottingInitFunc_4 0xA9DF89 +#define fnRipper_CorpseRottingInitFunc_0 0xA9DFA6 +#define fnRipper_CorpseRottingInitFunc_2 0xA9DFC3 +#define fnSkree_CorpseRottingInitFunc_0 0xA9DFE0 +#define fnSkree_CorpseRottingInitFunc_2 0xA9E019 +#define fnSkree_CorpseRottingInitFunc_4 0xA9E052 +#define fnMotherBrain_CorpseRottingInitFunc 0xA9E08B +#define fnTorizo_CorpseRottingMoveFunc 0xA9E272 +#define fnTorizo_CorpseRottingCopyFunc 0xA9E38B +#define fnSidehopper_CorpseRottingMoveFunc_0 0xA9E468 +#define fnSidehopper_CorpseRottingCopyFunc_0 0xA9E4F5 +#define fnSidehopper_CorpseRottingMoveFunc_2 0xA9E564 +#define fnSidehopper_CorpseRottingCopyFunc_2 0xA9E5F6 +#define fnZoomer_CorpseRottingMoveFunc_0 0xA9E66A +#define fnZoomer_CorpseRottingCopyFunc_0 0xA9E6B9 +#define fnZoomer_CorpseRottingMoveFunc_2 0xA9E6F6 +#define fnZoomer_CorpseRottingCopyFunc_2 0xA9E745 +#define fnZoomer_CorpseRottingMoveFunc_4 0xA9E782 +#define fnZoomer_CorpseRottingCopyFunc_4 0xA9E7D1 +#define fnRipper_CorpseRottingMoveFunc_0 0xA9E80E +#define fnRipper_CorpseRottingCopyFunc_0 0xA9E85D +#define fnRipper_CorpseRottingMoveFunc_2 0xA9E89A +#define fnRipper_CorpseRottingCopyFunc_2 0xA9E8E9 +#define fnSkree_CorpseRottingMoveFunc_0 0xA9E926 +#define fnSkree_CorpseRottingCopyFunc_0 0xA9E95B +#define fnSkree_CorpseRottingMoveFunc_2 0xA9E984 +#define fnSkree_CorpseRottingCopyFunc_2 0xA9E9B9 +#define fnSkree_CorpseRottingMoveFunc_4 0xA9E9E2 +#define fnSkree_CorpseRottingCopyFunc_4 0xA9EA17 +#define fnMotherBrain_CorpseRottingMoveFunc 0xA9EA40 +#define fnMotherBrain_CorpseRottingCopyFunc 0xA9EB0B +#define fnsub_A9ECD0 0xA9ECD0 +#define fnShitroid_Func_1 0xA9EED1 +#define fnShitroid_Func_2 0xA9EF06 +#define fnShitroid_Init 0xA9EF37 +#define fnShitroid_Powerbomb 0xA9EFBA +#define fnShitroid_Main 0xA9EFC5 +#define fnShitroid_Func_3 0xA9EFDF +#define fnShitroid_Func_4 0xA9EFE6 +#define fnShitroid_Func_5 0xA9F02B +#define fnShitroid_Func_6 0xA9F037 +#define fnShitroid_Func_7 0xA9F049 +#define fnShitroid_Func_8 0xA9F06D +#define fnShitroid_Func_9 0xA9F094 +#define fnShitroid_Func_10 0xA9F0E6 +#define fnShitroid_Func_11 0xA9F125 +#define fnShitroid_Func_12 0xA9F138 +#define fnShitroid_Func_13 0xA9F180 +#define fnShitroid_Func_14 0xA9F1FA +#define fnShitroid_Func_15 0xA9F20E +#define fnShitroid_Func_16 0xA9F21B +#define fnShitroid_Func_17 0xA9F2A2 +#define fnShitroid_Func_18 0xA9F2AE +#define fnShitroid_Func_19 0xA9F2C0 +#define fnShitroid_Func_20 0xA9F2FB +#define fnShitroid_Func_21 0xA9F324 +#define fnShitroid_Func_22 0xA9F360 +#define fnShitroid_Func_23 0xA9F36D +#define fnShitroid_Func_24 0xA9F3A3 +#define fnShitroid_Func_25 0xA9F3BE +#define fnShitroid_GraduallyAccelerateTowards0x8 0xA9F45F +#define fnShitroid_GraduallyAccelerateTowards0x10 0xA9F466 +#define fnShitroid_HandleCutscenePalette 0xA9F683 +#define fnShitroid_HandleCutscenePalette_LowHealth 0xA9F68F +#define fnShitroid_Touch 0xA9F789 +#define fnShitroid_Shot 0xA9F842 +#define fnShitroid_Instr_3 0xA9F920 +#define fnShitroid_Instr_4 0xA9F936 +#define fnShitroid_Instr_6 0xA9F990 +#define fnShitroid_Instr_5 0xA9F994 +#define fnEnemy_GrappleReact_CancelBeam_AA 0xAA800F +#define fnEnemy_NormalPowerBombAI_AA 0xAA8037 +#define fnEnemy_NormalFrozenAI_AA 0xAA8041 +#define fnnullsub_170_AA 0xAA804C +#define fnEnemy_SetAiPreInstr_AA 0xAA806B +#define fnEnemy_ClearAiPreInstr_AA 0xAA8074 +#define fnnullsub_171_AA 0xAA807B +#define fnEnemyInstr_StopScript_AA 0xAA807C +#define fnEnemyInstr_Goto_AA 0xAA80ED +#define fnEnemyInstr_DecTimerAndGoto2_AA 0xAA8110 +#define fnEnemyInstr_SetTimer_AA 0xAA8123 +#define fnEnemyInstr_Sleep_AA 0xAA812F +#define fnEnemyInstr_WaitNframes_AA 0xAA813A +#define fnEnemyInstr_CopyToVram_AA 0xAA814B +#define fnTorizo_Instr_3 0xAAB09C +#define fnTorizo_Instr_31 0xAAB11D +#define fnTorizo_Instr_33 0xAAB1BE +#define fnTorizo_Instr_36 0xAAB224 +#define fnTorizo_Instr_37 0xAAB22E +#define fnTorizo_Instr_35 0xAAB238 +#define fnTorizo_Instr_38 0xAAB24D +#define fnTorizo_Instr_6 0xAAB271 +#define fnTorizo_Instr_5 0xAAB94D +#define fnTorizo_Instr_9 0xAAB951 +#define fnTorizo_Instr_7 0xAAC2C8 +#define fnTorizo_Instr_2 0xAAC2C9 +#define fnTorizo_Instr_8 0xAAC2D1 +#define fnTorizo_Instr_25 0xAAC2D9 +#define fnTorizo_Instr_22 0xAAC2ED +#define fnTorizo_Instr_19 0xAAC2F7 +#define fnTorizo_Instr_32 0xAAC2FD +#define fnTorizo_Instr_30 0xAAC303 +#define fnTorizo_Instr_34 0xAAC32F +#define fnTorizo_Instr_24 0xAAC34A +#define fnTorizo_Instr_12 0xAAC35B +#define fnTorizo_Instr_10 0xAAC36D +#define fnTorizo_Instr_11 0xAAC377 +#define fnTorizo_Instr_29 0xAAC38A +#define fnTorizo_Instr_1 0xAAC3A0 +#define fnTorizo_Instr_28 0xAAC3B6 +#define fnTorizo_Instr_4 0xAAC3CC +#define fnTorizo_Instr_40 0xAAC41E +#define fnTorizo_Instr_16 0xAAC470 +#define fnTorizo_Instr_27 0xAAC4E5 +#define fnTorizo_Instr_23 0xAAC55A +#define fnTorizo_Instr_14 0xAAC567 +#define fnTorizo_Instr_15 0xAAC58B +#define fnTorizo_Instr_26 0xAAC5A4 +#define fnTorizo_Instr_18 0xAAC5CB +#define fnTorizo_Instr_20 0xAAC5E3 +#define fnTorizo_Instr_44 0xAAC5F2 +#define fnTorizo_Instr_21 0xAAC601 +#define fnTorizo_Instr_17 0xAAC610 +#define fnTorizo_Instr_13 0xAAC618 +#define fnTorizo_Hurt 0xAAC67E +#define fnTorizo_Main 0xAAC6A4 +#define fnnullsub_270 0xAAC6AB +#define fnTorizo_Func_3 0xAAC6BF +#define fnTorizo_Func_4 0xAAC6C6 +#define fnTorizo_Func_1 0xAAC6FF +#define fnTorizo_Func_5 0xAAC752 +#define fnTorizo_Func_6 0xAAC828 +#define fnTorizo_Func_7 0xAAC82C +#define fnTorizo_Init 0xAAC87F +#define fnnullsub_344 0xAAC95E +#define fnGoldTorizo_Touch 0xAAC977 +#define fnTorizo_Shot 0xAAC97C +#define fnnullsub_271 0xAAC9C1 +#define fnTorizo_Func_8 0xAAC9C2 +#define fnTorizo_Instr_39 0xAACACE +#define fnTorizo_Instr_41 0xAACADE +#define fnTorizo_Instr_42 0xAACAE2 +#define fnTorizo_Instr_48 0xAACDD7 +#define fnTorizo_Instr_57 0xAAD0E9 +#define fnTorizo_Instr_58 0xAAD0F3 +#define fnTorizo_Instr_59 0xAAD17B +#define fnTorizo_Instr_62 0xAAD187 +#define fnTorizo_Instr_63 0xAAD1E7 +#define fnGoldTorizo_Main 0xAAD369 +#define fnTorizo_Instr_56 0xAAD38F +#define fnTorizo_Instr_60 0xAAD397 +#define fnTorizo_Instr_46 0xAAD39F +#define fnGoldTorizo_Hurt 0xAAD3BA +#define fnTorizo_Instr_47 0xAAD3E0 +#define fnTorizo_Instr_49 0xAAD3EA +#define fnTorizo_Instr_61 0xAAD436 +#define fnTorizo_Instr_53 0xAAD445 +#define fnTorizo_Instr_55 0xAAD474 +#define fnTorizo_Instr_52 0xAAD49B +#define fnTorizo_Instr_50 0xAAD4BA +#define fnTorizo_Instr_43 0xAAD4F3 +#define fnTorizo_Instr_51 0xAAD4FD +#define fnTorizo_Instr_45 0xAAD526 +#define fnTorizo_Instr_54 0xAAD54D +#define fnTorizo_Func_9 0xAAD5C2 +#define fnTorizo_Func_10 0xAAD5DF +#define fnTorizo_D5E6 0xAAD5E6 +#define fnTorizo_D5ED 0xAAD5ED +#define fnTorizo_D5F1 0xAAD5F1 +#define fnGoldTorizo_Shot 0xAAD667 +#define fnnullsub_49 0xAAD7C7 +#define fnTourianEntranceStatue_Init 0xAAD7C8 +#define fnShaktool_Instr_2 0xAAD931 +#define fnShaktool_Instr_3 0xAAD93F +#define fnShaktool_Instr_4 0xAAD94A +#define fnShaktool_Instr_5 0xAAD953 +#define fnShaktool_Instr_6 0xAAD99F +#define fnShaktool_Instr_1 0xAAD9BA +#define fnShaktool_Hurt 0xAADCA3 +#define fnnullsub_274 0xAADCAA +#define fnnullsub_275 0xAADCAB +#define fnShaktool_DCAC 0xAADCAC +#define fnShaktool_DCD7 0xAADCD7 +#define fnShaktool_DD25 0xAADD25 +#define fnShaktool_Init 0xAADE43 +#define fnShaktool_Touch 0xAADF2F +#define fnShaktool_Shot 0xAADF34 +#define fnShaktool_Instr_9 0xAAE429 +#define fnShaktool_Instr_11 0xAAE436 +#define fnShaktool_Instr_10 0xAAE43D +#define fnsub_AAE445 0xAAE445 +#define fnShaktool_Instr_8 0xAAE57F +#define fnShaktool_Instr_13 0xAAE587 +#define fnShaktool_Instr_12 0xAAE58F +#define fnShaktool_Instr_7 0xAAE5D8 +#define fnShaktool_Instr_14 0xAAE6F0 +#define fnN00bTubeCracks_Init 0xAAE716 +#define fnChozoStatue_Init 0xAAE725 +#define fnnullsub_276 0xAAE7A6 +#define fnChozoStatue_Main 0xAAE7A7 +#define fnShaktool_PreInstr_0 0xAAE7AE +#define fnnullsub_277 0xAAE7DA +#define fnnullsub_51 0xAAE7DB +#define fnnullsub_52 0xAAE7DC +#define fnEnemy_GrappleReact_CancelBeam_B2 0xB2800F +#define fnEnemy_NormalPowerBombAI_B2 0xB28037 +#define fnEnemy_NormalFrozenAI_B2 0xB28041 +#define fnnullsub_169_B2 0xB2804B +#define fnnullsub_170_B2 0xB2804C +#define fnEnemyInstr_Goto_B2 0xB280ED +#define fnEnemyInstr_DecTimerAndGoto2_B2 0xB28110 +#define fnEnemyInstr_SetTimer_B2 0xB28123 +#define fnEnemyInstr_Sleep_B2 0xB2812F +#define fnEnemyInstr_WaitNframes_B2 0xB2813A +#define fnWalkingSpacePirates_Powerbomb 0xB28767 +#define fnWalkingSpacePirates_Touch 0xB2876C +#define fnWalkingSpacePirates_Shot 0xB28779 +#define fnWalkingSpacePirates_87C8 0xB287C8 +#define fnWalkingSpacePirates_883E 0xB2883E +#define fnSpacePirates_Instr_MovePixelsDownAndChangeDirFaceRight 0xB2EE40 +#define fnSpacePirates_Instr_MovePixelsDownAndChangeDirFaceLeft 0xB2EE72 +#define fnSpacePirates_Instr_RandomNewDirFaceR 0xB2EEA4 +#define fnSpacePirates_Instr_RandomNewDirFaceL 0xB2EEBC +#define fnSpacePirates_Instr_PrepareWallJumpR 0xB2EED4 +#define fnSpacePirates_Instr_PrepareWallJumpL 0xB2EEFD +#define fnSpacePirates_Instr_FireLaserL 0xB2EF2A +#define fnSpacePirates_Instr_FireLaserR 0xB2EF5D +#define fnSpacePirates_Instr_SetEnemyFunc 0xB2EF83 +#define fnSpacePirates_Instr_PlaySfx 0xB2EF93 +#define fnWallSpacePirates_Init 0xB2EF9F +#define fnWallSpacePirates_Main 0xB2F02D +#define fnSpacePirates_Func_1 0xB2F034 +#define fnnullsub_279 0xB2F04F +#define fnSpacePirates_Func_2 0xB2F050 +#define fnSpacePirates_Func_3 0xB2F0C8 +#define fnnullsub_281 0xB2F0E3 +#define fnSpacePirates_Func_4 0xB2F0E4 +#define fnSpacePirates_Instr_20 0xB2F536 +#define fnSpacePirates_Instr_16 0xB2F546 +#define fnSpacePirates_Instr_15 0xB2F564 +#define fnSpacePirates_Instr_18 0xB2F590 +#define fnSpacePirates_Instr_17 0xB2F5D6 +#define fnNinjaSpacePirates_Init 0xB2F5DE +#define fnNinjaSpacePirates_Main 0xB2F6A2 +#define fnSpacePirates_Func_5 0xB2F6A9 +#define fnSpacePirates_Func_6 0xB2F6E4 +#define fnSpacePirates_Func_11 0xB2F817 +#define fnSpacePirates_Func_12 0xB2F84C +#define fnSpacePirates_Func_13 0xB2F890 +#define fnSpacePirates_Func_14 0xB2F8C5 +#define fnSpacePirates_Func_15 0xB2F909 +#define fnSpacePirates_Instr_19 0xB2F969 +#define fnSpacePirates_F985 0xB2F985 +#define fnSpacePirates_F9C1 0xB2F9C1 +#define fnSpacePirates_FA15 0xB2FA15 +#define fnSpacePirates_Instr_21 0xB2FA3D +#define fnSpacePirates_FA59 0xB2FA59 +#define fnSpacePirates_FA95 0xB2FA95 +#define fnSpacePirates_FAE9 0xB2FAE9 +#define fnSpacePirates_Instr_12 0xB2FC68 +#define fnSpacePirates_Instr_14 0xB2FC90 +#define fnSpacePirates_Instr_11 0xB2FCB8 +#define fnSpacePirates_Instr_13 0xB2FCC8 +#define fnWalkingSpacePirates_Init 0xB2FD02 +#define fnWalkingSpacePirates_Main 0xB2FD32 +#define fnWalkingSpacePirates_FD44 0xB2FD44 +#define fnWalkingSpacePirates_FDCE 0xB2FDCE +#define fnnullsub_282 0xB2FE4A +#define fnEnemy_GrappleReact_NoInteract_B3 0xB38000 +#define fnEnemy_GrappleReact_KillEnemy_B3 0xB3800A +#define fnEnemy_GrappleReact_CancelBeam_B3 0xB3800F +#define fnEnemy_NormalTouchAI_B3 0xB38023 +#define fnEnemy_NormalShotAI_B3 0xB3802D +#define fnEnemy_NormalPowerBombAI_B3 0xB38037 +#define fnEnemy_NormalFrozenAI_B3 0xB38041 +#define fnnullsub_170_B3 0xB3804C +#define fnEnemy_SetAiPreInstr_B3 0xB3806B +#define fnEnemy_ClearAiPreInstr_B3 0xB38074 +#define fnnullsub_171_B3 0xB3807B +#define fnEnemyInstr_Goto_B3 0xB380ED +#define fnEnemyInstr_DecTimerAndGoto2_B3 0xB38110 +#define fnEnemyInstr_SetTimer_B3 0xB38123 +#define fnEnemyInstr_Sleep_B3 0xB3812F +#define fnUnusedSpinningTurtleEye_Init 0xB386FB +#define fnUnusedSpinningTurtleEye_Main 0xB3870E +#define fnBrinstarPipeBug_Init 0xB3883B +#define fnBrinstarPipeBug_Main 0xB3887A +#define fnBrinstarPipeBug_PreInstr_1 0xB38880 +#define fnBrinstarPipeBug_PreInstr_2 0xB38890 +#define fnBrinstarPipeBug_PreInstr_3 0xB388E3 +#define fnBrinstarPipeBug_PreInstr_4 0xB3891C +#define fnBrinstarPipeBug_PreInstr_5 0xB3897E +#define fnNorfairPipeBug_Init 0xB38B61 +#define fnNorfairPipeBug_Main 0xB38B9E +#define fnNorfairPipeBug_Func_1 0xB38BCD +#define fnNorfairPipeBug_Func_2 0xB38BFF +#define fnNorfairPipeBug_Func_4 0xB38CA6 +#define fnNorfairPipeBug_Func_5 0xB38CFF +#define fnNorfairPipeBug_Func_6 0xB38D0C +#define fnNorfairPipeBug_Func_7 0xB38D4E +#define fnNorfairPipeBug_Func_8 0xB38D90 +#define fnNorfairPipeBug_Func_9 0xB38DD2 +#define fnNorfairPipeBug_Func_10 0xB38E14 +#define fnNorfairPipeBug_Func_11 0xB38E35 +#define fnNorfairPipeBug_Func_12 0xB38E5A +#define fnBrinstarYellowPipeBug_Init 0xB38F4C +#define fnBrinstarYellowPipeBug_Main 0xB38FAE +#define fnBrinstarYellowPipeBug_Func_1 0xB38FB5 +#define fnBrinstarYellowPipeBug_Func_2 0xB38FF5 +#define fnBrinstarYellowPipeBug_Func_3 0xB39028 +#define fnBrinstarYellowPipeBug_Func_5 0xB390BD +#define fnBrinstarYellowPipeBug_Func_7 0xB3915A +#define fnBrinstarYellowPipeBug_Func_8 0xB391D8 +#define fnBotwoon_Instr_1 0xB394C7 +#define fnBotwoon_Instr_2 0xB394D7 +#define fnBotwoon_Instr_3 0xB394E7 +#define fnBotwoon_Instr_4 0xB394F7 +#define fnBotwoon_Instr_5 0xB39507 +#define fnBotwoon_Instr_6 0xB39517 +#define fnBotwoon_Instr_7 0xB39527 +#define fnBotwoon_Instr_8 0xB39537 +#define fnBotwoon_Instr_9 0xB39547 +#define fnBotwoon_Instr_10 0xB39557 +#define fnBotwoon_Instr_SetSpitting 0xB39567 +#define fnBotwoon_Instr_QueueSpitSfx 0xB39572 +#define fnnullsub_30 0xB3957A +#define fnBotwoon_Init 0xB39583 +#define fnBotwoon_Main 0xB39668 +#define fnBotwoon_Func_1 0xB3967B +#define fnBotwoon_Func_2 0xB39696 +#define fnBotwoon_Func_3 0xB396C6 +#define fnBotwoon_Func_6 0xB39878 +#define fnBotwoon_Func_7 0xB3989D +#define fnBotwoon_Func_12 0xB399A4 +#define fnBotwoon_Func_13 0xB399E4 +#define fnBotwoon_Func_14 0xB39A46 +#define fnBotwoon_Func_15 0xB39A5E +#define fnBotwoon_Func_16 0xB39ACA +#define fnBotwoon_Func_18 0xB39AF9 +#define fnBotwoon_Func_19 0xB39BB7 +#define fnBotwoon_Func_26 0xB39DC0 +#define fnBotwoon_Func_27 0xB39E7D +#define fnBotwoon_Func_28 0xB39EE0 +#define fnBotwoon_Func_29 0xB39F34 +#define fnBotwoon_Func_30 0xB39F7A +#define fnBotwoon_Touch 0xB39FFF +#define fnBotwoon_Shot 0xB3A016 +#define fnBotwoon_Powerbomb 0xB3A041 +#define fnBotwoon_Func_32 0xB3E250 +#define fnBotwoon_Func_33 0xB3E28C +#define fnEscapeEtecoon_Instr_1 0xB3E545 +#define fnEscapeEtecoon_Instr_2 0xB3E610 +#define fnEscapeEtecoon_Main 0xB3E655 +#define fnEscapeEtecoon_E65C 0xB3E65C +#define fnEscapeEtecoon_Init 0xB3E6CB +#define fnEscapeDachora_Instr_2 0xB3EAA8 +#define fnEscapeDachora_Instr_3 0xB3EAB8 +#define fnEscapeDachora_Instr_1 0xB3EAC9 +#define fnEscapeDachora_Instr_4 0xB3EAD7 +#define fnEscapeDachora_Init 0xB3EAE5 +#define fnnullsub_54 0xB3EB1A +#define fnSpriteObject_Instr_RepeatLast 0xB4BCF0 +#define fnSpriteObject_Instr_Terminate 0xB4BD07 +#define fnSpriteObject_Instr_Goto 0xB4BD12 +#define fnlocret_828C81 0x828C81 +#define fnlocret_8B9585 0x8B9585 +#define FUNC16(x) ((fn##x) & 0xffff) diff --git a/src/glsl_shader.c b/src/glsl_shader.c new file mode 100644 index 0000000..534f6b9 --- /dev/null +++ b/src/glsl_shader.c @@ -0,0 +1,617 @@ +// This file is heavily influenced by Snes9x +#include "third_party/gl_core/gl_core_3_1.h" +#include "glsl_shader.h" +#include "util.h" +#include "config.h" +#include +#include +#include +#define STB_IMAGE_IMPLEMENTATION +#define STBI_NO_THREAD_LOCALS +#define STBI_ONLY_PNG +#define STBI_MAX_DIMENSIONS 4096 +#define STBI_NO_FAILURE_STRINGS +#include "third_party/stb/stb_image.h" + +static GlslPass *ParseConfigKeyPass(GlslShader *gs, const char *key, const char *match) { + char *endp; + for (; *match; key++, match++) { + if (*key != *match) + return NULL; + } + if ((uint8)(*key - '0') >= 10) + return NULL; + uint pass = strtoul(key, &endp, 10); + if (pass >= (uint)gs->n_pass || *endp != 0) + return NULL; + return gs->pass + pass + 1; +} + +static uint8 ParseScaleType(const char *s) { + return StringEqualsNoCase(s, "source") ? GLSL_SOURCE : + StringEqualsNoCase(s, "viewport") ? GLSL_VIEWPORT : + StringEqualsNoCase(s, "absolute") ? GLSL_ABSOLUTE : GLSL_NONE; +} + +static uint ParseWrapMode(const char *s) { + return StringEqualsNoCase(s, "repeat") ? GL_REPEAT : + StringEqualsNoCase(s, "clamp_to_edge") ? GL_CLAMP_TO_EDGE : + StringEqualsNoCase(s, "clamp") ? GL_CLAMP : GL_CLAMP_TO_BORDER; +} + +static void GlslPass_Initialize(GlslPass *pass) { + pass->scale_x = 1.0f; + pass->scale_y = 1.0f; + pass->wrap_mode = GL_CLAMP_TO_BORDER; +} + +static void ParseTextures(GlslShader *gs, char *value) { + char *id; + GlslTexture **nextp = &gs->first_texture; + for (int num = 0; (id = NextDelim(&value, ';')) != NULL && num < kGlslMaxTextures; num++) { + GlslTexture *t = (GlslTexture * )calloc(sizeof(GlslTexture), 1); + t->id = strdup(id); + t->wrap_mode = GL_CLAMP_TO_BORDER; + t->filter = GL_NEAREST; + *nextp = t; + nextp = &t->next; + } +} + +static bool ParseTextureKeyValue(GlslShader *gs, const char *key, const char *value) { + for (GlslTexture *t = gs->first_texture; t != NULL; t = t->next) { + const char *key2 = SkipPrefix(key, t->id); + if (!key2) continue; + if (*key2 == 0) { + StrSet(&t->filename, value); + return true; + } else if (!strcmp(key2, "_wrap_mode")) { + t->wrap_mode = ParseWrapMode(value); + return true; + } else if (!strcmp(key2, "_mipmap")) { + t->mipmap = ParseBool(value, NULL); + return true; + } else if (!strcmp(key2, "_linear")) { + t->filter = ParseBool(value, NULL) ? GL_LINEAR : GL_NEAREST; + return true; + } + } + return false; +} + +static GlslParam *GlslShader_GetParam(GlslShader *gs, const char *id) { + GlslParam **pp = &gs->first_param; + for (; (*pp) != NULL; pp = &(*pp)->next) + if (!strcmp((*pp)->id, id)) + return *pp; + GlslParam *p = (GlslParam *)calloc(1, sizeof(GlslParam)); + *pp = p; + p->id = strdup(id); + return p; +} + +static void ParseParameters(GlslShader *gs, char *value) { + char *id; + while ((id = NextDelim(&value, ';')) != NULL) + GlslShader_GetParam(gs, id); +} + +static bool ParseParameterKeyValue(GlslShader *gs, const char *key, const char *value) { + for (GlslParam *p = gs->first_param; p != NULL; p = p->next) { + if (strcmp(p->id, key) == 0) { + p->value = atof(value); + p->has_value = true; + return true; + } + } + return false; +} + +static void GlslShader_InitializePasses(GlslShader *gs, int passes) { + gs->n_pass = passes; + gs->pass = (GlslPass *)calloc(gs->n_pass + 1, sizeof(GlslPass)); + for (int i = 0; i < gs->n_pass; i++) + GlslPass_Initialize(gs->pass + i + 1); +} + +static bool GlslShader_ReadPresetFile(GlslShader *gs, const char *filename) { + char *data = (char *)ReadWholeFile(filename, NULL), *data_org = data, *line; + GlslPass *pass; + if (data == NULL) + return false; + for (int lineno = 1; (line = NextLineStripComments(&data)) != NULL; lineno++) { + char *value = SplitKeyValue(line), *t; + if (value == NULL) { + if (*line) + fprintf(stderr, "%s:%d: Expecting key=value\n", filename, lineno); + continue; + } + if (*value == '"') { + for (t = ++value; *t && *t != '"'; t++); + if (*t) *t = 0; + } + + if (gs->n_pass == 0) { + if (strcmp(line, "shaders") != 0) { + fprintf(stderr, "%s:%d: Expecting 'shaders'\n", filename, lineno); + break; + } + int passes = strtoul(value, NULL, 10); + if (passes < 1 || passes > kGlslMaxPasses) + break; + GlslShader_InitializePasses(gs, passes); + continue; + } + if ((pass = ParseConfigKeyPass(gs, line, "filter_linear")) != NULL) + pass->filter = ParseBool(value, NULL) ? GL_LINEAR : GL_NEAREST; + else if ((pass = ParseConfigKeyPass(gs, line, "scale_type")) != NULL) + pass->scale_type_x = pass->scale_type_y = ParseScaleType(value); + else if ((pass = ParseConfigKeyPass(gs, line, "scale_type_x")) != NULL) + pass->scale_type_x = ParseScaleType(value); + else if ((pass = ParseConfigKeyPass(gs, line, "scale_type_y")) != NULL) + pass->scale_type_y = ParseScaleType(value); + else if ((pass = ParseConfigKeyPass(gs, line, "scale")) != NULL) + pass->scale_x = pass->scale_y = atof(value); + else if ((pass = ParseConfigKeyPass(gs, line, "scale_x")) != NULL) + pass->scale_x = atof(value); + else if ((pass = ParseConfigKeyPass(gs, line, "scale_y")) != NULL) + pass->scale_y = atof(value); + else if ((pass = ParseConfigKeyPass(gs, line, "shader")) != NULL) + StrSet(&pass->filename, value); + else if ((pass = ParseConfigKeyPass(gs, line, "wrap_mode")) != NULL) + pass->wrap_mode = ParseWrapMode(value); + else if ((pass = ParseConfigKeyPass(gs, line, "mipmap_input")) != NULL) + pass->mipmap_input = ParseBool(value, NULL); + else if ((pass = ParseConfigKeyPass(gs, line, "frame_count_mod")) != NULL) + pass->frame_count_mod = atoi(value); + else if ((pass = ParseConfigKeyPass(gs, line, "float_framebuffer")) != NULL) + pass->float_framebuffer = ParseBool(value, NULL); + else if ((pass = ParseConfigKeyPass(gs, line, "srgb_framebuffer")) != NULL) + pass->srgb_framebuffer = ParseBool(value, NULL); + else if ((pass = ParseConfigKeyPass(gs, line, "alias")) != NULL) + ; + else if (strcmp(line, "textures") == 0 && gs->first_texture == NULL) + ParseTextures(gs, value); + else if (strcmp(line, "parameters") == 0) + ParseParameters(gs, value); + else if (!ParseTextureKeyValue(gs, line, value) && !ParseParameterKeyValue(gs, line, value)) + fprintf(stderr, "%s:%d: Unknown key '%s'\n", filename, lineno, line); + } + free(data_org); + return gs->n_pass != 0; +} + +void GlslShader_ReadShaderFile(GlslShader *gs, const char *filename, ByteArray *result) { + char *data = (char *)ReadWholeFile(filename, NULL), *data_org = data, *line; + if (data == NULL) { + fprintf(stderr, "Unable to read file '%s'\n", filename); + return; + } + while ((line = NextDelim(&data, '\n')) != NULL) { + size_t linelen = strlen(line); + if (linelen >= 8 && memcmp(line, "#include", 8) == 0) { + char *tt = line + 8; + char *new_filename = ReplaceFilenameWithNewPath(filename, NextPossiblyQuotedString(&tt)); + GlslShader_ReadShaderFile(gs, new_filename, result); + free(new_filename); + } else if (linelen >= 17 && memcmp(line, "#pragma parameter", 17) == 0) { + char *tt = line + 17; + GlslParam *param = GlslShader_GetParam(gs, NextPossiblyQuotedString(&tt)); + NextPossiblyQuotedString(&tt); // skip name + float value = atof(NextPossiblyQuotedString(&tt)); + if (!param->has_value) + param->value = value; + param->min = atof(NextPossiblyQuotedString(&tt)); + param->max = atof(NextPossiblyQuotedString(&tt)); + // skip step + } else { + line[linelen] = '\n'; + ByteArray_AppendData(result, (uint8 *)line, linelen + 1); + } + } + free(data_org); +} + +static bool GlslPass_Compile(GlslPass *p, uint type, const uint8 *data, size_t size) { + static const char kVertexPrefix[] = "#define VERTEX\n#define PARAMETER_UNIFORM\n"; + static const char kFragmentPrefix[] = "#define FRAGMENT\n#define PARAMETER_UNIFORM\n"; + const GLchar *strings[3]; + GLint lengths[3]; + char buffer[256]; + GLint compile_status = 0; + size_t skip = 0; + + if (size < 8 || memcmp(data, "#version", 8) != 0) { + strings[0] = "#version 330\n"; + lengths[0] = sizeof("#version 330\n") - 1; + } else { + while (skip < size && data[skip++] != '\n') {} + strings[0] = (char*)data; + lengths[0] = (int)skip; + } + strings[1] = (type == GL_VERTEX_SHADER) ? (char*)kVertexPrefix : kFragmentPrefix; + lengths[1] = (type == GL_VERTEX_SHADER) ? sizeof(kVertexPrefix) - 1 : sizeof(kFragmentPrefix) - 1; + strings[2] = (GLchar *)data + skip; + lengths[2] = (int)(size - skip); + uint shader = glCreateShader(type); + glShaderSource(shader, 3, strings, lengths); + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); + buffer[0] = 0; + glGetShaderInfoLog(shader, sizeof(buffer), NULL, buffer); + if (compile_status != GL_TRUE || buffer[0]) { + fprintf(stderr, "%s compiling %s shader in file '%s':\n%s\n", + compile_status != GL_TRUE ? "Error" : "While", + type == GL_VERTEX_SHADER ? "vertex" : "fragment", p->filename, buffer); + } + if (compile_status == GL_TRUE) + glAttachShader(p->gl_program, shader); + glDeleteShader(shader); + return (compile_status == GL_TRUE); +} + +static void GlslTextureUniform_Read(uint program, const char *prefix, int i, GlslTextureUniform *result) { + char buf[40]; + char *e = &buf[snprintf(buf, sizeof(buf), i >= 0 ? "%s%u" : "%s", prefix, i)]; + memcpy(e, "Texture", 8); + result->Texture = glGetUniformLocation(program, buf); + memcpy(e, "InputSize", 10); + result->InputSize = glGetUniformLocation(program, buf); + memcpy(e, "TextureSize", 12); + result->TextureSize = glGetUniformLocation(program, buf); + memcpy(e, "TexCoord", 9); + result->TexCoord = glGetAttribLocation(program, buf); +} + +static const float kMvpMatrixOrtho[16] = { + 2.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 2.0f, 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 1.0f +}; + +static void GlslShader_GetUniforms(GlslShader *gs) { + int pass_idx = 1; + gs->max_prev_frame = 0; + for (GlslPass *p = gs->pass + 1, *p_end = p + gs->n_pass; p < p_end; p++, pass_idx++) { + uint program = p->gl_program; + glUseProgram(program); + + GLint MVPMatrix = glGetUniformLocation(program, "MVPMatrix"); + if (MVPMatrix >= 0) + glUniformMatrix4fv(MVPMatrix, 1, GL_FALSE, kMvpMatrixOrtho); + + GlslTextureUniform_Read(program, "", -1, &p->unif.Top); + p->unif.OutputSize = glGetUniformLocation(program, "OutputSize"); + p->unif.FrameCount = glGetUniformLocation(program, "FrameCount"); + p->unif.FrameDirection = glGetUniformLocation(program, "FrameDirection"); + p->unif.LUTTexCoord = glGetAttribLocation(program, "LUTTexCoord"); + p->unif.VertexCoord = glGetAttribLocation(program, "VertexCoord"); + GlslTextureUniform_Read(program, "Orig", -1, &p->unif.Orig); + for (int j = 0; j < 7; j++) { + GlslTextureUniform_Read(program, "Prev", j ? j : -1, &p->unif.Prev[j]); + if (p->unif.Prev[j].Texture >= 0) + gs->max_prev_frame = j + 1; + } + for (int j = 0; j < gs->n_pass; j++) { + GlslTextureUniform_Read(program, "Pass", j, &p->unif.Pass[j]); + GlslTextureUniform_Read(program, "PassPrev", j, &p->unif.PassPrev[j]); + } + GlslTexture *t = gs->first_texture; + for (int j = 0; t != NULL; t = t->next, j++) + p->unif.Texture[j] = glGetUniformLocation(program, t->id); + for (GlslParam *pa = gs->first_param; pa != NULL; pa = pa->next) + pa->uniform[pass_idx] = glGetUniformLocation(program, pa->id); + } + glUseProgram(0); +} + +static bool IsGlslFilename(const char *filename) { + size_t len = strlen(filename); + return len >= 5 && memcmp(filename + len - 5, ".glsl", 5) == 0; +} + +GlslShader *GlslShader_CreateFromFile(const char *filename) { + char buffer[256]; + GLint link_status; + ByteArray shader_code = { 0 }; + bool success = false; + GlslShader *gs = (GlslShader *)calloc(sizeof(GlslShader), 1); + if (!gs) + return gs; + + if (IsGlslFilename(filename)) { + GlslShader_InitializePasses(gs, 1); + gs->pass[1].filename = strdup(filename); + filename = ""; + } else { + if (!GlslShader_ReadPresetFile(gs, filename)) { + fprintf(stderr, "Unable to read file '%s'\n", filename); + goto FAIL; + } + } + for (int i = 1; i <= gs->n_pass; i++) { + GlslPass *p = gs->pass + i; + shader_code.size = 0; + + if (p->filename == NULL) { + fprintf(stderr, "shader%d attribute missing\n", i - 1); + goto FAIL; + } + + char *new_filename = ReplaceFilenameWithNewPath(filename, p->filename); + GlslShader_ReadShaderFile(gs, new_filename, &shader_code); + free(new_filename); + + if (shader_code.size == 0) { + fprintf(stderr, "Couldn't read shader in file '%s'\n", p->filename); + goto FAIL; + } + p->gl_program = glCreateProgram(); + if (!GlslPass_Compile(p, GL_VERTEX_SHADER, shader_code.data, shader_code.size) || + !GlslPass_Compile(p, GL_FRAGMENT_SHADER, shader_code.data, shader_code.size)) { + goto FAIL; + } + glLinkProgram(p->gl_program); + glGetProgramiv(p->gl_program, GL_LINK_STATUS, &link_status); + buffer[0] = 0; + glGetProgramInfoLog(p->gl_program, sizeof(buffer), NULL, buffer); + if (link_status != GL_TRUE || buffer[0]) + fprintf(stderr, "%s linking shader in file '%s':\n%s\n", + link_status != GL_TRUE ? "Error" : "While", p->filename, buffer); + if (link_status != GL_TRUE) + goto FAIL; + glGenFramebuffers(1, &p->gl_fbo); + glGenTextures(1, &p->gl_texture); + } + for (GlslTexture *t = gs->first_texture; t; t = t->next) { + glGenTextures(1, &t->gl_texture); + glBindTexture(GL_TEXTURE_2D, t->gl_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, t->wrap_mode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, t->wrap_mode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, t->filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, t->mipmap ? + (t->filter == GL_LINEAR ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST) : t->filter); + if (t->filename) { + char *new_filename = ReplaceFilenameWithNewPath(filename, t->filename); + int imw, imh, imn; + unsigned char *data = stbi_load(new_filename, &imw, &imh, &imn, 0); + if (!data) { + fprintf(stderr, "Unable to read PNG '%s'\n", new_filename); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imw, imh, 0, + (imn == 4) ? GL_RGBA : (imn == 3) ? GL_RGB : GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + } + free(data); + free(new_filename); + } + if (t->mipmap) + glGenerateMipmap(GL_TEXTURE_2D); + } + for (GlslParam *p = gs->first_param; p; p = p->next) + p->value = (p->value < p->min) ? p->min : (p->value > p->max) ? p->max : p->value; + + GlslShader_GetUniforms(gs); + + for (int i = 0; i < gs->max_prev_frame; i++) + glGenTextures(1, &gs->prev_frame[-i - 1 & 7].gl_texture); + + static const GLfloat kTexCoords[16] = { + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f + }; + glGenBuffers(1, &gs->gl_vbo); + glBindBuffer(GL_ARRAY_BUFFER, gs->gl_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(kTexCoords), kTexCoords, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + success = true; +FAIL: + if (!success) { + GlslShader_Destroy(gs); + gs = NULL; + } + ByteArray_Destroy(&shader_code); + return gs; +} + +void GlslShader_Destroy(GlslShader *gs) { + for (GlslPass *p = gs->pass + 1, *p_end = p + gs->n_pass; p < p_end; p++) { + glDeleteProgram(p->gl_program); + glDeleteTextures(1, &p->gl_texture); + glDeleteFramebuffers(1, &p->gl_fbo); + free(p->filename); + } + free(gs->pass); + GlslTexture *t; + while ((t = gs->first_texture) != NULL) { + gs->first_texture = t->next; + glDeleteTextures(1, &t->gl_texture); + free(t->id); + free(t->filename); + free(t); + } + GlslParam *pp; + while ((pp = gs->first_param) != NULL) { + gs->first_param = pp->next; + free(pp->id); + free(pp); + } + for (int i = 0; i < 8; i++) + glDeleteTextures(1, &gs->prev_frame[i].gl_texture); + glDeleteBuffers(1, &gs->gl_vbo); + free(gs); +} + +enum { + kMaxVaosInRenderCtx = 11 + kGlslMaxPasses * 2 +}; + +typedef struct RenderCtx { + uint texture_unit; + uint offset; + uint num_vaos; + uint vaos[kMaxVaosInRenderCtx]; +} RenderCtx; + +static void RenderCtx_SetTexture(RenderCtx *ctx, int textureu, uint texture_id) { + if (textureu >= 0) { + glActiveTexture(GL_TEXTURE0 + ctx->texture_unit); + glBindTexture(GL_TEXTURE_2D, texture_id); + glUniform1i(textureu, ctx->texture_unit++); + } +} + +static void RenderCtx_SetTexCoords(RenderCtx *ctx, int tex_coord, uintptr_t offset) { + if (tex_coord >= 0) { + assert(ctx->num_vaos < kMaxVaosInRenderCtx); + ctx->vaos[ctx->num_vaos++] = tex_coord; + glVertexAttribPointer(tex_coord, 2, GL_FLOAT, GL_FALSE, 0, (void *)offset); + glEnableVertexAttribArray(tex_coord); + } +} + +static void RenderCtx_SetGlslTextureUniform(RenderCtx *ctx, GlslTextureUniform *u, + int width, int height, uint texture) { + float size[2] = { (float)width, (float)height }; + RenderCtx_SetTexture(ctx, u->Texture, texture); + if (u->InputSize >= 0) + glUniform2fv(u->InputSize, 1, size); + if (u->TextureSize >= 0) + glUniform2fv(u->TextureSize, 1, size); + RenderCtx_SetTexCoords(ctx, u->TexCoord, ctx->offset); +} + +static void GlslShader_SetShaderVars(GlslShader *gs, RenderCtx *ctx, int pass) { + GlslPass *p = &gs->pass[pass]; + + RenderCtx_SetGlslTextureUniform(ctx, &p->unif.Top, p[-1].width, p[-1].height, p[-1].gl_texture); + if (p->unif.OutputSize >= 0) { + float output_size[2] = { (float)p[0].width, (float)p[0].height }; + glUniform2fv(p->unif.OutputSize, 1, output_size); + } + if (p->unif.FrameCount >= 0) + glUniform1i(p->unif.FrameCount, p->frame_count_mod ? + gs->frame_count % p->frame_count_mod : gs->frame_count); + if (p->unif.FrameDirection >= 0) + glUniform1i(p->unif.FrameDirection, 1); + RenderCtx_SetTexCoords(ctx, p->unif.LUTTexCoord, ctx->offset); + RenderCtx_SetTexCoords(ctx, p->unif.VertexCoord, 0); + RenderCtx_SetGlslTextureUniform(ctx, &p->unif.Orig, gs->pass[0].width, gs->pass[0].height, gs->pass[0].gl_texture); + // Prev, Prev1-Prev6 uniforms + for (int i = 0; i < gs->max_prev_frame; i++) { + GlTextureWithSize *t = &gs->prev_frame[(gs->frame_count - 1 - i) & 7]; + assert(t->gl_texture != 0); + if (t->width) + RenderCtx_SetGlslTextureUniform(ctx, &p->unif.Prev[i], t->width, t->height, t->gl_texture); + } + // Texture uniforms + int tctr = 0; + for (GlslTexture *t = gs->first_texture; t; t = t->next, tctr++) + RenderCtx_SetTexture(ctx, p->unif.Texture[tctr], t->gl_texture); + // PassX uniforms + for (int i = 1; i < pass; i++) + RenderCtx_SetGlslTextureUniform(ctx, &p->unif.Pass[i], gs->pass[i].width, gs->pass[i].height, gs->pass[i].gl_texture); + // PassPrevX uniforms + for (int i = 1; i < pass; i++) + RenderCtx_SetGlslTextureUniform(ctx, &p->unif.PassPrev[pass - i], gs->pass[i].width, gs->pass[i].height, gs->pass[i].gl_texture); + // #parameter uniforms + for (GlslParam *pa = gs->first_param; pa != NULL; pa = pa->next) + if (pa->uniform[pass] >= 0) + glUniform1f(pa->uniform[pass], pa->value); + + glActiveTexture(GL_TEXTURE0); +} + +void GlslShader_Render(GlslShader *gs, GlTextureWithSize *tex, int viewport_x, int viewport_y, int viewport_width, int viewport_height) { + gs->pass[0].gl_texture = tex->gl_texture; + gs->pass[0].width = tex->width; + gs->pass[0].height = tex->height; + + GLint previous_framebuffer; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &previous_framebuffer); + glBindBuffer(GL_ARRAY_BUFFER, gs->gl_vbo); + + for (int pass = 1; pass <= gs->n_pass; pass++) { + bool last_pass = pass == gs->n_pass; + GlslPass *p = gs->pass + pass; + + switch (p->scale_type_x) { + case GLSL_ABSOLUTE: p->width = (uint16)p->scale_x; break; + case GLSL_SOURCE: p->width = (uint16)(p[-1].width * p->scale_x); break; + case GLSL_VIEWPORT: p->width = (uint16)(viewport_width * p->scale_x); break; + default: p->width = (uint16)(last_pass ? viewport_width : (p[-1].width * p->scale_x)); break; + } + + switch (p->scale_type_y) { + case GLSL_ABSOLUTE: p->height = (uint16)p->scale_y; break; + case GLSL_SOURCE: p->height = (uint16)(p[-1].height * p->scale_y); break; + case GLSL_VIEWPORT: p->height = (uint16)(viewport_height * p->scale_y); break; + default: p->height = (uint16)(last_pass ? viewport_height : (p[-1].height * p->scale_y)); break; + } + + if (!last_pass) { + // output to a texture + glBindTexture(GL_TEXTURE_2D, p->gl_texture); + if (p->srgb_framebuffer) { + glEnable(GL_FRAMEBUFFER_SRGB); + glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, p->width, p->height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, NULL); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, p->float_framebuffer ? GL_RGBA32F : GL_RGBA, + p->width, p->height, 0, GL_RGBA, + p->float_framebuffer ? GL_FLOAT : GL_UNSIGNED_INT_8_8_8_8, NULL); + } + glViewport(0, 0, p->width, p->height); + glBindFramebuffer(GL_FRAMEBUFFER, p->gl_fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p->gl_texture, 0); + } else { + // output to screen + glBindFramebuffer(GL_FRAMEBUFFER, previous_framebuffer); + glViewport(viewport_x, viewport_y, viewport_width, viewport_height); + } + + glBindTexture(GL_TEXTURE_2D, p[-1].gl_texture); + + uint filter = p->filter ? p->filter : (last_pass && g_config.linear_filtering) ? GL_LINEAR : GL_NEAREST; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, p->mipmap_input ? + (filter == GL_LINEAR ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST) : filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, p->wrap_mode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, p->wrap_mode); + if (p->mipmap_input) + glGenerateMipmap(GL_TEXTURE_2D); + glUseProgram(p->gl_program); + + RenderCtx ctx; + ctx.texture_unit = ctx.num_vaos = 0; + ctx.offset = last_pass ? sizeof(float) * 8 : 0; + GlslShader_SetShaderVars(gs, &ctx, pass); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + for(int i = 0; i < (int)ctx.num_vaos; i++) + glDisableVertexAttribArray(ctx.vaos[i]); + if (p->srgb_framebuffer) + glDisable(GL_FRAMEBUFFER_SRGB); + } + + glBindFramebuffer(GL_FRAMEBUFFER, previous_framebuffer); + glUseProgram(0); + glBindTexture(GL_TEXTURE_2D, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + // Store the input frame in the prev array, and extract the next one. + if (gs->max_prev_frame != 0) { + // 01234567 + // 43210 + // ^-- store pos + // ^-- load pos + GlTextureWithSize *store_pos = &gs->prev_frame[gs->frame_count & 7]; + GlTextureWithSize *load_pos = &gs->prev_frame[gs->frame_count - gs->max_prev_frame & 7]; + assert(store_pos->gl_texture == 0); + *store_pos = *tex; + *tex = *load_pos; + memset(load_pos, 0, sizeof(GlTextureWithSize)); + } + + gs->frame_count++; +} + diff --git a/src/glsl_shader.h b/src/glsl_shader.h new file mode 100644 index 0000000..e48a65a --- /dev/null +++ b/src/glsl_shader.h @@ -0,0 +1,99 @@ +#ifndef ZELDA3_GLSL_SHADER_H_ +#define ZELDA3_GLSL_SHADER_H_ + +#include "types.h" + +enum { + kGlslMaxPasses = 20, + kGlslMaxTextures = 10, +}; + +enum GLSLScaleType { + GLSL_NONE, + GLSL_SOURCE, + GLSL_VIEWPORT, + GLSL_ABSOLUTE +}; + +typedef struct GlslTextureUniform { + int Texture; + int InputSize; + int TextureSize; + int TexCoord; +} GlslTextureUniform; + +typedef struct GlslUniforms { + GlslTextureUniform Top; + int OutputSize; + int FrameCount, FrameDirection; + int LUTTexCoord; + int VertexCoord; + GlslTextureUniform Orig; + GlslTextureUniform Prev[7]; + GlslTextureUniform Pass[kGlslMaxPasses]; + GlslTextureUniform PassPrev[kGlslMaxPasses]; + int Texture[kGlslMaxTextures]; +} GlslUniforms; + +typedef struct GlslPass { + char *filename; + uint8 scale_type_x, scale_type_y; + bool float_framebuffer; + bool srgb_framebuffer; + bool mipmap_input; + float scale_x, scale_y; + uint wrap_mode; + uint frame_count_mod; + uint frame_count; + uint gl_program, gl_fbo; + uint filter; + uint gl_texture; + uint16 width, height; + GlslUniforms unif; +} GlslPass; + +typedef struct GlTextureWithSize { + uint gl_texture; + uint16 width, height; +} GlTextureWithSize; + +typedef struct GlslTexture { + struct GlslTexture *next; + char *id; + char *filename; + uint filter; + uint gl_texture; + uint wrap_mode; + bool mipmap; + int width; + int height; +} GlslTexture; + +typedef struct GlslParam { + struct GlslParam *next; + char *id; + bool has_value; + float value; + float min; + float max; + uint uniform[kGlslMaxPasses]; +} GlslParam; + +typedef struct GlslShader { + int n_pass; + GlslPass *pass; + GlslParam *first_param; + GlslTexture *first_texture; + uint *gl_vao; + uint gl_vbo; + uint frame_count; + int max_prev_frame; + GlTextureWithSize prev_frame[8]; +} GlslShader; + +GlslShader *GlslShader_CreateFromFile(const char *filename); +void GlslShader_Destroy(GlslShader *gs); +void GlslShader_Render(GlslShader *gs, GlTextureWithSize *tex, int viewport_x, int viewport_y, int viewport_width, int viewport_height); + + +#endif // ZELDA3_GLSL_SHADER_H_ diff --git a/src/ida_types.h b/src/ida_types.h new file mode 100644 index 0000000..37ad0f5 --- /dev/null +++ b/src/ida_types.h @@ -0,0 +1,2792 @@ +/* + This file has been generated by IDA. + It contains local type definitions from + the type library 'data.x86.bin_20221113031206' +*/ + + +#include "types.h" +#include "sm_rtl.h" + +#pragma pack(push, 1) + +/* 2 */ +typedef struct PlmHeader_Size4 { + VoidP func_ptr; + VoidP instr_list_ptr; +} PlmHeader_Size4; + +/* 3 */ +typedef struct FxDef { + uint16 door_ptr; + uint16 base_y_pos; + uint16 target_y_pos; + uint16 y_vel; + uint8 timer; + uint8 type; + uint8 default_layer_blend; + uint8 layer3_layer_blend; + uint8 fx_liquid_options_; + uint8 palette_fx_bitset; + uint8 animtiles_bitset; + uint8 palette_blend; +} FxDef; + +/* 4 */ +typedef struct LoadStationList { + VoidP room_ptr; + VoidP door_ptr; + uint16 door_bts; + uint16 screen_x_pos; + uint16 screen_y_pos; + uint16 samus_y_offset; + uint16 samus_x_offset; +} LoadStationList; + +/* 5 */ +typedef struct DebugDoorDef { + VoidP room_definition_ptr; + uint8 door_bitflags; + uint8 door_orientation; + uint8 x_pos_plm; + uint8 y_pos_plm; + uint8 x_pos_in_room; + uint8 y_pos_in_room; + uint8 field_8; + uint16 field_9; +} DebugDoorDef; + +/* 6 */ +typedef struct XraySpecialCasing { + uint8 x_block; + uint8 y_block; + uint16 level_data_block; +} XraySpecialCasing; + +/* 7 */ +typedef struct SpawnHardcodedPlmArgs { + uint8 field_0; + uint8 field_1; + VoidP field_2; +} SpawnHardcodedPlmArgs; + +/* 8 */ +typedef struct RoomPlmEntry { + VoidP plm_header_ptr_; + uint8 x_block; + uint8 y_block; + uint16 plm_room_argument; +} RoomPlmEntry; + +/* 9 */ +typedef struct PlmHeader_Size6 { + VoidP func_ptr; + VoidP instr_list_1_ptr; + VoidP instr_list_2_ptr; +} PlmHeader_Size6; + +/* 10 */ +typedef struct MsgBoxConfig { + VoidP modify_box_func; + VoidP draw_initial_tilemap; + VoidP message_tilemap; +} MsgBoxConfig; + +/* 11 */ +typedef struct EnemyProjectileDef { + VoidP init_code_ptr; + VoidP pre_instr_ptr; + VoidP instr_list; + uint16 radius; + uint16 properties; + VoidP hit_instruction_list; + VoidP shot_instruction_list; +} EnemyProjectileDef; + +/* 12 */ +typedef struct Eproj_InitXYVelRandom_Args { + VoidP field_0; + uint16 field_2; + uint16 field_4; + uint16 field_6; + uint16 field_8; +} Eproj_InitXYVelRandom_Args; + +/* 84 */ +typedef uint16 uint16; + +/* 13 */ +typedef struct EnemyData { + uint16 enemy_ptr; + uint16 x_pos; + uint16 x_subpos; + uint16 y_pos; + uint16 y_subpos; + uint16 x_width; + uint16 y_height; + uint16 properties; + uint16 extra_properties; + uint16 ai_handler_bits; + uint16 health; + uint16 spritemap_pointer; + uint16 timer; + uint16 current_instruction; + uint16 instruction_timer; + uint16 palette_index; + uint16 vram_tiles_index; + uint16 layer; + uint16 flash_timer; + uint16 frozen_timer; + uint16 invincibility_timer; + uint16 shake_timer; + uint16 frame_counter; + uint8 bank; + uint8 field_2F; + uint16 ai_var_A; + uint16 ai_var_B; + uint16 ai_var_C; + uint16 ai_var_D; + uint16 ai_var_E; + uint16 ai_preinstr; + uint16 parameter_1; + uint16 parameter_2; +} EnemyData; + +typedef struct EnemyBase { + uint16 enemy_ptr; + uint16 x_pos; + uint16 x_subpos; + uint16 y_pos; + uint16 y_subpos; + uint16 x_width; + uint16 y_height; + uint16 properties; + uint16 extra_properties; + uint16 ai_handler_bits; + uint16 health; + uint16 spritemap_pointer; + uint16 timer; + uint16 current_instruction; + uint16 instruction_timer; + uint16 palette_index; + uint16 vram_tiles_index; + uint16 layer; + uint16 flash_timer; + uint16 frozen_timer; + uint16 invincibility_timer; + uint16 shake_timer; + uint16 frame_counter; + uint8 bank; + uint8 field_2F; +} EnemyBase; + + +/* 14 */ +typedef struct AnimtilesDef { + VoidP instruction_list; + uint16 size; + uint16 vram_addr; +} AnimtilesDef; + +/* 15 */ +typedef struct HdmaScrollEntry { + uint16 top_pos; + uint16 scroll_subspeed; + uint16 scroll_speed; + VoidP hdma_data_table_entry; +}HdmaScrollEntry; + +/* 16 */ +typedef struct SpawnHdmaObject_Args { + uint8 field_0; + uint8 field_1; + VoidP addr; +}SpawnHdmaObject_Args; + +/* 17 */ +typedef struct CinematicSpriteObjectDef { + VoidP init_func; + VoidP pre_instr_func; + VoidP instr_list; +}CinematicSpriteObjectDef; + +/* 18 */ +typedef struct Mode7ObjectDef { + VoidP field_0; + VoidP field_2; + VoidP field_4; +}Mode7ObjectDef; + +/* 19 */ +typedef struct Mode7TransferData { + uint8 field_0; +}Mode7TransferData; + +/* 20 */ +typedef struct CinematicBgObjectDef { + VoidP init_func; + VoidP pre_instr_func; + VoidP instr_list; +}CinematicBgObjectDef; + +/* 21 */ +typedef struct PalFxDef { + VoidP func; + VoidP instrs; +}PalFxDef; + +/* 22 */ +typedef struct RoomDefStateSelect_E6E5_Finish { + VoidP code_ptr; +}RoomDefStateSelect_E6E5_Finish; + +/* 23 */ +typedef struct LoadBg_E { + uint16 field_0; + uint16 field_2; +}LoadBg_E; + +/* 24 */ +typedef struct LoadBg_28 { + uint16 field_0; + uint16 field_2; +}LoadBg_28; + +/* 25 */ +typedef struct LoadBg_4 { + uint16 field_0; +}LoadBg_4; + +/* 26 */ +enum LoadLibaryOpcode { + kLoadLibOp_0_DONE = 0x0, + kLoadBg_2_TransferToVram = 0x2, + kLoadBg_4_Decompress = 0x4, + kLoadLibOp_6_ClearFxTilemap = 0x6, + kLoadBg_8_TransferToVramSetBG3 = 0x8, + kLoadLibaryOpcode_A_ClearBG2Tilemap = 0xA, + kLoadLibaryOpcode_C_ClearKraidLayer2 = 0xC, + kLoadBg_E_DoorDepXferVram = 0xE, +}; + +/* 27 */ +typedef struct DoorDef { + VoidP room_definition_ptr; + uint8 door_bitflags; + uint8 door_orientation; + uint8 x_pos_plm; + uint8 y_pos_plm; + uint8 x_pos_in_room; + uint8 y_pos_in_room; + uint16 samus_distance_from_door; + VoidP door_setup_code; +}DoorDef; + +/* 28 */ +typedef enum SamusPose { + kPose_00_FaceF_Powersuit = 0x0, + kPose_01_FaceR_Normal = 0x1, + kPose_02_FaceL_Normal = 0x2, + kPose_03_FaceR_AimU = 0x3, + kPose_04_FaceL_AimU = 0x4, + kPose_05_FaceR_AimUR = 0x5, + kPose_06_FaceL_AimUL = 0x6, + kPose_07_FaceR_AimDR = 0x7, + kPose_08_FaceL_AimDL = 0x8, + kPose_09_MoveR_NoAim = 0x9, + kPose_0A_MoveL_NoAim = 0xA, + kPose_0B_MoveR_Gun = 0xB, + kPose_0C_MoveL_Gun = 0xC, + kPose_0F_MoveR_AimUR = 0xF, + kPose_10_MoveL_AimUL = 0x10, + kPose_11_MoveR_AimDR = 0x11, + kPose_12_MoveL_AimDL = 0x12, + kPose_13_FaceR_Jump_NoAim_NoMove_Gun = 0x13, + kPose_14_FaceL_Jump_NoAim_NoMove_Gun = 0x14, + kPose_15_FaceR_Jump_AimU = 0x15, + kPose_16_FaceL_Jump_AimU = 0x16, + kPose_17_FaceR_Jump_AimD = 0x17, + kPose_18_FaceL_Jump_AimD = 0x18, + kPose_19_FaceR_SpinJump = 0x19, + kPose_1A_FaceL_SpinJump = 0x1A, + kPose_1B_FaceR_SpaceJump = 0x1B, + kPose_1C_FaceL_SpaceJump = 0x1C, + kPose_1D_FaceR_Morphball_Ground = 0x1D, + kPose_1E_MoveR_Morphball_Ground = 0x1E, + kPose_1F_MoveL_Morphball_Ground = 0x1F, + kPose_25_FaceR_Turn_Stand = 0x25, + kPose_26_FaceL_Turn_Stand = 0x26, + kPose_27_FaceR_Crouch = 0x27, + kPose_28_FaceL_Crouch = 0x28, + kPose_29_FaceR_Fall = 0x29, + kPose_2A_FaceL_Fall = 0x2A, + kPose_2B_FaceR_Fall_AimU = 0x2B, + kPose_2C_FaceL_Fall_AimU = 0x2C, + kPose_2D_FaceR_Fall_AimD = 0x2D, + kPose_2E_FaceL_Fall_AimD = 0x2E, + kPose_2F_FaceR_Turn_Jump = 0x2F, + kPose_30_FaceL_Turn_Jump = 0x30, + kPose_31_FaceR_Morphball_Air = 0x31, + kPose_32_FaceL_Morphball_Air = 0x32, + kPose_35_FaceR_CrouchTrans = 0x35, + kPose_36_FaceL_CrouchTrans = 0x36, + kPose_37_FaceR_MorphTrans = 0x37, + kPose_38_FaceL_MorphTrans = 0x38, + kPose_3B_FaceR_StandTrans = 0x3B, + kPose_3C_FaceL_StandTrans = 0x3C, + kPose_3D_FaceR_UnmorphTrans = 0x3D, + kPose_3E_FaceL_UnmorphTrans = 0x3E, + kPose_41_FaceL_Morphball_Ground = 0x41, + kPose_43_FaceR_Turn_Crouch = 0x43, + kPose_44_FaceL_Turn_Crouch = 0x44, + kPose_49_FaceL_Moonwalk = 0x49, + kPose_4A_FaceR_Moonwalk = 0x4A, + kPose_4B_FaceR_Jumptrans = 0x4B, + kPose_4C_FaceL_Jumptrans = 0x4C, + kPose_4D_FaceR_Jump_NoAim_NoMove_NoGun = 0x4D, + kPose_4E_FaceL_Jump_NoAim_NoMove_NoGun = 0x4E, + kPose_4F_FaceL_Dmgboost = 0x4F, + kPose_50_FaceR_Dmgboost = 0x50, + kPose_51_FaceR_Jump_NoAim_MoveF = 0x51, + kPose_52_FaceL_Jump_NoAim_MoveF = 0x52, + kPose_53_FaceR_Knockback = 0x53, + kPose_54_FaceL_Knockback = 0x54, + kPose_55_FaceR_Jumptrans_AimU = 0x55, + kPose_56_FaceL_Jumptrans_AimU = 0x56, + kPose_57_FaceR_Jumptrans_AimUR = 0x57, + kPose_58_FaceL_Jumptrans_AimUL = 0x58, + kPose_59_FaceR_Jumptrans_AimDR = 0x59, + kPose_5A_FaceL_Jumptrans_AimDL = 0x5A, + kPose_5B = 0x5B, + kPose_67_FaceR_Fall_Gun = 0x67, + kPose_68_FaceL_Fall_Gun = 0x68, + kPose_69_FaceR_Jump_AimUR = 0x69, + kPose_6A_FaceL_Jump_AimUL = 0x6A, + kPose_6B_FaceR_Jump_AimDR = 0x6B, + kPose_6C_FaceL_Jump_AimDL = 0x6C, + kPose_6D_FaceR_Fall_AimUR = 0x6D, + kPose_6E_FaceL_Fall_AimUL = 0x6E, + kPose_6F_FaceR_Fall_AimDR = 0x6F, + kPose_70_FaceL_Fall_AimDL = 0x70, + kPose_71_FaceR_Crouch_AimUR = 0x71, + kPose_72_FaceL_Crouch_AimUL = 0x72, + kPose_73_FaceR_Crouch_AimDR = 0x73, + kPose_74_FaceL_Crouch_AimDL = 0x74, + kPose_75_FaceL_Moonwalk_AimUL = 0x75, + kPose_76_FaceR_Moonwalk_AimUR = 0x76, + kPose_77_FaceL_Moonwalk_AimDL = 0x77, + kPose_78_FaceR_Moonwalk_AimDR = 0x78, + kPose_79_FaceR_Springball_Ground = 0x79, + kPose_7A_FaceL_Springball_Ground = 0x7A, + kPose_7B_MoveR_Springball_Ground = 0x7B, + kPose_7C_MoveL_Springball_Ground = 0x7C, + kPose_7D_FaceR_Springball_Fall = 0x7D, + kPose_7E_FaceL_Springball_Fall = 0x7E, + kPose_7F_FaceR_Springball_Air = 0x7F, + kPose_80_FaceL_Springball_Air = 0x80, + kPose_81_FaceR_Screwattack = 0x81, + kPose_82_FaceL_Screwattack = 0x82, + kPose_83_FaceR_Walljump = 0x83, + kPose_84_FaceL_Walljump = 0x84, + kPose_85_FaceR_Crouch_AimU = 0x85, + kPose_86_FaceL_Crouch_AimU = 0x86, + kPose_87_FaceR_Turn_Fall = 0x87, + kPose_88_FaceL_Turn_Fall = 0x88, + kPose_89_FaceR_Ranintowall = 0x89, + kPose_8A_FaceL_Ranintowall = 0x8A, + kPose_8B_FaceR_Turn_Stand_AimU = 0x8B, + kPose_8C_FaceL_Turn_Stand_AimU = 0x8C, + kPose_8D_FaceR_Turn_Stand_AimDR = 0x8D, + kPose_8E_FaceL_Turn_Stand_AimDL = 0x8E, + kPose_8F_FaceR_Turn_Air_AimU = 0x8F, + kPose_90_FaceL_Turn_Air_AimU = 0x90, + kPose_91_FaceR_Turn_Air_AimDDR = 0x91, + kPose_92_FaceL_Turn_Air_AimDDL = 0x92, + kPose_93_FaceR_Turn_Fall_AimU = 0x93, + kPose_94_FaceL_Turn_Fall_AimU = 0x94, + kPose_95_FaceR_Turn_Fall_AimDDR = 0x95, + kPose_96_FaceL_Turn_Fall_AimDDL = 0x96, + kPose_97_FaceR_Turn_Crouch_AimU = 0x97, + kPose_98_FaceL_Turn_Crouch_AimU = 0x98, + kPose_99_FaceR_Turn_Crouch_AimDDR = 0x99, + kPose_9A_FaceL_Turn_Crouch_AimDDL = 0x9A, + kPose_9B_FaceF_VariaGravitySuit = 0x9B, + kPose_9C_FaceR_Turn_Stand_AimUR = 0x9C, + kPose_9D_FaceL_Turn_Stand_AimUL = 0x9D, + kPose_9E_FaceR_Turn_Air_AimUR = 0x9E, + kPose_9F_FaceL_Turn_Air_AimUL = 0x9F, + kPose_A0_FaceR_Turn_Fall_AimUR = 0xA0, + kPose_A1_FaceL_Turn_Fall_AimUL = 0xA1, + kPose_A2_FaceR_Turn_Crouch_AimUR = 0xA2, + kPose_A3_FaceL_Turn_Crouch_AimUL = 0xA3, + kPose_A4_FaceR_LandJump = 0xA4, + kPose_A5_FaceL_LandJump = 0xA5, + kPose_A6_FaceR_LandSpinJump = 0xA6, + kPose_A7_FaceL_LandSpinJump = 0xA7, + kPose_A8_FaceR_Grappling = 0xA8, + kPose_A9_FaceL_Grappling = 0xA9, + kPose_AA_FaceR_Grappling_AimDR = 0xAA, + kPose_AB_FaceL_Grappling_AimDL = 0xAB, + kPose_B2_FaceR_Grapple_Air = 0xB2, + kPose_B3_FaceL_Grapple_Air = 0xB3, + kPose_B4_FaceR_Grappling_Crouch = 0xB4, + kPose_B5_FaceL_Grappling_Crouch = 0xB5, + kPose_B6_FaceR_Grappling_Crouch_AimDR = 0xB6, + kPose_B7_FaceL_Grappling_Crouch_AimDL = 0xB7, + kPose_B8_FaceL_GrappleWalljumpPose = 0xB8, + kPose_B9_FaceR_GrappleWalljumpPose = 0xB9, + kPose_BA_FaceL_Draygon_NoMove_NoAim = 0xBA, + kPose_BB_FaceL_Draygon_NoMove_AimUL = 0xBB, + kPose_BC_FaceL_Draygon_Fire = 0xBC, + kPose_BD_FaceL_Draygon_NoMove_AimDL = 0xBD, + kPose_BE_FaceL_Draygon_Move = 0xBE, + kPose_BF_FaceR_Moonwalk_TurnjumpL = 0xBF, + kPose_C0_FaceL_Moonwalk_TurnjumpR = 0xC0, + kPose_C1_FaceR_Moonwalk_TurnjumpL_AimUR = 0xC1, + kPose_C2_FaceL_Moonwalk_TurnjumpR_AimUL = 0xC2, + kPose_C3_FaceR_Moonwalk_TurnjumpL_AimDR = 0xC3, + kPose_C4_FaceL_Moonwalk_TurnjumpR_AimDL = 0xC4, + kPose_C7_FaceR_ShinesparkWindup_Vert = 0xC7, + kPose_C8_FaceL_ShinesparkWindup_Vert = 0xC8, + kPose_C9_FaceR_Shinespark_Horiz = 0xC9, + kPose_CA_FaceL_Shinespark_Horiz = 0xCA, + kPose_CB_FaceR_Shinespark_Vert = 0xCB, + kPose_CC_FaceL_Shinespark_Vert = 0xCC, + kPose_CD_FaceR_Shinespark_Diag = 0xCD, + kPose_CE_FaceL_Shinespark_Diag = 0xCE, + kPose_CF_FaceR_Ranintowall_AimUR = 0xCF, + kPose_D0_FaceL_Ranintowall_AimUL = 0xD0, + kPose_D1_FaceR_Ranintowall_AimDR = 0xD1, + kPose_D2_FaceL_Ranintowall_AimDL = 0xD2, + kPose_D3_FaceR_CrystalFlash = 0xD3, + kPose_D4_FaceL_CrystalFlash = 0xD4, + kPose_D5_FaceR_Xray_Stand = 0xD5, + kPose_D6_FaceL_Xray_Stand = 0xD6, + kPose_D7_FaceR_CrystalFlashEnd = 0xD7, + kPose_D8_FaceL_CrystalFlashEnd = 0xD8, + kPose_D9_FaceR_Xray_Crouch = 0xD9, + kPose_DA_FaceL_Xray_Crouch = 0xDA, + kPose_DB = 0xDB, + kPose_E0_FaceR_LandJump_AimU = 0xE0, + kPose_E1_FaceL_LandJump_AimU = 0xE1, + kPose_E2_FaceR_LandJump_AimUR = 0xE2, + kPose_E3_FaceL_LandJump_AimUL = 0xE3, + kPose_E4_FaceR_LandJump_AimDR = 0xE4, + kPose_E5_FaceL_LandJump_AimDL = 0xE5, + kPose_E6_FaceR_LandJump_Fire = 0xE6, + kPose_E7_FaceL_LandJump_Fire = 0xE7, + kPose_E8_FaceR_Drained_CrouchFalling = 0xE8, + kPose_E9_FaceL_Drained_CrouchFalling = 0xE9, + kPose_EA_FaceR_Drained_Stand = 0xEA, + kPose_EB_FaceL_Drained_Stand = 0xEB, + kPose_EC_FaceR_Draygon_NoMove_NoAim = 0xEC, + kPose_ED_FaceR_Draygon_NoMove_AimUR = 0xED, + kPose_EE_FaceR_Draygon_Fire = 0xEE, + kPose_EF_FaceR_Draygon_NoMove_AimDR = 0xEF, + kPose_F0_FaceR_Draygon_Move = 0xF0, + kPose_F1_FaceR_CrouchTrans_AimU = 0xF1, + kPose_F2_FaceL_CrouchTrans_AimU = 0xF2, + kPose_F3_FaceR_CrouchTrans_AimUR = 0xF3, + kPose_F4_FaceL_CrouchTrans_AimUL = 0xF4, + kPose_F5_FaceR_CrouchTrans_AimDR = 0xF5, + kPose_F6_FaceL_CrouchTrans_AimDL = 0xF6, + kPose_F7_FaceR_StandTrans_AimU = 0xF7, + kPose_F8_FaceL_StandTrans_AimU = 0xF8, + kPose_F9_FaceR_StandTrans_AimUR = 0xF9, + kPose_FA_FaceL_StandTrans_AimUL = 0xFA, + kPose_FB_FaceR_StandTrans_AimDR = 0xFB, + kPose_FC_FaceL_StandTrans_AimDL = 0xFC, +} SamusPose; + +/* 29 */ +enum LiquidPhysicsType { + kLiquidPhysicsType_Air = 0x0, + kLiquidPhysicsType_Water = 0x1, + kLiquidPhysicsType_LavaAcid = 0x2, +}; + +/* 30 */ +typedef struct SamusPoseParams { + uint8 pose_x_dir; + uint8 movement_type; + uint8 new_pose_unless_buttons; + uint8 direction_shots_fired; + uint8 y_offset_to_gfx; + uint8 field_5; + uint8 y_radius; + uint8 field_7; +} SamusPoseParams; + +/* 31 */ +typedef struct SamusSpeedTableEntry { + uint16 accel; + uint16 accel_sub; + uint16 max_speed; + uint16 max_speed_sub; + uint16 decel; + uint16 decel_sub; +} SamusSpeedTableEntry; + +/* 32 */ +enum SamusMovementType { + kMovementType_00_Standing = 0x0, + kMovementType_01_Running = 0x1, + kMovementType_02_NormalJumping = 0x2, + kMovementType_03_SpinJumping = 0x3, + kMovementType_04_MorphBallOnGround = 0x4, + kMovementType_05_Crouching = 0x5, + kMovementType_06_Falling = 0x6, + kMovementType_07_Unused = 0x7, + kMovementType_08_MorphBallFalling = 0x8, + kMovementType_09_Unused = 0x9, + kMovementType_0A_KnockbackOrCrystalFlashEnding = 0xA, + kMovementType_0B_Unused = 0xB, + kMovementType_0C_Unused = 0xC, + kMovementType_0D_Unused = 0xD, + kMovementType_0E_TurningAroundOnGround = 0xE, + kMovementType_0F_CrouchingEtcTransition = 0xF, + kMovementType_10_Moonwalking = 0x10, + kMovementType_11_SpringBallOnGround = 0x11, + kMovementType_12_SpringBallInAir = 0x12, + kMovementType_13_SpringBallFalling = 0x13, + kMovementType_14_WallJumping = 0x14, + kMovementType_15_RanIntoWall = 0x15, + kMovementType_16_Grappling = 0x16, + kMovementType_17_TurningAroundJumping = 0x17, + kMovementType_18_TurningAroundFalling = 0x18, + kMovementType_19_DamageBoost = 0x19, + kMovementType_1A_GrabbedByDraygon = 0x1A, + kMovementType_1B_ShinesparkEtc = 0x1B, +}; + +/* 33 */ +typedef struct DisableMinimapAndMarkBossRoomAsExploredEnt { + uint16 boss_id_; + VoidP ptrs; +} DisableMinimapAndMarkBossRoomAsExploredEnt; + +/* 34 */ +typedef struct ProjectileDamagesAndInstrPtr { + unsigned int damages; + VoidP instr_ptr; +} ProjectileDamagesAndInstrPtr; + +/* 36 */ +typedef struct DemoInputObject { + VoidP ptr; + VoidP pre_instr; + VoidP instr_ptr; +} DemoInputObject; + +/* 37 */ +typedef struct DemoSetDef { + uint16 items; + uint16 missiles; + uint16 super_missiles; + uint16 power_bombs; + uint16 health; + uint16 beams; + uint16 equipped_beams_; + VoidP demo_obj; +} DemoSetDef; + +/* 38 */ +typedef struct DemoInputEntry { + uint16 timer; + uint16 input; + uint16 input_new; +} DemoInputEntry; + +/* 39 */ +typedef struct PoseEntry { + uint16 new_input; + uint16 cur_input; + uint16 new_pose; +} PoseEntry; + +/* 40 */ +typedef struct XrayBlockData { + uint16 value; + VoidP addr; +} XrayBlockData; + +/* 41 */ +typedef struct SamusCrystalFlashPalTable { + VoidP ptr; + uint16 timer; +} SamusCrystalFlashPalTable; + +/* 42 */ +typedef struct SamusTileAnimationDefs { + uint8 top_half_idx; + uint8 top_half_pos; + uint8 bottom_half_idx; + uint8 bottom_half_pos; +} SamusTileAnimationDefs; + +/* 43 */ +typedef struct SamusTileAnimationTileDefs { + uint16 src; + uint8 gap2; + uint16 part1_size; + uint16 part2_size; +}SamusTileAnimationTileDefs; + +/* 44 */ +typedef struct ProjectileDataTable { + uint16 damage; + VoidP field_2; + VoidP field_4; + VoidP field_6; + VoidP field_8; + VoidP field_A; + VoidP field_C; + VoidP field_E; + VoidP field_10; + VoidP field_12; + VoidP field_14; +} ProjectileDataTable; + +/* 45 */ +typedef struct ProjectileInstr { + uint16 timer; + VoidP spritemap_ptr; + uint8 x_radius; + uint8 y_radius; + uint16 field_6; +} ProjectileInstr; + +/* 46 */ +typedef struct GrappleBeamSpecialAngles { + uint16 field_0; + uint16 field_2; + uint16 field_4; + uint16 field_6; + VoidP field_8; +} GrappleBeamSpecialAngles; + +/* 47 */ +typedef struct ExtendedSpriteMap { + uint16 xpos; + uint16 ypos; + VoidP spritemap; + VoidP hitbox_ptr_; +} ExtendedSpriteMap; + +/* 48 */ +typedef struct Hitbox { + uint16 left; + uint16 top; + uint16 right; + uint16 bottom; + VoidP func_ptr; + VoidP func_ptrA; +} Hitbox; + +/* 49 */ +typedef struct EnemySpawnData { + uint16 some_flag; + uint16 cause_of_death; + uint16 field_4; + uint16 vram_tiles_index; + uint16 palette_index; + uint16 field_A; + uint16 field_C; + uint16 field_E; + uint16 xpos2; + uint16 ypos2; + uint16 field_14; + uint16 field_16; + uint16 field_18; + uint16 field_1A; + uint16 field_1C; + uint16 id; + uint16 x_pos; + uint16 y_pos; + uint16 init_param; + uint16 properties; + uint16 extra_properties; + uint16 param_1; + uint16 param_2; + uint8 name[18]; +} EnemySpawnData; + +/* 50 */ +enum EnemyExtraProps { + kEnemyExtraProps_DisableEnemyAI = 0x1, + kEnemyExtraProps_MultiHitbox = 0x4, + kEnemyExtraProps_UpdateGfx = 0x8000, +} ; + +/* 52 */ +enum ProjectileType { + kProjectileType_Missile = 0x100, + kProjectileType_SuperMissile = 0x200, + kProjectileType_PowerBomb = 0x300, + kProjectileType_Bomb = 0x500, + kProjectileType_BeamExplosion = 0x700, + kProjectileType_MissileExplosion = 0x800, + kProjectileType_TypeMask = 0xF00, + kProjectileType_DontInteractWithSamus = 0x8000, +}; + +/* 53 */ +enum EnemyProps { + kEnemyProps_Invisible = 0x100, + kEnemyProps_Deleted = 0x200, + kEnemyProps_Tangible = 0x400, + kEnemyProps_ProcessedOffscreen = 0x800, + kEnemyProps_BlockPlasmaBeam = 0x1000, + kEnemyProps_DisableSamusColl = 0x2000, + kEnemyProps_RespawnIfKilled = 0x4000, +}; + +/* 54 */ +typedef struct EnemyPopulation { + VoidP enemy_ptr; + uint16 x_pos; + uint16 y_pos; + uint16 init_param; + uint16 properties; + uint16 extra_properties; + uint16 parameter1; + uint16 parameter2; +} EnemyPopulation; + +/* 55 */ +typedef struct EnemySetName { + uint8 field_0[7]; +} EnemySetName; + +/* 56 */ +typedef struct EnemyTileset { + VoidP enemy_def; + uint16 vram_dst; +} EnemyTileset; + +/* 57 */ +enum EnemyAiBits { + kEnemyAiBits_Grapple = 0x1, + kEnemyAiBits_Hurt = 0x2, + kEnemyAiBits_Frozen = 0x4, +}; + +/* 58 */ +typedef struct Vulnerability { + uint8 power; + uint8 wave; + uint8 ice; + uint8 ice_wave; + uint8 spazer; + uint8 spazer_wave; + uint8 spazer_ice; + uint8 spazer_ice_wave; + uint8 plasma; + uint8 plasma_wave; + uint8 plasma_ice; + uint8 plasma_ice_wave; + uint8 missile; + uint8 super_missile; + uint8 bomb; + uint8 power_bomb; + uint8 speed_booster; + uint8 shinespark; + uint8 screw_attack; + uint8 charged_beam; + uint8 pseudo_screw_attack; + uint8 field_15; +} Vulnerability; + +/* 59 */ +typedef struct EnemyDropChances { + uint8 field_0; + uint8 field_1; + uint8 field_2; + uint8 field_3; + uint8 field_4; + uint8 field_5; +} EnemyDropChances; + +typedef struct SpriteDrawInstr { + uint16 field_0; + VoidP field_2; +} SpriteDrawInstr; + +/* 70 */ +typedef struct MaridiaSnailData { + uint16 field_0; + uint16 field_2; + VoidP field_4; + VoidP field_6; +} MaridiaSnailData; + +/* 71 */ +typedef struct MaridiaSnailData2 { + VoidP field_0; + uint16 field_2; + VoidP field_4; + uint16 field_6; +} MaridiaSnailData2; + +/* 73 */ +typedef struct Mode7VramWriteQueue { + uint8 field_0; + uint16 field_1; + uint8 gap3[2]; + uint16 field_5; +} Mode7VramWriteQueue; + +/* 74 */ +typedef struct KraidInstrList { + uint16 timer; + VoidP tilemap; + VoidP vuln_mouth_hitbox; + VoidP invuln_mouth_hitbox; +} KraidInstrList; + +/* 75 */ +typedef struct KraidMouthHitbox { + uint16 field_0; + uint16 field_2; + uint16 field_4; + uint16 field_6; +} KraidMouthHitbox; + +/* 76 */ +typedef struct KraidSinkTable { + uint16 field_0; + uint16 field_2; + VoidP field_4; +} KraidSinkTable; + +/* 77 */ +typedef struct MotherBrainHitbox { + uint16 field_0; + uint16 field_2; + uint16 field_4; + uint16 field_6; +} MotherBrainHitbox; + +/* 78 */ +typedef struct ShitroidMovementTable { + uint16 field_0; + uint16 field_2; + uint16 field_4; + VoidP field_6; +} ShitroidMovementTable; + +/* 79 */ +typedef struct RoomPaletteInstrList { + uint16 field_0; + VoidP field_2; +} RoomPaletteInstrList; + +/* 80 */ +typedef struct CorpseRottingVramTransferDefs { + uint16 field_0; + uint16 field_2; + uint16 field_4; + uint16 field_6; +} CorpseRottingVramTransferDefs; + +/* 81 */ +typedef struct CorpseRottingDef { + VoidP field_0; + VoidP field_2; + VoidP field_4; + VoidP field_6; + uint16 field_8; + VoidP field_A; + VoidP field_C; + VoidP field_E; +} CorpseRottingDef; + +/* 82 */ +typedef struct BotwoonMovementData { + VoidP field_0; + uint16 field_2; + uint16 field_4; + uint16 field_6; +} BotwoonMovementData; + +typedef struct RoomDefHeader { + uint8 semiunique_room_number; + uint8 area_index_; + uint8 x_coordinate_on_map; + uint8 y_coordinate_on_map; + uint8 width; + uint8 height; + uint8 up_scroller_; + uint8 down_scroller_; + uint8 cre_bitset_; + VoidP ptr_to_doorout; +} RoomDefHeader; + +/* 93 */ +enum GameState { + kGameState_0_Reset = 0x0, + kGameState_1_OpeningCinematic = 0x1, + kGameState_2_GameOptionsMenu = 0x2, + kGameState_3_Unused = 0x3, + kGameState_4_FileSelectMenus = 0x4, + kGameState_5_FileSelectMap = 0x5, + kGameState_6_LoadingGameData = 0x6, + kGameState_7_MainGameplayFadeIn = 0x7, + kGameState_8_MainGameplay = 0x8, + kGameState_9_HitDoorBlock = 0x9, + kGameState_10_LoadingNextRoom = 0xA, + kGameState_11_LoadingNextRoom = 0xB, + kGameState_12_Pausing = 0xC, + kGameState_13_Pausing = 0xD, + kGameState_14_Paused = 0xE, + kGameState_15_Paused = 0xF, + kGameState_16_Unpausing = 0x10, + kGameState_17_Unpausing = 0x11, + kGameState_18_Unpausing = 0x12, + kGameState_19_SamusNoHealth = 0x13, + kGameState_20_SamusNoHealth = 0x14, + kGameState_21_SamusNoHealth = 0x15, + kGameState_22_SamusNoHealth = 0x16, + kGameState_23_SamusNoHealth = 0x17, + kGameState_24_SamusNoHealth = 0x18, + kGameState_25_SamusNoHealth = 0x19, + kGameState_26_GameOverMenu = 0x1A, + kGameState_27_ReserveTanksAuto = 0x1B, + kGameState_28_Unused = 0x1C, + kGameState_29_DebugGameOverMenu = 0x1D, + kGameState_30_IntroCinematic = 0x1E, + kGameState_31_SetUpNewGame = 0x1F, + kGameState_32_MadeItToCeresElevator = 0x20, + kGameState_33_BlackoutFromCeres = 0x21, + kGameState_34_CeresGoesBoom = 0x22, + kGameState_35_TimeUp = 0x23, + kGameState_36_WhitingOutFromTimeUp = 0x24, + kGameState_37_CeresGoesBoomWithSamus = 0x25, + kGameState_38_SamusEscapesFromZebes = 0x26, + kGameState_39_EndingAndCredits = 0x27, + kGameState_40_TransitionToDemo = 0x28, + kGameState_41_TransitionToDemo = 0x29, + kGameState_42_PlayingDemo = 0x2A, + kGameState_43_TransitionFromDemo = 0x2B, + kGameState_44_TransitionFromDemo = 0x2C, +}; + +/* 94 */ +enum LoadingGameState { + kLoadingGameState_0_Intro = 0x0, + kLoadingGameState_5_Main = 0x5, + kLoadingGameState_1F_StartingAtCeres = 0x1F, + kLoadingGameState_22_EscapingCeres = 0x22, +}; + +/* 95 */ +typedef enum Buttons { + kButton_R = 0x10, + kButton_L = 0x20, + kButton_X = 0x40, + kButton_A = 0x80, + kButton_Right = 0x100, + kButton_Left = 0x200, + kButton_Down = 0x400, + kButton_Up = 0x800, + kButton_Start = 0x1000, + kButton_Select = 0x2000, + kButton_Y = 0x4000, + kButton_B = 0x8000, +} Buttons; + +/* 96 */ +typedef struct StateHeaderTiles { + LongPtr tile_table_ptr; + LongPtr tiles_ptr; + LongPtr palette_ptr; +} StateHeaderTiles; + +/* 97 */ +typedef struct RoomDefRoomstate { + LongPtr compressed_room_map_ptr; + uint8 graphics_set; + uint8 music_track; + uint8 music_control; + VoidP room_layer3_fx_ptr; + VoidP enemy_population_ptr_; + VoidP enemy_tilesets_ptr; + uint16 vertical_screen_nudge_limit; + VoidP rdf_scroll_ptr; + VoidP xray_special_casing_ptr; + VoidP main_code_ptr; + VoidP room_plm_header_ptr; + VoidP bg_data_ptr; + VoidP room_setup_code; +} RoomDefRoomstate; + +/* 98 */ +typedef struct RoomDefStateSelect_EBE5_Door { + VoidP code_ptr; + uint16 dddd; + uint16 ssss; +} RoomDefStateSelect_EBE5_Door; + +/* 99 */ +typedef struct RoomDefStateSelect_FFE5_TourianBoss01 { + VoidP code_ptr; + uint16 ssss; +} RoomDefStateSelect_FFE5_TourianBoss01; + +/* 100 */ +typedef struct Ram7800_Kraid { + uint16 kraid_next; + uint16 field_2; + uint16 field_4; + uint16 kraid_thinking; + uint16 kraid_min_y_pos_eject; + uint16 kraid_mouth_flags; + uint16 kraid_healths_8ths[8]; + uint16 field_1C; + uint16 kraid_target_x; + uint16 kraid_healths_4ths[4]; + uint16 field_28; + uint16 kraid_hurt_frame; + uint16 kraid_hurt_frame_timer; +} Ram7800_Kraid; + +/* 101 */ +typedef struct StartDmaCopy { + uint8 chan; + uint8 dmap; + uint8 bbad; + LongPtr a1; + VoidP das; +} StartDmaCopy; + +/* 102 */ +typedef struct DecompressToParams { + LongPtr field_0; +} DecompressToParams; + +/* 103 */ +typedef struct OpcodeData3 { + uint16 field_0; + uint8 field_2; +} OpcodeData3; + +/* 104 */ +typedef struct OamEnt { + uint8 xcoord; + uint8 ycoord; + uint8 charnum; + uint8 flags; +} OamEnt; + +/* 105 */ +typedef struct VramWriteEntry { + uint16 size; + LongPtr src; + uint16 vram_dst; +} VramWriteEntry; + +/* 106 */ +typedef struct VramReadQueueEnt { + uint16 vram_target; + uint16 dma_parameters; + LongPtr src; + uint16 size; +} VramReadQueueEnt; + +/* 107 */ +typedef struct SpriteDrawEnt { + uint16 x_and_flags; + uint8 xcoord; + uint16 char_flags; +} SpriteDrawEnt; + +/* 108 */ +typedef struct EnemyTileLoadData { + uint16 tile_data_size; + LongPtr tile_data_ptr; + uint16 offset_into_ram; +} EnemyTileLoadData; + +/* 109 */ +typedef struct ExpandingSquareTransitionHdma { + uint8 field_0; + uint8 field_1; + uint8 field_2; +} ExpandingSquareTransitionHdma; + +/* 110 */ +typedef struct TileTable { + uint16 top_left; + uint16 top_right; + uint16 bottom_left; + uint16 bottom_right; +} TileTable; + +/* 111 */ +typedef struct TileTables { + TileTable tables[1024]; +} TileTables; + +/* 112 */ +typedef struct ElevatorsUsedConf { + uint8 sourcce_area; + uint8 source_bit; + uint8 dest_area; + uint8 dest_bit; +} ElevatorsUsedConf; + +/* 113 */ +typedef struct MenuTilemaps { + uint16 size; + VoidP src; + uint16 field_4; + VoidP vram_dst; +} MenuTilemaps; + +/* 114 */ +typedef struct MapIconDataPointers { + VoidP crateria; + VoidP brinstar; + VoidP norfair; + VoidP wrecked_ship; + VoidP maraidia; + VoidP tourian; + VoidP ceres; + VoidP debug; +} MapIconDataPointers; + +/* 115 */ +typedef struct ExpandingSquareVels { + uint16 left_subvel; + uint16 left_vel; + uint16 right_subvel; + uint16 right_vel; + uint16 top_subvel; + uint16 top_vel; + uint16 bottom_subvel; + uint16 bottom_vel; +} ExpandingSquareVels; + +/* 116 */ +typedef struct MapScrollArrowData { + uint16 xpos; + uint16 ypos; + uint16 pause_screen_animation_id; + uint16 joypad_input; + uint16 map_scroll_dir; +} MapScrollArrowData; + +/* 117 */ +typedef struct DemoRoomData { + VoidP room_ptr_; + uint16 door_ptr; + uint16 door_slot; + uint16 screen_x_pos; + uint16 screen_y_pos; + uint16 samus_x_offs; + uint16 samus_y_offs; + uint16 demo_length; + VoidP demo_code_ptr; +} DemoRoomData; + +/* 118 */ +typedef struct PauseScreenSpriteAnimationData { + VoidP unused; + VoidP lr_highlight; + VoidP item_selector; + VoidP unused2; + VoidP unused3; + VoidP map_scroll_arrow_up; + VoidP map_scroll_arrow_down; + VoidP map_scroll_arrow_right; + VoidP map_scroll_arrow_left; +} PauseScreenSpriteAnimationData; + +/* 119 */ +typedef struct FileCopyArrowStuff { + uint16 spritemap; + uint16 xpos; + uint16 ypos; +} FileCopyArrowStuff; + +/* 120 */ +typedef struct GameOverBabyMetroidInstruction { + VoidP field_0; + VoidP field_2; + VoidP field_4; +} GameOverBabyMetroidInstruction; + +/* 121 */ +typedef struct CopyToVramAtNextInterruptArgs { + LongPtr source; + VoidP dest; + uint16 size; +}CopyToVramAtNextInterruptArgs; + +/* 122 */ +typedef struct EnemyDef_A2 { + uint16 tile_data_size; + VoidP palette_ptr; + uint16 health; + uint16 damage; + uint16 x_radius; + uint16 y_radius; + uint8 bank; + uint8 hurt_ai_time; + uint16 hurt_sfx; + uint16 boss_fight_value; + VoidP ai_init; + uint16 num_parts; + uint16 field_16; + VoidP main_ai; + VoidP grapple_ai; + VoidP hurt_ai; + VoidP frozen_ai; + VoidP time_is_frozen_ai; + uint16 death_anim; + uint16 field_24; + uint16 field_26; + VoidP powerbomb_reaction; + VoidP field_2A; + uint16 field_2C; + uint16 field_2E; + VoidP touch_ai; + VoidP shot_ai; + VoidP field_34; + LongPtr tile_data; + uint8 layer; + VoidP item_drop_chances_ptr; + VoidP vulnerability_ptr; + VoidP name_ptr; +} EnemyDef_A2; + +typedef EnemyDef_A2 EnemyDef_A3; +typedef EnemyDef_A2 EnemyDef_A4; +typedef EnemyDef_A2 EnemyDef_A5; +typedef EnemyDef_A2 EnemyDef_A6; +typedef EnemyDef_A2 EnemyDef_A7; +typedef EnemyDef_A2 EnemyDef_A8; +typedef EnemyDef_A2 EnemyDef_AA; + +typedef EnemyDef_A2 EnemyDef_B2; +typedef EnemyDef_A2 EnemyDef_B3; +/* 133 */ + +typedef struct Ram3000_MsgBox { + uint8 pad[188]; + uint16 msg_box_anim_y_radius_neg[30]; + uint16 msg_box_anim_y_radius[30]; + uint8 field_134[204]; + uint16 tilemap[192]; + uint8 indirect_hdma[7]; + uint8 field_387[99]; + uint8 backup_of_enabled_hdma_channels; + uint16 backup_of_bg3_tilemap_and_size; +} Ram3000_MsgBox; + +/* 134 */ +typedef struct Ram3000_Misc { + uint8 field_0[472]; + uint16 pause_screen_samus_witeframe_tilemap[264]; + uint8 field_3E8[24]; +} Ram3000_Misc; + +/* 135 */ +typedef struct Ram3000_Menu { + uint8 field_0[768]; + uint16 palette_backup_in_menu[256]; + uint8 backup_of_io_registers_in_gameover[54]; + uint8 field_536[202]; + uint8 menu_tilemap[512]; +} Ram3000_Menu; + +/* 136 */ +typedef union Ram3800 { + uint16 cinematic_bg_tilemap[1024]; + uint16 equipment_screen_bg1_tilemap[1024]; + uint16 debug_game_over_tilemap[1024]; + uint16 cleared_message_box_bg3_tilemap[1024]; +} Ram3800; + +/* 137 */ +typedef struct Ram4000_Backups { + uint8 field_0[256]; + uint16 backup_of_vram_0x5880_msgbox[896]; + uint8 field_800[2048]; + uint8 backup_of_0x3e00_in_kraid_pause[1024]; +} Ram4000_Backups; + +/* 138 */ +typedef union Ram4000 { + uint16 xray_tilemaps[6144]; + uint16 bg2_tilemap[2048]; + uint16 decomp_buffer_kraid[1024]; + uint16 bg2_room_select_map_tilemap[1024]; + uint16 intro_japanese_text_tiles[768]; + Ram4000_Backups backups; +} Ram4000; + +/* 139 */ +typedef struct Mode7CgvmWriteQueue { + uint8 tag; + LongPtr src_addr; + uint16 count; + uint16 vram_addr; + uint8 vmain; +} Mode7CgvmWriteQueue; + +/* 140 */ +typedef struct RoomDefStateSelect_29E6_BossBitFlags { + VoidP code_ptr; + uint8 bb; + VoidP ssss; +} RoomDefStateSelect_29E6_BossBitFlags; + +/* 141 */ +typedef struct RoomDefStateSelect_12E6_EventBitArray { + VoidP code_ptr; + uint8 rr; + VoidP ssss; +} RoomDefStateSelect_12E6_EventBitArray; + +/* 142 */ +typedef struct RoomDefStateSelect_52E6_MorphMissile { + VoidP code_ptr; + uint16 ssss; +} RoomDefStateSelect_52E6_MorphMissile; + +/* 143 */ +typedef struct RoomDefStateSelect_69E6_PowerBombs { + VoidP code_ptr; + VoidP ssss; +} RoomDefStateSelect_69E6_PowerBombs; + +/* 144 */ +typedef struct RoomDefStateSelect_78E6_SpeedBooster { + VoidP code_ptr; + uint16 ssss; +} RoomDefStateSelect_78E6_SpeedBooster; + +/* 151 */ +typedef struct Ram7800_SpikeShootingPlant { + uint16 var_a; + uint16 var_b; +}Ram7800_SpikeShootingPlant; + +/* 152 */ +typedef struct Ram7800_MaridiaSpikeyShell { + uint16 field_0; + uint16 field_2; + uint16 field_4; +}Ram7800_MaridiaSpikeyShell; + +/* 153 */ +typedef struct Ram7800_MiniMaridiaTurtle { + uint16 var_a; + uint16 var_b; + uint16 var_c; + uint16 var_d; + uint16 var_e; + uint16 var_f; + uint16 var_g; + uint16 var_h; +}Ram7800_MiniMaridiaTurtle; + +/* 154 */ +typedef struct Ram7800_ThinHoppingBlobs { + uint16 var_a; + uint16 var_b; + uint16 var_c; + uint16 var_d; + uint16 var_e; + uint16 var_f; + uint16 var_g; + uint16 var_h; +}Ram7800_ThinHoppingBlobs; + +/* 155 */ +typedef struct Ram7800_NorfairLavajumpingEnemy { + uint16 var_a; + uint16 var_b; + uint16 var_c; + uint16 var_d; + uint16 var_e; + uint16 var_f; + uint16 var_g; + uint16 var_h; +}Ram7800_NorfairLavajumpingEnemy; + +/* 156 */ +typedef struct Ram7800_NorfairRio { + uint16 var_a; + uint16 var_b; + uint16 var_c; + uint16 var_d; + uint16 var_e; + uint16 var_f; + uint16 var_g; + uint16 var_h; +}Ram7800_NorfairRio; + +/* 157 */ +typedef struct Ram7800_FireFlea { + uint16 var_a; + uint16 var_b; + uint16 var_c; +}Ram7800_FireFlea; + +/* 145 */ +typedef union ExtraEnemyRam7800 { + Ram7800_Kraid kraid; +}ExtraEnemyRam7800; + +/* 146 */ +typedef union ExtraEnemyRam8000 { + uint8 pad[64]; +}ExtraEnemyRam8000; + +/* 147 */ +typedef struct ExtraEnemyRam8800 { + uint8 pad[64]; +}ExtraEnemyRam8800; + +/* 149 */ +typedef union Ram3000 { + uint16 pause_menu_map_tilemap[1024]; + uint16 cinematic_bg_tilemap[1024]; + Ram3000_MsgBox msgbox; + uint8 msgbox_y_scroll_hdma[240]; + Ram3000_Misc misc; + Ram3000_Menu menu; +} Ram3000; + +/* 150 */ +typedef struct OptionsEntry { + VoidP func_ptr; + VoidP field_2; + VoidP field_4; +} OptionsEntry; + +typedef struct Ram7800_Default { + uint16 var_00; + uint16 var_01; + uint16 var_02; + uint16 var_03; + uint16 var_04; + uint16 var_05; + uint16 var_06; + uint16 var_07; + uint16 var_08; + uint16 var_09; + uint16 var_0A; + uint16 var_0B; + uint16 var_0C; + uint16 var_0D; + uint16 var_0E; + uint16 var_0F; + uint16 var_10; + uint16 var_11; + uint16 var_12; + uint16 var_13; + uint16 var_14; + uint16 var_15; + uint16 var_16; + uint16 var_17; + uint16 var_18; + uint16 var_19; + uint16 var_1A; + uint16 var_1B; + uint16 var_1C; + uint16 var_1D; + uint16 var_1E; + uint16 var_1F; +} Ram7800_Default; + + +enum Consts_60 { + addr_unk_604800 = 0x4800, + addr_unk_604C00 = 0x4C00, + addr_unk_605000 = 0x5000, + addr_unk_6053E0 = 0x53E0, + addr_unk_605400 = 0x5400, + addr_unk_605800 = 0x5800, + addr_unk_605820 = 0x5820, + addr_unk_605880 = 0x5880, + addr_unk_6059A0 = 0x59A0, + addr_unk_605BE0 = 0x5BE0, + addr_unk_6061F0 = 0x61F0, + addr_unk_606300 = 0x6300, +}; +enum Consts_80 { + addr_kHudTilemaps_AutoReserve = 0x998B, + addr_kHudTilemaps_Missiles = 0x99A3, + addr_kDigitTilesetsHealth = 0x9DBF, + addr_kDigitTilesetsWeapon = 0x9DD3, + addr_word_80A060 = 0xA060, +}; +enum Consts_81 { + addr_kMenuTilemap_GameOver = 0x92DC, + addr_kMenuTilemap_FindMetroidLarva = 0x9304, + addr_kMenuTilemap_TryAgain = 0x9334, + addr_kMenuTilemap_YesReturnToGame = 0x934C, + addr_kMenuTilemap_NoGoToTitle = 0x93A0, + addr_kLeftMapScrollArrowData = 0xAF32, + addr_kRightMapScrollArrowData = 0xAF3C, + addr_kUpMapScrollArrowData = 0xAF46, + addr_kDownMapScrollArrowData = 0xAF50, + addr_kMenuTilemap_SamusData = 0xB40A, + addr_kMenuTilemap_SamusA = 0xB436, + addr_kMenuTilemap_SamusB = 0xB456, + addr_kMenuTilemap_SamusC = 0xB476, + addr_kMenuTilemap_Energy = 0xB496, + addr_kMenuTilemap_TIME = 0xB4A0, + addr_word_81B4A8 = 0xB4A8, + addr_kMenuTilemap_NoData = 0xB4AC, + addr_kMenuTilemap_DataCopy = 0xB4C4, + addr_kMenuTilemap_DataClear = 0xB4D8, + addr_kMenuTilemap_Exit = 0xB4EE, + addr_kMenuTilemap_DataCopyMode = 0xB4F8, + addr_kMenuTilemap_DataClearMode = 0xB534, + addr_kMenuTilemap_CopyWhichData = 0xB574, + addr_kMenuTilemap_CopySamusToWhere = 0xB596, + addr_kMenuTilemap_CopySamusToSamus = 0xB5C8, + addr_kMenuTilemap_IsThisOk = 0xB602, + addr_kMenuTilemap_Yes = 0xB61A, + addr_kMenuTilemap_No = 0xB62A, + addr_kMenuTilemap_CopyCompleted = 0xB63A, + addr_kMenuTilemap_ClearWhichData = 0xB65A, + addr_kMenuTilemap_ClearSamusA = 0xB69A, + addr_kMenuTilemap_DataCleared = 0xB6DA, + addr_kAreaSelectForegroundTilemap = 0xB71A, +}; +enum Consts_82 { + addr_kPauseMenuMapData = 0x9717, + addr_stru_82B9A0 = 0xB9A0, + addr_stru_82B9AA = 0xB9AA, + addr_stru_82B9B4 = 0xB9B4, + addr_stru_82B9BE = 0xB9BE, + addr_kgameOverBabyMetridInstructionList = 0xBC27, + addr_kEquipmentScreenTilemap_MANUAL = 0xBF22, + addr_kEquipmentScreenTilemap_AUTO = 0xBF2A, + addr_kEquipmentScreenTilemap_Blank = 0xC01A, + addr_kEquipmentTilemapOffs_Tanks = 0xC068, + addr_kEquipmentTilemapOffs_Weapons = 0xC06C, + addr_kEquipmentTilemapOffs_Suits = 0xC076, + addr_kEquipmentTilemapOffs_Boots = 0xC082, + addr_kDummySamusWireframeTilemap = 0xC639, + addr_kMapIconDataPointers = 0xC7CB, + addr_off_82F4B6 = 0xF4B6, + addr_stru_82F4B8 = 0xF4B8, + addr_stru_82F4C4 = 0xF4C4, + addr_stru_82F4CA = 0xF4CA, + addr_stru_82F4D0 = 0xF4D0, + addr_stru_82F4D6 = 0xF4D6, +}; +enum Consts_83 { + addr_kDoorDef_947a = 0x947A, +}; +enum Consts_84 { + addr_PlmPreInstr_Empty4 = 0x8AA6, + addr_locret_848AE0 = 0x8AE0, + addr_kDefaultPlmDrawInstruction = 0x8DA0, + addr_word_84AD76 = 0xAD76, + addr_kPlmHeader_B6FF = 0xB6FF, + addr_locret_84BB6A = 0xBB6A, + addr_locret_84BBDC = 0xBBDC, + addr_kPlmInstrList_C91C = 0xC91C, + addr_kPlmInstrList_C922 = 0xC922, + addr_kPlmHeader_D113 = 0xD113, + addr_kPlmHeader_D6EA = 0xD6EA, + addr_locret_84D779 = 0xD779, +}; +enum Consts_86 { + addr_stru_868BC2 = 0x8BC2, + addr_stru_868BD0 = 0x8BD0, + addr_stru_868BDE = 0x8BDE, + addr_stru_868BEC = 0x8BEC, + addr_stru_868BFA = 0x8BFA, + addr_stru_868C08 = 0x8C08, + addr_stru_868C16 = 0x8C16, + addr_stru_868C24 = 0x8C24, + addr_stru_868E50 = 0x8E50, + addr_stru_868E5E = 0x8E5E, + addr_word_868EDF = 0x8EDF, + addr_stru_868F8F = 0x8F8F, + addr_stru_868F9D = 0x8F9D, + addr_kEproj_CrocomireSpikeWallPieces = 0x90C1, + addr_kRidleysFireball_Tab0 = 0x9408, + addr_off_869574 = 0x9574, + addr_stru_869634 = 0x9634, + addr_stru_869650 = 0x9650, + addr_stru_86966C = 0x966C, + addr_stru_86967A = 0x967A, + addr_stru_869688 = 0x9688, + addr_stru_869696 = 0x9696, + addr_stru_869734 = 0x9734, + addr_stru_869742 = 0x9742, + addr_word_86976C = 0x976C, + addr_word_869772 = 0x9772, + addr_word_869782 = 0x9782, + addr_word_8697AC = 0x97AC, + addr_off_8697B4 = 0x97B4, + addr_off_8697F8 = 0x97F8, + addr_kEproj_DestroyableFireballs = 0x9C29, + addr_kEproj_StartingFireballs = 0x9C37, + addr_kEproj_RocksKraidSpits = 0x9C45, + addr_kEproj_RocksFallingKraidCeiling = 0x9C53, + addr_kEproj_RocksWhenKraidRisesLeft = 0x9C61, + addr_kEproj_RocksWhenKraidRisesRight = 0x9C6F, + addr_kEproj_MiniKraidSpit = 0x9DB0, + addr_kEproj_MiniKraidSpikesLeft = 0x9DBE, + addr_kEproj_MiniKraidSpikesRight = 0x9DCC, + addr_word_869F41 = 0x9F41, + addr_word_869F7D = 0x9F7D, + addr_off_869FB9 = 0x9FB9, + addr_off_869FE1 = 0x9FE1, + addr_stru_86A17B = 0xA17B, + addr_kEproj_PirateClaw = 0xA189, + addr_off_86A28B = 0xA28B, + addr_stru_86A379 = 0xA379, + addr_kEproj_CeresElevatorPad = 0xA387, + addr_kEproj_CeresElevatorPlatform = 0xA395, + addr_kEproj_PrePhantomRoom = 0xA3B0, + addr_stru_86A95B = 0xA95B, + addr_kEproj_BombTorizoLowHealthInitialDrool = 0xA969, + addr_kEproj_BombTorizoExplosiveSwipe = 0xA985, + addr_kEproj_BombTorizoLowHealthExplode = 0xA9A1, + addr_kEproj_BombTorizoDeathExplosion = 0xA9AF, + addr_kEprojInit_AB07_Tile0 = 0xA9BD, + addr_kEprojInit_AB07_Tile1 = 0xA9FD, + addr_off_86AB25 = 0xAB25, + addr_off_86AB41 = 0xAB41, + addr_kEprojInit_BombTorizosChozoOrbs_init0 = 0xAC08, + addr_kEprojInit_BombTorizosChozoOrbs_init1 = 0xAC12, + addr_kEprojInit_GoldenTorizosChozoOrbs_init0 = 0xAC99, + addr_kEprojInit_GoldenTorizosChozoOrbs_init1 = 0xACA3, + addr_kEproj_BombTorizosChozoOrbs = 0xAD5E, + addr_kEproj_GoldenTorizosChozoOrbs = 0xAD7A, + addr_off_86ADBF = 0xADBF, + addr_off_86ADD2 = 0xADD2, + addr_off_86ADE5 = 0xADE5, + addr_kEproj_BombTorizoSonicBoom = 0xAEA8, + addr_kEproj_GoldenTorizoSonicBoom = 0xAEB6, + addr_kEproj_WreckedShipChozoSpikeFootsteps_1 = 0xAF68, + addr_kEproj_TourianStatueDustClouds = 0xAF84, + addr_kEproj_TourianLandingDustCloudsRightFoot = 0xAFE5, + addr_stru_86AFF3 = 0xAFF3, + addr_kEprojInit_GoldenTorizoEgg0 = 0xB02F, + addr_kEprojInit_GoldenTorizoEgg1 = 0xB039, + addr_off_86B14B = 0xB14B, + addr_off_86B166 = 0xB166, + addr_off_86B190 = 0xB190, + addr_off_86B1A8 = 0xB1A8, + addr_stru_86B1C0 = 0xB1C0, + addr_off_86B2EF = 0xB2EF, + addr_kEproj_GoldenTorizoSuperMissile = 0xB31A, + addr_stru_86B376 = 0xB376, + addr_stru_86B380 = 0xB380, + addr_off_86B3CD = 0xB3CD, + addr_off_86B3E5 = 0xB3E5, + addr_kEproj_GoldenTorizoEyeBeam = 0xB428, + addr_word_86B4BF = 0xB4BF, + addr_word_86B4CB = 0xB4CB, + addr_word_86B4D7 = 0xB4D7, + addr_word_86B4E3 = 0xB4E3, + addr_kEproj_LavaSeahorseFireball = 0xB5CB, + addr_off_86B5F3 = 0xB5F3, + addr_off_86B61D = 0xB61D, + addr_kEproj_EyeDoorProjectile = 0xB743, + addr_kEproj_EyeDoorSweat = 0xB751, + addr_off_86B79F = 0xB79F, + addr_stru_86BA5C = 0xBA5C, + addr_kEproj_TourianStatueEyeGlow = 0xBA6A, + addr_kEproj_TourianStatueUnlockingParticle = 0xBA78, + addr_kEproj_TourianStatueUnlockingParticleTail = 0xBA86, + addr_kEproj_TourianStatueSoul = 0xBA94, + addr_kEproj_TourianStatueRidley = 0xBAA2, + addr_kEproj_TourianStatuePhantoon = 0xBAB0, + addr_kEproj_TourianStatueBaseDecoration = 0xBABE, + addr_kEproj_NuclearWaffleBody = 0xBBC7, + addr_word_86BBD5 = 0xBBD5, + addr_stru_86BD5A = 0xBD5A, + addr_kEproj_ShaktoolAttackFrontCircle = 0xBE25, + addr_kEproj_ShaktoolAttackMiddleCircle = 0xBE33, + addr_kEproj_ShaktoolAttackBackCircle = 0xBE41, + addr_kEproj_MotherBrainRoomTurrets = 0xC17E, + addr_kEproj_MotherBrainRoomTurretBullets = 0xC18C, + addr_off_86C8E1 = 0xC8E1, + addr_kEproj_MotherBrainDeathExplosion = 0xCB13, + addr_kEproj_MotherBrainExplodedEscapeDoor = 0xCB21, + addr_kEproj_MotherBrainPurpleBreathBig = 0xCB2F, + addr_kEproj_MotherBrainPurpleBreathSmall = 0xCB3D, + addr_kEproj_MotherBrainBlueRingLasers = 0xCB4B, + addr_kEproj_MotherBrainBomb = 0xCB59, + addr_kEproj_MotherBrainDeathBeamCharging = 0xCB67, + addr_kEproj_MotherBrainDeathBeamFired = 0xCB75, + addr_kEproj_MotherBrainRainbowBeamCharging = 0xCB83, + addr_kEproj_MotherBrainDrool = 0xCB91, + addr_kEproj_MotherBrainDyingDrool = 0xCB9F, + addr_kEproj_MotherBrainRainbowBeamExplosion = 0xCBAD, + addr_kEproj_TimeBombSetJapaneseText = 0xCBBB, + addr_kEproj_MotherBrainTubeFalling_TopLeft = 0xCC69, + addr_kEproj_MotherBrainTubeFalling_TopMiddleLeft = 0xCC77, + addr_kEproj_MotherBrainTubeFalling_TopMiddleRight = 0xCC85, + addr_kEproj_MotherBrainGlassShatteringSparkle = 0xCF0A, + addr_off_86CF56 = 0xCF56, + addr_word_86D03C = 0xD03C, + addr_word_86D04A = 0xD04A, + addr_word_86D052 = 0xD052, + addr_off_86D218 = 0xD218, + addr_kEproj_MaridiaFloatersSpikes = 0xD298, + addr_kEproj_WreckedShipRobotLaserUpLeft = 0xD2A6, + addr_kEproj_WreckedShipRobotLaserHorizontal = 0xD2B4, + addr_kEproj_WreckedShipRobotLaserDownLeft = 0xD2C2, + addr_kEproj_WreckedShipRobotLaserUpRight = 0xD2D0, + addr_kEproj_WreckedShipRobotLaserDownRight = 0xD2DE, + addr_kEproj_N00bTubeShards = 0xD912, + addr_kEproj_N00bTubeReleasedAirBubbles = 0xD920, + addr_kEproj_SpikeShootingPlantSpikes = 0xDAFE, + addr_word_86DB0C = 0xDB0C, + addr_Eproj_DBF2 = 0xDBF2, + addr_word_86DC06 = 0xDC06, + addr_kEproj_SporeSpawnsStalk = 0xDE6C, + addr_kEproj_Spores = 0xDE7A, + addr_kEproj_SporeSpawners = 0xDE88, + addr_word_86DE96 = 0xDE96, + addr_word_86DEA6 = 0xDEA6, + addr_stru_86DFBC = 0xDFBC, + addr_stru_86DFCA = 0xDFCA, + addr_word_86DFD8 = 0xDFD8, + addr_word_86DFDE = 0xDFDE, + addr_kEproj_LavaThrownByLavaman = 0xE0E0, + addr_word_86E208 = 0xE208, + addr_kEproj_DustCloudExplosion = 0xE509, + addr_kEproj_EyeDoorSmoke = 0xE517, + addr_kEproj_SaveStationElectricity = 0xE6D2, + addr_kEproj_BotwoonsBody = 0xEBA0, + addr_word_86EBAE = 0xEBAE, + addr_kEproj_BotwoonsSpit = 0xEC48, + addr_word_86EC56 = 0xEC56, + addr_word_86EC5C = 0xEC5C, + addr_kEproj_YappingMawsBody = 0xEC95, + addr_word_86ECA3 = 0xECA3, + addr_kEproj_Pickup = 0xF337, + addr_kEproj_EnemyDeathExplosion = 0xF345, + addr_kEproj_Sparks = 0xF498, +}; +enum Consts_87 { + addr_kAnimtiles_WreckedShipTradmillRight = 0x8275, + addr_kAnimtiles_WreckedShipTradmillLeft = 0x827B, + addr_kAnimtiles_Lava = 0x82AB, + addr_kAnimtiles_Acid = 0x82C9, + addr_kAnimtiles_Rain = 0x82E7, + addr_kAnimtiles_Spores = 0x82FD, + addr_kAnimtiles_TourianStatue_Phantoon = 0x854C, + addr_kAnimtiles_TourianStatue_Ridley = 0x8552, + addr_kAnimtiles_TourianStatue_Kraid = 0x8558, + addr_kAnimtiles_TourianStatue_Draygon = 0x855E, +}; +enum Consts_88 { + addr_locret_88858A = 0x858A, + addr_loc_889180 = 0x9180, + addr_kPowerBombExplosionShapeDef0 = 0x9246, + addr_byte_889F06 = 0x9F06, + addr_word_88A8E8 = 0xA8E8, + addr_word_88A8E8__plus__2 = 0xA8EA, + addr_word_88A8E8__plus__4 = 0xA8EC, + addr_word_88A8E8__plus__6 = 0xA8EE, + addr_off_88AD9C = 0xAD9C, + addr_off_88ADA6 = 0xADA6, + addr_word_88DF5F = 0xDF5F, + addr_word_88DF65 = 0xDF65, + addr_word_88DF6B = 0xDF6B, + addr_word_88DF71 = 0xDF71, +}; +enum Consts_89 { + addr_kIndirectHdmaTable_PowerBombExplodeLeft = 0x9800, + addr_kIndirectHdmaTable_PowerBombExplodeRight = 0xA101, +}; +enum Consts_8B { + addr_kCinematicSpriteObjectDef_8BA0EF = 0xA0EF, + addr_kCinematicSpriteObjectDef_8BA0F5 = 0xA0F5, + addr_kCinematicSpriteObjectDef_8BA0FB = 0xA0FB, + addr_kCinematicSpriteObjectDef_8BA101 = 0xA101, + addr_kCinematicSpriteObjectDef_8BA107 = 0xA107, + addr_kCinematicSpriteObjectDef_8BA113 = 0xA113, + addr_kCinematicSpriteObjectDef_8BA119 = 0xA119, + addr_kCinematicSpriteObjectDef_8BA125 = 0xA125, + addr_kMode7ObjBabyMetroidInTitle = 0xA355, + addr_kCinematicFunction_Intro_Func56_M7 = 0xBE74, + addr_kCinematicFunction_Intro_Func76_M7_0 = 0xC3E6, + addr_kCinematicFunction_Intro_Func76_M7_1 = 0xC3F0, + addr_kCinematicFunction_Intro_Func76_M7_2 = 0xC3FA, + addr_off_8BCB19 = 0xCB19, + addr_word_8BCB3B = 0xCB3B, + addr_word_8BCBFB = 0xCBFB, + addr_unk_8BCC03 = 0xCC03, + addr_word_8BCC23 = 0xCC23, + addr_word_8BCD71 = 0xCD71, + addr_off_8BCE53 = 0xCE53, + addr_kCinematicSpriteObjectDef_8BCE55 = 0xCE55, + addr_kCinematicSpriteObjectDef_8BCE5B = 0xCE5B, + addr_kCinematicSpriteObjectDef_8BCE61 = 0xCE61, + addr_kCinematicSpriteObjectDef_8BCE67 = 0xCE67, + addr_kCinematicSpriteObjectDef_8BCE6D = 0xCE6D, + addr_kCinematicSpriteObjectDef_8BCE73 = 0xCE73, + addr_kCinematicSpriteObjectDef_8BCE79 = 0xCE79, + addr_kCinematicSpriteObjectDef_8BCE7F = 0xCE7F, + addr_kCinematicSpriteObjectDef_8BCE85 = 0xCE85, + addr_kCinematicSpriteObjectDef_8BCE8B = 0xCE8B, + addr_kCinematicSpriteObjectDef_8BCE91 = 0xCE91, + addr_kCinematicSpriteObjectDef_8BCEA3 = 0xCEA3, + addr_kCinematicSpriteObjectDef_8BCEAF = 0xCEAF, + addr_kCinematicSpriteObjectDef_8BCEB5 = 0xCEB5, + addr_kCinematicSpriteObjectDef_8BCEBB = 0xCEBB, + addr_kCinematicSpriteObjectDef_8BCEC1 = 0xCEC1, + addr_kCinematicSpriteObjectDef_8BCEC7 = 0xCEC7, + addr_kCinematicSpriteObjectDef_8BCECD = 0xCECD, + addr_kCinematicSpriteObjectDef_8BCED3 = 0xCED3, + addr_kCinematicSpriteObjectDef_8BCED9 = 0xCED9, + addr_kCinematicSpriteObjectDef_8BCEDF = 0xCEDF, + addr_kCinematicSpriteObjectDef_8BCEE5 = 0xCEE5, + addr_kCinematicSpriteObjectDef_8BCEEB = 0xCEEB, + addr_kCinematicSpriteObjectDef_8BCEF1 = 0xCEF1, + addr_kCinematicSpriteObjectDef_8BCEF7 = 0xCEF7, + addr_kCinematicSpriteObjectDef_8BCEFD = 0xCEFD, + addr_kCinematicSpriteObjectDef_8BCF03 = 0xCF03, + addr_kCinematicSpriteObjectDef_8BCF09 = 0xCF09, + addr_kCinematicSpriteObjectDef_8BCF0F = 0xCF0F, + addr_kCinematicSpriteObjectDef_8BCF15 = 0xCF15, + addr_kCinematicSpriteObjectDef_8BCF1B = 0xCF1B, + addr_kCinematicSpriteObjectDef_8BCF21 = 0xCF21, + addr_kCinematicSpriteObjectDef_8BCF27 = 0xCF27, + addr_kCinematicSpriteObjectDef_8BCF2D = 0xCF2D, + addr_kCinematicSpriteObjectDef_8BCF33 = 0xCF33, + addr_kCinematicSpriteObjectDef_8BCF39 = 0xCF39, + addr_kCinematicBgObjectDef_8BCF3F = 0xCF3F, + addr_kCinematicBgObjectDef_8BCF45 = 0xCF45, + addr_kCinematicBgObjectDef_8BCF4B = 0xCF4B, + addr_kCinematicBgObjectDef_8BCF51 = 0xCF51, + addr_kCinematicBgObjectDef_8BCF57 = 0xCF57, + addr_kCinematicBgObjectDef_8BCF5D = 0xCF5D, + addr_kCinematicBgObjectDef_8BCF63 = 0xCF63, + addr_kCinematicBgObjectDef_8BCF69 = 0xCF69, + addr_word_8BCF75 = 0xCF75, + addr_word_8BCFBD = 0xCFBD, + addr_word_8BCFFD = 0xCFFD, + addr_word_8BD055 = 0xD055, + addr_word_8BD085 = 0xD085, + addr_word_8BD0E1 = 0xD0E1, + addr_word_8BD0F9 = 0xD0F9, + addr_word_8BD15D = 0xD15D, + addr_word_8BD1B9 = 0xD1B9, + addr_word_8BD215 = 0xD215, + addr_word_8BD259 = 0xD259, + addr_word_8BD2A5 = 0xD2A5, + addr_word_8BD2D5 = 0xD2D5, + addr_word_8BD30D = 0xD30D, + addr_word_8BD371 = 0xD371, + addr_word_8BD389 = 0xD389, + addr_off_8BD3E7 = 0xD3E7, + addr_kMode7ObjectDef_8BD401 = 0xD401, + addr_kMode7ObjectDef_8BD407 = 0xD407, + addr_kMode7ObjectDef_8BD40D = 0xD40D, + addr_kMode7ObjectDef_8BD413 = 0xD413, + addr_kMode7ObjectDef_8BD419 = 0xD419, + addr_kMode7ObjectDef_8BD41F = 0xD41F, + addr_kMode7ObjectDef_8BD425 = 0xD425, + addr_kMode7ObjectDef_8BD42B = 0xD42B, + addr_kMode7ObjectDef_8BD431 = 0xD431, + addr_kMode7ObjectDef_8BD437 = 0xD437, + addr_loc_8BE1B4 = 0xE1B4, + addr_word_8BED95 = 0xED95, + addr_word_8BED9D = 0xED9D, + addr_off_8BEE9B = 0xEE9B, + addr_kCinematicSpriteObjectDef_8BEE9D = 0xEE9D, + addr_kCinematicSpriteObjectDef_8BEEA3 = 0xEEA3, + addr_kCinematicSpriteObjectDef_8BEEA9 = 0xEEA9, + addr_kCinematicSpriteObjectDef_8BEEAF = 0xEEAF, + addr_kCinematicSpriteObjectDef_8BEEB5 = 0xEEB5, + addr_kCinematicSpriteObjectDef_8BEEBB = 0xEEBB, + addr_kCinematicSpriteObjectDef_8BEEC1 = 0xEEC1, + addr_kCinematicSpriteObjectDef_8BEEC7 = 0xEEC7, + addr_kCinematicSpriteObjectDef_8BEECD = 0xEECD, + addr_kCinematicSpriteObjectDef_8BEED3 = 0xEED3, + addr_kCinematicSpriteObjectDef_8BEED9 = 0xEED9, + addr_kCinematicSpriteObjectDef_8BEEDF = 0xEEDF, + addr_kCinematicSpriteObjectDef_8BEEE5 = 0xEEE5, + addr_kCinematicSpriteObjectDef_8BEEEB = 0xEEEB, + addr_kCinematicSpriteObjectDef_8BEEF1 = 0xEEF1, + addr_kCinematicSpriteObjectDef_8BEEF7 = 0xEEF7, + addr_kCinematicSpriteObjectDef_8BEEFD = 0xEEFD, + addr_kCinematicSpriteObjectDef_8BEF03 = 0xEF03, + addr_kCinematicSpriteObjectDef_8BEF09 = 0xEF09, + addr_kCinematicSpriteObjectDef_8BEF0F = 0xEF0F, + addr_kCinematicSpriteObjectDef_8BEF15 = 0xEF15, + addr_kCinematicSpriteObjectDef_8BEF1B = 0xEF1B, + addr_kCinematicSpriteObjectDef_8BEF27 = 0xEF27, + addr_kCinematicSpriteObjectDef_8BEF2D = 0xEF2D, + addr_kCinematicSpriteObjectDef_8BEF33 = 0xEF33, + addr_kCinematicSpriteObjectDef_8BEF39 = 0xEF39, + addr_kCinematicSpriteObjectDef_8BEF3F = 0xEF3F, + addr_kCinematicSpriteObjectDef_8BEF45 = 0xEF45, + addr_kCinematicSpriteObjectDef_8BEF4B = 0xEF4B, + addr_kCinematicSpriteObjectDef_8BEF51 = 0xEF51, + addr_kCinematicSpriteObjectDef_8BEF57 = 0xEF57, + addr_kCinematicSpriteObjectDef_8BEF5D = 0xEF5D, + addr_kCinematicSpriteObjectDef_8BEF63 = 0xEF63, + addr_kCinematicSpriteObjectDef_8BEF69 = 0xEF69, + addr_kCinematicSpriteObjectDef_8BEF6F = 0xEF6F, + addr_kCinematicSpriteObjectDef_8BEF75 = 0xEF75, + addr_kCinematicSpriteObjectDef_8BEF7B = 0xEF7B, + addr_kCinematicSpriteObjectDef_8BEF81 = 0xEF81, + addr_kCinematicSpriteObjectDef_8BEF87 = 0xEF87, + addr_kCinematicSpriteObjectDef_8BEF8D = 0xEF8D, + addr_kCinematicSpriteObjectDef_8BEF93 = 0xEF93, + addr_stru_8BF6F8 = 0xF6F8, + addr_kCinematicBgObjectDef_8BF748 = 0xF748, + addr_kCinematicBgObjectDef_8BF74E = 0xF74E, +}; +enum Consts_8C { + addr_kSpriteMap_NintendoLogo = 0x80BB, +}; +enum Consts_8D { + addr_locret_8DC5E3 = 0xC5E3, + addr_off_8DE192 = 0xE192, + addr_kPalfx_E194 = 0xE194, + addr_kPalfx_E198 = 0xE198, + addr_kPalfx_E19C = 0xE19C, + addr_kPalfx_E1A0 = 0xE1A0, + addr_kPalfx_E1A4 = 0xE1A4, + addr_kPalfx_E1A8 = 0xE1A8, + addr_kPalfx_E1AC = 0xE1AC, + addr_kPalfx_E1B0 = 0xE1B0, + addr_kPalfx_E1B8 = 0xE1B8, + addr_kPalfx_E1BC = 0xE1BC, + addr_stru_8DE1C0 = 0xE1C0, + addr_kPalfx_E1C4 = 0xE1C4, + addr_kPalfx_E1C8 = 0xE1C8, + addr_kPalfx_E1CC = 0xE1CC, + addr_kPalfx_E1D0 = 0xE1D0, + addr_kPalfx_E1D4 = 0xE1D4, + addr_kPalfx_E1D8 = 0xE1D8, + addr_kPalfx_E1DC = 0xE1DC, + addr_kPalfx_E1E0 = 0xE1E0, + addr_kPalfx_E1E4 = 0xE1E4, + addr_kPalfx_E1E8 = 0xE1E8, + addr_stru_8DE1F0 = 0xE1F0, + addr_stru_8DE1F4 = 0xE1F4, + addr_stru_8DE1F8 = 0xE1F8, + addr_stru_8DE1FC = 0xE1FC, + addr_kPalfx_E200 = 0xE200, + addr_off_8DE3E0 = 0xE3E0, + addr_off_8DE400 = 0xE400, + addr_off_8DE420 = 0xE420, + addr_kPalfxInstrList_E45E = 0xE45E, + addr_off_8DE68A = 0xE68A, + addr_off_8DE8B6 = 0xE8B6, + addr_word_8DEB43 = 0xEB43, + addr_word_8DEC76 = 0xEC76, + addr_stru_8DF759 = 0xF759, + addr_stru_8DF75D = 0xF75D, + addr_kPalfx_FFC9 = 0xFFC9, + addr_kPalfx_FFCD = 0xFFCD, + addr_kPalfx_FFD1 = 0xFFD1, + addr_kPalfx_FFD5 = 0xFFD5, +}; +enum Consts_8F { + addr_kRoom_96ba = 0x96BA, + addr_kRoom_9804 = 0x9804, + addr_kRoom_a66a = 0xA66A, + addr_kRoom_b32e = 0xB32E, + addr_kRoom_b457 = 0xB457, + addr_kRoom_cefb = 0xCEFB, + addr_kRoom_dd58 = 0xDD58, + addr_kRoom_dede = 0xDEDE, +}; +enum Consts_90 { + addr_loc_908029 = 0x8029, + addr_stru_909F25 = 0x9F25, + addr_stru_909F31 = 0x9F31, + addr_stru_909F3D = 0x9F3D, + addr_kSamusSpeedTable_Normal_X = 0x9F49, + addr_kSamusSpeedTable_Normal_X__plus__12 = 0x9F55, + addr_kSamusSpeedTable_Water_X = 0xA08D, + addr_kSamusSpeedTable_LavaAcid_X = 0xA1DD, + addr_loc_90C4F0 = 0xC4F0, +}; +enum Consts_91 { + addr_off_91864B = 0x864B, + addr_kDemoInstrs_LeaveDemo = 0x8776, + addr_stru_91877E = 0x877E, + addr_stru_918784 = 0x8784, + addr_stru_919346 = 0x9346, +}; +enum Consts_94 { + addr_word_94B18B = 0xB18B, + addr_word_94B18F = 0xB18F, + addr_word_94B193 = 0xB193, + addr_word_94B197 = 0xB197, +}; +enum Consts_9B { + addr_kSamusPalette_PowerSuit = 0x9400, + addr_kSamusPalette_VariaSuit = 0x9520, + addr_kSamusPalette_GravitySuit = 0x9800, + addr_word_9BA380 = 0xA380, + addr_word_9BA3A0 = 0xA3A0, +}; +enum Consts_A0 { + addr_kSpritemap_Nothing_A0 = 0x804D, + addr_kExtendedSpritemap_Nothing_A0 = 0x804F, + addr_kEnemyDef_DAFF = 0xDAFF, + addr_kEnemyDef_DD7F = 0xDD7F, + addr_kEnemyDef_DDBF = 0xDDBF, + addr_kEnemyDef_DE3F = 0xDE3F, + addr_kEnemyDef_DE7F = 0xDE7F, + addr_kEnemyDef_DF3F = 0xDF3F, + addr_kEnemyDef_DF7F = 0xDF7F, + addr_kEnemyDef_E0FF = 0xE0FF, + addr_kEnemyDef_E17F = 0xE17F, + addr_kEnemyDef_E2BF = 0xE2BF, + addr_kEnemyDef_E4BF = 0xE4BF, + addr_kEnemyDef_E4FF = 0xE4FF, + addr_kEnemyDef_E7FF = 0xE7FF, + addr_kEnemyDef_E83F = 0xE83F, + addr_kEnemyDef_EC3F = 0xEC3F, + addr_kEnemyDef_EEFF = 0xEEFF, + addr_kEnemyDef_F293 = 0xF293, + addr_kEnemyDef_F353 = 0xF353, + addr_kEnemyDef_F593 = 0xF593, +}; +enum Consts_A2 { + addr_kSpritemap_Nothing_A2 = 0x804D, + addr_kBouncingGoofball_Ilist_86A7 = 0x86A7, + addr_kBouncingGoofball_Ilist_86BF = 0x86BF, + addr_kMiniCrocomire_Ilist_8932 = 0x8932, + addr_kMiniCrocomire_Ilist_8948 = 0x8948, + addr_kMiniCrocomire_Ilist_8958 = 0x8958, + addr_kMiniCrocomire_Ilist_896E = 0x896E, + addr_kMaridiaBeybladeTurtle_Ilist_8B80 = 0x8B80, + addr_kMaridiaBeybladeTurtle_Ilist_8BD2 = 0x8BD2, + addr_kMaridiaBeybladeTurtle_Ilist_8C02 = 0x8C02, + addr_kMaridiaBeybladeTurtle_Ilist_8C1C = 0x8C1C, + addr_kMaridiaBeybladeTurtle_Ilist_8C30 = 0x8C30, + addr_kMaridiaBeybladeTurtle_Ilist_8C44 = 0x8C44, + addr_kMaridiaBeybladeTurtle_Ilist_8C4A = 0x8C4A, + addr_kMaridiaBeybladeTurtle_Ilist_8C62 = 0x8C62, + addr_kMaridiaBeybladeTurtle_Ilist_8C72 = 0x8C72, + addr_kMaridiaBeybladeTurtle_Ilist_8D00 = 0x8D00, + addr_kMaridiaBeybladeTurtle_Ilist_8D14 = 0x8D14, + addr_kMaridiaBeybladeTurtle_Ilist_8D28 = 0x8D28, + addr_kMaridiaBeybladeTurtle_Ilist_8D40 = 0x8D40, + addr_locret_A28E09 = 0x8E09, + addr_kThinHoppingBlobs_Ilist_99AD = 0x99AD, + addr_kThinHoppingBlobs_Ilist_99C1 = 0x99C1, + addr_kThinHoppingBlobs_Ilist_99D5 = 0x99D5, + addr_kThinHoppingBlobs_Ilist_99E9 = 0x99E9, + addr_kThinHoppingBlobs_Ilist_99EF = 0x99EF, + addr_kThinHoppingBlobs_Ilist_99F5 = 0x99F5, + addr_kThinHoppingBlobs_Ilist_99FB = 0x99FB, + addr_kThinHoppingBlobs_Ilist_9A01 = 0x9A01, + addr_kSpikeShootingPlant_Ilist_9E8A = 0x9E8A, + addr_kSpikeShootingPlant_Ilist_9EB0 = 0x9EB0, + addr_kSpikeShootingPlant_Ilist_9EDA = 0x9EDA, + addr_kSpikeShootingPlant_Ilist_9F00 = 0x9F00, + addr_kMaridiaSpikeyShell_Ilist_A3AB = 0xA3AB, + addr_kMaridiaSpikeyShell_Ilist_A3BD = 0xA3BD, + addr_kGunshipTop_Ilist_A5BE = 0xA5BE, + addr_kGunshipTop_Ilist_A5EE = 0xA5EE, + addr_kGunshipTop_Ilist_A60E = 0xA60E, + addr_kGunshipTop_Ilist_A616 = 0xA616, + addr_kGunshipTop_Ilist_A61C = 0xA61C, + addr_kFlies_Ilist_B013 = 0xB013, + addr_kNorfairErraticFireball_Ilist_B2DC = 0xB2DC, + addr_kNorfairErraticFireball_Ilist_B51A = 0xB51A, + addr_kRinka_Ilist_B9E0 = 0xB9E0, + addr_kRinka_Ilist_BA0C = 0xBA0C, + addr_kRio_Ilist_BB4B = 0xBB4B, + addr_stru_A2BB53 = 0xBB53, + addr_kRio_Ilist_BB7F = 0xBB7F, + addr_kRio_Ilist_BB97 = 0xBB97, + addr_kRio_Ilist_BBA3 = 0xBBA3, + addr_kNorfairLavajumpingEnemy_Ilist_BE3C = 0xBE3C, + addr_kNorfairLavajumpingEnemy_Ilist_BE42 = 0xBE42, + addr_kNorfairLavajumpingEnemy_Ilist_BE62 = 0xBE62, + addr_kNorfairRio_Ilist_C0F1 = 0xC0F1, + addr_kNorfairRio_Ilist_C107 = 0xC107, + addr_kNorfairRio_Ilist_C12F = 0xC12F, + addr_kNorfairRio_Ilist_C145 = 0xC145, + addr_kNorfairRio_Ilist_C179 = 0xC179, + addr_kNorfairRio_Ilist_C18F = 0xC18F, + addr_kNorfairRio_Ilist_C1A3 = 0xC1A3, + addr_kLowerNorfairRio_Ilist_C61A = 0xC61A, + addr_kLowerNorfairRio_Ilist_C630 = 0xC630, + addr_kLowerNorfairRio_Ilist_C65A = 0xC65A, + addr_kLowerNorfairRio_Ilist_C662 = 0xC662, + addr_kLowerNorfairRio_Ilist_C674 = 0xC674, + addr_kLowerNorfairRio_Ilist_C686 = 0xC686, + addr_kLowerNorfairRio_Ilist_C6B0 = 0xC6B0, + addr_kMaridiaLargeSnail_Ilist_CA4B = 0xCA4B, + addr_kHirisingSlowfalling_Ilist_D82C = 0xD82C, + addr_kHirisingSlowfalling_Ilist_D834 = 0xD834, + addr_kHirisingSlowfalling_Ilist_D840 = 0xD840, + addr_kGripper_Ilist_E19B = 0xE19B, + addr_kGripper_Ilist_E1AF = 0xE1AF, + addr_kRipper_Ilist_E2E0 = 0xE2E0, + addr_kRipper_Ilist_E2F4 = 0xE2F4, + addr_kGripper_Sprmap_E43F = 0xE43F, + addr_kGripper_Sprmap_E44B = 0xE44B, + addr_kRipper_Ilist_E477 = 0xE477, + addr_kRipper_Ilist_E48B = 0xE48B, + addr_kLavaSeahorse_Ilist_E59B = 0xE59B, + addr_kLavaSeahorse_Ilist_E5A1 = 0xE5A1, + addr_kTimedShutter_Ilist_E998 = 0xE998, + addr_kTimedShutter_Ilist_E99E = 0xE99E, + addr_kTimedShutter_Ilist_E9A4 = 0xE9A4, + addr_kTimedShutter_Ilist_E9AA = 0xE9AA, + addr_kTimedShutter_Ilist_E9D4 = 0xE9D4, + addr_kRisingFallingPlatform_Ilist_EDE7 = 0xEDE7, +}; +enum Consts_A3 { + addr_kSpritemap_Nothing_A3 = 0x804D, + addr_kWaver_Ilist_86A7 = 0x86A7, + addr_kMetalee_Ilist_8910 = 0x8910, + addr_kFireflea_Ilist_8C2F = 0x8C2F, + addr_kMaridiaFish_Ilist_902A = 0x902A, + addr_kMaridiaFish_Ilist_903C = 0x903C, + addr_kMaridiaFish_Ilist_9060 = 0x9060, + addr_kMaridiaFish_Ilist_9072 = 0x9072, + addr_kElevator_Ilist_94D6 = 0x94D6, + addr_kPlatformThatFallsWithSamus_Ilist_9BBB = 0x9BBB, + addr_kPlatformThatFallsWithSamus_Ilist_9BD1 = 0x9BD1, + addr_kPlatformThatFallsWithSamus_Ilist_9BE7 = 0x9BE7, + addr_kPlatformThatFallsWithSamus_Ilist_9BFD = 0x9BFD, + addr_kPlatformThatFallsWithSamus_Ilist_9C13 = 0x9C13, + addr_kPlatformThatFallsWithSamus_Ilist_9C29 = 0x9C29, + addr_kPlatformThatFallsWithSamus_Ilist_9C3F = 0x9C3F, + addr_kPlatformThatFallsWithSamus_Ilist_9C55 = 0x9C55, + addr_kPlatformThatFallsWithSamus_Sprmap_A009 = 0xA009, + addr_kPlatformThatFallsWithSamus_Sprmap_A015 = 0xA015, + addr_kMochtroid_Ilist_A745 = 0xA745, + addr_kMochtroid_Ilist_A759 = 0xA759, + addr_kMaridiaRefillCandy_Ilist_B3C1 = 0xB3C1, + addr_kBang_Ilist_B75E = 0xB75E, + addr_kSkree_Ilist_C65E = 0xC65E, + addr_stru_A3CCE2 = 0xCCE2, + addr_stru_A3CCEA = 0xCCEA, + addr_stru_A3CCF2 = 0xCCF2, + addr_stru_A3CCFA = 0xCCFA, + addr_stru_A3CD02 = 0xCD02, + addr_stru_A3CD0A = 0xCD0A, + addr_stru_A3CD12 = 0xCD12, + addr_stru_A3CD1A = 0xCD1A, + addr_stru_A3CD22 = 0xCD22, + addr_stru_A3CD2A = 0xCD2A, + addr_stru_A3CD32 = 0xCD32, + addr_stru_A3CD3A = 0xCD3A, + addr_kWreckedShipOrangeZoomer_Ilist_DFCB = 0xDFCB, + addr_kWreckedShipOrangeZoomer_Ilist_DFE7 = 0xDFE7, + addr_kWreckedShipOrangeZoomer_Ilist_E003 = 0xE003, + addr_kWreckedShipOrangeZoomer_Ilist_E01F = 0xE01F, + addr_locret_A3E08A = 0xE08A, + addr_kMetroid_Ilist_E9CF = 0xE9CF, + addr_kMetroid_Ilist_EA25 = 0xEA25, +}; +enum Consts_A4 { + addr_kSpritemap_Nothing_A4 = 0x804D, + addr_kExtendedSpritemap_Nothing_A4 = 0x804F, + addr_kCrocomire_Ilist_BADE = 0xBADE, + addr_kCrocomire_Ilist_BAEA = 0xBAEA, + addr_kCrocomire_Ilist_BB36 = 0xBB36, + addr_kCrocomire_Ilist_BBCA = 0xBBCA, + addr_kCrocomire_Ilist_BBCE = 0xBBCE, + addr_kCrocomire_Ilist_BC30 = 0xBC30, + addr_kCrocomire_Ilist_BC34 = 0xBC34, + addr_kCrocomire_Ilist_BC56 = 0xBC56, + addr_kCrocomire_Ilist_BCD8 = 0xBCD8, + addr_kCrocomire_Ilist_BD2A = 0xBD2A, + addr_kCrocomire_Ilist_BD8E = 0xBD8E, + addr_kCrocomire_Ilist_BDAE = 0xBDAE, + addr_kCrocomire_Ilist_BDB2 = 0xBDB2, + addr_kCrocomire_Ilist_BDB6 = 0xBDB6, + addr_kCrocomire_Ilist_BE56 = 0xBE56, + addr_kCrocomire_Ilist_BE7E = 0xBE7E, + addr_kCrocomire_Ilist_BF3C = 0xBF3C, + addr_kCrocomire_Ilist_BF62 = 0xBF62, + addr_kCrocomire_Ilist_BF64 = 0xBF64, + addr_kCrocomire_Ilist_BF6C = 0xBF6C, + addr_kCrocomire_Ilist_BF72 = 0xBF72, + addr_kCrocomire_Ilist_BF78 = 0xBF78, + addr_kCrocomire_Ilist_BF7E = 0xBF7E, + addr_kCrocomire_Ilist_BF86 = 0xBF86, + addr_kCrocomire_Ilist_BF8C = 0xBF8C, + addr_kCrocomire_Ilist_BF92 = 0xBF92, + addr_kCrocomire_Ilist_BF98 = 0xBF98, + addr_kCrocomire_Ilist_BFB0 = 0xBFB0, + addr_kCrocomire_BigSprmap_D51C = 0xD51C, + addr_kCrocomire_BigSprmap_D600 = 0xD600, + addr_kCrocomire_Ilist_E14A = 0xE14A, + addr_kCrocomire_Ilist_E158 = 0xE158, + addr_kCrocomire_Ilist_E1CC = 0xE1CC, + addr_kCrocomire_Ilist_E1D2 = 0xE1D2, +}; +enum Consts_A5 { + addr_kDraygon_Ilist_97B9 = 0x97B9, + addr_kDraygon_Ilist_97BB = 0x97BB, + addr_kDraygon_Ilist_97D1 = 0x97D1, + addr_kDraygon_Ilist_97E7 = 0x97E7, + addr_kDraygon_Ilist_9813 = 0x9813, + addr_kDraygon_Ilist_9825 = 0x9825, + addr_kDraygon_Ilist_9845 = 0x9845, + addr_kDraygon_Ilist_9867 = 0x9867, + addr_kDraygon_Ilist_9889 = 0x9889, + addr_kDraygon_Ilist_98ED = 0x98ED, + addr_kDraygon_Ilist_98FE = 0x98FE, + addr_kDraygon_Ilist_9922 = 0x9922, + addr_kDraygon_Ilist_9944 = 0x9944, + addr_kDraygon_Ilist_997A = 0x997A, + addr_kDraygon_Ilist_999C = 0x999C, + addr_kDraygon_Ilist_99AE = 0x99AE, + addr_kDraygon_Ilist_99B4 = 0x99B4, + addr_kDraygon_Ilist_99BA = 0x99BA, + addr_kDraygon_Ilist_99C0 = 0x99C0, + addr_kDraygon_Ilist_99FC = 0x99FC, + addr_kDraygon_Ilist_9A68 = 0x9A68, + addr_kDraygon_Ilist_9AE8 = 0x9AE8, + addr_kDraygon_Ilist_9B5A = 0x9B5A, + addr_kDraygon_Ilist_9BDA = 0x9BDA, + addr_kDraygon_Ilist_9C06 = 0x9C06, + addr_kDraygon_Ilist_9C18 = 0x9C18, + addr_kDraygon_Ilist_9C38 = 0x9C38, + addr_kDraygon_Ilist_9C5A = 0x9C5A, + addr_kDraygon_Ilist_9C90 = 0x9C90, + addr_kDraygon_Ilist_9CB4 = 0x9CB4, + addr_kDraygon_Ilist_9D1C = 0x9D1C, + addr_kDraygon_Ilist_9D3E = 0x9D3E, + addr_kDraygon_Ilist_9D50 = 0x9D50, + addr_kDraygon_Ilist_9D56 = 0x9D56, + addr_kDraygon_Ilist_9D5C = 0x9D5C, + addr_kDraygon_Ilist_9D62 = 0x9D62, + addr_kDraygon_Ilist_9D9E = 0x9D9E, + addr_kDraygon_Ilist_9E21 = 0x9E21, + addr_kDraygon_Ilist_9EA1 = 0x9EA1, + addr_kDraygon_Ilist_9F15 = 0x9F15, + addr_kDraygon_Palette = 0xA1F7, + addr_kDraygon_MorePalettes2 = 0xA277, + addr_word_A5A297 = 0xA297, + addr_kDraygon_BigSprmap_C08F__plus__17 = 0xC0A0, + addr_kDraygon_BigSprmap_C11B__plus__197 = 0xC1E0, + addr_kDraygon_Ilist_E6B9 = 0xE6B9, + addr_kDraygon_Ilist_E6C7 = 0xE6C7, + addr_kDraygon_Ilist_E6D5 = 0xE6D5, + addr_stru_A5E729 = 0xE729, + addr_kDraygon_Ilist_E77D = 0xE77D, +}; +enum Consts_A6 { + addr_kBoulder_Ilist_86A7 = 0x86A7, + addr_kBoulder_Ilist_86CB = 0x86CB, + addr_kSpikeyPlatform_Ilist_8B29 = 0x8B29, + addr_kFireGeyser_Ilist_8D1B = 0x8D1B, + addr_kFireGeyser_Ilist_8DA9 = 0x8DA9, + addr_kNuclearWaffle_Ilist_9490 = 0x9490, + addr_stru_A699AE = 0x99AE, + addr_stru_A699C6 = 0x99C6, + addr_kFakeKraid_Ilist_99DC = 0x99DC, + addr_stru_A699FC = 0x99FC, + addr_stru_A69A14 = 0x9A14, + addr_kFakeKraid_Ilist_9A2A = 0x9A2A, + addr_kCeresRidley_Sprmap_A329 = 0xA329, + addr_loc_A6A7F9 = 0xA7F9, + addr_word_A6A9E3 = 0xA9E3, + addr_word_A6AA01 = 0xAA01, + addr_stru_A6AA2F = 0xAA2F, + addr_stru_A6AA3F = 0xAA3F, + addr_off_A6B38C = 0xB38C, + addr_off_A6B39C = 0xB39C, + addr_off_A6B3AC = 0xB3AC, + addr_off_A6B3BC = 0xB3BC, + addr_off_A6B3CC = 0xB3CC, + addr_off_A6B3DC = 0xB3DC, + addr_loc_A6B455 = 0xB455, + addr_locret_A6BF19 = 0xBF19, + addr_kBabyMetroid_Ilist_BF31 = 0xBF31, + addr_byte_A6C15D = 0xC15D, + addr_stru_A6C3B8 = 0xC3B8, + addr_stru_A6C4CB = 0xC4CB, + addr_locret_A6C600 = 0xC600, + addr_stru_A6C987 = 0xC987, + addr_stru_A6C997 = 0xC997, + addr_stru_A6C9A7 = 0xC9A7, + addr_stru_A6C9B7 = 0xC9B7, + addr_stru_A6C9C7 = 0xC9C7, + addr_stru_A6C9D7 = 0xC9D7, + addr_stru_A6C9E7 = 0xC9E7, + addr_stru_A6C9F7 = 0xC9F7, + addr_stru_A6CA07 = 0xCA07, + addr_stru_A6CA17 = 0xCA17, + addr_stru_A6CA27 = 0xCA27, + addr_stru_A6CA37 = 0xCA37, + addr_kRidleysExplosion_Ilist_CA47 = 0xCA47, + addr_kRidleysExplosion_Ilist_CA4D = 0xCA4D, + addr_kRidleysExplosion_Ilist_CA53 = 0xCA53, + addr_word_A6D36E = 0xD36E, + addr_word_A6D37C = 0xD37C, + addr_word_A6D38A = 0xD38A, + addr_word_A6D398 = 0xD398, + addr_word_A6D3A6 = 0xD3A6, + addr_word_A6DA71 = 0xDA71, + addr_off_A6DAD0 = 0xDAD0, + addr_off_A6DAD4 = 0xDAD4, + addr_word_A6E16F = 0xE16F, + addr_word_A6E1CF = 0xE1CF, + addr_kRidley_Ilist_E538 = 0xE538, + addr_kRidley_Ilist_E548 = 0xE548, + addr_kRidley_Ilist_E658 = 0xE658, + addr_kRidley_Ilist_E690 = 0xE690, + addr_kRidley_Ilist_E6C8 = 0xE6C8, + addr_kRidley_Ilist_E6F0 = 0xE6F0, + addr_kRidley_Ilist_E706 = 0xE706, + addr_kRidley_Ilist_E73A = 0xE73A, + addr_kRidley_Ilist_E91D = 0xE91D, + addr_kCeresDoor_Palette__plus__2 = 0xF4EE, + addr_word_A6F50C__plus__2 = 0xF50E, + addr_kCeresDoor_Sprmap_FAC7 = 0xFAC7, + addr_stru_A6FCE1 = 0xFCE1, + addr_stru_A6FCF9 = 0xFCF9, +}; +enum Consts_A7 { + addr_kSpritemap_Nothing_A7 = 0x804D, + addr_kKraid_Ilist_86E7 = 0x86E7, + addr_kKraid_Ilist_86ED = 0x86ED, + addr_kKraid_Ilist_86F3 = 0x86F3, + addr_off_A787BB = 0x87BB, + addr_kKraid_Ilist_87BD = 0x87BD, + addr_off_A78885 = 0x8885, + addr_kKraid_Ilist_8887 = 0x8887, + addr_kKraid_Ilist_89F3 = 0x89F3, + addr_kKraid_Ilist_8A41 = 0x8A41, + addr_kKraid_Ilist_8AA4 = 0x8AA4, + addr_kKraid_Ilist_8AF0 = 0x8AF0, + addr_kKraid_Ilist_8AFE = 0x8AFE, + addr_kKraid_Ilist_8B04 = 0x8B04, + addr_kKraid_Ilist_8B0A = 0x8B0A, + addr_kKraid_Sprmap_8C6C = 0x8C6C, + addr_stru_A796DA = 0x96DA, + addr_stru_A7974A__plus__8 = 0x9752, + addr_stru_A79764__plus__8 = 0x976C, + addr_kKraidTilemaps_0 = 0x97C8, + addr_kKraidTilemaps_1 = 0x9AC8, + addr_kKraidTilemaps_2 = 0x9DC8, + addr_kKraidTilemaps_3 = 0xA0C8, + addr_kKraid_Sprmap_A5DF = 0xA5DF, + addr_kKraidsRoomBg = 0xA716, + addr_locret_A7B831 = 0xB831, + addr_kKraid_Ilist_CC41 = 0xCC41, + addr_kKraid_Ilist_CC47 = 0xCC47, + addr_kKraid_Ilist_CC4D = 0xCC4D, + addr_kKraid_Ilist_CC53 = 0xCC53, + addr_kKraid_Ilist_CC81 = 0xCC81, + addr_kKraid_Ilist_CC91 = 0xCC91, + addr_kKraid_Ilist_CC9D = 0xCC9D, + addr_kKraid_Ilist_CCEB = 0xCCEB, + addr_kPhantoonMoveData = 0xE3D2, + addr_kEtecoon_Ilist_E81E = 0xE81E, + addr_stru_A7E828 = 0xE828, + addr_kEtecoon_Ilist_E83C = 0xE83C, + addr_kEtecoon_Ilist_E854 = 0xE854, + addr_stru_A7E862 = 0xE862, + addr_kEtecoon_Ilist_E870 = 0xE870, + addr_kEtecoon_Ilist_E876 = 0xE876, + addr_stru_A7E880 = 0xE880, + addr_kEtecoon_Ilist_E894 = 0xE894, + addr_stru_A7E898 = 0xE898, + addr_kEtecoon_Ilist_E8AC = 0xE8AC, + addr_kEtecoon_Ilist_E8C8 = 0xE8C8, + addr_kEtecoon_Ilist_E8CE = 0xE8CE, + addr_kEtecoon_Ilist_E8D6 = 0xE8D6, + addr_kDachora_Palette = 0xF225, + addr_kDachora_Ilist_F345 = 0xF345, + addr_kDachora_Ilist_F399 = 0xF399, + addr_kDachora_Ilist_F3C9 = 0xF3C9, + addr_kDachora_Ilist_F3F7 = 0xF3F7, + addr_kDachora_Ilist_F3FF = 0xF3FF, + addr_kDachora_Ilist_F407 = 0xF407, + addr_kDachora_Ilist_F45B = 0xF45B, + addr_kDachora_Ilist_F48B = 0xF48B, + addr_kDachora_Ilist_F4B3 = 0xF4B3, + addr_kDachora_Ilist_F4B9 = 0xF4B9, + addr_kDachora_Ilist_F4C1 = 0xF4C1, +}; +enum Consts_A8 { + addr_kSpritemap_Nothing_A8 = 0x804D, + addr_kMiniDraygon_Ilist_86A7 = 0x86A7, + addr_kMiniDraygon_Ilist_86C3 = 0x86C3, + addr_kMiniDraygon_Ilist_870B = 0x870B, + addr_kMiniDraygon_Ilist_8727 = 0x8727, + addr_kMiniDraygon_Ilist_876F = 0x876F, + addr_kMiniDraygon_Ilist_8775 = 0x8775, + addr_kMorphBallEye_Ilist_8FF0 = 0x8FF0, + addr_stru_A88FFC = 0x8FFC, + addr_kMorphBallEye_Ilist_9002 = 0x9002, + addr_stru_A8900E = 0x900E, + addr_kMorphBallEye_Ilist_9014 = 0x9014, + addr_kMorphBallEye_Ilist_9026 = 0x9026, + addr_off_A896D7 = 0x96D7, + addr_off_A896DF = 0x96DF, + addr_kWreckedShipGhost_Ilist_9A8C = 0x9A8C, + addr_loc_A89E90 = 0x9E90, + addr_kYappingMaw_Ilist_9F6F = 0x9F6F, + addr_kYappingMaw_Ilist_9FC7 = 0x9FC7, + addr_kYappingMaw_Ilist_A01F = 0xA01F, + addr_off_A8A025 = 0xA025, + addr_kYappingMaw_Ilist_A03D = 0xA03D, + addr_kYappingMaw_Ilist_A05B = 0xA05B, + addr_off_A8A061 = 0xA061, + addr_kYappingMaw_Ilist_A079 = 0xA079, + addr_kKago_Ilist_AB1E = 0xAB1E, + addr_kKago_Ilist_AB32 = 0xAB32, + addr_kNorfairLavaMan_Ilist_AC9C = 0xAC9C, + addr_kNorfairLavaMan_Ilist_ACB0 = 0xACB0, + addr_kNorfairLavaMan_Ilist_ACDE = 0xACDE, + addr_kNorfairLavaMan_Ilist_AD0C = 0xAD0C, + addr_kNorfairLavaMan_Ilist_AD3C = 0xAD3C, + addr_kNorfairLavaMan_Ilist_AD50 = 0xAD50, + addr_kNorfairLavaMan_Ilist_AD7E = 0xAD7E, + addr_kNorfairLavaMan_Ilist_ADAC = 0xADAC, + addr_kNorfairLavaMan_Ilist_ADDC = 0xADDC, + addr_kNorfairLavaMan_Ilist_AE0C = 0xAE0C, + addr_kBeetom_Ilist_B696 = 0xB696, + addr_kBeetom_Ilist_B6AC = 0xB6AC, + addr_kBeetom_Ilist_B6CC = 0xB6CC, + addr_kBeetom_Ilist_B6F2 = 0xB6F2, + addr_kBeetom_Ilist_B708 = 0xB708, + addr_kBeetom_Ilist_B728 = 0xB728, + addr_kMaridiaFloater_Ilist_C163 = 0xC163, + addr_kMaridiaFloater_Ilist_C173 = 0xC173, + addr_kMaridiaFloater_Ilist_C183 = 0xC183, + addr_kMaridiaFloater_Ilist_C191 = 0xC191, + addr_stru_A8C199 = 0xC199, + addr_kWreckedShipRobot_Ilist_C6E5 = 0xC6E5, + addr_stru_A8C6E9 = 0xC6E9, + addr_kWreckedShipRobot_Ilist_C73F = 0xC73F, + addr_kWreckedShipRobot_Ilist_C7BB = 0xC7BB, + addr_kWreckedShipRobot_Ilist_C833 = 0xC833, + addr_kWreckedShipRobot_Ilist_C8B1 = 0xC8B1, + addr_kWreckedShipRobot_Ilist_C8BD = 0xC8BD, + addr_kWreckedShipRobot_Ilist_C8D1 = 0xC8D1, + addr_kWreckedShipRobot_Ilist_C91B = 0xC91B, + addr_kWreckedShipRobot_Ilist_C92D = 0xC92D, + addr_kWreckedShipRobot_Ilist_C985 = 0xC985, + addr_kWreckedShipRobot_Ilist_CA01 = 0xCA01, + addr_kWreckedShipRobot_Ilist_CA7D = 0xCA7D, + addr_kWreckedShipRobot_Ilist_CAFD = 0xCAFD, + addr_kWreckedShipRobot_Ilist_CB09 = 0xCB09, + addr_kWreckedShipRobot_Ilist_CB1D = 0xCB1D, + addr_kWreckedShipRobot_Ilist_CB65 = 0xCB65, + addr_loc_A8CF18 = 0xCF18, + addr_loc_A8CF26 = 0xCF26, + addr_loc_A8D02E = 0xD02E, + addr_kMaridiaPuffer_Ilist_D841 = 0xD841, + addr_kMaridiaPuffer_Ilist_D855 = 0xD855, + addr_kWalkingLavaSeahorse_Ilist_DBE7 = 0xDBE7, + addr_stru_A8DBE9 = 0xDBE9, + addr_kWalkingLavaSeahorse_Ilist_DC03 = 0xDC03, + addr_stru_A8DC4B = 0xDC4B, + addr_kWalkingLavaSeahorse_Ilist_DC51 = 0xDC51, + addr_kWalkingLavaSeahorse_Ilist_DC57 = 0xDC57, + addr_stru_A8DC59 = 0xDC59, + addr_kWalkingLavaSeahorse_Ilist_DC73 = 0xDC73, + addr_stru_A8DCBB = 0xDCBB, + addr_kWalkingLavaSeahorse_Ilist_DCC1 = 0xDCC1, + addr_kWreckedShipSpark_Ilist_E5A7 = 0xE5A7, + addr_kWreckedShipSpark_Ilist_E5E5 = 0xE5E5, + addr_kBlueBrinstarFaceBlock_Ilist_E80C = 0xE80C, + addr_kBlueBrinstarFaceBlock_Ilist_E81A = 0xE81A, + addr_kBlueBrinstarFaceBlock_Ilist_E828 = 0xE828, + addr_kKiHunter_Ilist_E9FA = 0xE9FA, + addr_kKiHunter_Ilist_EA08 = 0xEA08, + addr_kKiHunter_Ilist_EA24 = 0xEA24, + addr_kKiHunter_Ilist_EA32 = 0xEA32, + addr_kKiHunter_Ilist_EA4E = 0xEA4E, + addr_kKiHunter_Ilist_EA5E = 0xEA5E, + addr_kKiHunter_Ilist_EA7E = 0xEA7E, + addr_kKiHunter_Ilist_EA8A = 0xEA8A, + addr_kKiHunter_Ilist_EAA6 = 0xEAA6, + addr_kKiHunter_Ilist_EAC2 = 0xEAC2, + addr_kKiHunter_Ilist_EADA = 0xEADA, + addr_kKiHunter_Ilist_EAF2 = 0xEAF2, + addr_kKiHunter_Ilist_EB10 = 0xEB10, + addr_locret_A8F5E3 = 0xF5E3, +}; +enum Consts_A9 { + addr_locret_A98AE4 = 0x8AE4, + addr_stru_A98AE5 = 0x8AE5, + addr_stru_A98AF5 = 0x8AF5, + addr_stru_A98B05 = 0x8B05, + addr_stru_A98B25 = 0x8B25, + addr_stru_A98F8F = 0x8F8F, + addr_stru_A98FC7 = 0x8FC7, + addr_stru_A98FE5 = 0x8FE5, + addr_stru_A99003 = 0x9003, + addr_stru_A9902F = 0x902F, + addr_kMotherBrainsBrain_Palette__plus__2 = 0x9474, + addr_kMotherBrainPalette_0__plus__2 = 0x9494, + addr_kMotherBrainPalette_1__plus__2 = 0x94B4, + addr_kMotherBrainPalette_2__plus__2 = 0x94D4, + addr_kMotherBrainPalette_3__plus__2 = 0x94F4, + addr_kMotherBrainPalette_4__plus__2 = 0x9514, + addr_kMotherBrainPalette_5__plus__2 = 0x9534, + addr_kMotherBrain_Ilist_97A4 = 0x97A4, + addr_kMotherBrain_Ilist_98C6 = 0x98C6, + addr_kMotherBrain_Ilist_99AA = 0x99AA, + addr_kMotherBrain_Ilist_99C6 = 0x99C6, + addr_kMotherBrain_Ilist_99E2 = 0x99E2, + addr_kMotherBrain_Ilist_99F2 = 0x99F2, + addr_kMotherBrain_Ilist_9A02 = 0x9A02, + addr_kMotherBrain_Ilist_9A0A = 0x9A0A, + addr_kMotherBrain_Ilist_9A26 = 0x9A26, + addr_kMotherBrain_Ilist_9A42 = 0x9A42, + addr_kMotherBrain_Ilist_9B7F = 0x9B7F, + addr_kMotherBrain_Ilist_9BB3 = 0x9BB3, + addr_kMotherBrain_Ilist_9BE7 = 0x9BE7, + addr_kMotherBrain_Ilist_9C13 = 0x9C13, + addr_stru_A99C21 = 0x9C21, + addr_kMotherBrain_Ilist_9C29 = 0x9C29, + addr_kMotherBrain_Ilist_9C39 = 0x9C39, + addr_stru_A99C47 = 0x9C47, + addr_stru_A99C5F = 0x9C5F, + addr_kMotherBrain_Ilist_9C77 = 0x9C77, + addr_kMotherBrain_Ilist_9C87 = 0x9C87, + addr_stru_A99C9F = 0x9C9F, + addr_stru_A99CD1 = 0x9CD1, + addr_kMotherBrain_Ilist_9D25 = 0x9D25, + addr_kMotherBrain_Ilist_9D3D = 0x9D3D, + addr_kMotherBrain_Ilist_9D7F = 0x9D7F, + addr_kMotherBrain_Ilist_9DB1 = 0x9DB1, + addr_kMotherBrain_Ilist_9DBB = 0x9DBB, + addr_kMotherBrain_Ilist_9ECC = 0x9ECC, + addr_kMotherBrain_Ilist_9F00 = 0x9F00, + addr_kMotherBrain_Ilist_9F34 = 0x9F34, + addr_kMotherBrain_Ilist_9F6C = 0x9F6C, + addr_kMotherBrain_Sprmap_A694 = 0xA694, + addr_word_A9B109 = 0xB109, + addr_word_A9B10F = 0xB10F, + addr_word_A9B427 = 0xB427, + addr_byte_A9B6DC = 0xB6DC, + addr_byte_A9B6DF = 0xB6DF, + addr_stru_A9BE28 = 0xBE28, + addr_locret_A9C18D = 0xC18D, + addr_locret_A9C353 = 0xC353, + addr_loc_A9C49C = 0xC49C, + addr_loc_A9C959 = 0xC959, + addr_stru_A9CA24 = 0xCA24, + addr_kShitroid_Ilist_CFA2 = 0xCFA2, + addr_kShitroid_Ilist_CFB8 = 0xCFB8, + addr_kShitroid_Ilist_CFCE = 0xCFCE, + addr_stru_A9D046 = 0xD046, + addr_word_A9D082 = 0xD082, + addr_kDeadTorizo_Ilist_D6DC = 0xD6DC, + addr_kDeadTorizo_Sprmap_D761 = 0xD761, + addr_kDeadTorizo_Hitbox_D77C = 0xD77C, + addr_stru_A9DD58 = 0xDD58, + addr_stru_A9DD68 = 0xDD68, + addr_stru_A9DD78 = 0xDD78, + addr_stru_A9DE08 = 0xDE08, + addr_kDeadMonsters_Ilist_ECAC = 0xECAC, + addr_kDeadMonsters_Ilist_ECE3 = 0xECE3, + addr_kDeadMonsters_Ilist_ECE9 = 0xECE9, + addr_kDeadMonsters_Ilist_ECEF = 0xECEF, + addr_word_A9F6D1 = 0xF6D1, + addr_word_A9F711 = 0xF711, + addr_kDeadSidehopper_Palette_0 = 0xF8A6, + addr_word_A9F8C6 = 0xF8C6, + addr_kShitroidInCutscene_Palette = 0xF8E6, + addr_kShitroid_Ilist_F906 = 0xF906, + addr_kShitroid_Ilist_F90E = 0xF90E, + addr_kShitroid_Ilist_F924 = 0xF924, + addr_kShitroid_Ilist_F93A = 0xF93A, +}; +enum Consts_AA { + addr_kSpritemap_Nothing_AA = 0x804D, + addr_kTorizo_ExtSprmap_87D0 = 0x87D0, + addr_kTorizo_Ilist_B0E5 = 0xB0E5, + addr_kTorizo_Ilist_B155 = 0xB155, + addr_kTorizo_Ilist_B1C8 = 0xB1C8, + addr_kTorizo_Ilist_B962 = 0xB962, + addr_off_AABC78 = 0xBC78, + addr_kTorizo_Ilist_BD0E = 0xBD0E, + addr_kTorizo_Ilist_BDD8 = 0xBDD8, + addr_off_AAC0F2 = 0xC0F2, + addr_kTorizo_Ilist_C188 = 0xC188, + addr_locret_AAC95E = 0xC95E, + addr_kTorizo_Ilist_CDE1 = 0xCDE1, + addr_kTorizo_Ilist_CE43 = 0xCE43, + addr_kTorizo_Ilist_CEA5 = 0xCEA5, + addr_kTorizo_Ilist_CEFF = 0xCEFF, + addr_kTorizo_Ilist_D1F1 = 0xD1F1, + addr_kTorizo_Ilist_D203 = 0xD203, + addr_kTorizo_Ilist_D2AD = 0xD2AD, + addr_kTorizo_Ilist_D2BF = 0xD2BF, + addr_kShaktool_Ilist_E3A7 = 0xE3A7, + addr_kShaktool_Ilist_E461 = 0xE461, +}; +enum Consts_AD { + addr_kTurnOffLightsForShitroidDeath = 0xF22F, +}; +enum Consts_B2 { + addr_kSpacePirates_Ilist_ECC0 = 0xECC0, + addr_kSpacePirates_Ilist_ECE4 = 0xECE4, + addr_off_B2ECEC = 0xECEC, + addr_kSpacePirates_Ilist_ED36 = 0xED36, + addr_kSpacePirates_Ilist_ED80 = 0xED80, + addr_kSpacePirates_Ilist_EDA4 = 0xEDA4, + addr_off_B2EDAC = 0xEDAC, + addr_kSpacePirates_Ilist_EDF6 = 0xEDF6, + addr_kSpacePirates_Ilist_F15C = 0xF15C, + addr_kSpacePirates_Ilist_F1C4 = 0xF1C4, + addr_kSpacePirates_Ilist_F22E = 0xF22E, + addr_kSpacePirates_Ilist_F270 = 0xF270, + addr_kSpacePirates_Ilist_F2A0 = 0xF2A0, + addr_kSpacePirates_Ilist_F2B2 = 0xF2B2, + addr_kSpacePirates_Ilist_F2DA = 0xF2DA, + addr_kSpacePirates_Ilist_F2F8 = 0xF2F8, + addr_kSpacePirates_Ilist_F32E = 0xF32E, + addr_kSpacePirates_Ilist_F34A = 0xF34A, + addr_kSpacePirates_Ilist_F3B2 = 0xF3B2, + addr_kSpacePirates_Ilist_F420 = 0xF420, + addr_kSpacePirates_Ilist_F462 = 0xF462, + addr_kSpacePirates_Ilist_F492 = 0xF492, + addr_kSpacePirates_Ilist_F4A4 = 0xF4A4, + addr_kSpacePirates_Ilist_F4CC = 0xF4CC, + addr_kSpacePirates_Ilist_F4EA = 0xF4EA, + addr_kSpacePirates_Ilist_F51A = 0xF51A, + addr_kSpacePirates_Ilist_FB4C = 0xFB4C, + addr_kSpacePirates_Ilist_FB58 = 0xFB58, + addr_kSpacePirates_Ilist_FB64 = 0xFB64, + addr_kSpacePirates_Ilist_FB8C = 0xFB8C, + addr_kSpacePirates_Ilist_FBC6 = 0xFBC6, + addr_kSpacePirates_Ilist_FBE6 = 0xFBE6, + addr_kSpacePirates_Ilist_FC0E = 0xFC0E, + addr_kSpacePirates_Ilist_FC48 = 0xFC48, +}; +enum Consts_B3 { + addr_kSpritemap_Nothing_B3 = 0x804D, + addr_kUnusedSpinningTurtleEye_Ilist_86A7 = 0x86A7, + addr_kBrinstarPipeBug_Ilist_87AB = 0x87AB, + addr_kBrinstarPipeBug_Ilist_8A1D = 0x8A1D, + addr_kNorfairPipeBug_Ilist_8AE1 = 0x8AE1, + addr_kNorfairPipeBug_Ilist_8B05 = 0x8B05, + addr_kNorfairPipeBug_Ilist_8B21 = 0x8B21, + addr_kNorfairPipeBug_Ilist_8B45 = 0x8B45, + addr_kBrinstarYellowPipeBug_Ilist_8EFC = 0x8EFC, + addr_kBrinstarYellowPipeBug_Ilist_8F10 = 0x8F10, + addr_kBrinstarYellowPipeBug_Ilist_8F24 = 0x8F24, + addr_kBrinstarYellowPipeBug_Ilist_8F38 = 0x8F38, + addr_kBotwoon_Ilist_9389 = 0x9389, + addr_loc_B3E28C = 0xE28C, + addr_kEscapeEtecoon_Ilist_E556 = 0xE556, + addr_kEscapeEtecoon_Ilist_E582 = 0xE582, + addr_kEscapeEtecoon_Ilist_E5AE = 0xE5AE, + addr_kEscapeEtecoon_Ilist_E5DA = 0xE5DA, + addr_kEscapeDachora_Ilist_E964 = 0xE964, +}; +enum Consts_B4 { + addr_kSpriteObject_Ilist_C3BA = 0xC3BA, + addr_kSpriteObject_Ilist_C4B6 = 0xC4B6, + addr_asc_B4DD89 = 0xDD89, + addr_stru_B4EC1C = 0xEC1C, +}; +enum Consts_B7 { + addr_kDeadTorizo_TileData__plus__288 = 0xA920, + addr_kDeadTorizo_TileData__plus__800 = 0xAB20, + addr_kDeadTorizo_TileData__plus__1280 = 0xAD00, + addr_kDeadTorizo_TileData__plus__1792 = 0xAF00, + addr_kDeadTorizo_TileData__plus__2304 = 0xB100, + addr_kDeadTorizo_TileData__plus__2816 = 0xB300, + addr_kDeadTorizo_TileData__plus__3328 = 0xB500, + addr_kDeadTorizo_TileData__plus__3840 = 0xB700, + addr_kDeadTorizo_TileData__plus__4352 = 0xB900, + addr_kDeadTorizo_TileData__plus__4832 = 0xBAE0, + addr_kDeadTorizo_TileData__plus__5312 = 0xBCC0, + addr_kDeadTorizo_TileData__plus__5824 = 0xBEC0, + addr_kDeadMonsters_TileData__plus__64 = 0xC040, + addr_kDeadMonsters_TileData__plus__224 = 0xC0E0, + addr_kDeadMonsters_TileData__plus__288 = 0xC120, + addr_kDeadMonsters_TileData__plus__448 = 0xC1C0, + addr_kDeadMonsters_TileData__plus__512 = 0xC200, + addr_kDeadMonsters_TileData__plus__672 = 0xC2A0, + addr_kDeadMonsters_TileData__plus__736 = 0xC2E0, + addr_kDeadMonsters_TileData__plus__800 = 0xC320, + addr_kDeadMonsters_TileData__plus__960 = 0xC3C0, + addr_kDeadMonsters_TileData__plus__1024 = 0xC400, + addr_kDeadMonsters_TileData__plus__1184 = 0xC4A0, + addr_kDeadMonsters_TileData__plus__1248 = 0xC4E0, + addr_kDeadMonsters_TileData__plus__1312 = 0xC520, + addr_kDeadMonsters_TileData__plus__1472 = 0xC5C0, + addr_kDeadMonsters_TileData__plus__1536 = 0xC600, + addr_kDeadMonsters_TileData__plus__1696 = 0xC6A0, + addr_kDeadMonsters_TileData__plus__1760 = 0xC6E0, + addr_kDeadMonsters_TileData__plus__1824 = 0xC720, + addr_kDeadMonsters_TileData__plus__1984 = 0xC7C0, + addr_kDeadMonsters_TileData__plus__2048 = 0xC800, + addr_kDeadMonsters_TileData__plus__2208 = 0xC8A0, + addr_kDeadMonsters_TileData__plus__2336 = 0xC920, + addr_kDeadMonsters_TileData__plus__2560 = 0xCA00, + addr_kDeadMonsters_TileData__plus__2656 = 0xCA60, + addr_kDeadMonsters_TileData__plus__2752 = 0xCAC0, + addr_kDeadMonsters_TileData__plus__2848 = 0xCB20, + addr_kDeadMonsters_TileData__plus__2944 = 0xCB80, + addr_kDeadMonsters_TileData__plus__3072 = 0xCC00, + addr_kDeadMonsters_TileData__plus__3168 = 0xCC60, + addr_kDeadMonsters_TileData__plus__3264 = 0xCCC0, + addr_kDeadMonsters_TileData__plus__3360 = 0xCD20, + addr_kDeadMonsters_TileData__plus__3456 = 0xCD80, + addr_kMotherBrain_Misc_TileData__plus__192 = 0xCEC0, + addr_kMotherBrain_Misc_TileData__plus__704 = 0xD0C0, + addr_kMotherBrain_Misc_TileData__plus__1216 = 0xD2C0, + addr_kMotherBrain_Misc_TileData__plus__1728 = 0xD4C0, + addr_kMotherBrain_Misc_TileData__plus__2240 = 0xD6C0, + addr_kMotherBrain_Misc_TileData__plus__2752 = 0xD8C0, +}; +enum Consts_B9 { + addr_byte_B9FA38 = 0xFA38, + addr_byte_B9FE3E = 0xFE3E, +}; + +static inline OamEnt *gOamEnt(int v) { return (OamEnt *)&g_ram[0x370 + v]; } +static inline VramWriteEntry *gVramWriteEntry(int a) { return (VramWriteEntry *)&g_ram[0xd0 + a]; } +struct DoorDef; static inline DoorDef *get_DoorDef(uint16 a) { return (DoorDef *)RomPtr(0x830000 | a); } +struct RoomDefHeader; static inline RoomDefHeader *get_RoomDefHeader(uint16 a) { return (RoomDefHeader *)RomPtr(0x8F0000 | a); } +struct RoomDefRoomstate; static inline RoomDefRoomstate *get_RoomDefRoomstate(uint16 a) { return (RoomDefRoomstate *)RomPtr(0x8F0000 | a); } +struct StateHeaderTiles; static inline StateHeaderTiles *get_StateHeaderTiles(uint16 a) { return (StateHeaderTiles *)RomPtr(0x8F0000 | a); } +struct EnemyDef_A2; static inline EnemyDef_A2 *get_EnemyDef_A2(uint16 a) { return (EnemyDef_A2 *)RomPtr(0xA00000 | a); } +struct EnemyTileset; static inline EnemyTileset *get_EnemyTileset(uint16 a) { return (EnemyTileset *)RomPtr(0xB40000 | a); } +struct RoomPlmEntry; static inline RoomPlmEntry *get_RoomPlmEntry(uint16 a) { return (RoomPlmEntry *)RomPtr(0x8F0000 | a); } +struct PlmHeader_Size6; static inline PlmHeader_Size6 *get_PlmHeader_Size6(uint16 a) { return (PlmHeader_Size6 *)RomPtr(0x8F0000 | a); } +struct EnemyProjectileDef; static inline EnemyProjectileDef *get_EnemyProjectileDef(uint16 a) { return (EnemyProjectileDef *)RomPtr(0x860000 | a); } +struct Vulnerability; static inline Vulnerability *get_Vulnerability(uint16 a) { return (Vulnerability *)RomPtr(0xB40000 | a); } +struct ExtendedSpriteMap; static inline ExtendedSpriteMap *get_ExtendedSpriteMap(uint8 db, uint16 a) { return (ExtendedSpriteMap *)RomPtr(db << 16 | a); } +struct Hitbox; static inline Hitbox *get_Hitbox(uint8 db, uint16 a) { return (Hitbox *)RomPtr(db << 16 | a); } +struct Mode7CgvmWriteQueue; static inline Mode7CgvmWriteQueue *get_Mode7CgvmWriteQueue(uint16 a) { return (Mode7CgvmWriteQueue *)RomPtr(0x800000 | a); } +struct PoseEntry; static inline PoseEntry *get_PoseEntry(uint16 a) { return (PoseEntry *)RomPtr(0x910000 | a); } +struct ProjectileDataTable; static inline ProjectileDataTable *get_ProjectileDataTable(uint16 a) { return (ProjectileDataTable *)RomPtr(0x930000 | a); } +struct DemoInputObject; static inline DemoInputObject *get_DemoInputObject(uint16 a) { return (DemoInputObject *)RomPtr(0x910000 | a); } +struct DemoRoomData; static inline DemoRoomData *get_DemoRoomData(uint16 a) { return (DemoRoomData *)RomPtr(0x820000 | a); } +struct DemoSetDef; static inline DemoSetDef *get_DemoSetDef(uint16 a) { return (DemoSetDef *)RomPtr(0x910000 | a); } +struct EnemyPopulation; static inline EnemyPopulation *get_EnemyPopulation(uint8 db, uint16 a) { return (EnemyPopulation *)RomPtr(db << 16 | a); } +struct FxDef; static inline FxDef *get_FxDef(uint16 a) { return (FxDef *)RomPtr(0x830000 | a); } +struct LoadBg_E; static inline LoadBg_E *get_LoadBg_E(uint16 a) { return (LoadBg_E *)RomPtr(0x8F0000 | a); } +struct Mode7VramWriteQueue; static inline Mode7VramWriteQueue *get_Mode7VramWriteQueue(uint16 a) { return (Mode7VramWriteQueue *)RomPtr(0xA60000 | a); } +struct ProjectileInstr; static inline ProjectileInstr *get_ProjectileInstr(uint16 a) { return (ProjectileInstr *)RomPtr(0x930000 | a); } +struct PlmHeader_Size4; static inline PlmHeader_Size4 *get_PlmHeader_Size4(uint16 a) { return (PlmHeader_Size4 *)RomPtr(0x840000 | a); } +struct RoomDefStateSelect_E6E5_Finish; static inline RoomDefStateSelect_E6E5_Finish *get_RoomDefStateSelect_E6E5_Finish(uint16 a) { return (RoomDefStateSelect_E6E5_Finish *)RomPtr(0x8F0000 | a); } +struct SamusSpeedTableEntry; static inline SamusSpeedTableEntry *get_SamusSpeedTableEntry(uint16 a) { return (SamusSpeedTableEntry *)RomPtr(0x900000 | a); } +struct SpriteDrawEnt; static inline SpriteDrawEnt *get_SpriteDrawEnt(uint16 a) { return (SpriteDrawEnt *)RomPtr(0xA60000 | a); } +struct SamusTileAnimationDefs; static inline SamusTileAnimationDefs *get_SamusTileAnimationDefs(uint16 a) { return (SamusTileAnimationDefs *)RomPtr(0x920000 | a); } +struct LoadBg_28; static inline LoadBg_28 *get_LoadBg_28(uint16 a) { return (LoadBg_28 *)RomPtr(0x8F0000 | a); } +struct PalFxDef; static inline PalFxDef *get_PalFxDef(uint16 a) { return (PalFxDef *)RomPtr(0x8D0000 | a); } +struct Mode7ObjectDef; static inline Mode7ObjectDef *get_Mode7ObjectDef(uint16 a) { return (Mode7ObjectDef *)RomPtr(0x8B0000 | a); } +static inline Ram7800_Default *gRam7800_Default(uint16 a) { return (Ram7800_Default *)&g_ram[0x7800 + a]; } + + +#pragma pack(pop) diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..db3d418 --- /dev/null +++ b/src/main.c @@ -0,0 +1,795 @@ +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include "platform/win32/volume_control.h" +#include +#else +#include +#include +#include +#endif + +#include "snes/ppu.h" + +#include "types.h" +#include "sm_rtl.h" +#include "sm_cpu_infra.h" +#include "config.h" +#include "util.h" +#include "spc_player.h" + +static void playAudio(Snes *snes, SDL_AudioDeviceID device, int16_t *audioBuffer); +static void renderScreen(Snes *snes, SDL_Renderer *renderer, SDL_Texture *texture); +static void SDLCALL AudioCallback(void *userdata, Uint8 *stream, int len); +static void SwitchDirectory(); +static void RenderNumber(uint8 *dst, size_t pitch, int n, uint8 big); +static void OpenOneGamepad(int i); +static void HandleVolumeAdjustment(int volume_adjustment); +static void HandleGamepadAxisInput(int gamepad_id, int axis, int value); +static int RemapSdlButton(int button); +static void HandleGamepadInput(int button, bool pressed); +static void HandleInput(int keyCode, int keyMod, bool pressed); +void OpenGLRenderer_Create(struct RendererFuncs *funcs); + +bool g_is_turbo; +bool g_is_turbo; +bool g_want_dump_memmap_flags; +bool g_new_ppu; +bool g_new_ppu = true; +bool g_other_image; +struct SpcPlayer *g_spc_player; +static uint32_t button_state; + +static uint8_t g_pixels[256 * 4 * 240]; +static uint8_t g_my_pixels[256 * 4 * 240]; + +int g_got_mismatch_count; + + +enum { + kDefaultFullscreen = 0, + kMaxWindowScale = 10, + kDefaultFreq = 44100, + kDefaultChannels = 2, + kDefaultSamples = 2048, +}; + +static const char kWindowTitle[] = "SuperMet"; +static uint32 g_win_flags = SDL_WINDOW_RESIZABLE; +static SDL_Window *g_window; + +static uint8 g_paused, g_turbo, g_replay_turbo = true, g_cursor = true; +static uint8 g_current_window_scale; +static uint8 g_gamepad_buttons; +static int g_input1_state; +static bool g_display_perf; +static int g_curr_fps; +static int g_ppu_render_flags = 0; +static int g_snes_width, g_snes_height; +static int g_sdl_audio_mixer_volume = SDL_MIX_MAXVOLUME; +static struct RendererFuncs g_renderer_funcs; +static uint32 g_gamepad_modifiers; +static uint16 g_gamepad_last_cmd[kGamepadBtn_Count]; +extern Snes *g_snes; + +void NORETURN Die(const char *error) { +#if defined(NDEBUG) && defined(_WIN32) + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, kWindowTitle, error, NULL); +#endif + fprintf(stderr, "Error: %s\n", error); + exit(1); +} + +void ChangeWindowScale(int scale_step) { + if ((SDL_GetWindowFlags(g_window) & (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED)) != 0) + return; + int screen = SDL_GetWindowDisplayIndex(g_window); + if (screen < 0) screen = 0; + int max_scale = kMaxWindowScale; + SDL_Rect bounds; + int bt = -1, bl, bb, br; + // note this takes into effect Windows display scaling, i.e., resolution is divided by scale factor + if (SDL_GetDisplayUsableBounds(screen, &bounds) == 0) { + // this call may take a while before it is reported by Windows (or not at all in my testing) + if (SDL_GetWindowBordersSize(g_window, &bt, &bl, &bb, &br) != 0) { + // guess based on Windows 10/11 defaults + bl = br = bb = 1; + bt = 31; + } + // Allow a scale level slightly above the max that fits on screen + int mw = (bounds.w - bl - br + g_snes_width / 4) / g_snes_width; + int mh = (bounds.h - bt - bb + g_snes_height / 4) / g_snes_height; + max_scale = IntMin(mw, mh); + } + int new_scale = IntMax(IntMin(g_current_window_scale + scale_step, max_scale), 1); + g_current_window_scale = new_scale; + int w = new_scale * g_snes_width; + int h = new_scale * g_snes_height; + + //SDL_RenderSetLogicalSize(g_renderer, w, h); + SDL_SetWindowSize(g_window, w, h); + if (bt >= 0) { + // Center the window on top of the mouse + int mx, my; + SDL_GetGlobalMouseState(&mx, &my); + int wx = IntMax(IntMin(mx - w / 2, bounds.x + bounds.w - bl - br - w), bounds.x + bl); + int wy = IntMax(IntMin(my - h / 2, bounds.y + bounds.h - bt - bb - h), bounds.y + bt); + SDL_SetWindowPosition(g_window, wx, wy); + } else { + SDL_SetWindowPosition(g_window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + } +} + +#define RESIZE_BORDER 20 +static SDL_HitTestResult HitTestCallback(SDL_Window *win, const SDL_Point *pt, void *data) { + uint32 flags = SDL_GetWindowFlags(win); + if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0 || (flags & SDL_WINDOW_FULLSCREEN) != 0) + return SDL_HITTEST_NORMAL; + + if ((SDL_GetModState() & KMOD_CTRL) != 0) + return SDL_HITTEST_DRAGGABLE; + + int w, h; + SDL_GetWindowSize(win, &w, &h); + + if (pt->y < RESIZE_BORDER) { + return (pt->x < RESIZE_BORDER) ? SDL_HITTEST_RESIZE_TOPLEFT : + (pt->x >= w - RESIZE_BORDER) ? SDL_HITTEST_RESIZE_TOPRIGHT : SDL_HITTEST_RESIZE_TOP; + } else if (pt->y >= h - RESIZE_BORDER) { + return (pt->x < RESIZE_BORDER) ? SDL_HITTEST_RESIZE_BOTTOMLEFT : + (pt->x >= w - RESIZE_BORDER) ? SDL_HITTEST_RESIZE_BOTTOMRIGHT : SDL_HITTEST_RESIZE_BOTTOM; + } else { + if (pt->x < RESIZE_BORDER) { + return SDL_HITTEST_RESIZE_LEFT; + } else if (pt->x >= w - RESIZE_BORDER) { + return SDL_HITTEST_RESIZE_RIGHT; + } + } + return SDL_HITTEST_NORMAL; +} + +void RtlDrawPpuFrame(uint8 *pixel_buffer, size_t pitch, uint32 render_flags) { + uint8 *ppu_pixels = g_other_image ? g_my_pixels : g_pixels; + for (size_t y = 0; y < 240; y++) + memcpy((uint8_t *)pixel_buffer + y * pitch, ppu_pixels + y * 256 * 4, 256 * 4); +} + +static void DrawPpuFrameWithPerf(void) { + int render_scale = PpuGetCurrentRenderScale(g_snes->ppu, g_ppu_render_flags); + uint8 *pixel_buffer = 0; + int pitch = 0; + + g_renderer_funcs.BeginDraw(g_snes_width * render_scale, + g_snes_height * render_scale, + &pixel_buffer, &pitch); + if (g_display_perf || g_config.display_perf_title) { + static float history[64], average; + static int history_pos; + uint64 before = SDL_GetPerformanceCounter(); + RtlDrawPpuFrame(pixel_buffer, pitch, g_ppu_render_flags); + uint64 after = SDL_GetPerformanceCounter(); + float v = (double)SDL_GetPerformanceFrequency() / (after - before); + average += v - history[history_pos]; + history[history_pos] = v; + history_pos = (history_pos + 1) & 63; + g_curr_fps = average * (1.0f / 64); + } else { + RtlDrawPpuFrame(pixel_buffer, pitch, g_ppu_render_flags); + } + if (g_display_perf) + RenderNumber(pixel_buffer + pitch * render_scale, pitch, g_curr_fps, render_scale == 4); + + if (g_got_mismatch_count) + RenderNumber(pixel_buffer + pitch * render_scale, pitch, g_got_mismatch_count, render_scale == 4); + + g_renderer_funcs.EndDraw(); +} + +static SDL_mutex *g_audio_mutex; +static uint8 *g_audiobuffer, *g_audiobuffer_cur, *g_audiobuffer_end; +static int g_frames_per_block; +static uint8 g_audio_channels; +static SDL_AudioDeviceID g_audio_device; + +void RtlApuLock(void) { + SDL_LockMutex(g_audio_mutex); +} + +void RtlApuUnlock(void) { + SDL_UnlockMutex(g_audio_mutex); +} + +static void SDLCALL AudioCallback(void *userdata, Uint8 *stream, int len) { + if (SDL_LockMutex(g_audio_mutex)) Die("Mutex lock failed!"); + while (len != 0) { + if (g_audiobuffer_end - g_audiobuffer_cur == 0) { + RtlRenderAudio((int16 *)g_audiobuffer, g_frames_per_block, g_audio_channels); + g_audiobuffer_cur = g_audiobuffer; + g_audiobuffer_end = g_audiobuffer + g_frames_per_block * g_audio_channels * sizeof(int16); + } + int n = IntMin(len, g_audiobuffer_end - g_audiobuffer_cur); + if (g_sdl_audio_mixer_volume == SDL_MIX_MAXVOLUME) { + memcpy(stream, g_audiobuffer_cur, n); + } else { + SDL_memset(stream, 0, n); + SDL_MixAudioFormat(stream, g_audiobuffer_cur, AUDIO_S16, n, g_sdl_audio_mixer_volume); + } + g_audiobuffer_cur += n; + stream += n; + len -= n; + } + SDL_UnlockMutex(g_audio_mutex); +} + + +// State for sdl renderer +static SDL_Renderer *g_renderer; +static SDL_Texture *g_texture; +static SDL_Rect g_sdl_renderer_rect; + +static bool SdlRenderer_Init(SDL_Window *window) { + + if (g_config.shader) + fprintf(stderr, "Warning: Shaders are supported only with the OpenGL backend\n"); + + SDL_Renderer *renderer = SDL_CreateRenderer(g_window, -1, + g_config.output_method == kOutputMethod_SDLSoftware ? SDL_RENDERER_SOFTWARE : + SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (renderer == NULL) { + printf("Failed to create renderer: %s\n", SDL_GetError()); + return false; + } + SDL_RendererInfo renderer_info; + SDL_GetRendererInfo(renderer, &renderer_info); + if (kDebugFlag) { + printf("Supported texture formats:"); + for (Uint32 i = 0; i < renderer_info.num_texture_formats; i++) + printf(" %s", SDL_GetPixelFormatName(renderer_info.texture_formats[i])); + printf("\n"); + } + g_renderer = renderer; + if (!g_config.ignore_aspect_ratio) + SDL_RenderSetLogicalSize(renderer, g_snes_width, g_snes_height); + if (g_config.linear_filtering) + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); + + int tex_mult = (g_ppu_render_flags & kPpuRenderFlags_4x4Mode7) ? 4 : 1; + g_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, + g_snes_width * tex_mult, g_snes_height * tex_mult); + if (g_texture == NULL) { + printf("Failed to create texture: %s\n", SDL_GetError()); + return false; + } + return true; +} + +static void SdlRenderer_Destroy(void) { + SDL_DestroyTexture(g_texture); + SDL_DestroyRenderer(g_renderer); +} + +static void SdlRenderer_BeginDraw(int width, int height, uint8 **pixels, int *pitch) { + g_sdl_renderer_rect.w = width; + g_sdl_renderer_rect.h = height; + if (SDL_LockTexture(g_texture, &g_sdl_renderer_rect, (void **)pixels, pitch) != 0) { + printf("Failed to lock texture: %s\n", SDL_GetError()); + return; + } +} + +static void SdlRenderer_EndDraw(void) { + // uint64 before = SDL_GetPerformanceCounter(); + SDL_UnlockTexture(g_texture); + // uint64 after = SDL_GetPerformanceCounter(); + // float v = (double)(after - before) / SDL_GetPerformanceFrequency(); + // printf("%f ms\n", v * 1000); + SDL_RenderClear(g_renderer); + SDL_RenderCopy(g_renderer, g_texture, &g_sdl_renderer_rect, NULL); + SDL_RenderPresent(g_renderer); // vsyncs to 60 FPS? +} + +static const struct RendererFuncs kSdlRendererFuncs = { + &SdlRenderer_Init, + &SdlRenderer_Destroy, + &SdlRenderer_BeginDraw, + &SdlRenderer_EndDraw, +}; + + + +#undef main +int main(int argc, char** argv) { + argc--, argv++; + const char *config_file = NULL; + if (argc >= 2 && strcmp(argv[0], "--config") == 0) { + config_file = argv[1]; + argc -= 2, argv += 2; + } else { + SwitchDirectory(); + } + ParseConfigFile(config_file); + + g_snes_width = (g_config.extended_aspect_ratio * 2 + 256); + g_snes_height = 240;// (g_config.extend_y ? 240 : 224); + g_ppu_render_flags = g_config.new_renderer * kPpuRenderFlags_NewRenderer | + g_config.enhanced_mode7 * kPpuRenderFlags_4x4Mode7 | + g_config.extend_y * kPpuRenderFlags_Height240 | + g_config.no_sprite_limits * kPpuRenderFlags_NoSpriteLimits; + + if (g_config.fullscreen == 1) + g_win_flags ^= SDL_WINDOW_FULLSCREEN_DESKTOP; + else if (g_config.fullscreen == 2) + g_win_flags ^= SDL_WINDOW_FULLSCREEN; + + // Window scale (1=100%, 2=200%, 3=300%, etc.) + g_current_window_scale = (g_config.window_scale == 0) ? 2 : IntMin(g_config.window_scale, kMaxWindowScale); + + // audio_freq: Use common sampling rates (see user config file. values higher than 48000 are not supported.) + if (g_config.audio_freq < 11025 || g_config.audio_freq > 48000) + g_config.audio_freq = kDefaultFreq; + + // Currently, the SPC/DSP implementation only supports up to stereo. + if (g_config.audio_channels < 1 || g_config.audio_channels > 2) + g_config.audio_channels = kDefaultChannels; + + // audio_samples: power of 2 + if (g_config.audio_samples <= 0 || ((g_config.audio_samples & (g_config.audio_samples - 1)) != 0)) + g_config.audio_samples = kDefaultSamples; + + // set up SDL + if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER) != 0) { + printf("Failed to init SDL: %s\n", SDL_GetError()); + return 1; + } + + bool custom_size = g_config.window_width != 0 && g_config.window_height != 0; + int window_width = custom_size ? g_config.window_width : g_current_window_scale * g_snes_width; + int window_height = custom_size ? g_config.window_height : g_current_window_scale * g_snes_height; + + if (g_config.output_method == kOutputMethod_OpenGL) { + g_win_flags |= SDL_WINDOW_OPENGL; + OpenGLRenderer_Create(&g_renderer_funcs); + } else { + g_renderer_funcs = kSdlRendererFuncs; + } + + + SDL_Window *window = SDL_CreateWindow(kWindowTitle, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, g_win_flags); + if(window == NULL) { + printf("Failed to create window: %s\n", SDL_GetError()); + return 1; + } + g_window = window; + SDL_SetWindowHitTest(window, HitTestCallback, NULL); + + if (!g_renderer_funcs.Initialize(window)) + return 1; + + g_audio_mutex = SDL_CreateMutex(); + if (!g_audio_mutex) Die("No mutex"); + + g_spc_player = SpcPlayer_Create(); + SpcPlayer_Initialize(g_spc_player); + + bool enable_audio = true; + if (enable_audio) { + SDL_AudioSpec want = { 0 }, have; + want.freq = 44100; + want.format = AUDIO_S16; + want.channels = 2; + want.samples = 2048; + want.callback = &AudioCallback; + g_audio_device = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0); + if (g_audio_device == 0) { + printf("Failed to open audio device: %s\n", SDL_GetError()); + return 1; + } + g_audio_channels = 2; + g_frames_per_block = (534 * have.freq) / 32000; + g_audiobuffer = (uint8 *)malloc(g_frames_per_block * have.channels * sizeof(int16)); + } + + // init snes, load rom + Snes *snes = SnesInit(argv[0] ? argv[0] : "sm.smc"); + + PpuBeginDrawing(snes->snes_ppu, g_pixels, 256 * 4, 0); + PpuBeginDrawing(snes->my_ppu, g_my_pixels, 256 * 4, 0); + +#if defined(_WIN32) + _mkdir("saves"); +#else + mkdir("saves", 0755); +#endif + + RtlReadSram(); + + for (int i = 0; i < SDL_NumJoysticks(); i++) + OpenOneGamepad(i); + + + bool running = true; + uint32 lastTick = SDL_GetTicks(); + uint32 curTick = 0; + uint32 frameCtr = 0; + uint8 audiopaused = true; + bool has_bug_in_title = false; + + while (running) { + SDL_Event event; + + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_CONTROLLERDEVICEADDED: + OpenOneGamepad(event.cdevice.which); + break; + case SDL_CONTROLLERAXISMOTION: + HandleGamepadAxisInput(event.caxis.which, event.caxis.axis, event.caxis.value); + break; + case SDL_CONTROLLERBUTTONDOWN: + case SDL_CONTROLLERBUTTONUP: { + int b = RemapSdlButton(event.cbutton.button); + if (b >= 0) + HandleGamepadInput(b, event.type == SDL_CONTROLLERBUTTONDOWN); + break; + } + case SDL_MOUSEWHEEL: + if (SDL_GetModState() & KMOD_CTRL && event.wheel.y != 0) + ChangeWindowScale(event.wheel.y > 0 ? 1 : -1); + break; + case SDL_MOUSEBUTTONDOWN: + if (event.button.button == SDL_BUTTON_LEFT && event.button.state == SDL_PRESSED && event.button.clicks == 2) { + if ((g_win_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0 && (g_win_flags & SDL_WINDOW_FULLSCREEN) == 0 && SDL_GetModState() & KMOD_SHIFT) { + g_win_flags ^= SDL_WINDOW_BORDERLESS; + SDL_SetWindowBordered(g_window, (g_win_flags & SDL_WINDOW_BORDERLESS) == 0 ? SDL_TRUE : SDL_FALSE); + } + } + break; + case SDL_KEYDOWN: + HandleInput(event.key.keysym.sym, event.key.keysym.mod, true); + break; + case SDL_KEYUP: + HandleInput(event.key.keysym.sym, event.key.keysym.mod, false); + break; + case SDL_QUIT: + running = false; + break; + } + } + + if (g_paused != audiopaused) { + audiopaused = g_paused; + if (g_audio_device) + SDL_PauseAudioDevice(g_audio_device, audiopaused); + } + + if (g_paused) { + SDL_Delay(16); + continue; + } + + // Clear gamepad inputs when joypad directional inputs to avoid wonkiness + int inputs = g_input1_state; + if (g_input1_state & 0xf0) + g_gamepad_buttons = 0; + inputs |= g_gamepad_buttons; + + uint8 is_replay = RtlRunFrame(inputs); + + frameCtr++; + g_snes->disableRender = (g_turbo ^ (is_replay & g_replay_turbo)) && (frameCtr & (g_turbo ? 0xf : 0x7f)) != 0; + + if (!g_snes->disableRender) + DrawPpuFrameWithPerf(); + + bool want_bug_in_title = (g_got_mismatch_count != 0); + if (want_bug_in_title != has_bug_in_title) { + has_bug_in_title = want_bug_in_title; + char title[60]; + if (want_bug_in_title) { + snprintf(title, sizeof(title), "%s | BUG FOUND!", kWindowTitle); + SDL_SetWindowTitle(g_window, title); + } else { + SDL_SetWindowTitle(g_window, kWindowTitle); + } + } + + // if vsync isn't working, delay manually + curTick = SDL_GetTicks(); + + if (!g_snes->disableRender && !g_config.disable_frame_delay) { + static const uint8 delays[3] = { 17, 17, 16 }; // 60 fps + lastTick += delays[frameCtr % 3]; + + if (lastTick > curTick) { + uint32 delta = lastTick - curTick; + if (delta > 500) { + lastTick = curTick - 500; + delta = 500; + } + // printf("Sleeping %d\n", delta); + SDL_Delay(delta); + } else if (curTick - lastTick > 500) { + lastTick = curTick; + } + } + + } + + // clean sdl + SDL_PauseAudioDevice(g_audio_device, 1); + SDL_CloseAudioDevice(g_audio_device); + SDL_DestroyMutex(g_audio_mutex); + free(g_audiobuffer); + + g_renderer_funcs.Destroy(); + + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; +} + +static void RenderDigit(uint8 *dst, size_t pitch, int digit, uint32 color, bool big) { + static const uint8 kFont[] = { + 0x1c, 0x36, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1c, + 0x18, 0x1c, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, + 0x3e, 0x63, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x63, 0x7f, + 0x3e, 0x63, 0x60, 0x60, 0x3c, 0x60, 0x60, 0x60, 0x63, 0x3e, + 0x30, 0x38, 0x3c, 0x36, 0x33, 0x7f, 0x30, 0x30, 0x30, 0x78, + 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x60, 0x60, 0x60, 0x63, 0x3e, + 0x1c, 0x06, 0x03, 0x03, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x3e, + 0x7f, 0x63, 0x60, 0x60, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, + 0x3e, 0x63, 0x63, 0x63, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x3e, + 0x3e, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x60, 0x60, 0x30, 0x1e, + }; + const uint8 *p = kFont + digit * 10; + if (!big) { + for (int y = 0; y < 10; y++, dst += pitch) { + int v = *p++; + for (int x = 0; v; x++, v >>= 1) { + if (v & 1) + ((uint32 *)dst)[x] = color; + } + } + } else { + for (int y = 0; y < 10; y++, dst += pitch * 2) { + int v = *p++; + for (int x = 0; v; x++, v >>= 1) { + if (v & 1) { + ((uint32 *)dst)[x * 2 + 1] = ((uint32 *)dst)[x * 2] = color; + ((uint32 *)(dst + pitch))[x * 2 + 1] = ((uint32 *)(dst + pitch))[x * 2] = color; + } + } + } + } +} + + +static void RenderNumber(uint8 *dst, size_t pitch, int n, uint8 big) { + char buf[32], *s; + int i; + sprintf(buf, "%d", n); + for (s = buf, i = 2 * 4; *s; s++, i += 8 * 4) + RenderDigit(dst + ((pitch + i + 4) << big), pitch, *s - '0', 0x404040, big); + for (s = buf, i = 2 * 4; *s; s++, i += 8 * 4) + RenderDigit(dst + (i << big), pitch, *s - '0', 0xffffff, big); +} + +static void HandleCommand_Locked(uint32 j, bool pressed); + +static void HandleCommand(uint32 j, bool pressed) { + if (j <= kKeys_Controls_Last) { + static const uint8 kKbdRemap[] = { 0, 4, 5, 6, 7, 2, 3, 8, 0, 9, 1, 10, 11 }; + if (pressed) + g_input1_state |= 1 << kKbdRemap[j]; + else + g_input1_state &= ~(1 << kKbdRemap[j]); + return; + } + + if (j == kKeys_Turbo) { + g_turbo = pressed; + return; + } + + if (!pressed) + return; + if (j <= kKeys_Load_Last) { + RtlSaveLoad(kSaveLoad_Load, j - kKeys_Load); + } else if (j <= kKeys_Save_Last) { + RtlSaveLoad(kSaveLoad_Save, j - kKeys_Save); + } else if (j <= kKeys_Replay_Last) { + RtlSaveLoad(kSaveLoad_Replay, j - kKeys_Replay); + } else if (j <= kKeys_LoadRef_Last) { + RtlSaveLoad(kSaveLoad_Load, 256 + j - kKeys_LoadRef); + } else if (j <= kKeys_ReplayRef_Last) { + RtlSaveLoad(kSaveLoad_Replay, 256 + j - kKeys_ReplayRef); + } else { + switch (j) { + case kKeys_CheatLife: RtlCheat('w'); break; + case kKeys_CheatJump: RtlCheat('q'); break; + case kKeys_ToggleWhichFrame: + g_other_image = !g_other_image; + break; + case kKeys_ClearKeyLog: RtlClearKeyLog(); break; + case kKeys_StopReplay: RtlStopReplay(); break; + case kKeys_Fullscreen: + g_win_flags ^= SDL_WINDOW_FULLSCREEN_DESKTOP; + SDL_SetWindowFullscreen(g_window, g_win_flags & SDL_WINDOW_FULLSCREEN_DESKTOP); + g_cursor = !g_cursor; + SDL_ShowCursor(g_cursor); + break; + case kKeys_Reset: + //RtlReset(true); + break; + case kKeys_Pause: g_paused = !g_paused; break; + case kKeys_PauseDimmed: + g_paused = !g_paused; + // SDL_RenderPresent may not be called more than once per frame. + // Seems to work on Windows still. Temporary measure until it's fixed. +#ifdef _WIN32 + if (g_paused) { + SDL_SetRenderDrawBlendMode(g_renderer, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 159); + SDL_RenderFillRect(g_renderer, NULL); + SDL_RenderPresent(g_renderer); + } +#endif + break; + case kKeys_ReplayTurbo: g_replay_turbo = !g_replay_turbo; break; + case kKeys_WindowBigger: ChangeWindowScale(1); break; + case kKeys_WindowSmaller: ChangeWindowScale(-1); break; + case kKeys_DisplayPerf: g_display_perf ^= 1; break; + case kKeys_ToggleRenderer: + g_ppu_render_flags ^= kPpuRenderFlags_NewRenderer; + g_new_ppu = (g_ppu_render_flags & kPpuRenderFlags_NewRenderer) != 0; + break; + case kKeys_VolumeUp: + case kKeys_VolumeDown: HandleVolumeAdjustment(j == kKeys_VolumeUp ? 1 : -1); break; + default: assert(0); + } + } +} + +static void HandleInput(int keyCode, int keyMod, bool pressed) { + int j = FindCmdForSdlKey(keyCode, (SDL_Keymod)keyMod); + if (j != 0) + HandleCommand(j, pressed); +} + +static void OpenOneGamepad(int i) { + if (SDL_IsGameController(i)) { + SDL_GameController *controller = SDL_GameControllerOpen(i); + if (!controller) + fprintf(stderr, "Could not open gamepad %d: %s\n", i, SDL_GetError()); + } +} + +static int RemapSdlButton(int button) { + switch (button) { + case SDL_CONTROLLER_BUTTON_A: return kGamepadBtn_A; + case SDL_CONTROLLER_BUTTON_B: return kGamepadBtn_B; + case SDL_CONTROLLER_BUTTON_X: return kGamepadBtn_X; + case SDL_CONTROLLER_BUTTON_Y: return kGamepadBtn_Y; + case SDL_CONTROLLER_BUTTON_BACK: return kGamepadBtn_Back; + case SDL_CONTROLLER_BUTTON_GUIDE: return kGamepadBtn_Guide; + case SDL_CONTROLLER_BUTTON_START: return kGamepadBtn_Start; + case SDL_CONTROLLER_BUTTON_LEFTSTICK: return kGamepadBtn_L3; + case SDL_CONTROLLER_BUTTON_RIGHTSTICK: return kGamepadBtn_R3; + case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: return kGamepadBtn_L1; + case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: return kGamepadBtn_R1; + case SDL_CONTROLLER_BUTTON_DPAD_UP: return kGamepadBtn_DpadUp; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: return kGamepadBtn_DpadDown; + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: return kGamepadBtn_DpadLeft; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: return kGamepadBtn_DpadRight; + default: return -1; + } +} + +static void HandleGamepadInput(int button, bool pressed) { + if (!!(g_gamepad_modifiers & (1 << button)) == pressed) + return; + g_gamepad_modifiers ^= 1 << button; + if (pressed) + g_gamepad_last_cmd[button] = FindCmdForGamepadButton(button, g_gamepad_modifiers); + if (g_gamepad_last_cmd[button] != 0) + HandleCommand(g_gamepad_last_cmd[button], pressed); +} + +static void HandleVolumeAdjustment(int volume_adjustment) { +#if SYSTEM_VOLUME_MIXER_AVAILABLE + int current_volume = GetApplicationVolume(); + int new_volume = IntMin(IntMax(0, current_volume + volume_adjustment * 5), 100); + SetApplicationVolume(new_volume); + printf("[System Volume]=%i\n", new_volume); +#else + g_sdl_audio_mixer_volume = IntMin(IntMax(0, g_sdl_audio_mixer_volume + volume_adjustment * (SDL_MIX_MAXVOLUME >> 4)), SDL_MIX_MAXVOLUME); + printf("[SDL mixer volume]=%i\n", g_sdl_audio_mixer_volume); +#endif +} + +// Approximates atan2(y, x) normalized to the [0,4) range +// with a maximum error of 0.1620 degrees +// normalized_atan(x) ~ (b x + x^2) / (1 + 2 b x + x^2) +static float ApproximateAtan2(float y, float x) { + uint32 sign_mask = 0x80000000; + float b = 0.596227f; + // Extract the sign bits + uint32 ux_s = sign_mask & *(uint32 *)&x; + uint32 uy_s = sign_mask & *(uint32 *)&y; + // Determine the quadrant offset + float q = (float)((~ux_s & uy_s) >> 29 | ux_s >> 30); + // Calculate the arctangent in the first quadrant + float bxy_a = b * x * y; + if (bxy_a < 0.0f) bxy_a = -bxy_a; // avoid fabs + float num = bxy_a + y * y; + float atan_1q = num / (x * x + bxy_a + num + 0.000001f); + // Translate it to the proper quadrant + uint32_t uatan_2q = (ux_s ^ uy_s) | *(uint32 *)&atan_1q; + return q + *(float *)&uatan_2q; +} + +static void HandleGamepadAxisInput(int gamepad_id, int axis, int value) { + static int last_gamepad_id, last_x, last_y; + if (axis == SDL_CONTROLLER_AXIS_LEFTX || axis == SDL_CONTROLLER_AXIS_LEFTY) { + // ignore other gamepads unless they have a big input + if (last_gamepad_id != gamepad_id) { + if (value > -16000 && value < 16000) + return; + last_gamepad_id = gamepad_id; + last_x = last_y = 0; + } + *(axis == SDL_CONTROLLER_AXIS_LEFTX ? &last_x : &last_y) = value; + int buttons = 0; + if (last_x * last_x + last_y * last_y >= 10000 * 10000) { + // in the non deadzone part, divide the circle into eight 45 degree + // segments rotated by 22.5 degrees that control which direction to move. + // todo: do this without floats? + static const uint8 kSegmentToButtons[8] = { + 1 << 4, // 0 = up + 1 << 4 | 1 << 7, // 1 = up, right + 1 << 7, // 2 = right + 1 << 7 | 1 << 5, // 3 = right, down + 1 << 5, // 4 = down + 1 << 5 | 1 << 6, // 5 = down, left + 1 << 6, // 6 = left + 1 << 6 | 1 << 4, // 7 = left, up + }; + uint8 angle = (uint8)(int)(ApproximateAtan2(last_y, last_x) * 64.0f + 0.5f); + buttons = kSegmentToButtons[(uint8)(angle + 16 + 64) >> 5]; + } + g_gamepad_buttons = buttons; + } else if ((axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT || axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)) { + if (value < 12000 || value >= 16000) // hysteresis + HandleGamepadInput(axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT ? kGamepadBtn_L2 : kGamepadBtn_R2, value >= 12000); + } +} + +// Go some steps up and find sm.ini +static void SwitchDirectory(void) { + char buf[4096]; + if (!getcwd(buf, sizeof(buf) - 32)) + return; + size_t pos = strlen(buf); + + for (int step = 0; pos != 0 && step < 3; step++) { + memcpy(buf + pos, "/sm.ini", 8); + FILE *f = fopen(buf, "rb"); + if (f) { + fclose(f); + buf[pos] = 0; + if (step != 0) { + printf("Found sm.ini in %s\n", buf); + int err = chdir(buf); + (void)err; + } + return; + } + pos--; + while (pos != 0 && buf[pos] != '/' && buf[pos] != '\\') + pos--; + } +} diff --git a/src/opengl.c b/src/opengl.c new file mode 100644 index 0000000..bcb49e1 --- /dev/null +++ b/src/opengl.c @@ -0,0 +1,220 @@ +#include "third_party/gl_core/gl_core_3_1.h" +#include +#include +#include +#include "types.h" +#include "util.h" +#include "glsl_shader.h" +#include "config.h" + +#define CODE(...) #__VA_ARGS__ + +static SDL_Window *g_window; +static uint8 *g_screen_buffer; +static size_t g_screen_buffer_size; +static int g_draw_width, g_draw_height; +static unsigned int g_program, g_VAO; +static GlTextureWithSize g_texture; +static GlslShader *g_glsl_shader; + +static void GL_APIENTRY MessageCallback(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar *message, + const void *userParam) { + if (type == GL_DEBUG_TYPE_OTHER) + return; + + fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", + (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), + type, severity, message); + if (type == GL_DEBUG_TYPE_ERROR) + Die("OpenGL error!\n"); +} + +static bool OpenGLRenderer_Init(SDL_Window *window) { + g_window = window; + SDL_GLContext context = SDL_GL_CreateContext(window); + (void)context; + + SDL_GL_SetSwapInterval(1); + ogl_LoadFunctions(); + + if (!ogl_IsVersionGEQ(3, 3)) + Die("You need OpenGL 3.3"); + + if (kDebugFlag) { + glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glDebugMessageCallback(MessageCallback, 0); + } + + glGenTextures(1, &g_texture.gl_texture); + + static const float kVertices[] = { + // positions // texture coords + -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, // top left + -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, // bottom left + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // top right + 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, // bottom right + }; + + // create a vertex buffer object + unsigned int vbo; + glGenBuffers(1, &vbo); + + // vertex array object + glGenVertexArrays(1, &g_VAO); + // 1. bind Vertex Array Object + glBindVertexArray(g_VAO); + // 2. copy our vertices array in a buffer for OpenGL to use + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW); + // position attribute + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0); + glEnableVertexAttribArray(0); + // texture coord attribute + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)(3 * sizeof(float))); + glEnableVertexAttribArray(1); + + // vertex shader + const GLchar *vs_code = "#version 330 core\n" CODE( + layout(location = 0) in vec3 aPos; + layout(location = 1) in vec2 aTexCoord; + out vec2 TexCoord; + void main(void) { + gl_Position = vec4(aPos, 1.0); + TexCoord = vec2(aTexCoord.x, aTexCoord.y); + } +); + + unsigned int vs = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vs, 1, &vs_code, NULL); + glCompileShader(vs); + + int success; + char infolog[512]; + glGetShaderiv(vs, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(vs, 512, NULL, infolog); + printf("%s\n", infolog); + } + + // fragment shader + const GLchar *fs_code = "#version 330 core\n" CODE( + out vec4 FragColor; + in vec2 TexCoord; + // texture samplers + uniform sampler2D texture1; + void main(void) { + FragColor = texture(texture1, TexCoord); + } +); + + unsigned int fs = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fs, 1, &fs_code, NULL); + glCompileShader(fs); + + glGetShaderiv(fs, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(fs, 512, NULL, infolog); + printf("%s\n", infolog); + } + + // create program + int program = g_program = glCreateProgram(); + glAttachShader(program, vs); + glAttachShader(program, fs); + glLinkProgram(program); + glGetProgramiv(program, GL_LINK_STATUS, &success); + + if (!success) { + glGetProgramInfoLog(program, 512, NULL, infolog); + printf("%s\n", infolog); + } + + if (g_config.shader) + g_glsl_shader = GlslShader_CreateFromFile(g_config.shader); + + return true; +} + +static void OpenGLRenderer_Destroy(void) { +} + +static void OpenGLRenderer_BeginDraw(int width, int height, uint8 **pixels, int *pitch) { + int size = width * height; + + if (size > g_screen_buffer_size) { + g_screen_buffer_size = size; + free(g_screen_buffer); + g_screen_buffer = (uint8*)malloc(size * 4); + } + + g_draw_width = width; + g_draw_height = height; + *pixels = g_screen_buffer; + *pitch = width * 4; +} + +static void OpenGLRenderer_EndDraw(void) { + int drawable_width, drawable_height; + + SDL_GL_GetDrawableSize(g_window, &drawable_width, &drawable_height); + + int viewport_width = drawable_width, viewport_height = drawable_height; + + if (!g_config.ignore_aspect_ratio) { + if (viewport_width * g_draw_height < viewport_height * g_draw_width) + viewport_height = viewport_width * g_draw_height / g_draw_width; // limit height + else + viewport_width = viewport_height * g_draw_width / g_draw_height; // limit width + } + + int viewport_x = (drawable_width - viewport_width) >> 1; + int viewport_y = (viewport_height - viewport_height) >> 1; + + glBindTexture(GL_TEXTURE_2D, g_texture.gl_texture); + if (g_draw_width == g_texture.width && g_draw_height == g_texture.height) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g_draw_width, g_draw_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, g_screen_buffer); + } else { + g_texture.width = g_draw_width; + g_texture.height = g_draw_height; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g_draw_width, g_draw_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, g_screen_buffer); + } + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (g_glsl_shader == NULL) { + glViewport(viewport_x, viewport_y, viewport_width, viewport_height); + glUseProgram(g_program); + int filter = g_config.linear_filtering ? GL_LINEAR : GL_NEAREST; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glBindVertexArray(g_VAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } else { + GlslShader_Render(g_glsl_shader, &g_texture, viewport_x, viewport_y, viewport_width, viewport_height); + } + + SDL_GL_SwapWindow(g_window); +} + + +static const struct RendererFuncs kOpenGLRendererFuncs = { + &OpenGLRenderer_Init, + &OpenGLRenderer_Destroy, + &OpenGLRenderer_BeginDraw, + &OpenGLRenderer_EndDraw, +}; + +void OpenGLRenderer_Create(struct RendererFuncs *funcs) { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + *funcs = kOpenGLRendererFuncs; +} + diff --git a/src/packages.config b/src/packages.config new file mode 100644 index 0000000..7ede8af --- /dev/null +++ b/src/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/platform/win32/resource.h b/src/platform/win32/resource.h new file mode 100644 index 0000000..65b144b --- /dev/null +++ b/src/platform/win32/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by zelda3.rc +// +#define IDI_ICON1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/platform/win32/sm.rc b/src/platform/win32/sm.rc new file mode 100644 index 0000000..4701546 --- /dev/null +++ b/src/platform/win32/sm.rc @@ -0,0 +1,71 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "platform\\win32\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "platform\\win32\\triforce.ico" + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/platform/win32/volume_control.c b/src/platform/win32/volume_control.c new file mode 100644 index 0000000..1c90fe8 --- /dev/null +++ b/src/platform/win32/volume_control.c @@ -0,0 +1,82 @@ +#include "volume_control.h" + +#define COBJMACROS +#define CINTERFACE + +#define MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS 0 + +#include +#include +#include +#include + +static ISimpleAudioVolume *GetSimpleAudioVolume(); + +DEFINE_GUID(IID_IMMDeviceEnumerator, 0XA95664D2, 0X9614, 0X4F35, 0XA7, 0X46, 0XDE, 0X8D, 0XB6, 0X36, 0X17, 0XE6); +DEFINE_GUID(CLSID_MMDeviceEnumerator, 0XBCDE0395, 0XE52F, 0X467C, 0X8E, 0X3D, 0XC4, 0X57, 0X92, 0X91, 0X69, 0X2E); +DEFINE_GUID(IID_IAudioSessionManager, 0X77AA99A0, 0X1BD6, 0X484F, 0X8B, 0XC7, 0X2C, 0X65, 0X4C, 0X9A, 0X9B, 0X6F); + +static void InitializeCom(void) { + static bool com_initialized; + if (!com_initialized) + com_initialized = SUCCEEDED(CoInitialize(NULL)); +} + +int GetApplicationVolume(void) { + ISimpleAudioVolume *simple_audio_volume = GetSimpleAudioVolume(); + if (!simple_audio_volume) + return false; + float volume_level = -1; + HRESULT result = ISimpleAudioVolume_GetMasterVolume(simple_audio_volume, &volume_level); + ISimpleAudioVolume_Release(simple_audio_volume); + return (int)(volume_level * 100); +} + +bool SetApplicationVolume(int volume_level) { + ISimpleAudioVolume *simple_audio_volume = GetSimpleAudioVolume(); + if (!simple_audio_volume) + return false; + HRESULT result = ISimpleAudioVolume_SetMasterVolume(simple_audio_volume, (float)(volume_level / 100.0), NULL); + ISimpleAudioVolume_Release(simple_audio_volume); + return SUCCEEDED(result); +} + +bool SetApplicationMuted(bool muted) { + ISimpleAudioVolume *simple_audio_volume = GetSimpleAudioVolume(); + if (!simple_audio_volume) + return false; + HRESULT result = ISimpleAudioVolume_SetMute(simple_audio_volume, muted, NULL); + ISimpleAudioVolume_Release(simple_audio_volume); + return SUCCEEDED(result); +} + +static ISimpleAudioVolume *GetSimpleAudioVolume(void) { + HRESULT result; + IMMDeviceEnumerator *device_enumerator = NULL; + IMMDevice *device = NULL; + IAudioSessionManager *audio_session_manager = NULL; + ISimpleAudioVolume *simple_audio_volume = NULL; + + InitializeCom(); + + result = CoCreateInstance(&CLSID_MMDeviceEnumerator, + NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &device_enumerator); + if (FAILED(result) || device_enumerator == NULL) + goto done; + + result = IMMDeviceEnumerator_GetDefaultAudioEndpoint(device_enumerator, eRender, eConsole, &device); + if (FAILED(result) || device == NULL) + goto done; + + result = IMMDevice_Activate(device, &IID_IAudioSessionManager, CLSCTX_INPROC_SERVER, NULL, &audio_session_manager); + if (FAILED(result) || audio_session_manager == NULL) + goto done; + result = IAudioSessionManager_GetSimpleAudioVolume(audio_session_manager, &GUID_NULL, 0, &simple_audio_volume); + +done: + if (device_enumerator) IMMDeviceEnumerator_Release(device_enumerator); + if (device) IMMDevice_Release(device); + if (audio_session_manager) IAudioSessionManager_Release(audio_session_manager); + + return simple_audio_volume; +} diff --git a/src/platform/win32/volume_control.h b/src/platform/win32/volume_control.h new file mode 100644 index 0000000..51c0d24 --- /dev/null +++ b/src/platform/win32/volume_control.h @@ -0,0 +1,14 @@ +#ifndef ZELDA3_PLATFORM_WIN32_VOLUME_CONTROL_H_ +#define ZELDA3_PLATFORM_WIN32_VOLUME_CONTROL_H_ + +#include + +#ifndef SYSTEM_VOLUME_MIXER_AVAILABLE +#define SYSTEM_VOLUME_MIXER_AVAILABLE 1 +#endif // SYSTEM_VOLUME_MIXER_AVAILABLE + +int GetApplicationVolume(); +bool SetApplicationVolume(int volume_level); +bool SetApplicationMuted(bool muted); + +#endif // ZELDA3_PLATFORM_WIN32_VOLUME_CONTROL_H_ diff --git a/src/sm.vcxproj b/src/sm.vcxproj new file mode 100644 index 0000000..b1e5723 --- /dev/null +++ b/src/sm.vcxproj @@ -0,0 +1,276 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + {1F8AB1B4-DAFB-4D6E-BF1E-F802FF5A52EE} + Win32Proj + 10.0 + + + + Application + true + v143 + + + Application + false + v143 + + + Application + true + v143 + + + Application + false + v143 + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)build\bin-$(Platform)-$(Configuration)\ + $(SolutionDir)build\obj-$(Platform)-$(Configuration)\ + + + true + $(SolutionDir)build\bin-$(Platform)-$(Configuration)\ + $(SolutionDir)build\obj-$(Platform)-$(Configuration)\ + + + $(SolutionDir)build\bin-$(Platform)-$(Configuration)\ + $(SolutionDir)build\obj-$(Platform)-$(Configuration)\ + + + $(SolutionDir)build\bin-$(Platform)-$(Configuration)\ + $(SolutionDir)build\obj-$(Platform)-$(Configuration)\ + + + + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + $(SolutionDir) + Default + 4996 + stdc11 + + + MachineX86 + true + Console + $(CoreLibraryDependencies);%(AdditionalDependencies);D:\Lib\SDL2-2.0.20\lib\x64\sdl2.lib + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS + MultiThreadedDLL + Level3 + ProgramDatabase + $(SolutionDir) + 4996 + stdc11 + + + MachineX86 + true + Console + true + true + $(CoreLibraryDependencies);%(AdditionalDependencies);D:\Lib\SDL2-2.0.20\lib\x64\sdl2.lib + + + + + $(SolutionDir) + Level3 + ;_CRT_SECURE_NO_WARNINGS + Default + 4996 + stdc11 + + + $(CoreLibraryDependencies);%(AdditionalDependencies);D:\Lib\SDL2-2.0.20\lib\x64\sdl2.lib + + + + + $(SolutionDir) + Level3 + ;_CRT_SECURE_NO_WARNINGS + 4996 + stdc11 + + + $(CoreLibraryDependencies);%(AdditionalDependencies);D:\Lib\SDL2-2.0.20\lib\x64\sdl2.lib + + + + + + + + + + + + + + + + + + + + stdc17 + stdc17 + stdc17 + stdc17 + + + + + + + + + + + + + + + + + + + + + + + + + + + Disabled + Disabled + + + MinSpace + MinSpace + + + Disabled + Disabled + + + Disabled + Disabled + + + Disabled + Disabled + + + MinSpace + MinSpace + + + Disabled + Disabled + + + + + MinSpace + MinSpace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/src/sm.vcxproj.filters b/src/sm.vcxproj.filters new file mode 100644 index 0000000..9a527b6 --- /dev/null +++ b/src/sm.vcxproj.filters @@ -0,0 +1,273 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + {e1763dbc-4fb3-417f-ad1a-8436411c3b7a} + + + {2b72ed96-9194-4c2c-b1e5-15445f0a9550} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Shader + + + Shader + + + Shader + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Snes + + + Shader + + + Shader + + + Source Files + + + + + + \ No newline at end of file diff --git a/src/sm.vcxproj.user b/src/sm.vcxproj.user new file mode 100644 index 0000000..531c9a5 --- /dev/null +++ b/src/sm.vcxproj.user @@ -0,0 +1,23 @@ + + + + + + WindowsLocalDebugger + + + + + WindowsLocalDebugger + + + + + WindowsLocalDebugger + + + + + WindowsLocalDebugger + + \ No newline at end of file diff --git a/src/sm_80.c b/src/sm_80.c new file mode 100644 index 0000000..a175d15 --- /dev/null +++ b/src/sm_80.c @@ -0,0 +1,2849 @@ +// System routines + +#include "sm_rtl.h" +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" +#include "spc_player.h" + + +void APU_UploadBank(void) { // 0x808028 + if (!g_use_my_apu_code) + return; + RtlApuUpload(RomPtr(Load24(&R0_))); +} + +uint16 NextRandom(void) { // 0x808111 + uint16 RegWord = LOBYTE(random_number) * 5; + uint8 Reg = HIBYTE(random_number) * 5; + + int carry = HIBYTE(RegWord) + Reg + 1; + HIBYTE(RegWord) = carry; + uint16 result = (carry >> 8) + RegWord + 17; + random_number = result; + return result; +} + +void ReleaseButtonsFilter(uint16 v0) { // 0x808146 + timed_held_input_timer_reset = v0; + R18_ = ~joypad1_newkeys & joypad1_lastkeys; + bool v1 = ((uint16)~joypad1_newkeys & joypad1_lastkeys) == joypad_released_keys; + joypad_released_keys = ~joypad1_newkeys & joypad1_lastkeys; + if (!v1) { + timed_held_input_timer = timed_held_input_timer_reset; + timed_held_input = 0; + goto LABEL_6; + } + if ((--timed_held_input_timer & 0x8000u) == 0) { + timed_held_input = 0; + goto LABEL_6; + } + timed_held_input_timer = 0; + previous_timed_held_input = timed_held_input; + timed_held_input = ~joypad1_newkeys & joypad1_lastkeys; +LABEL_6: + newly_held_down_timed_held_input = timed_held_input & (previous_timed_held_input ^ timed_held_input); +} + +uint16 PrepareBitAccess(uint16 a) { // 0x80818E + bitmask = 1 << (a & 7); + return a >> 3; +} + +void SetBossBitForCurArea(uint16 a) { // 0x8081A6 + LOBYTE(bitmask) = a; + boss_bits_for_area[area_index] |= a; +} + +void ClearBossBitForCurArea(uint16 a) { // 0x8081C0 + LOBYTE(bitmask) = ~a; + boss_bits_for_area[area_index] &= ~a; +} + +uint8 CheckBossBitForCurArea(uint16 a) { // 0x8081DC + LOBYTE(bitmask) = a; + return ((uint8)a & boss_bits_for_area[area_index]) != 0; +} + +void SetEventHappened(uint16 a) { // 0x8081FA + uint16 v1 = PrepareBitAccess(a); + events_that_happened[v1] |= bitmask; +} + +void ClearEventHappened(uint16 v0) { // 0x808212 + uint16 v1 = PrepareBitAccess(v0); + bitmask = ~bitmask; + events_that_happened[v1] &= bitmask; +} + +uint16 CheckEventHappened(uint16 a) { // 0x808233 + uint16 idx = PrepareBitAccess(a); + return (bitmask & events_that_happened[idx]) != 0; +} + +void CopySuperMetroidString(void) { // 0x80824F + memcpy(&g_sram[0x1fe0], "supermetroid", 12); + RtlWriteSram(); +} + +void VerifySRAM(void) { // 0x808261 + num_demo_sets = 3; + if (LoadFromSram(0) && LoadFromSram(1) && LoadFromSram(2)) { + memcpy(&g_sram[0x1fe0], "madadameyohn", 12); + RtlWriteSram(); + } else { + if (!memcmp(&g_sram[0x1fe0], "supermetroid", 12)) + num_demo_sets = 4; + } +} + +void Multiply16x16(uint16 a, uint16 j) { // 0x8082D6 + uint32 result = (uint32)a * (uint32)j; + mult_product_lo = result; + mult_product_hi = result >> 16; +} + +CoroutineRet WaitForNMI_Async(void) { // 0x808338 + // Return 0 from this routine as soon as the coroutine has finished + if (coroutine_completion_flags) { + coroutine_completion_flags = 0; + return 0; + } + waiting_for_nmi = 1; + coroutine_completion_flags = 1; + return 1; +} + +CoroutineRet WaitForNMI_NoUpdate_Async(void) { + // Return 0 from this routine as soon as the coroutine has finished + if (coroutine_completion_flags) { + coroutine_completion_flags = 0; + return 0; + } + coroutine_completion_flags = 1; + return 1; +} + +void EnableNMI(void) { // 0x80834B + uint8 v0 = reg_NMITIMEN | 0x80; + WriteReg(NMITIMEN, reg_NMITIMEN | 0x80); + reg_NMITIMEN = v0; +} + +void DisableNMI(void) { // 0x80835D + uint8 v0 = reg_NMITIMEN & 0x7F; + WriteReg(NMITIMEN, reg_NMITIMEN & 0x7F); + reg_NMITIMEN = v0; +} + +void ScreenOff(void) { + reg_INIDISP |= 0x80; +} + +void ScreenOn(void) { + reg_INIDISP &= ~0x80; +} + +void memset7E(uint16 k, uint16 a, uint16 j) { // 0x8083F6 + do { + *(uint16 *)RomPtr_7E(k) = a; + k += 2; + j -= 2; + } while (j); +} + +void memset7F(uint16 k, uint16 a, uint16 j) { // 0x808409 + do { + *(uint16 *)RomPtr_7F(k) = a; + k += 2; + j -= 2; + } while (j); +} + +CoroutineRet Vector_RESET_Async(void) { // 0x80841C + COROUTINE_BEGIN(coroutine_state_0, 1) + WriteReg(MEMSEL, 1u); + reg_MEMSEL = 1; + // Removed code to wait 4 frames + for (int i = 8190; i >= 0; i -= 2) + *(uint16 *)RomPtr_RAM(i) = 0; + COROUTINE_AWAIT(2, InitializeIoDisplayLogo_Async()); + COROUTINE_MANUAL_POS(3); // Soft reset position + mov24(&R0_, 0xCF8000); + APU_UploadBank(); + WriteReg(INIDISP, 0x8F); + memset(g_ram, 0, 0x10000); + WriteReg(NMITIMEN, 0); + reg_NMITIMEN = 0; + reg_INIDISP = 0x8f; + InitializeCpuIoRegs(); + InitializePpuIoRegs(); + WriteLotsOf0x1c2f(); + sfx_readpos[0] = 0; + sfx_readpos[1] = 0; + sfx_readpos[2] = 0; + sfx_writepos[0] = 0; + sfx_writepos[1] = 0; + sfx_writepos[2] = 0; + sfx_state[0] = 0; + sfx_state[1] = 0; + sfx_state[2] = 0; + sfx_cur[0] = 0; + sfx_cur[1] = 0; + sfx_cur[2] = 0; + sfx_clear_delay[0] = 0; + sfx_clear_delay[1] = 0; + sfx_clear_delay[2] = 0; + sfx1_queue[0] = 0; + sfx2_queue[0] = 0; + sfx3_queue[0] = 0; + oam_next_ptr = 0; + reg_OAMaddr_UNUSED = 0; + ClearOamExt(); + ClearUnusedOam(); + nmi_copy_samus_halves = 0; + nmi_copy_samus_top_half_src = 0; + nmi_copy_samus_bottom_half_src = 0; + EnableNMI(); + RtlApuWrite(APUI00, 0); + RtlApuWrite(APUI02, 0); + + // Removed code to wait 4 frames + random_number = 97; + music_timer = 0; + music_queue_delay[0] = 0; + music_queue_delay[1] = 0; + music_queue_delay[2] = 0; + music_queue_delay[3] = 0; + music_queue_delay[4] = 0; + music_queue_delay[5] = 0; + music_queue_delay[6] = 0; + music_queue_delay[7] = 0; + enable_debug = 0; + VerifySRAM(); + debug_disable_sounds = 0; + sound_handler_downtime = 0; + COROUTINE_END(2); +} + +void InvalidInterrupt_Crash(void) { // 0x808573 + printf("InvalidInterrupt_Crash\n"); + Unreachable(); + for (;;); +} + +void LoadMirrorOfExploredMapTiles(void) { // 0x80858C + uint16 v1 = swap16(area_index); + uint16 v2 = 0; + do { + *(uint16 *)&map_tiles_explored[v2] = explored_map_tiles_saved[v1 >> 1]; + v1 += 2; + v2 += 2; + } while ((int16)(v2 - 256) < 0); + has_area_map = map_station_byte_array[area_index]; +} + +void SaveExploredMapTilesToSaved(void) { // 0x8085C6 + uint16 v1 = swap16(area_index); + uint16 v2 = 0; + do { + explored_map_tiles_saved[v1 >> 1] = *(uint16 *)&map_tiles_explored[v2]; + v1 += 2; + v2 += 2; + } while ((int16)(v2 - 256) < 0); + if (has_area_map) + *(uint16 *)&map_station_byte_array[area_index] |= 0xFFu; +} + +void InitializeCpuIoRegs(void) { // 0x80875D + WriteReg(NMITIMEN, 1u); + reg_NMITIMEN = 1; + WriteReg(WRIO, 0); + WriteReg(WRMPYA, 0); + WriteReg(WRMPYB, 0); + WriteReg(WRDIVL, 0); + WriteReg(WRDIVH, 0); + WriteReg(WRDIVB, 0); + WriteReg(HTIMEL, 0); + WriteReg(HTIMEH, 0); + WriteReg(VTIMEL, 0); + WriteReg(VTIMEH, 0); + WriteReg(MDMAEN, 0); + WriteReg(HDMAEN, 0); + reg_HDMAEN = 0; + WriteReg(MEMSEL, 1u); + reg_MEMSEL = 1; +} + +void InitializePpuIoRegs(void) { // 0x808792 + WriteReg(INIDISP, 0x8Fu); + reg_INIDISP = 0x8f; + WriteReg(OBSEL, 3u); + reg_OBSEL = 3; + WriteReg(OAMADDL, 0); + LOBYTE(reg_OAMaddr_UNUSED) = 0; + WriteReg(OAMADDH, 0x80); + HIBYTE(reg_OAMaddr_UNUSED) = 0x80; + WriteReg(OAMDATA, 0); + WriteReg(OAMDATA, 0); + WriteReg(BGMODE, 9u); + reg_BGMODE = 9; + WriteReg(MOSAIC, 0); + reg_MOSAIC = 0; + WriteReg(BG1SC, 0x40u); + reg_BG1SC = 64; + WriteReg(BG2SC, 0x44u); + reg_BG2SC = 68; + WriteReg(BG3SC, 0x48u); + reg_BG3SC = 72; + WriteReg(BG4SC, 0); + reg_BG4SC = 0; + WriteReg(BG12NBA, 0); + reg_BG12NBA = 0; + WriteReg(BG34NBA, 5u); + reg_BG34NBA = 5; + WriteReg(BG1HOFS, 0); + WriteReg(BG1HOFS, 0); + WriteReg(BG1VOFS, 0); + WriteReg(BG1VOFS, 0); + WriteReg(BG2HOFS, 0); + WriteReg(BG2HOFS, 0); + WriteReg(BG2VOFS, 0); + WriteReg(BG2VOFS, 0); + WriteReg(BG3HOFS, 0); + WriteReg(BG3HOFS, 0); + WriteReg(BG3VOFS, 0); + WriteReg(BG3VOFS, 0); + WriteReg(BG4HOFS, 0); + WriteReg(BG4HOFS, 0); + WriteReg(BG4VOFS, 0); + WriteReg(BG4VOFS, 0); + WriteReg(VMAIN, 0); + WriteReg(M7SEL, 0); + reg_M7SEL = 0; + WriteReg(M7A, 0); + WriteReg(M7B, 0); + WriteReg(M7C, 0); + WriteReg(M7D, 0); + WriteReg(M7X, 0); + WriteReg(M7Y, 0); + WriteReg(W12SEL, 0); + reg_W12SEL = 0; + WriteReg(W34SEL, 0); + reg_W34SEL = 0; + WriteReg(WOBJSEL, 0); + reg_WOBJSEL = 0; + WriteReg(WH0, 0); + reg_WH0 = 0; + WriteReg(WH1, 0xF8u); + reg_WH1 = -8; + WriteReg(WH2, 0); + reg_WH2 = 0; + WriteReg(WH3, 0); + reg_WH3 = 0; + WriteReg(WBGLOG, 0); + reg_WBGLOG = 0; + WriteReg(WOBJLOG, 0); + reg_WOBJLOG = 0; + WriteReg(TM, 0x11u); + reg_TM = 17; + WriteReg(TMW, 0x11u); + reg_TMW = 17; + WriteReg(TS, 2u); + reg_TS = 2; + WriteReg(TSW, 2u); + reg_TSW = 2; + WriteReg(CGWSEL, 2u); + next_gameplay_CGWSEL = 2; + WriteReg(CGADSUB, 0xA1u); + next_gameplay_CGADSUB = -95; + WriteReg(COLDATA, 0xE0u); + WriteReg(COLDATA, 0xE0u); + WriteReg(COLDATA, 0x80); + reg_COLDATA[0] = 0x80; + WriteReg(COLDATA, 0x40u); + reg_COLDATA[1] = 64; + WriteReg(COLDATA, 0x20u); + reg_COLDATA[2] = 32; + WriteReg(SETINI, 0); + reg_SETINI = 0; +} + +void WriteLotsOf0x1c2f(void) { // 0x8088D1 + sub_8088EB(0x1C2Fu); + sub_8088FE(0x1C2Fu); + sub_808911(0x1C2Fu); +} + +void sub_8088EB(uint16 a) { // 0x8088EB + memset7E(0x3000u, a, 0x800u); +} + +void sub_8088FE(uint16 a) { // 0x8088FE + memset7E(0x4000u, a, 0x800u); +} + +void sub_808911(uint16 a) { // 0x808911 + memset7E(0x6000u, a, 0x800u); +} + +void HandleFadeOut(void) { // 0x808924 + if ((int16)(screen_fade_counter - 1) < 0) { + screen_fade_counter = screen_fade_delay; + if ((reg_INIDISP & 0xF) != 0) { + if ((reg_INIDISP & 0xF) == 1) + reg_INIDISP = 0x80; + else + reg_INIDISP = (reg_INIDISP & 0xF) - 1; + } + } else { + --screen_fade_counter; + } +} + +void HandleFadeIn(void) { // 0x80894D + if ((int16)(screen_fade_counter - 1) < 0) { + screen_fade_counter = screen_fade_delay; + if (((reg_INIDISP + 1) & 0xF) != 0) + reg_INIDISP = (reg_INIDISP + 1) & 0xF; + } else { + --screen_fade_counter; + } +} + +void ClearUnusedOam(void) { + for (int i = oam_next_ptr >> 2; i < 0x80; i++) + oam_ent[i].ycoord = 0xf0; + oam_next_ptr = 0; +} + +void ClearOamExt(void) { // 0x808B1A + memset(oam_ext, 0, sizeof(oam_ext[0]) * 16); +} + +void QueueMode7Transfers(uint8 db, uint16 k) { // 0x808B4F + int16 v4; // dx + + uint16 v2 = mode7_vram_write_queue_tail; + for (int i = k - 1; ; i += 7) { + while (1) { + v4 = *(uint16 *)RomPtrWithBank(db, i); + if (v4 >= 0) + break; + uint8 *v6 = RomPtrWithBank(db, i); + *(uint16 *)(&mode7_write_queue[0].field_0 + v2) = *(uint16 *)(v6 + 1); + *(uint16 *)((char *)&mode7_write_queue[0].field_1 + v2 + 1) = *(uint16 *)(v6 + 3); + *(uint16 *)&mode7_write_queue[0].gap3[v2 + 1] = *(uint16 *)(v6 + 5); + *(uint16 *)&mode7_write_queue[0].gap3[v2 + 3] = *(uint16 *)(v6 + 7); + *(uint16 *)((char *)&mode7_write_queue[1].field_1 + v2) = v6[9]; + i += 9; + v2 += 9; + } + if ((v4 & 0x4000) == 0) + break; + uint8 *v5 = RomPtrWithBank(db, i); + *(uint16 *)(&mode7_write_queue[0].field_0 + v2) = *(uint16 *)(v5 + 1); + *(uint16 *)((char *)&mode7_write_queue[0].field_1 + v2 + 1) = *(uint16 *)(v5 + 3); + *(uint16 *)&mode7_write_queue[0].gap3[v2 + 1] = *(uint16 *)(v5 + 5); + *(uint16 *)&mode7_write_queue[0].gap3[v2 + 3] = v5[7]; + v2 += 7; + } + mode7_vram_write_queue_tail = v2; +} + +void NMI_ProcessMode7Queue(void) { // 0x808BBA + if (mode7_vram_write_queue_tail) { + NMI_ProcessMode7QueueInner(0x2D0u); + *(uint16 *)&mode7_write_queue[0].field_0 = 0; + mode7_vram_write_queue_tail = 0; + } +} + +static inline Mode7CgvmWriteQueue *get_Mode7CgvmWriteQueue_RAM(uint16 a) { return (Mode7CgvmWriteQueue *)RomPtr_RAM(a); } +void NMI_ProcessMode7QueueInner(uint16 k) { // 0x808BD3 + char v2; + char v3; + char v4; + Mode7CgvmWriteQueue *v5; + uint8 *v1; + + while (1) { + while (1) { + v1 = RomPtr_RAM(k); + v2 = *v1; + if ((*v1 & 0x80) == 0) + break; + v4 = 2 * v2; + WriteReg(DMAP1, ((uint8)v4 >> 1) & 0x1F); + v5 = get_Mode7CgvmWriteQueue_RAM(k); + WriteRegWord(A1T1L, v5->src_addr.addr); + WriteReg(A1B1, v5->src_addr.bank); + WriteRegWord(DAS1L, v5->count); + if (v4 < 0) + WriteReg(BBAD1, 0x19u); + else + WriteReg(BBAD1, 0x18u); + WriteRegWord(VMADDL, v5->vram_addr); + WriteReg(VMAIN, v5->vmain); + WriteReg(MDMAEN, 2u); + k += 9; + } + v3 = 2 * v2; + if (v3 >= 0) + break; + WriteReg(DMAP1, ((uint8)v3 >> 1) & 0x1F); + WriteRegWord(A1T1L, *(uint16 *)(v1 + 1)); + WriteReg(A1B1, v1[3]); + WriteRegWord(DAS1L, *((uint16 *)v1 + 2)); + WriteReg(BBAD1, 0x22u); + WriteReg(CGADD, v1[6]); + WriteReg(MDMAEN, 2u); + k += 7; + } +} + +void NMI_ProcessVramWriteQueue(void) { // 0x808C83 + int16 v3; + + if (vram_write_queue_tail) { + gVramWriteEntry(vram_write_queue_tail)->size = 0; + WriteRegWord(DMAP1, 0x1801u); + for (int i = 0; ; i += 7) { + uint16 *v1 = (uint16 *)gVramWriteEntry(i); + if (!v1[0]) + break; + WriteRegWord(DAS1L, v1[0]); + WriteRegWord(A1T1L, v1[1]); + WriteRegWord(A1T1H, *(uint16 *)((char *)v1 + 3)); + v3 = *(uint16 *)((char *)v1 + 5); + uint16 v2 = (sign16(v3)) ? 129 : 128; + WriteRegWord(VMAIN, v2); + WriteRegWord(VMADDL, v3); + WriteReg(MDMAEN, 2u); + } + } + vram_write_queue_tail = 0; + Nmi_ProcessHorizScrollingDma(); + Nmi_ProcessVertScrollingDma(); +} + +void Nmi_ProcessHorizScrollingDma(void) { // 0x808CD8 + WriteReg(VMAIN, 0x81u); + if ((uint8)bg1_update_col_enable) { + LOBYTE(bg1_update_col_enable) = 0; + uint16 v0 = bg1_update_col_unwrapped_dst; + WriteRegWord(VMADDL, bg1_update_col_unwrapped_dst); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg1_column_update_tilemap_left_halves)); + WriteReg(A1B1, 0x7Eu); + uint16 v1 = bg1_update_col_unwrapped_size; + WriteRegWord(DAS1L, bg1_update_col_unwrapped_size); + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, v0 + 1); + WriteRegWord(DAS1L, v1); + WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg1_column_update_tilemap_right_halves)); + WriteReg(MDMAEN, 2u); + WriteRegWord(A1T1L, bg1_update_col_wrapped_left_src); + uint16 v2 = bg1_update_col_wrapped_size; + if (bg1_update_col_wrapped_size) { + WriteRegWord(DAS1L, bg1_update_col_wrapped_size); + uint16 v3 = bg1_update_col_wrapped_dst; + WriteRegWord(VMADDL, bg1_update_col_wrapped_dst); + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, v3 + 1); + WriteRegWord(DAS1L, v2); + WriteRegWord(A1T1L, bg1_update_col_wrapped_right_src); + WriteReg(MDMAEN, 2u); + } + } + if ((uint8)bg2_update_col_enable) { + LOBYTE(bg2_update_col_enable) = 0; + uint16 v4 = bg2_update_col_unwrapped_dst; + WriteRegWord(VMADDL, bg2_update_col_unwrapped_dst); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg2_column_update_tilemap_left_halves)); + WriteReg(A1B1, 0x7Eu); + uint16 v5 = bg2_update_col_unwrapped_size; + WriteRegWord(DAS1L, bg2_update_col_unwrapped_size); + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, v4 + 1); + WriteRegWord(DAS1L, v5); + WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg2_column_update_tilemap_right_halves)); + WriteReg(MDMAEN, 2u); + WriteRegWord(A1T1L, bg2_update_col_wrapped_left_src); + uint16 v6 = bg2_update_col_wrapped_size; + if (bg2_update_col_wrapped_size) { + WriteRegWord(DAS1L, bg2_update_col_wrapped_size); + uint16 v7 = bg2_update_col_wrapped_dst; + WriteRegWord(VMADDL, bg2_update_col_wrapped_dst); + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, v7 + 1); + WriteRegWord(DAS1L, v6); + WriteRegWord(A1T1L, bg2_update_col_wrapped_right_src); + WriteReg(MDMAEN, 2u); + } + } +} + +void Nmi_ProcessVertScrollingDma(void) { // 0x808DAC + WriteReg(VMAIN, 0x80); + if ((uint8)bg1_update_row_enable) { + LOBYTE(bg1_update_row_enable) = 0; + uint16 v0 = bg1_update_row_unwrapped_dst; + WriteRegWord(VMADDL, bg1_update_row_unwrapped_dst); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg1_column_update_tilemap_top_halves)); + WriteReg(A1B1, 0x7Eu); + uint16 v1 = bg1_update_row_unwrapped_size; + WriteRegWord(DAS1L, bg1_update_row_unwrapped_size); + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, v0 | 0x20); + WriteRegWord(DAS1L, v1); + WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg1_column_update_tilemap_bottom_halves)); + WriteReg(MDMAEN, 2u); + WriteRegWord(A1T1L, bg1_update_row_wrapped_top_src); + uint16 v2 = bg1_update_row_wrapped_size; + if (bg1_update_row_wrapped_size) { + WriteRegWord(DAS1L, bg1_update_row_wrapped_size); + uint16 v3 = bg1_update_row_wrapped_dst; + WriteRegWord(VMADDL, bg1_update_row_wrapped_dst); + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, v3 | 0x20); + WriteRegWord(DAS1L, v2); + WriteRegWord(A1T1L, bg1_update_row_wrapped_bottom_src); + WriteReg(MDMAEN, 2u); + } + } + if ((uint8)bg2_update_row_enable) { + LOBYTE(bg2_update_row_enable) = 0; + uint16 v4 = bg2_update_row_unwrapped_dst; + WriteRegWord(VMADDL, bg2_update_row_unwrapped_dst); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg2_column_update_tilemap_top_halves)); + WriteReg(A1B1, 0x7Eu); + uint16 v5 = bg2_update_row_unwrapped_size; + WriteRegWord(DAS1L, bg2_update_row_unwrapped_size); + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, v4 | 0x20); + WriteRegWord(DAS1L, v5); + WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg2_column_update_tilemap_bottom_halves)); + WriteReg(MDMAEN, 2u); + WriteRegWord(A1T1L, bg2_update_row_wrapped_top_src); + uint16 v6 = bg2_update_row_wrapped_size; + if (bg2_update_row_wrapped_size) { + WriteRegWord(DAS1L, bg2_update_row_wrapped_size); + uint16 v7 = bg2_update_row_wrapped_dst; + WriteRegWord(VMADDL, bg2_update_row_wrapped_dst); + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, v7 | 0x20); + WriteRegWord(DAS1L, v6); + WriteRegWord(A1T1L, bg2_update_row_wrapped_bottom_src); + WriteReg(MDMAEN, 2u); + } + } +} + +void NMI_ProcessVramReadQueue(void) { // 0x808EA2 + if ((uint8)vram_read_queue_tail) { + *((uint8 *)&vram_read_queue[0].vram_target + (uint8)vram_read_queue_tail) = 0; + int v0 = 0; + WriteReg(VMAIN, 0x80); + while (vram_read_queue[v0].vram_target) { + WriteRegWord(VMADDL, vram_read_queue[v0].vram_target); + ReadRegWord(RDVRAML); + WriteRegWord(DMAP1, vram_read_queue[v0].dma_parameters); + WriteRegWord(A1T1L, vram_read_queue[v0].src.addr); + WriteRegWord(A1T1H, *(VoidP *)((char *)&vram_read_queue[v0].src.addr + 1)); + WriteRegWord(DAS1L, vram_read_queue[v0].size); + WriteRegWord(DAS10, 0); + WriteRegWord(A2A1H, 0); + WriteReg(MDMAEN, 2u); + ++v0; + } + LOBYTE(vram_read_queue_tail) = 0; + } +} + +uint8 HasQueuedMusic(void) { // 0x808EF4 + int v0 = 14; + while (!music_queue_delay[v0 >> 1]) { + v0 -= 2; + if (v0 < 0) + return 0; + } + return 1; +} +#define kMusicPointers (*(LongPtr*)RomPtr(0x8fe7e1)) +void HandleMusicQueue(void) { // 0x808F0C + bool v0 = music_timer-- == 1; + if ((music_timer & 0x8000u) == 0) { + if (!v0) + return; + if ((music_entry & 0x8000u) != 0) { + music_data_index = (uint8)music_entry; + cur_music_track = -1; + copy24(&R0_, (LongPtr *)((char *)&kMusicPointers + (uint8)music_entry)); + APU_UploadBank(); + cur_music_track = 0; + int v5 = music_queue_read_pos; + music_queue_track[v5 >> 1] = 0; + music_queue_delay[v5 >> 1] = 0; + music_queue_read_pos = (v5 + 2) & 0xE; + sound_handler_downtime = 8; + return; + } + uint8 v1 = music_entry & 0x7F; + music_track_index = music_entry & 0x7F; + RtlApuWrite(APUI00, music_entry & 0x7F); + cur_music_track = v1; + sound_handler_downtime = 8; + int v2 = music_queue_read_pos; + music_queue_track[v2 >> 1] = 0; + music_queue_delay[v2 >> 1] = 0; + music_queue_read_pos = (v2 + 2) & 0xE; + } + if (music_queue_read_pos == music_queue_write_pos) { + music_timer = 0; + } else { + int v4 = music_queue_read_pos >> 1; + music_entry = music_queue_track[v4]; + music_timer = music_queue_delay[v4]; + } +} + +void QueueMusic_Delayed8(uint16 a) { // 0x808FC1 + char v1; + + if (game_state < kGameState_40_TransitionToDemo && (((uint8)music_queue_write_pos + 2) & 0xE) != music_queue_read_pos) { + v1 = music_queue_write_pos; + int v2 = music_queue_write_pos >> 1; + music_queue_track[v2] = a; + music_queue_delay[v2] = 8; + music_queue_write_pos = (v1 + 2) & 0xE; + } +} + +void QueueMusic_DelayedY(uint16 a, uint16 j) { // 0x808FF7 + if (game_state < 0x28u) { + int v2 = music_queue_write_pos; + music_queue_track[v2 >> 1] = a; + int v4 = j; + if (j < 8u) + v4 = 8; + music_queue_delay[v2 >> 1] = v4; + music_queue_write_pos = (v2 + 2) & 0xE; + } +} + +void QueueSfx1_Max15(uint16 a) { // 0x809021 + QueueSfx1_Internal(a << 8 | 15); +} + +void QueueSfx1_Max9(uint16 a) { // 0x80902B + QueueSfx1_Internal(a << 8 | 9); +} + +void QueueSfx1_Max3(uint16 a) { // 0x809035 + QueueSfx1_Internal(a << 8 | 3); +} + +void QueueSfx1_Max1(uint16 a) { // 0x80903F + QueueSfx1_Internal(a << 8 | 1); +} + +void QueueSfx1_Max6(uint16 a) { // 0x809049 + QueueSfx1_Internal(a << 8 | 6); +} + +void QueueSfx1_Internal(uint16 a) { // 0x809051 + uint16 v2; + + sfx_max_queued[0] = a; + if ((uint8)((sfx_writepos[0] - sfx_readpos[0]) & 0xF) < (uint8)a) { + LOBYTE(v2) = HIBYTE(a); + HIBYTE(v2) = (sfx_writepos[0] - sfx_readpos[0]) & 0xF; + if (!debug_disable_sounds && game_state < 0x28u && (power_bomb_explosion_status & 0x8000u) == 0) { + uint16 v1 = sfx_writepos[0]; + uint16 v3 = sfx_writepos[0] + 1; + if ((uint8)(sfx_writepos[0] + 1) >= 0x10u) + v3 = 0; + if (v3 == sfx_readpos[0]) { + if (v2 < *(uint16 *)&sfx1_queue[v1]) + *(uint16 *)&sfx1_queue[v1] = v2; + } else { + sfx1_queue[sfx_writepos[0]] = v2; + sfx_writepos[0] = v3; + sfx1_queue[v3] = 0; + } + } + } +} + +void QueueSfx2_Max15(uint16 a) { // 0x8090A3 + QueueSfx2_Internal(a << 8 | 15); +} + +void QueueSfx2_Max9(uint16 a) { // 0x8090AD + QueueSfx2_Internal(a << 8 | 9); +} + +void QueueSfx2_Max3(uint16 a) { // 0x8090B7 + QueueSfx2_Internal(a << 8 | 3); +} + +void QueueSfx2_Max1(uint16 a) { // 0x8090C1 + QueueSfx2_Internal(a << 8 | 1); +} + +void QueueSfx2_Max6(uint16 a) { // 0x8090CB + QueueSfx2_Internal(a << 8 | 6); +} + +void QueueSfx2_Internal(uint16 a) { // 0x8090D3 + uint16 v1; + uint16 v2; + + sfx_max_queued[1] = a; + if ((uint8)((sfx_writepos[1] - sfx_readpos[1]) & 0xF) < (uint8)a) { + LOBYTE(v2) = HIBYTE(a); + HIBYTE(v2) = (sfx_writepos[1] - sfx_readpos[1]) & 0xF; + if (!debug_disable_sounds && game_state < 0x28u && (power_bomb_explosion_status & 0x8000u) == 0) { + LOBYTE(v1) = sfx_writepos[1]; + uint8 v3 = sfx_writepos[1] + 1; + if ((uint8)(sfx_writepos[1] + 1) >= 0x10u) + v3 = 0; + if (v3 == sfx_readpos[1]) { + if (v2 < *(uint16 *)&sfx2_queue[v1]) + *(uint16 *)&sfx2_queue[v1] = v2; + } else { + sfx2_queue[sfx_writepos[1]] = v2; + sfx_writepos[1] = v3; + sfx2_queue[v3] = 0; + } + } + } +} + +void QueueSfx3_Max15(uint16 a) { // 0x809125 + QueueSfx3_Internal(a << 8 | 15); +} + +void QueueSfx3_Max9(uint16 a) { // 0x80912F + QueueSfx3_Internal(a << 8 | 9); +} + +void QueueSfx3_Max3(uint16 a) { // 0x809139 + QueueSfx3_Internal(a << 8 | 3); +} + +void QueueSfx3_Max1(uint16 a) { // 0x809143 + QueueSfx3_Internal(a << 8 | 1); +} + +void QueueSfx3_Max6(uint16 a) { // 0x80914D + QueueSfx3_Internal(a << 8 | 6); +} + +void QueueSfx3_Internal(uint16 a) { // 0x809155 + sfx_max_queued[2] = a; + if ((uint8)((sfx_writepos[2] - sfx_readpos[2]) & 0xF) < (uint8)a) { + uint16 v2 = 0; + LOBYTE(v2) = HIBYTE(a); + HIBYTE(v2) = (sfx_writepos[2] - sfx_readpos[2]) & 0xF; + if (!debug_disable_sounds && game_state < 0x28u && (power_bomb_explosion_status & 0x8000u) == 0) { + uint16 v1 = sfx_writepos[2]; + int v3 = sfx_writepos[2] + 1; + if (v3 >= 0x10u) + v3 = 0; + if (v3 == sfx_readpos[2]) { + if (v2 < *(uint16 *)&sfx3_queue[v1]) + *(uint16 *)&sfx3_queue[v1] = v2; + } else { + sfx3_queue[sfx_writepos[2]] = v2; + sfx_writepos[2] = v3; + sfx3_queue[v3] = 0; + } + } + } +} + +void SetupDmaTransfer(const void *p) { // 0x8091A9 + const StartDmaCopy *s = (const StartDmaCopy *)p; + + int v2 = s->chan * 16; + WriteRegWord((SnesRegs)(v2 + DMAP0), *(uint16 *)&s->dmap); + WriteRegWord((SnesRegs)(v2 + A1T0L), *(uint16 *)&s->a1.addr); + WriteReg((SnesRegs)(v2 + A1B0), s->a1.bank); + WriteRegWord((SnesRegs)(v2 + DAS0L), s->das); +} + +void NmiUpdateIoRegisters(void) { // 0x8091EE + WriteReg(NMITIMEN, reg_NMITIMEN); + WriteReg(INIDISP, reg_INIDISP); + WriteReg(OBSEL, reg_OBSEL); + WriteReg(BGMODE, reg_BGMODE); + WriteReg(MOSAIC, reg_MOSAIC); + WriteReg(BG1SC, reg_BG1SC); + WriteReg(BG2SC, reg_BG2SC); + WriteReg(BG3SC, reg_BG3SC); + WriteReg(BG4SC, reg_BG4SC); + WriteReg(BG12NBA, reg_BG12NBA); + WriteReg(BG34NBA, reg_BG34NBA); + WriteReg(M7SEL, reg_M7SEL); + WriteReg(W12SEL, reg_W12SEL); + WriteReg(W34SEL, reg_W34SEL); + WriteReg(WOBJSEL, reg_WOBJSEL); + WriteReg(WH0, reg_WH0); + WriteReg(WH1, reg_WH1); + WriteReg(WH2, reg_WH2); + WriteReg(WH3, reg_WH3); + WriteReg(WBGLOG, reg_WBGLOG); + WriteReg(WOBJLOG, reg_WOBJLOG); + gameplay_TM = reg_TM; + WriteReg(TM, reg_TM); + WriteReg(TMW, reg_TMW); + WriteReg(TS, reg_TS); + WriteReg(TSW, reg_TSW); + WriteReg(CGWSEL, reg_CGWSEL); + WriteReg(CGADSUB, reg_CGADSUB); + gameplay_CGWSEL = next_gameplay_CGWSEL; + gameplay_CGADSUB = next_gameplay_CGADSUB; + WriteReg(COLDATA, reg_COLDATA[0]); + WriteReg(COLDATA, reg_COLDATA[1]); + WriteReg(COLDATA, reg_COLDATA[2]); + WriteReg(SETINI, reg_SETINI); + WriteReg(BG1HOFS, reg_BG1HOFS); + WriteReg(BG1HOFS, HIBYTE(reg_BG1HOFS)); + WriteReg(BG1VOFS, reg_BG1VOFS); + WriteReg(BG1VOFS, HIBYTE(reg_BG1VOFS)); + WriteReg(BG2HOFS, reg_BG2HOFS); + WriteReg(BG2HOFS, HIBYTE(reg_BG2HOFS)); + WriteReg(BG2VOFS, reg_BG2VOFS); + WriteReg(BG2VOFS, HIBYTE(reg_BG2VOFS)); + WriteReg(BG3HOFS, reg_BG3HOFS); + WriteReg(BG3HOFS, HIBYTE(reg_BG3HOFS)); + WriteReg(BG3VOFS, reg_BG3VOFS); + WriteReg(BG3VOFS, HIBYTE(reg_BG3VOFS)); + WriteReg(BG4HOFS, reg_BG4HOFS); + WriteReg(BG4HOFS, HIBYTE(reg_BG4HOFS)); + WriteReg(BG4VOFS, reg_BG4VOFS); + WriteReg(BG4VOFS, HIBYTE(reg_BG4VOFS)); + HIBYTE(hdma_data_table_in_ceres) = reg_BGMODE_fake; + if ((reg_BGMODE & 7) == 7 || (reg_BGMODE_fake & 7) == 7) { + WriteReg(M7A, reg_M7A); + WriteReg(M7A, HIBYTE(reg_M7A)); + WriteReg(M7B, reg_M7B); + WriteReg(M7B, HIBYTE(reg_M7B)); + WriteReg(M7C, reg_M7C); + WriteReg(M7C, HIBYTE(reg_M7C)); + WriteReg(M7D, reg_M7D); + WriteReg(M7D, HIBYTE(reg_M7D)); + WriteReg(M7X, reg_M7X); + WriteReg(M7X, HIBYTE(reg_M7X)); + WriteReg(M7Y, reg_M7Y); + WriteReg(M7Y, HIBYTE(reg_M7Y)); + } +} + +void NmiUpdatePalettesAndOam(void) { // 0x80933A + WriteRegWord(DMAP0, 0x400u); + WriteRegWord(A1T0L, ADDR16_OF_RAM(*oam_ent)); + WriteReg(A1B0, 0); + WriteRegWord(DAS0L, 0x220u); + WriteRegWord(OAMADDL, 0); + WriteRegWord(DMAP1, 0x2200u); + WriteRegWord(A1T1L, ADDR16_OF_RAM(*palette_buffer)); + WriteReg(A1B1, 0x7Eu); + WriteRegWord(DAS1L, 0x200u); + WriteReg(CGADD, 0); + WriteReg(MDMAEN, 3u); +} + +void NmiTransferSamusToVram(void) { // 0x809376 + WriteReg(VMAIN, 0x80); + if ((uint8)nmi_copy_samus_halves) { + nmicopy1_var_d = nmi_copy_samus_top_half_src; + WriteRegWord(VMADDL, 0x6000u); + WriteRegWord(DMAP1, 0x1801u); + uint16 v0 = *(uint16 *)RomPtr_92(nmicopy1_var_d); + WriteRegWord(A1T1L, v0); + R20_ = v0; + uint8 *v1 = RomPtr_92(nmicopy1_var_d); + WriteRegWord(A1B1, *((uint16 *)v1 + 1)); + uint16 v2 = *(uint16 *)(RomPtr_92(nmicopy1_var_d) + 3); + WriteRegWord(DAS1L, v2); + R20_ += v2; + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, 0x6100u); + WriteRegWord(A1T1L, R20_); + uint8 *v3 = RomPtr_92(nmicopy1_var_d); + if (*(uint16 *)(v3 + 5)) { + WriteRegWord(DAS1L, *(uint16 *)(v3 + 5)); + WriteReg(MDMAEN, 2u); + } + } + if (HIBYTE(nmi_copy_samus_halves)) { + nmicopy1_var_d = nmi_copy_samus_bottom_half_src; + WriteRegWord(VMADDL, 0x6080u); + WriteRegWord(DMAP1, 0x1801u); + uint16 v4 = *(uint16 *)RomPtr_92(nmicopy1_var_d); + WriteRegWord(A1T1L, v4); + R20_ = v4; + uint8 *v5 = RomPtr_92(nmicopy1_var_d); + WriteRegWord(A1B1, *((uint16 *)v5 + 1)); + uint16 v6 = *(uint16 *)(RomPtr_92(nmicopy1_var_d) + 3); + WriteRegWord(DAS1L, v6); + R20_ += v6; + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, 0x6180u); + WriteRegWord(A1T1L, R20_); + uint8 *v7 = RomPtr_92(nmicopy1_var_d); + if (*(uint16 *)(v7 + 5)) { + WriteRegWord(DAS1L, *(uint16 *)(v7 + 5)); + WriteReg(MDMAEN, 2u); + } + } +} + +void NmiProcessAnimtilesVramTransfers(void) { // 0x809416 + if ((animtiles_enable_flag & 0x8000u) != 0) { + for (int i = 10; (i & 0x80) == 0; i -= 2) { + int v1 = i >> 1; + if (animtiles_ids[v1]) { + if (animtiles_src_ptr[v1]) { + WriteRegWord(A1T0L, animtiles_src_ptr[v1]); + WriteReg(A1B0, 0x87u); + WriteRegWord(DMAP0, 0x1801u); + WriteRegWord(DAS0L, animtiles_sizes[v1]); + WriteRegWord(VMADDL, animtiles_vram_ptr[v1]); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 1u); + animtiles_src_ptr[v1] = 0; + } + } + } + } +} + +void ReadJoypadInputs(void) { // 0x809459 + uint16 RegWord = ReadRegWord(JOY1L); + joypad1_lastkeys = RegWord; + joypad1_newkeys = RegWord & (joypad1_prev ^ RegWord); + joypad1_newkeys2_UNUSED = RegWord & (joypad1_prev ^ RegWord); + if (RegWord && RegWord == joypad1_prev) { + if (!--joypad1_keyrepeat_ctr) { + joypad1_newkeys2_UNUSED = joypad1_lastkeys; + joypad1_keyrepeat_ctr = joypad_ctr_repeat_next; + } + } else { + joypad1_keyrepeat_ctr = joypad_ctr_repeat_first; + } + joypad1_prev = joypad1_lastkeys; + if (enable_debug) { + uint16 v1 = ReadRegWord(JOY2L); + joypad2_last = v1; + joypad2_new_keys = v1 & (joypad2_prev ^ v1); + joypad2_newkeys2 = v1 & (joypad2_prev ^ v1); + if (v1 && v1 == joypad2_prev) { + if (!--joypad2_keyrepeat_ctr) { + joypad2_newkeys2 = joypad2_last; + joypad2_keyrepeat_ctr = joypad_ctr_repeat_next; + } + } else { + joypad2_keyrepeat_ctr = joypad_ctr_repeat_first; + } + joypad2_prev = joypad2_last; + if (is_uploading_apu || joypad1_lastkeys != (kButton_Select | kButton_Start | kButton_L | kButton_R)) { + if (enable_debug) { + joypad_dbg_1 = 0; + joypad_dbg_2 = 0; + if ((joypad_dbg_flags & 0x4000) == 0) { + if ((joypad1_lastkeys & (kButton_Select | kButton_L)) == (kButton_Select | kButton_L)) { + joypad_dbg_1 = joypad1_newkeys; + joypad1_lastkeys = 0; + joypad1_newkeys = 0; + } + if ((joypad1_lastkeys & (kButton_Select | kButton_R)) == (kButton_Select | kButton_R)) { + joypad_dbg_2 = joypad1_newkeys; + joypad1_lastkeys = 0; + joypad1_newkeys = 0; + } + if ((joypad_dbg_2 & 0x80) != 0) + *(uint16 *)®_NMITIMEN ^= 0x30u; + if ((joypad_dbg_2 & 0x8000u) != 0) { + bool v2 = (~joypad_dbg_flags & 0x8000u) != 0; + joypad_dbg_flags ^= 0x8000u; + if (v2) { + joypad_dbg_missiles_swap = samus_missiles; + joypad_dbg_super_missiles_swap = samus_super_missiles; + joypad_dbg_power_bombs_swap = samus_power_bombs; + samus_missiles = 0; + samus_super_missiles = 0; + samus_power_bombs = 0; + } else { + samus_missiles = joypad_dbg_missiles_swap; + samus_super_missiles = joypad_dbg_super_missiles_swap; + samus_power_bombs = joypad_dbg_power_bombs_swap; + } + } + if ((joypad_dbg_2 & 0x40) != 0) + joypad_dbg_flags ^= 0x2000u; + } + } else { + joypad_dbg_1 = 0; + joypad_dbg_2 = 0; + joypad2_last &= 0x10u; + joypad2_new_keys &= 0x10u; + } + } else { + debug_disable_sounds = 0; + SoftReset(); + } + } +} + +void Vector_NMI(void) { // 0x809583 + if (waiting_for_nmi) { + NmiUpdatePalettesAndOam(); + NmiTransferSamusToVram(); + NmiProcessAnimtilesVramTransfers(); + NmiUpdateIoRegisters(); + for (int i = 0; i != 6; ++i) { + if (hdma_object_channels_bitmask[i]) + WriteRegWord((SnesRegs)(LOBYTE(hdma_object_bank_slot[i]) + 17154), hdma_object_table_pointers[i]); + } + if (reg_BGMODE == 7 || reg_BGMODE_fake == 7) + NMI_ProcessMode7Queue(); + NMI_ProcessVramWriteQueue(); + NMI_ProcessVramReadQueue(); + WriteReg(HDMAEN, reg_HDMAEN); + waiting_for_nmi = 0; + nmi_frames_missed = 0; + ++nmi_frame_counter_byte; + ++nmi_frame_counter_word; + } else if (++nmi_frames_missed >= nmi_frames_missed_max) { + nmi_frames_missed_max = nmi_frames_missed; + } + ++nmi_frame_counter_including_lag; +} + +void Irq_DoorTransitionVramUpdate(void) { // 0x809632 + WriteReg(INIDISP, 0x80); + WriteRegWord(VMADDL, door_transition_vram_update_dst); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1T1L, door_transition_vram_update_src.addr); + WriteReg(A1B1, door_transition_vram_update_src.bank); + WriteRegWord(DAS1L, door_transition_vram_update_size); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 2u); + door_transition_vram_update_enabled &= ~0x8000; + WriteReg(INIDISP, 0xFu); +} + +void WaitForIrqDoorTransitionVramUpdate(void) { + door_transition_vram_update_enabled |= 0x8000u; + Irq_DoorTransitionVramUpdate(); +} + +void IrqHandler_SetResult(uint16 a, uint16 y, uint16 x) { + // printf("Setting irq next: %d, %d, %d\n", a, x, y); + cur_irq_handler = a; + WriteRegWord(VTIMEL, y); + WriteRegWord(HTIMEL, x); +} + +void IrqHandler_0_Nothing(void) { // 0x80966E + uint16 a = irqhandler_next_handler; + irqhandler_next_handler = 0; + IrqHandler_SetResult(a, 0, 0); +} + +void IrqHandler_2_DisableIRQ(void) { // 0x809680 + *(uint16 *)®_NMITIMEN &= ~0x30; + IrqHandler_SetResult(0, 0, 0); +} + +void IrqHandler_4_Main_BeginHudDraw(void) { // 0x80968B + WriteReg(BG3SC, 0x5Au); + WriteReg(CGWSEL, 0); + WriteReg(CGADSUB, 0); + WriteReg(TM, 4u); + IrqHandler_SetResult(6, 31, 152); +} + +void IrqHandler_6_Main_EndHudDraw(void) { // 0x8096A9 + WriteReg(CGWSEL, gameplay_CGWSEL); + WriteReg(CGADSUB, gameplay_CGADSUB); + WriteReg(BG3SC, gameplay_BG3SC); + WriteReg(TM, gameplay_TM); + + uint16 a = irqhandler_next_handler; + irqhandler_next_handler = 0; + IrqHandler_SetResult(a ? a : 4, 0, 152); +} + +void IrqHandler_8_StartOfDoor_BeginHud(void) { // 0x8096D3 + WriteReg(BG3SC, 0x5Au); + WriteReg(TM, 4u); + WriteReg(CGWSEL, 0); + WriteReg(CGADSUB, 0); + IrqHandler_SetResult(10, 31, 152); +} + +void IrqHandler_10_StartOfDoor_EndHud(void) { // 0x8096F1 + uint8 v0; + if ((((uint8)previous_cre_bitset | (uint8)cre_bitset) & 1) != 0) + v0 = 16; + else + v0 = 17; + WriteReg(TM, v0); + uint16 a = irqhandler_next_handler; + irqhandler_next_handler = 0; + IrqHandler_SetResult(a ? a : 8, 0, 152); +} + +void IrqHandler_12_Draygon_BeginHud(void) { // 0x80971A + WriteReg(TM, 4u); + WriteReg(CGWSEL, 0); + WriteReg(CGADSUB, 0); + IrqHandler_SetResult(14, 31, 152); +} + +void IrqHandler_14_Draygon_EndHud(void) { // 0x809733 + WriteReg(BG3SC, gameplay_BG3SC); + WriteReg(CGWSEL, gameplay_CGWSEL); + WriteReg(CGADSUB, gameplay_CGADSUB); + uint16 a = irqhandler_next_handler; + irqhandler_next_handler = 0; + IrqHandler_SetResult(a ? a : 12, 0, 152); +} + +void IrqHandler_16_VerticalDoor_BeginHud(void) { // 0x809758 + WriteReg(TM, 4u); + WriteReg(CGWSEL, 0); + WriteReg(CGADSUB, 0); + IrqHandler_SetResult(18, 31, 152); +} + +void IrqHandler_18_VerticalDoor_EndHud(void) { // 0x809771 + uint8 v0; + if (((previous_cre_bitset | cre_bitset) & 1) != 0) + v0 = 16; + else + v0 = 17; + WriteReg(TM, v0); + WriteReg(CGWSEL, 0); + WriteReg(CGADSUB, 0); +// if ((door_transition_vram_update_enabled & 0x8000u) != 0) +// Irq_DoorTransitionVramUpdate(); + if ((door_transition_flag & 0x8000u) == 0) + Irq_FollowDoorTransition(); + IrqHandler_SetResult(20, 216, 152); +} + +void IrqHandler_20_VerticalDoor_EndDraw(void) { // 0x8097A9 +// *(uint16 *)&waiting_for_nmi = 1; + uint16 a = irqhandler_next_handler; + irqhandler_next_handler = 0; + IrqHandler_SetResult(a ? a : 16, 0, 152); +} + +void IrqHandler_22_HorizDoor_BeginHud(void) { // 0x8097C1 + WriteReg(TM, 4u); + WriteReg(CGWSEL, 0); + WriteReg(CGADSUB, 0); + IrqHandler_SetResult(24, 31, 152); +} + +void IrqHandler_24_HorizDoor_EndHud(void) { // 0x8097DA + uint8 v0; + + if (((previous_cre_bitset | cre_bitset) & 1) != 0) + v0 = 16; + else + v0 = 17; + WriteReg(TM, v0); + WriteReg(CGWSEL, 0); + WriteReg(CGADSUB, 0); + if ((door_transition_flag & 0x8000u) == 0) + Irq_FollowDoorTransition(); + IrqHandler_SetResult(26, 160, 152); +} + +void IrqHandler_26_HorizDoor_EndDraw(void) { // 0x80980A + uint16 a = irqhandler_next_handler; + irqhandler_next_handler = 0; + IrqHandler_SetResult(a ? a : 22, 0, 152); +} + +void EnableIrqInterrupts(void) { // 0x80982A + WriteRegWord(VTIMEL, 0); + WriteRegWord(HTIMEL, 152); + *(uint16 *)®_NMITIMEN |= 0x30u; +} + +void EnableIrqInterruptsNow(void) { // 0x809841 + WriteRegWord(VTIMEL, 0); + WriteRegWord(HTIMEL, 152); + *(uint16 *)®_NMITIMEN |= 0x30u; + WriteReg(NMITIMEN, reg_NMITIMEN); +} + +void DisableIrqInterrupts(void) { // 0x80985F + *(uint16 *)®_NMITIMEN &= ~0x30; +} + +static Func_V *const kIrqHandlers[14] = { // 0x80986A + IrqHandler_0_Nothing, + IrqHandler_2_DisableIRQ, + IrqHandler_4_Main_BeginHudDraw, + IrqHandler_6_Main_EndHudDraw, + IrqHandler_8_StartOfDoor_BeginHud, + IrqHandler_10_StartOfDoor_EndHud, + IrqHandler_12_Draygon_BeginHud, + IrqHandler_14_Draygon_EndHud, + IrqHandler_16_VerticalDoor_BeginHud, + IrqHandler_18_VerticalDoor_EndHud, + IrqHandler_20_VerticalDoor_EndDraw, + IrqHandler_22_HorizDoor_BeginHud, + IrqHandler_24_HorizDoor_EndHud, + IrqHandler_26_HorizDoor_EndDraw, +}; + +void Vector_IRQ(void) { + kIrqHandlers[cur_irq_handler >> 1](); +} + +static const uint16 kHudTilemaps[32] = { // 0x8099CF + 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, + 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1c, +}; +static const uint16 kHudTilemaps_Row1to3[96] = { + 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, + 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c12, 0x2c12, 0x2c23, 0x2c12, 0x2c12, 0x2c1e, + 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, + 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2822, 0x2822, 0x2823, 0x2813, 0x2c14, 0x2c1e, + 0x2c0f, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c32, 0x2c0f, 0x2c09, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, + 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c12, 0x2c12, 0xa824, 0x2815, 0x2c16, 0x2c1e, +}; +static const uint16 kHudTilemaps_AutoReserve[12] = { 0x3c33, 0x3c46, 0x3c47, 0x3c48, 0xbc33, 0xbc46, 0x2c33, 0x2c46, 0x2c47, 0x2c48, 0xac33, 0xac46 }; +static const uint16 kHudTilemaps_Missiles[22] = { + 0x344b, 0x3449, 0x744b, 0x344c, 0x344a, 0x744c, 0x3434, 0x7434, 0x3435, 0x7435, 0x3436, 0x7436, 0x3437, 0x7437, 0x3438, 0x7438, + 0x3439, 0x7439, 0x343a, 0x743a, 0x343b, 0x743b, +}; + +void AddMissilesToHudTilemap(void) { + if ((hud_tilemap[10] & 0x3FF) == 15) { + hud_tilemap[10] = kHudTilemaps_Missiles[0]; + hud_tilemap[11] = kHudTilemaps_Missiles[1]; + hud_tilemap[12] = kHudTilemaps_Missiles[2]; + hud_tilemap[42] = kHudTilemaps_Missiles[3]; + hud_tilemap[43] = kHudTilemaps_Missiles[4]; + hud_tilemap[44] = kHudTilemaps_Missiles[5]; + } +} + +void AddSuperMissilesToHudTilemap(void) { // 0x809A0E + AddToTilemapInner(0x1Cu, addr_kHudTilemaps_Missiles + 12); +} + +void AddPowerBombsToHudTilemap(void) { // 0x809A1E + AddToTilemapInner(0x22u, addr_kHudTilemaps_Missiles + 20); +} + +void AddGrappleToHudTilemap(void) { // 0x809A2E + AddToTilemapInner(0x28u, addr_kHudTilemaps_Missiles + 28); +} + +void AddXrayToHudTilemap(void) { // 0x809A3E + AddToTilemapInner(0x2Eu, addr_kHudTilemaps_Missiles + 36); +} + +void AddToTilemapInner(uint16 k, uint16 j) { // 0x809A4C + int v2 = k >> 1; + if ((hud_tilemap[v2] & 0x3FF) == 15) { + uint16 *v3 = (uint16 *)RomPtr_80(j); + hud_tilemap[v2] = *v3; + hud_tilemap[v2 + 1] = v3[1]; + hud_tilemap[v2 + 32] = v3[2]; + hud_tilemap[v2 + 33] = v3[3]; + } +} + +void InitializeHud(void) { // 0x809A79 + WriteRegWord(VMADDL, addr_unk_605800); + WriteRegWord(VMAIN, 0x80); + static const StartDmaCopy unk_809A8F = { 1, 1, 0x18, LONGPTR(0x80988b), 0x0040 }; + SetupDmaTransfer(&unk_809A8F); + WriteReg(MDMAEN, 2u); + for (int i = 0; i != 192; i += 2) + hud_tilemap[i >> 1] = kHudTilemaps_Row1to3[i >> 1]; + if ((equipped_items & 0x8000u) != 0) + AddXrayToHudTilemap(); + if ((equipped_items & 0x4000) != 0) + AddGrappleToHudTilemap(); + if (samus_max_missiles) + AddMissilesToHudTilemap(); + if (samus_max_super_missiles) + AddSuperMissilesToHudTilemap(); + if (samus_max_power_bombs) + AddPowerBombsToHudTilemap(); + samus_prev_health = 0; + samus_prev_missiles = 0; + samus_prev_super_missiles = 0; + samus_prev_power_bombs = 0; + samus_prev_hud_item_index = 0; + InitializeMiniMapBroken(); + R0_.addr = addr_kDigitTilesetsWeapon; + *(uint16 *)&R0_.bank = 128; + if (samus_max_missiles) + DrawThreeHudDigits(samus_missiles, 0x94u); + if (samus_max_super_missiles) + DrawTwoHudDigits(samus_super_missiles, 0x9Cu); + if (samus_max_power_bombs) + DrawTwoHudDigits(samus_power_bombs, 0xA2u); + ToggleHudItemHighlight(hud_item_index, 0x1000u); + ToggleHudItemHighlight(samus_prev_hud_item_index, 0x1400u); + HandleHudTilemap(); +} + +static const uint16 kEnergyTankIconTilemapOffsets[14] = { 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 2, 4, 6, 8, 0xa, 0xc, 0xe }; + +void HandleHudTilemap(void) { // 0x809B44 + R0_.bank = 0; + if (reserve_health_mode == 1) { + uint16 v0 = addr_kHudTilemaps_AutoReserve; + if (!samus_reserve_health) + v0 = addr_kHudTilemaps_AutoReserve + 12; + uint16 *v1 = (uint16 *)RomPtr_80(v0); + hud_tilemap[8] = *v1; + hud_tilemap[9] = v1[1]; + hud_tilemap[40] = v1[2]; + hud_tilemap[41] = v1[3]; + hud_tilemap[72] = v1[4]; + hud_tilemap[73] = v1[5]; + } + if (samus_health != samus_prev_health) { + samus_prev_health = samus_health; + + R20_ = SnesDivide(samus_health, 100); + R18_ = SnesModulus(samus_health, 100); + int v2 = 0; + R22_ = SnesDivide(samus_max_health, 100) + 1; + do { + if (!--R22_) + break; + uint16 v3 = 13360; + if (R20_) { + --R20_; + v3 = 10289; + } + hud_tilemap[kEnergyTankIconTilemapOffsets[v2 >> 1] >> 1] = v3; + v2 += 2; + } while ((int16)(v2 - 28) < 0); + R0_.addr = addr_kDigitTilesetsHealth; + DrawTwoHudDigits(R18_, 0x8Cu); + } + R0_.addr = addr_kDigitTilesetsWeapon; + if (samus_max_missiles && samus_missiles != samus_prev_missiles) { + samus_prev_missiles = samus_missiles; + DrawThreeHudDigits(samus_missiles, 0x94u); + } + if (samus_max_super_missiles && samus_super_missiles != samus_prev_super_missiles) { + samus_prev_super_missiles = samus_super_missiles; + if ((joypad_dbg_flags & 0x1F40) != 0) + DrawThreeHudDigits(samus_prev_super_missiles, 0x9Cu); + else + DrawTwoHudDigits(samus_prev_super_missiles, 0x9Cu); + } + if (samus_max_power_bombs && samus_power_bombs != samus_prev_power_bombs) { + samus_prev_power_bombs = samus_power_bombs; + DrawTwoHudDigits(samus_power_bombs, 0xA2u); + } + if (hud_item_index != samus_prev_hud_item_index) { + ToggleHudItemHighlight(hud_item_index, 0x1000u); + ToggleHudItemHighlight(samus_prev_hud_item_index, 0x1400u); + samus_prev_hud_item_index = hud_item_index; + if (samus_movement_type != 3 + && samus_movement_type != 20 + && grapple_beam_function == 0xC4F0 + && !time_is_frozen_flag) { + QueueSfx1_Max6(0x39u); + } + } + uint16 v4 = 5120; + if ((nmi_frame_counter_byte & 0x10) != 0) + v4 = 4096; + ToggleHudItemHighlight(samus_auto_cancel_hud_item_index, v4); + uint16 v5 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 192; + v5 += 2; + gVramWriteEntry(v5)->size = ADDR16_OF_RAM(*hud_tilemap); + v5 += 2; + gVramWriteEntry(v5++)->size = 126; + gVramWriteEntry(v5)->size = addr_unk_605820; + vram_write_queue_tail = v5 + 2; +} + +static const uint16 kHudItemTilemapOffsets[5] = { 0x14, 0x1c, 0x22, 0x28, 0x2e }; + +void ToggleHudItemHighlight(uint16 a, uint16 k) { // 0x809CEA + int16 v2; + + hud_item_tilemap_palette_bits = k; + v2 = a - 1; + if (v2 >= 0) { + int v3 = kHudItemTilemapOffsets[v2] >> 1; + if (hud_tilemap[v3] != 11279) + hud_tilemap[v3] = hud_item_tilemap_palette_bits | hud_tilemap[v3] & 0xE3FF; + if (hud_tilemap[v3 + 1] != 11279) + hud_tilemap[v3 + 1] = hud_item_tilemap_palette_bits | hud_tilemap[v3 + 1] & 0xE3FF; + if (hud_tilemap[v3 + 32] != 11279) + hud_tilemap[v3 + 32] = hud_item_tilemap_palette_bits | hud_tilemap[v3 + 32] & 0xE3FF; + if (hud_tilemap[v3 + 33] != 11279) + hud_tilemap[v3 + 33] = hud_item_tilemap_palette_bits | hud_tilemap[v3 + 33] & 0xE3FF; + if (!(2 * v2)) { + if (hud_tilemap[v3 + 2] != 11279) + hud_tilemap[v3 + 2] = hud_item_tilemap_palette_bits | hud_tilemap[v3 + 2] & 0xE3FF; + if (hud_tilemap[v3 + 34] != 11279) + hud_tilemap[v3 + 34] = hud_item_tilemap_palette_bits | hud_tilemap[v3 + 34] & 0xE3FF; + } + } +} + +void DrawThreeHudDigits(uint16 a, uint16 k) { // 0x809D78 + uint16 v2 = 2 * (a / 100); + hud_tilemap[k >> 1] = *(uint16 *)IndirPtr(&R0_, v2); + uint16 RegWord = (a % 100); + DrawTwoHudDigits(RegWord, k + 2); +} + +void DrawTwoHudDigits(uint16 a, uint16 k) { // 0x809D98 + uint16 RegWord = a / 10; + int v3 = k >> 1; + hud_tilemap[v3] = *(uint16 *)IndirPtr(&R0_, 2 * RegWord); + uint16 v4 = 2 * (a % 10); + hud_tilemap[v3 + 1] = *(uint16 *)IndirPtr(&R0_, v4); +} + +static Func_U8 *const kTimerProcessFuncs[7] = { // 0x809DE7 + ProcessTimer_Empty, + ProcessTimer_CeresStart, + ProcessTimer_MotherBrainStart, + ProcessTimer_InitialDelay, + ProcessTimer_MovementDelayed, + ProcessTimer_MovingIntoPlace, + j_ProcessTimer_Decrement, +}; + +uint8 ProcessTimer(void) { + return kTimerProcessFuncs[(uint16)(2 * (uint8)timer_status) >> 1](); +} + +uint8 ProcessTimer_CeresStart(void) { // 0x809E09 + ClearTimerRam(); + SetTimerMinutes(0x100); + timer_status = -32765; + return 0; +} + +uint8 ProcessTimer_Empty(void) { // 0x809E1A + return 0; +} + +uint8 ProcessTimer_MotherBrainStart(void) { // 0x809E1C + ClearTimerRam(); + SetTimerMinutes(0x300); + timer_status = -32765; + return 0; +} + +uint8 ProcessTimer_InitialDelay(void) { // 0x809E2F + LOBYTE(timer_x_pos) = timer_x_pos + 1; + if ((uint8)timer_x_pos >= 0x10u) + LOBYTE(timer_status) = timer_status + 1; + return 0; +} + +uint8 ProcessTimer_MovementDelayed(void) { // 0x809E41 + LOBYTE(timer_x_pos) = timer_x_pos + 1; + if ((uint8)timer_x_pos >= 0x60u) { + LOBYTE(timer_x_pos) = 0; + LOBYTE(timer_status) = timer_status + 1; + } + return ProcessTimer_Decrement(); +} + +uint8 ProcessTimer_MovingIntoPlace(void) { // 0x809E58 + int v0 = 0; + uint16 v1 = timer_x_pos + 224; + if ((uint16)(timer_x_pos + 224) >= 0xDC00u) { + v0 = 1; + v1 = -9216; + } + timer_x_pos = v1; + uint16 v2 = timer_y_pos - 193; + if ((uint16)(timer_y_pos - 193) < 0x3000u) { + ++v0; + v2 = 12288; + } + timer_y_pos = v2; + if (v0 == 2) + ++timer_status; + return j_ProcessTimer_Decrement(); +} + +uint8 j_ProcessTimer_Decrement(void) { // 0x809E89 + return ProcessTimer_Decrement(); +} + +void SetTimerMinutes(uint16 a) { // 0x809E8C + *(uint16 *)&timer_centiseconds = 0; + *(uint16 *)&timer_seconds = a; +} + +void ClearTimerRam(void) { // 0x809E93 + timer_x_pos = 0x8000; + timer_y_pos = 0x8000; + *(uint16 *)&timer_centiseconds = 0; + *(uint16 *)&timer_seconds = 0; + timer_status = 0; +} + +bool DecrementDecimal(uint8 *number, uint8 value) { + int result = (*number & 0xf) + (~value & 0xf) + 1; + if (result < 0x10) result = (result - 0x6) & ((result - 0x6 < 0) ? 0xf : 0x1f); + result = (*number & 0xf0) + (~value & 0xf0) + result; + if (result < 0x100) result -= 0x60; + *number = result; + return result < 0x100; +} + +uint8 ProcessTimer_Decrement(void) { // 0x809EA9 + static const uint8 kTimerCentisecondDecrements[128] = { + 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, + 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, + 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, + 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, + 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, + 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, + 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, + 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, + }; + if (DecrementDecimal(&timer_centiseconds, kTimerCentisecondDecrements[nmi_frame_counter_word & 0x7f])) { + if (DecrementDecimal(&timer_seconds, 1)) { + if (DecrementDecimal(&timer_minutes, 1)) { + timer_centiseconds = 0; + timer_seconds = 0; + timer_minutes = 0; + } else { + timer_seconds = 0x59; + } + } + } + return (timer_centiseconds | timer_seconds | timer_minutes) == 0; + +} + +void DrawTimer(void) { // 0x809F6C + DrawTimerSpritemap(0, addr_word_80A060); + DrawTwoTimerDigits(*(uint16 *)&timer_minutes, 0xFFE4u); + DrawTwoTimerDigits(*(uint16 *)&timer_seconds, 0xFFFCu); + DrawTwoTimerDigits(*(uint16 *)&timer_centiseconds, 0x14u); +} + +#define kTimerDigitsSpritemapPtr ((uint16*)RomPtr(0x809fd4)) + +void DrawTwoTimerDigits(uint16 a, uint16 k) { // 0x809F95 + char v2; + + v2 = a; + DrawTimerSpritemap(k, kTimerDigitsSpritemapPtr[(uint16)((uint8)(a & 0xF0) >> 3) >> 1]); + DrawTimerSpritemap(k + 8, kTimerDigitsSpritemapPtr[v2 & 0xF]); +} + +void DrawTimerSpritemap(uint16 a, uint16 j) { // 0x809FB3 + R20_ = a + HIBYTE(timer_x_pos); + R18_ = HIBYTE(timer_y_pos); + R22_ = 2560; + DrawSpritemap(0x80, j); +} + +CoroutineRet StartGameplay_Async(void) { // 0x80A07B + COROUTINE_BEGIN(coroutine_state_2, 0) + WriteRegWord(MDMAEN, 0); + scrolling_finished_hook = 0; + music_data_index = 0; + music_track_index = 0; + timer_status = 0; + ResetSoundQueues(); + debug_disable_sounds = -1; + DisableNMI(); + DisableIrqInterrupts(); + LoadDestinationRoomThings(); + COROUTINE_AWAIT(1, Play20FramesOfMusic_Async()); + ClearAnimtiles(); + WaitUntilEndOfVblankAndClearHdma(); + InitializeSpecialEffectsForNewRoom(); + ClearPLMs(); + ClearEnemyProjectiles(); + ClearPaletteFXObjects(); + UpdateBeamTilesAndPalette(); + LoadColorsForSpritesBeamsAndEnemies(); + LoadEnemies(); + LoadRoomMusic(); + COROUTINE_AWAIT(2, Play20FramesOfMusic_Async()); + UpdateMusicTrackIndex(); + NullFunc(); + ClearBG2Tilemap(); + LoadLevelDataAndOtherThings(); + LoadFXHeader(); + LoadLibraryBackground(); + CalculateLayer2Xpos(); + CalculateLayer2Ypos(); + bg2_x_scroll = layer2_x_pos; + bg2_y_scroll = layer2_y_pos; + CalculateBgScrolls(); + DisplayViewablePartOfRoom(); + EnableNMI(); + irqhandler_next_handler = (room_loading_irq_handler == 0) ? 4 : room_loading_irq_handler; + EnableIrqInterrupts(); + COROUTINE_AWAIT(3, Play20FramesOfMusic_Async()); + static const SpawnHardcodedPlmArgs unk_80A11E = { 0x08, 0x08, 0xb7eb }; + SpawnHardcodedPlm(&unk_80A11E); + door_transition_function = FUNC16(DoorTransition_FadeInScreenAndFinish); + COROUTINE_END(0); +} + +CoroutineRet Play20FramesOfMusic_Async(void) { // 0x80A12B + COROUTINE_BEGIN(coroutine_state_3, 0) + EnableNMI(); + for(my_counter = 0; my_counter != 20; my_counter++) { + HandleMusicQueue(); + COROUTINE_AWAIT(1, WaitForNMI_Async()); + } + DisableNMI(); + COROUTINE_END(0); +} + +void ResumeGameplay(void) { // 0x80A149 + WriteRegWord(MDMAEN, 0); + DisableNMI(); + DisableIrqInterrupts(); + LoadCRETilesTilesetTilesAndPalette(); + LoadLibraryBackground(); + DisplayViewablePartOfRoom(); + LoadRoomPlmGfx(); + EnableNMI(); + EnableIrqInterrupts(); +} + +void DisplayViewablePartOfRoom(void) { // 0x80A176 + int v1, v2, v3; + + v1 = (reg_BG1SC - reg_BG2SC) << 8; + size_of_bg2 = v1 & 0xF800; + CalculateBgScrollAndLayerPositionBlocks(); + v2 = 0; + do { + v3 = v2; + blocks_to_update_x_block = layer1_x_block; + blocks_to_update_y_block = layer1_y_block; + vram_blocks_to_update_x_block = bg1_x_block; + vram_blocks_to_update_y_block = bg1_y_block; + UploadLevelDataColumn(); + if (!(layer2_scroll_x & 1)) { + blocks_to_update_x_block = layer2_x_block; + blocks_to_update_y_block = layer2_y_block; + vram_blocks_to_update_x_block = bg2_x_block; + vram_blocks_to_update_y_block = bg2_y_block; + UploadBackgroundDataColumn(); + } + NMI_ProcessVramWriteQueue(); + ++layer1_x_block; + ++bg1_x_block; + ++layer2_x_block; + ++bg2_x_block; + ++v2; + } while (v3 != 16); +} + +void QueueClearingOfFxTilemap(void) { // 0x80A211 + for (int i = 3838; i >= 0; i -= 2) + *(uint16 *)((char *)ram4000.xray_tilemaps + (uint16)i) = 6222; + uint16 v1 = vram_write_queue_tail; + VramWriteEntry *v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 3840; + v2->src.addr = ADDR16_OF_RAM(ram4000); + *(uint16 *)&v2->src.bank = 126; + v2->vram_dst = addr_unk_605880; + vram_write_queue_tail = v1 + 7; +} + +void ClearBG2Tilemap(void) { // 0x80A23F + WriteRegWord(VMADDL, 0x4800u); + WriteRegWord(DMAP1, 0x1808u); + WriteRegWord(A1T1L, 0xA29Au); + WriteRegWord(A1B1, 0x80); + WriteRegWord(DAS1L, 0x800u); + WriteReg(VMAIN, 0); + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, 0x4800u); + WriteRegWord(DMAP1, 0x1908u); + WriteRegWord(A1T1L, 0xA29Au); + WriteRegWord(A1B1, 0x80); + WriteRegWord(DAS1L, 0x800u); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 2u); +} + +void ClearFXTilemap(void) { // 0x80A29C + WriteRegWord(VMADDL, 0x5880u); + WriteRegWord(DMAP1, 0x1808u); + WriteRegWord(A1T1L, 0xA2F7u); + WriteRegWord(A1B1, 0x80); + WriteRegWord(DAS1L, 0x780u); + WriteReg(VMAIN, 0); + WriteReg(MDMAEN, 2u); + WriteRegWord(VMADDL, 0x5880u); + WriteRegWord(DMAP1, 0x1908u); + WriteRegWord(A1T1L, 0xA2F8u); + WriteRegWord(A1B1, 0x80); + WriteRegWord(DAS1L, 0x780u); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 2u); +} + +uint8 CalculateLayer2Xpos(void) { // 0x80A2F9 + if (!layer2_scroll_x) { + layer2_x_pos = layer1_x_pos; + return 0; + } + if (layer2_scroll_x != 1) { + int t = layer2_scroll_x & 0xFE; + HIBYTE(temp933) = 0; + LOBYTE(temp933) = t * LOBYTE(layer1_x_pos) >> 8; + layer2_x_pos = t * HIBYTE(layer1_x_pos) + temp933; + return 0; + } + return 1; +} + +uint8 CalculateLayer2Ypos(void) { // 0x80A33A + if (!layer2_scroll_y) { + layer2_y_pos = layer1_y_pos; + return 0; + } + if (layer2_scroll_y != 1) { + int t = layer2_scroll_y & 0xFE; + HIBYTE(temp933) = 0; + LOBYTE(temp933) = t * (uint8)layer1_y_pos >> 8; + layer2_y_pos = t * HIBYTE(layer1_y_pos) + temp933; + return 0; + } + return 1; +} + +void CalculateBgScrolls(void) { // 0x80A37B + reg_BG1HOFS = bg1_x_offset + layer1_x_pos; + reg_BG1VOFS = bg1_y_offset + layer1_y_pos; + reg_BG2HOFS = bg2_x_scroll + layer2_x_pos; + reg_BG2VOFS = bg2_y_scroll + layer2_y_pos; +} + +void UpdateScrollVarsUpdateMap(void) { // 0x80A3A0 + CalculateBgScrolls(); + UpdateBgGraphicsWhenScrolling(); +} + +void CalculateLayer2PosAndScrollsWhenScrolling(void) { // 0x80A3AB + if (!time_is_frozen_flag) { + reg_BG1HOFS = bg1_x_offset + layer1_x_pos; + reg_BG1VOFS = bg1_y_offset + layer1_y_pos; + if (!CalculateLayer2Xpos()) + reg_BG2HOFS = bg2_x_scroll + layer2_x_pos; + if (!CalculateLayer2Ypos()) + reg_BG2VOFS = bg2_y_scroll + layer2_y_pos; + UpdateBgGraphicsWhenScrolling(); + } +} + +void UpdateBgGraphicsWhenScrolling(void) { // 0x80A3DF + CalculateBgScrollAndLayerPositionBlocks(); + int v0 = 0; + bool v1 = (int16)(layer1_x_block - previous_layer1_x_block) < 0; + if (layer1_x_block != previous_layer1_x_block) { + previous_layer1_x_block = layer1_x_block; + if (!v1) + v0 = 16; + blocks_to_update_x_block = layer1_x_block + v0; + vram_blocks_to_update_x_block = bg1_x_block + v0; + blocks_to_update_y_block = layer1_y_block; + vram_blocks_to_update_y_block = bg1_y_block; + UploadLevelDataColumn(); + } + if (!(layer2_scroll_x & 1)) { + int v2 = 0; + bool v3 = (int16)(layer2_x_block - previous_layer2_x_block) < 0; + if (layer2_x_block != previous_layer2_x_block) { + previous_layer2_x_block = layer2_x_block; + if (!v3) + v2 = 16; + blocks_to_update_x_block = layer2_x_block + v2; + vram_blocks_to_update_x_block = bg2_x_block + v2; + blocks_to_update_y_block = layer2_y_block; + vram_blocks_to_update_y_block = bg2_y_block; + UploadBackgroundDataColumn(); + } + } + int v4 = 1; + bool v5 = (int16)(layer1_y_block - previous_layer1_y_block) < 0; + if (layer1_y_block != previous_layer1_y_block) { + previous_layer1_y_block = layer1_y_block; + if (!v5) + v4 = 15; + blocks_to_update_y_block = layer1_y_block + v4; + vram_blocks_to_update_y_block = bg1_y_block + v4; + blocks_to_update_x_block = layer1_x_block; + vram_blocks_to_update_x_block = bg1_x_block; + UpdateLevelDataRow(); + } + if (!(layer2_scroll_y & 1)) { + int v6 = 1; + bool v7 = (int16)(layer2_y_block - previous_layer2_y_block) < 0; + if (layer2_y_block != previous_layer2_y_block) { + previous_layer2_y_block = layer2_y_block; + if (!v7) + v6 = 15; + blocks_to_update_y_block = layer2_y_block + v6; + vram_blocks_to_update_y_block = bg2_y_block + v6; + blocks_to_update_x_block = layer2_x_block; + vram_blocks_to_update_x_block = bg2_x_block; + UpdateBackgroundDataRow(); + } + } +} + +void CalculateBgScrollAndLayerPositionBlocks(void) { // 0x80A4BB + bg1_x_block = reg_BG1HOFS >> 4; + bg2_x_block = reg_BG2HOFS >> 4; + uint16 v0 = layer1_x_pos >> 4; + if (((layer1_x_pos >> 4) & 0x800) != 0) + v0 |= 0xF000u; + layer1_x_block = v0; + uint16 v1 = layer2_x_pos >> 4; + if (((layer2_x_pos >> 4) & 0x800) != 0) + v1 |= 0xF000u; + layer2_x_block = v1; + bg1_y_block = reg_BG1VOFS >> 4; + bg2_y_block = reg_BG2VOFS >> 4; + uint16 v2 = layer1_y_pos >> 4; + if (((layer1_y_pos >> 4) & 0x800) != 0) + v2 |= 0xF000u; + layer1_y_block = v2; + uint16 v3 = layer2_y_pos >> 4; + if (((layer2_y_pos >> 4) & 0x800) != 0) + v3 |= 0xF000u; + layer2_y_block = v3; +} + +void HandleAutoscrolling_X(void) { // 0x80A528 + int16 v1; + int16 v3; + int16 v6; + uint16 v4; + + if (!time_is_frozen_flag) { + loopcounter = layer1_x_pos; + if ((layer1_x_pos & 0x8000u) != 0) + layer1_x_pos = 0; + uint16 v0 = swap16(room_width_in_scrolls - 1); + if (v0 < layer1_x_pos) + layer1_x_pos = v0; + v1 = HIBYTE(layer1_x_pos); + uint16 v2 = Mult8x8((uint16)(layer1_y_pos + 128) >> 8, room_width_in_scrolls) + v1; + if (scrolls[v2]) { + if (scrolls[(uint16)(v2 + 1)]) + return; + temp933 = layer1_x_pos & 0xFF00; + uint16 v5 = (__PAIR32__(loopcounter - absolute_moved_last_frame_x, loopcounter) - (absolute_moved_last_frame_x | 0x20000)) >> 16; + + if ((int16)(v5 - (layer1_x_pos & 0xFF00)) < 0) { + v4 = temp933; + } else { + loopcounter = v5; + v6 = HIBYTE(loopcounter); + if (scrolls[(uint16)(Mult8x8((uint16)(layer1_y_pos + 128) >> 8, room_width_in_scrolls) + v6)]) + v4 = loopcounter; + else + v4 = (loopcounter & 0xFF00) + 256; + } + } else { + temp933 = (layer1_x_pos & 0xFF00) + 256; + if ((uint16)(absolute_moved_last_frame_x + + loopcounter + + 2) >= temp933) { + v4 = temp933; + } else { + loopcounter += absolute_moved_last_frame_x + 2; + v3 = (uint8)(HIBYTE(loopcounter) + 1); + if (scrolls[(uint16)(Mult8x8((uint16)(layer1_y_pos + 128) >> 8, room_width_in_scrolls) + v3)]) + v4 = loopcounter; + else + v4 = loopcounter & 0xFF00; + } + } + layer1_x_pos = v4; + } +} + +void HandleScrollingWhenTriggeringScrollRight(void) { // 0x80A641 + int16 v1; + + loopcounter = layer1_x_pos; + if ((int16)(ideal_layer1_xpos - layer1_x_pos) < 0) { + layer1_x_pos = ideal_layer1_xpos; + layer1_x_subpos = 0; + } + uint16 v0 = swap16(room_width_in_scrolls - 1); + if (v0 >= layer1_x_pos) { + v1 = HIBYTE(layer1_x_pos); + uint16 RegWord = Mult8x8((uint16)(layer1_y_pos + 128) >> 8, room_width_in_scrolls); + if (!scrolls[(uint16)(RegWord + 1 + v1)]) { + temp933 = layer1_x_pos & 0xFF00; + uint16 v4 = (__PAIR32__(loopcounter - absolute_moved_last_frame_x, loopcounter) - (absolute_moved_last_frame_x | 0x20000)) >> 16; + if ((int16)(v4 - (layer1_x_pos & 0xFF00)) < 0) + v4 = temp933; + layer1_x_pos = v4; + } + } else { + layer1_x_pos = v0; + } +} + +void HandleScrollingWhenTriggeringScrollLeft(void) { // 0x80A6BB + int16 v0; + + loopcounter = layer1_x_pos; + if ((int16)(layer1_x_pos - ideal_layer1_xpos) < 0) { + layer1_x_pos = ideal_layer1_xpos; + layer1_x_subpos = 0; + } + if ((layer1_x_pos & 0x8000u) == 0) { + v0 = HIBYTE(layer1_x_pos); + uint16 prod = Mult8x8((uint16)(layer1_y_pos + 128) >> 8, room_width_in_scrolls); + if (!scrolls[(uint16)(prod + v0)]) { + temp933 = (layer1_x_pos & 0xFF00) + 256; + uint16 v1 = absolute_moved_last_frame_x + loopcounter + 2; + if (v1 >= temp933) + v1 = temp933; + layer1_x_pos = v1; + } + } else { + layer1_x_pos = 0; + } +} + +void HandleAutoscrolling_Y(void) { // 0x80A731 + int16 v1; + int16 v2; + int16 v4; + int16 v7; + int16 v10; + uint16 v8; + + if (!time_is_frozen_flag) { + uint16 v0 = 0; + v1 = (uint16)(layer1_x_pos + 128) >> 8; + R20_ = Mult8x8(HIBYTE(layer1_y_pos), room_width_in_scrolls) + v1; + if (scrolls[R20_] != 1) + v0 = 31; + temp933 = v0; + loopcounter = layer1_y_pos; + if ((layer1_y_pos & 0x8000u) != 0) + layer1_y_pos = 0; + LOBYTE(v2) = (uint16)(room_height_in_scrolls - 1) >> 8; + HIBYTE(v2) = room_height_in_scrolls - 1; + uint16 v3 = temp933 + v2; + if (v3 < layer1_y_pos) + layer1_y_pos = v3; + v4 = (uint16)(layer1_x_pos + 128) >> 8; + uint16 v5 = Mult8x8(HIBYTE(layer1_y_pos), room_width_in_scrolls) + v4; + if (!scrolls[v5]) { + x_block_of_vram_blocks_to_update = (layer1_y_pos & 0xFF00) + 256; + uint16 v6 = absolute_moved_last_frame_y + loopcounter + 2; + if (v6 >= x_block_of_vram_blocks_to_update) { + v8 = x_block_of_vram_blocks_to_update; + } else { + loopcounter += absolute_moved_last_frame_y + 2; + v7 = (uint16)(layer1_x_pos + 128) >> 8; + uint16 prod = Mult8x8(HIBYTE(v6) + 1, room_width_in_scrolls); + if (scrolls[(uint16)(prod + v7)]) + v8 = loopcounter; + else + v8 = loopcounter & 0xFF00; + } + layer1_y_pos = v8; + return; + } + if (!scrolls[(uint16)(room_width_in_scrolls + v5)]) { + tmp_vram_base_addr = temp933 + (layer1_y_pos & 0xFF00); + if (tmp_vram_base_addr < layer1_y_pos) { + uint16 v9 = (__PAIR32__(loopcounter - absolute_moved_last_frame_y, loopcounter) - (absolute_moved_last_frame_y | 0x20000)) >> 16; + if ((int16)(v9 - tmp_vram_base_addr) < 0) { + v8 = tmp_vram_base_addr; + } else { + loopcounter = v9; + uint16 prod = Mult8x8(HIBYTE(v9), room_width_in_scrolls); + v10 = (uint16)(layer1_x_pos + 128) >> 8; + if (scrolls[(uint16)(prod + v10)]) + v8 = loopcounter; + else + v8 = (loopcounter & 0xFF00) + 256; + } + layer1_y_pos = v8; + return; + } + } + } +} + +void HandleScrollingWhenTriggeringScrollDown(void) { // 0x80A893 + loopcounter = layer1_y_pos; + int v0 = 0; + uint16 prod = Mult8x8(HIBYTE(layer1_y_pos), room_width_in_scrolls); + uint16 v1 = (uint16)(layer1_x_pos + 128) >> 8; + R20_ = prod + v1; + if (scrolls[R20_] != 1) + v0 = 31; + temp933 = v0; + if ((int16)(ideal_layer1_ypos - layer1_y_pos) < 0) { + layer1_y_pos = ideal_layer1_ypos; + layer1_y_subpos = 0; + } + uint16 v2 = swap16(room_height_in_scrolls - 1); + tmp_vram_base_addr = temp933 + v2; + if ((uint16)(temp933 + v2) < layer1_y_pos + || !scrolls[(uint16)(room_width_in_scrolls + R20_)] + && (tmp_vram_base_addr = temp933 + (layer1_y_pos & 0xFF00), tmp_vram_base_addr < layer1_y_pos)) { + uint16 v3 = (__PAIR32__(loopcounter - absolute_moved_last_frame_y, loopcounter) - (absolute_moved_last_frame_y | 0x20000)) >> 16; + if ((int16)(v3 - tmp_vram_base_addr) < 0) + v3 = tmp_vram_base_addr; + layer1_y_pos = v3; + } +} + +void HandleScrollingWhenTriggeringScrollUp(void) { // 0x80A936 + int16 v0; + + loopcounter = layer1_y_pos; + if ((int16)(layer1_y_pos - ideal_layer1_ypos) < 0) { + layer1_y_pos = ideal_layer1_ypos; + layer1_y_subpos = 0; + } + if ((layer1_y_pos & 0x8000u) == 0) { + uint16 prod = Mult8x8(HIBYTE(layer1_y_pos), room_width_in_scrolls); + v0 = (uint16)(layer1_x_pos + 128) >> 8; + if (!scrolls[(uint16)(prod + v0)]) { + temp933 = (layer1_y_pos & 0xFF00) + 256; + uint16 v1 = absolute_moved_last_frame_y + loopcounter + 2; + if (v1 >= temp933) + v1 = temp933; + layer1_y_pos = v1; + } + } else { + layer1_y_pos = 0; + } +} + +void DebugScrollPosSaveLoad(void) { // 0x80A9AC + if ((joypad2_new_keys & 0x40) != 0) + ++debug_saveload_scrollpos_toggle; + if (debug_saveload_scrollpos_toggle & 1) { + layer1_x_pos = debug_saved_xscroll; + layer1_y_pos = debug_saved_yscroll; + } else { + debug_saved_xscroll = layer1_x_pos; + debug_saved_yscroll = layer1_y_pos; + } +} + +void UploadBackgroundDataColumn(void) { // 0x80A9D6 + UpdateLevelOrBackgroundDataColumn(0x1c); +} + +void UploadLevelDataColumn(void) { // 0x80A9DB + UpdateLevelOrBackgroundDataColumn(0); +} + +void UpdateLevelOrBackgroundDataColumn(uint16 k) { // 0x80A9DE + if (!irq_enable_mode7) { + uint16 prod = Mult8x8(blocks_to_update_y_block, room_width_in_blocks); + uint16 v1 = blocks_to_update_x_block; + uint16 v2 = 2 * (prod + v1) + 2; + if (k) + v2 += 0x9600; + copywithflip_src.addr = v2; + copywithflip_src.bank = 127; + uint16 v3 = (4 * (uint8)vram_blocks_to_update_y_block) & 0x3C; + *(uint16 *)((char *)&bg1_update_col_wrapped_size + k) = v3; + *(uint16 *)((char *)&bg1_update_col_unwrapped_size + k) = (v3 ^ 0x3F) + 1; + prod = Mult8x8(vram_blocks_to_update_y_block & 0xF, 0x40u); + x_block_of_vram_blocks_to_update = vram_blocks_to_update_x_block & 0x1F; + uint16 v4 = 2 * x_block_of_vram_blocks_to_update; + temp933 = prod + v4; + uint16 v5 = addr_unk_605000; + if (x_block_of_vram_blocks_to_update >= 0x10u) + v5 = addr_unk_6053E0; + if (k) + v5 -= size_of_bg2; + tmp_vram_base_addr = v5; + *(uint16 *)((char *)&bg1_update_col_unwrapped_dst + k) = temp933 + v5; + *(uint16 *)((char *)&bg1_update_col_wrapped_dst + k) = x_block_of_vram_blocks_to_update + + x_block_of_vram_blocks_to_update + + tmp_vram_base_addr; + uint16 v6 = ADDR16_OF_RAM(*bg1_column_update_tilemap_left_halves); + uint16 v7 = 0; + if (k) { + v6 = ADDR16_OF_RAM(*bg2_column_update_tilemap_left_halves); + v7 = 264; + } + uint16 v8 = *(uint16 *)((char *)&bg1_update_col_unwrapped_size + k) + v6; + *(uint16 *)((char *)&bg1_update_col_wrapped_left_src + k) = v8; + *(uint16 *)((char *)&bg1_update_col_wrapped_right_src + k) = v8 + 64; + tmp_vram_base_addr = v7; + uint16 t2 = k; + uint16 v9 = 0; + loopcounter = 16; + do { + tmp_block_to_update = *(uint16 *)IndirPtr(©withflip_src, v9); + uint16 v10 = tmp_block_to_update & 0x3FF; + uint16 v17 = v9; + uint16 v11 = tmp_vram_base_addr; + uint16 v12 = tmp_block_to_update & 0xC00; + if ((tmp_block_to_update & 0xC00) != 0) { + if (v12 == 1024) { + uint16 v14 = tmp_vram_base_addr >> 1; + bg1_column_update_tilemap_left_halves[v14] = tile_table.tables[v10].top_right ^ 0x4000; + bg1_column_update_tilemap_right_halves[v14] = tile_table.tables[v10].top_left ^ 0x4000; + bg1_column_update_tilemap_left_halves[v14 + 1] = tile_table.tables[v10].bottom_right ^ 0x4000; + bg1_column_update_tilemap_right_halves[v14 + 1] = tile_table.tables[v10].bottom_left ^ 0x4000; + } else { + uint16 v15 = tmp_vram_base_addr >> 1; + uint16 v16; + if (v12 == 2048) { + bg1_column_update_tilemap_left_halves[v15] = tile_table.tables[v10].bottom_left ^ 0x8000; + bg1_column_update_tilemap_right_halves[v15] = tile_table.tables[v10].bottom_right ^ 0x8000; + bg1_column_update_tilemap_left_halves[v15 + 1] = tile_table.tables[v10].top_left ^ 0x8000; + v16 = tile_table.tables[v10].top_right ^ 0x8000; + } else { + bg1_column_update_tilemap_left_halves[v15] = tile_table.tables[v10].bottom_right ^ 0xC000; + bg1_column_update_tilemap_right_halves[v15] = tile_table.tables[v10].bottom_left ^ 0xC000; + bg1_column_update_tilemap_left_halves[v15 + 1] = tile_table.tables[v10].top_right ^ 0xC000; + v16 = tile_table.tables[v10].top_left ^ 0xC000; + } + bg1_column_update_tilemap_right_halves[v15 + 1] = v16; + } + } else { + uint16 v13 = tmp_vram_base_addr >> 1; + bg1_column_update_tilemap_left_halves[v13] = tile_table.tables[v10].top_left; + bg1_column_update_tilemap_right_halves[v13] = tile_table.tables[v10].top_right; + bg1_column_update_tilemap_left_halves[v13 + 1] = tile_table.tables[v10].bottom_left; + bg1_column_update_tilemap_right_halves[v13 + 1] = tile_table.tables[v10].bottom_right; + } + tmp_vram_base_addr = v11 + 4; + v9 = room_width_in_blocks + room_width_in_blocks + v17; + --loopcounter; + } while (loopcounter); + ++ *(uint16 *)((char *)&bg1_update_col_enable + t2); + } +} + +void UpdateBackgroundDataRow(void) { // 0x80AB70 + UpdateLevelOrBackgroundDataRow(0x1c); +} + +void UpdateLevelDataRow(void) { // 0x80AB75 + UpdateLevelOrBackgroundDataRow(0); +} + +void UpdateLevelOrBackgroundDataRow(uint16 v0) { // 0x80AB78 + if (!irq_enable_mode7) { + uint16 prod = Mult8x8(blocks_to_update_y_block, room_width_in_blocks); + uint16 v1 = blocks_to_update_x_block; + uint16 v2 = 2 * (prod + v1) + 2; + if (v0) + v2 -= 27136; + copywithflip_src.addr = v2; + copywithflip_src.bank = 127; + temp933 = vram_blocks_to_update_x_block & 0xF; + *(uint16 *)((char *)&bg1_update_row_unwrapped_size + v0) = 4 * (16 - temp933); + *(uint16 *)((char *)&bg1_update_row_wrapped_size + v0) = 4 * (temp933 + 1); + prod = Mult8x8(vram_blocks_to_update_y_block & 0xF, 0x40u); + x_block_of_vram_blocks_to_update = vram_blocks_to_update_x_block & 0x1F; + uint16 v3 = 2 * x_block_of_vram_blocks_to_update; + temp933 = prod + v3; + tmp_vram_base_addr = addr_unk_605400; + uint16 v4 = addr_unk_605000; + if (x_block_of_vram_blocks_to_update >= 0x10u) { + tmp_vram_base_addr = addr_unk_605000; + v4 = addr_unk_6053E0; + } + if (v0) + v4 -= size_of_bg2; + *(uint16 *)((char *)&bg1_update_row_unwrapped_dst + v0) = temp933 + v4; + uint16 v5 = tmp_vram_base_addr; + if (v0) + v5 = tmp_vram_base_addr - size_of_bg2; + *(uint16 *)((char *)&bg1_update_row_wrapped_dst + v0) = prod + v5; + uint16 v6 = ADDR16_OF_RAM(*bg1_column_update_tilemap_top_halves); + uint16 v7 = 0; + if (v0) { + v6 = ADDR16_OF_RAM(*bg2_column_update_tilemap_top_halves); + v7 = 264; + } + uint16 v8 = *(uint16 *)((char *)&bg1_update_row_unwrapped_size + v0) + v6; + *(uint16 *)((char *)&bg1_update_row_wrapped_top_src + v0) = v8; + *(uint16 *)((char *)&bg1_update_row_wrapped_bottom_src + v0) = v8 + 68; + tmp_vram_base_addr = v7; + uint16 t2 = v0; + uint16 v9 = 0; + loopcounter = 17; + do { + tmp_block_to_update = *(uint16 *)IndirPtr(©withflip_src, v9); + uint16 v10 = tmp_block_to_update & 0x3FF; + uint16 v17 = v9; + uint16 v11 = tmp_vram_base_addr; + uint16 v12 = tmp_block_to_update & 0xC00; + if ((tmp_block_to_update & 0xC00) != 0) { + if (v12 == 1024) { + uint16 v14 = tmp_vram_base_addr >> 1; + bg1_column_update_tilemap_top_halves[v14] = tile_table.tables[v10].top_right ^ 0x4000; + bg1_column_update_tilemap_top_halves[v14 + 1] = tile_table.tables[v10].top_left ^ 0x4000; + bg1_column_update_tilemap_bottom_halves[v14] = tile_table.tables[v10].bottom_right ^ 0x4000; + bg1_column_update_tilemap_bottom_halves[v14 + 1] = tile_table.tables[v10].bottom_left ^ 0x4000; + } else { + uint16 v15 = tmp_vram_base_addr >> 1; + uint16 v16; + if (v12 == 2048) { + bg1_column_update_tilemap_top_halves[v15] = tile_table.tables[v10].bottom_left ^ 0x8000; + bg1_column_update_tilemap_top_halves[v15 + 1] = tile_table.tables[v10].bottom_right ^ 0x8000; + bg1_column_update_tilemap_bottom_halves[v15] = tile_table.tables[v10].top_left ^ 0x8000; + v16 = tile_table.tables[v10].top_right ^ 0x8000; + } else { + bg1_column_update_tilemap_top_halves[v15] = tile_table.tables[v10].bottom_right ^ 0xC000; + bg1_column_update_tilemap_top_halves[v15 + 1] = tile_table.tables[v10].bottom_left ^ 0xC000; + bg1_column_update_tilemap_bottom_halves[v15] = tile_table.tables[v10].top_right ^ 0xC000; + v16 = tile_table.tables[v10].top_left ^ 0xC000; + } + bg1_column_update_tilemap_bottom_halves[v15 + 1] = v16; + } + } else { + uint16 v13 = tmp_vram_base_addr >> 1; + bg1_column_update_tilemap_top_halves[v13] = tile_table.tables[v10].top_left; + bg1_column_update_tilemap_top_halves[v13 + 1] = tile_table.tables[v10].top_right; + bg1_column_update_tilemap_bottom_halves[v13] = tile_table.tables[v10].bottom_left; + bg1_column_update_tilemap_bottom_halves[v13 + 1] = tile_table.tables[v10].bottom_right; + } + tmp_vram_base_addr = v11 + 4; + v9 = v17 + 2; + --loopcounter; + } while (loopcounter); + ++ *(uint16 *)((char *)&bg1_update_row_enable + t2); + } +} + +void FixDoorsMovingUp(void) { // 0x80AD1D + door_transition_frame_counter = 0; + CalculateBgScrollAndLayerPositionBlocks(); + UpdatePreviousLayerBlocks(); + ++previous_layer1_y_block; + ++previous_layer2_y_block; + DoorTransition_Up(); +} + +static Func_V *const kDoorTransitionSetupFuncs[4] = { // 0x80AD30 + DoorTransitionScrollingSetup_Right, + DoorTransitionScrollingSetup_Left, + DoorTransitionScrollingSetup_Down, + DoorTransitionScrollingSetup_Up, +}; + +void DoorTransitionScrollingSetup(void) { + layer1_x_pos = door_destination_x_pos; + layer1_y_pos = door_destination_y_pos; + kDoorTransitionSetupFuncs[door_direction & 3](); +} + +void DoorTransitionScrollingSetup_Right(void) { // 0x80AD4A + CalculateLayer2Xpos(); + layer2_x_pos -= 256; + CalculateLayer2Ypos(); + layer1_x_pos -= 256; + UpdateBgScrollOffsets(); + CalculateBgScrollAndLayerPositionBlocks(); + UpdatePreviousLayerBlocks(); + --previous_layer1_x_block; + --previous_layer2_x_block; + DoorTransition_Right(); +} + +void DoorTransitionScrollingSetup_Left(void) { // 0x80AD74 + CalculateLayer2Xpos(); + layer2_x_pos += 256; + CalculateLayer2Ypos(); + layer1_x_pos += 256; + UpdateBgScrollOffsets(); + CalculateBgScrollAndLayerPositionBlocks(); + UpdatePreviousLayerBlocks(); + ++previous_layer1_x_block; + ++previous_layer2_x_block; + DoorTransition_Left(); +} + +void DoorTransitionScrollingSetup_Down(void) { // 0x80AD9E + CalculateLayer2Xpos(); + CalculateLayer2Ypos(); + layer2_y_pos -= 224; + layer1_y_pos -= 224; + UpdateBgScrollOffsets(); + CalculateBgScrollAndLayerPositionBlocks(); + UpdatePreviousLayerBlocks(); + --previous_layer1_y_block; + --previous_layer2_y_block; + DoorTransition_Down(); +} + +void DoorTransitionScrollingSetup_Up(void) { // 0x80ADC8 + CalculateLayer2Xpos(); + uint16 v1 = layer1_y_pos; + layer1_y_pos += 31; + CalculateLayer2Ypos(); + layer2_y_pos += 224; + layer1_y_pos = v1 + 256; + UpdateBgScrollOffsets(); + door_destination_y_pos += 32; + CalculateBgScrollAndLayerPositionBlocks(); + UpdatePreviousLayerBlocks(); + ++previous_layer1_y_block; + ++previous_layer2_y_block; + --layer1_y_pos; + DoorTransition_Up(); +} + +void UpdatePreviousLayerBlocks(void) { // 0x80AE10 + previous_layer1_x_block = layer1_x_block; + previous_layer2_x_block = layer2_x_block; + previous_layer1_y_block = layer1_y_block; + previous_layer2_y_block = layer2_y_block; +} + +void UpdateBgScrollOffsets(void) { // 0x80AE29 + bg1_x_offset = reg_BG1HOFS - layer1_x_pos; + bg1_y_offset = reg_BG1VOFS - layer1_y_pos; + bg2_x_scroll = reg_BG2HOFS - layer1_x_pos; + bg2_y_scroll = reg_BG2VOFS - layer1_y_pos; +} + +static Func_U8 *const kDoorTransitionFuncs[4] = { + DoorTransition_Right, + DoorTransition_Left, + DoorTransition_Down, + DoorTransition_Up, +}; + +void Irq_FollowDoorTransition(void) { + if (kDoorTransitionFuncs[door_direction & 3]()) { + layer1_x_pos = door_destination_x_pos; + layer1_y_pos = door_destination_y_pos; + door_transition_flag |= 0x8000u; + } +} + +uint8 DoorTransition_Right(void) { // 0x80AE7E + uint16 v2 = door_transition_frame_counter; + uint16 v0 = (__PAIR32__(samus_door_transition_speed, samus_door_transition_subspeed) + + __PAIR32__(samus_x_pos, samus_x_subpos)) >> 16; + samus_x_subpos += samus_door_transition_subspeed; + samus_x_pos = v0; + samus_prev_x_pos = v0; + layer1_x_pos += 4; + layer2_x_pos += 4; + UpdateScrollVarsUpdateMap(); + door_transition_frame_counter = v2 + 1; + if (v2 != 63) + return 0; + UpdateScrollVarsUpdateMap(); + return 1; +} + +uint8 DoorTransition_Left(void) { // 0x80AEC2 + uint16 v2 = door_transition_frame_counter; + uint16 v0 = (__PAIR32__(samus_x_pos, samus_x_subpos) - __PAIR32__( + samus_door_transition_speed, + samus_door_transition_subspeed)) >> 16; + samus_x_subpos -= samus_door_transition_subspeed; + samus_x_pos = v0; + samus_prev_x_pos = v0; + layer1_x_pos -= 4; + layer2_x_pos -= 4; + UpdateScrollVarsUpdateMap(); + door_transition_frame_counter = v2 + 1; + return v2 == 63; +} + +uint8 DoorTransition_Down(void) { // 0x80AF02 + uint16 v6 = door_transition_frame_counter; + if (door_transition_frame_counter) { + if (door_transition_frame_counter < 0x39u) { + uint16 v0 = (__PAIR32__(samus_door_transition_speed, samus_door_transition_subspeed) + + __PAIR32__(samus_y_pos, samus_y_subpos)) >> 16; + samus_y_subpos += samus_door_transition_subspeed; + samus_y_pos = v0; + samus_prev_y_pos = v0; + layer1_y_pos += 4; + layer2_y_pos += 4; + UpdateScrollVarsUpdateMap(); + } + } else { + uint16 v5 = reg_BG1VOFS; + uint16 v4 = reg_BG2VOFS; + uint16 v3 = layer1_y_pos; + layer1_y_pos -= 15; + uint16 v2 = layer2_y_pos; + layer2_y_pos -= 15; + CalculateBgScrollAndLayerPositionBlocks(); + UpdatePreviousLayerBlocks(); + --previous_layer1_y_block; + --previous_layer2_y_block; + UpdateScrollVarsUpdateMap(); + layer2_y_pos = v2; + layer1_y_pos = v3; + reg_BG2VOFS = v4; + reg_BG1VOFS = v5; + } + door_transition_frame_counter = v6 + 1; + if ((uint16)(v6 + 1) < 0x39u) + return 0; + UpdateScrollVarsUpdateMap(); + return 1; +} + +uint8 DoorTransition_Up(void) { // 0x80AF89 + uint16 v6 = door_transition_frame_counter; + if (door_transition_frame_counter) { + uint16 v0 = (__PAIR32__(samus_y_pos, samus_y_subpos) + - __PAIR32__(samus_door_transition_speed, samus_door_transition_subspeed)) >> 16; + samus_y_subpos -= samus_door_transition_subspeed; + samus_y_pos = v0; + samus_prev_y_pos = v0; + layer1_y_pos -= 4; + layer2_y_pos -= 4; + if (door_transition_frame_counter >= 5u) { + UpdateScrollVarsUpdateMap(); + } else { + reg_BG1HOFS = bg1_x_offset + layer1_x_pos; + reg_BG1VOFS = bg1_y_offset + layer1_y_pos; + reg_BG2HOFS = bg2_x_scroll + layer2_x_pos; + reg_BG2VOFS = bg2_y_scroll + layer2_y_pos; + } + } else { + uint16 v5 = reg_BG1VOFS; + uint16 v4 = reg_BG2VOFS; + uint16 v3 = layer1_y_pos; + layer1_y_pos -= 16; + uint16 v2 = layer2_y_pos; + layer2_y_pos -= 16; + CalculateBgScrollAndLayerPositionBlocks(); + UpdatePreviousLayerBlocks(); + ++previous_layer1_y_block; + ++previous_layer2_y_block; + UpdateScrollVarsUpdateMap(); + layer2_y_pos = v2; + layer1_y_pos = v3; + reg_BG2VOFS = v4; + reg_BG1VOFS = v5; + } + door_transition_frame_counter = v6 + 1; + return v6 == 56; +} + +void ConfigureMode7RotationMatrix(void) { // 0x80B0C2 + if (irq_enable_mode7) { + if ((nmi_frame_counter_word & 7) == 0) { + reg_M7B = kSinCosTable8bit_Sext[((uint16)(2 * (uint8)mode7_rotation_angle) >> 1) + 64]; + reg_M7C = -reg_M7B; + reg_M7A = kSinCosTable8bit_Sext[((uint16)(2 * (uint8)(mode7_rotation_angle + 64)) >> 1) + 64]; + reg_M7D = reg_M7A; + ++mode7_rotation_angle; + } + } +} + +uint8 DecompNextByte(void) { + uint8 v2 = *RomPtrWithBank(decompress_src.bank, decompress_src.addr); + if (decompress_src.addr++ == 0xFFFF) { + decompress_src.addr = 0x8000; + decompress_src.bank++; + } + return v2; +} + +void DecompressToMem(void) { // 0x80B119 + HIBYTE(decompress_want_xor) = 0; + uint16 dst_pos = 0; + while (1) { + int len; + uint8 v2 = DecompNextByte(), cmd, b; + decompress_last_byte = v2; + if (v2 == 0xFF) + break; + if ((v2 & 0xE0) == 0xE0) { + cmd = (8 * decompress_last_byte) & 0xE0; + len = ((decompress_last_byte & 3) << 8 | DecompNextByte()) + 1; + } else { + cmd = v2 & 0xE0; + len = (decompress_last_byte & 0x1F) + 1; + } + if (cmd & 0x80) { + decompress_want_xor = cmd & 0x20; + if (cmd >= 0xC0u) { + decompress_last_byte = DecompNextByte(); + decompress_tmp1 = 0; + *(uint16 *)&decompress_last_byte = dst_pos - *(uint16 *)&decompress_last_byte; + } else { + decompress_last_byte = DecompNextByte(); + decompress_tmp1 = DecompNextByte(); + } + do { + uint16 v27 = *(uint16 *)&decompress_last_byte; + b = *IndirPtr(&decompress_dst, *(uint16 *)&decompress_last_byte); + *(uint16 *)&decompress_last_byte = v27 + 1; + if (decompress_want_xor) + b = ~b; + IndirWriteByte(&decompress_dst, dst_pos++, b); + } while (--len); + } else { + switch (cmd) { + case 0x20: + b = DecompNextByte(); + do { + IndirWriteByte(&decompress_dst, dst_pos++, b); + } while (--len); + break; + case 0x40: + decompress_last_byte = DecompNextByte(); + decompress_tmp1 = DecompNextByte(); + do { + IndirWriteByte(&decompress_dst, dst_pos++, decompress_last_byte); + if (!--len) + break; + IndirWriteByte(&decompress_dst, dst_pos++, decompress_tmp1); + } while (--len); + break; + case 0x60: + b = DecompNextByte(); + do { + IndirWriteByte(&decompress_dst, dst_pos++, b++); + } while (--len); + break; + default: + do { + b = DecompNextByte(); + IndirWriteByte(&decompress_dst, dst_pos++, b); + } while (--len); + break; + } + } + } +} + +void DecompressToVRAM(void) { // 0x80B271 + uint16 v0; // r8 + VoidP addr; + int16 v5; + int16 v7; + int16 v10; + int16 v13; + int16 v14; + int16 v16; + int16 v21; + int16 v28; + int16 v29; + int16 v30; + int16 v31; + int16 v32; + int16 v33; + int16 v34; + uint8 v35; + + uint8 bank = decompress_src.bank; + HIBYTE(decompress_want_xor) = 0; + addr = decompress_dst.addr; + while (1) { + uint8 v2 = DecompNextByte(); + decompress_last_byte = v2; + if (v2 == 0xFF) + break; + uint8 v4 = v2 & 0xE0; + if (v4 == 0xE0) { + v35 = (8 * decompress_last_byte) & 0xE0; + HIBYTE(v5) = decompress_last_byte & 3; + LOBYTE(v5) = DecompNextByte(); + } else { + v35 = v4; + v5 = decompress_last_byte & 0x1F; + } + v7 = v5 + 1; + LOBYTE(v0) = v35; + if ((uint8)sign8(v0)) { + if (v35 >= 0xC0u) { + LOBYTE(decompress_want_xor) = v35 & 0x20; + v34 = v5 + 1; + uint8 v25 = DecompNextByte(); + v21 = v34; + decompress_last_byte = v25; + decompress_tmp1 = 0; + *(uint16 *)&decompress_last_byte = addr - *(uint16 *)&decompress_last_byte; + } else { + LOBYTE(decompress_want_xor) = v35 & 0x20; + v32 = v5 + 1; + uint8 v17 = DecompNextByte(); + decompress_last_byte = v17; + uint8 v19 = DecompNextByte(); + v21 = v32; + decompress_tmp1 = v19; + *(uint16 *)&decompress_last_byte += decompress_dst.addr; + } + do { + v33 = v21; + WriteRegWord(VMADDL, *(uint16 *)&decompress_last_byte >> 1); + ReadRegWord(RDVRAML); + uint16 RegWord = ReadRegWord(RDVRAML); + uint8 v23 = RegWord; + if (decompress_last_byte & 1) + v23 = HIBYTE(RegWord); + ++ *(uint16 *)&decompress_last_byte; + if (decompress_want_xor) + v23 = ~v23; + WriteRegWord(VMADDL, addr >> 1); + HIBYTE(v0) = (uint16)(addr >> 1) >> 8; + if (addr & 1) + WriteReg(VMDATAH, v23); + else + WriteReg(VMDATAL, v23); + ++addr; + --v21; + } while (v33 != 1); + } else { + switch (v35) { + case ' ': + v29 = v5 + 1; + LOBYTE(v5) = DecompNextByte(); + v10 = v29; + do { + HIBYTE(v0) = HIBYTE(v5); + if (addr & 1) + WriteReg(VMDATAH, v5); + else + WriteReg(VMDATAL, v5); + ++addr; + --v10; + } while (v10); + break; + case '@': + v30 = v5 + 1; + LOBYTE(v5) = DecompNextByte(); + decompress_last_byte = v5; + LOBYTE(v5) = DecompNextByte(); + v13 = v30; + decompress_tmp1 = v5; + do { + HIBYTE(v0) = HIBYTE(v5); + if (addr & 1) + WriteReg(VMDATAH, decompress_last_byte); + else + WriteReg(VMDATAL, decompress_last_byte); + ++addr; + v14 = v13 - 1; + if (!v14) + break; + HIBYTE(v0) = HIBYTE(v5); + if (addr & 1) + WriteReg(VMDATAH, decompress_tmp1); + else + WriteReg(VMDATAL, decompress_tmp1); + ++addr; + v13 = v14 - 1; + } while (v13); + break; + case '`': + v31 = v5 + 1; + LOBYTE(v5) = DecompNextByte(); + v16 = v31; + do { + HIBYTE(v0) = HIBYTE(v5); + if (addr & 1) + WriteReg(VMDATAH, v5); + else + WriteReg(VMDATAL, v5); + ++addr; + LOBYTE(v5) = v5 + 1; + --v16; + } while (v16); + break; + default: + do { + v28 = v7; + LOBYTE(v5) = DecompNextByte(); + HIBYTE(v0) = HIBYTE(v5); + if (addr & 1) + WriteReg(VMDATAH, v5); + else + WriteReg(VMDATAL, v5); + ++addr; + v7 = v28 - 1; + } while (v28 != 1); + break; + } + } + } +} + +#define kLoadStationLists ((uint16*)RomPtr(0x80c4b5)) + +void LoadFromLoadStation(void) { // 0x80C437 + save_station_lockout_flag = 1; + R18_ = 2 * load_station_index; + uint16 *v0 = (uint16 *)RomPtr_80( + kLoadStationLists[area_index] + + 2 + * (load_station_index + + 6 * load_station_index)); + room_ptr = *v0; + door_def_ptr = v0[1]; + door_bts = v0[2]; + layer1_x_pos = v0[3]; + bg1_x_offset = layer1_x_pos; + layer1_y_pos = v0[4]; + bg1_y_offset = layer1_y_pos; + samus_y_pos = layer1_y_pos + v0[5]; + samus_prev_y_pos = samus_y_pos; + samus_x_pos = v0[6] + layer1_x_pos + 128; + samus_prev_x_pos = samus_x_pos; + reg_BG1HOFS = 0; + reg_BG1VOFS = 0; + LOBYTE(area_index) = RomPtr_8F(room_ptr)[1]; + LOBYTE(debug_disable_minimap) = 0; +} + +#define off_80CD46 ((uint16*)RomPtr(0x80cd46)) + +void SetElevatorsAsUsed(void) { // 0x80CD07 + uint8 *v0 = RomPtr_80( + off_80CD46[area_index] + + 4 * (((uint8)elevator_door_properties_orientation & 0xFu) - 1)); + used_save_stations_and_elevators[*v0] |= v0[1]; + used_save_stations_and_elevators[v0[2]] |= v0[3]; +} diff --git a/src/sm_81.c b/src/sm_81.c new file mode 100644 index 0000000..5e1f7ea --- /dev/null +++ b/src/sm_81.c @@ -0,0 +1,3015 @@ +// SRAM, spritemap processing & menus + +#include "sm_rtl.h" +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" + +#define kOffsetToSaveSlot ((uint16*)RomPtr(0x81812b)) +#define kPackedBytesPerArea_Count ((uint8*)RomPtr(0x818131)) +#define kPackedBytesPerArea_PackedOffs ((uint16*)RomPtr(0x818138)) +#define kPackedBytesPerArea_UnpackedOffs ((uint16*)RomPtr(0x8182d6)) +#define kMenuPalettes ((uint16*)RomPtr(0x8ee400)) +#define kZebesAndStarsTilemap ((uint16*)RomPtr(0x8edc00)) +#define kAreaMapForegroundSetDefs ((uint16*)RomPtr(0x81a4e6)) +#define kAreaMapForegroundColors ((uint16*)RomPtr(0x81a40e)) +#define kBg2RoomSelectMapTilemap ((uint16*)RomPtr(0xb6e000)) +#define kFileSelectExpandingSquareTilemap ((uint16*)RomPtr(0x81b14b)) +#define kMapIconDataPointers ((MapIconDataPointers*)RomPtr(0x82c7cb)) +#define g_word_82C749 ((uint16*)RomPtr(0x82c749)) +#define kRoomState_aa82_aa8f (*(RoomDefRoomstate*)RomPtr(0x8faa8f)) +#define kLeftMapScrollArrowData (*(MapScrollArrowData*)RomPtr(0x81af32)) +#define kRightMapScrollArrowData (*(MapScrollArrowData*)RomPtr(0x81af3c)) +#define kUpMapScrollArrowData (*(MapScrollArrowData*)RomPtr(0x81af46)) +#define kDownMapScrollArrowData (*(MapScrollArrowData*)RomPtr(0x81af50)) +static const uint16 kFileSelectMap_AreaIndexes[6] = { 0, 3, 5, 1, 4, 2 }; + +void SoftReset(void) { + game_state = 0xffff; +} + +void SaveToSram(uint16 a) { // 0x818000 + char v0 = a; + uint16 v2; + int16 v7; + int16 v11; + + R20_ = 0; + R18_ = 2 * (v0 & 3); + for (int i = 94; i >= 0; i -= 2) + player_data_saved[i >> 1] = *(uint16 *)((char *)&equipped_items + i); + LOBYTE(v2) = HIBYTE(area_index); + HIBYTE(v2) = area_index; + uint16 v3 = v2; + uint16 v4 = 0; + do { + explored_map_tiles_saved[v3 >> 1] = *(uint16 *)&map_tiles_explored[v4]; + v4 += 2; + v3 += 2; + } while ((int16)(v4 - 256) < 0); + PackMapToSave(); + sram_save_station_index = load_station_index; + sram_area_index = area_index; + uint16 v5 = kOffsetToSaveSlot[R18_ >> 1]; + uint16 v6 = ADDR16_OF_RAM(*player_data_saved); + do { + v7 = *(uint16 *)RomPtr_7E(v6); + *(uint16 *)(&g_sram[2 * (v5 >> 1)]) = v7; + R20_ += v7; + v5 += 2; + v6 += 2; + } while (v6 != ADDR16_OF_RAM(*plm_instruction_timer)); + uint16 v8 = R18_; + uint16 v9 = R20_; + int v10 = R18_ >> 1; + *(uint16 *)(&g_sram[2 * v10]) = R20_; + *(uint16 *)(&g_sram[2 * v10 + 0x1FF0]) = v9; + v11 = ~v9; + *(uint16 *)(&g_sram[2 * v10 + 8]) = v11; + *(uint16 *)(&g_sram[2 * v10 + 0x1FF8]) = v11; + + RtlWriteSram(); +} + +uint8 LoadFromSram(uint16 a) { // 0x818085 + R20_ = 0; + R18_ = 2 * (a & 3); + uint16 v1 = kOffsetToSaveSlot[a & 3]; + uint16 v2 = ADDR16_OF_RAM(*player_data_saved); + do { + uint16 v3 = kSramChecksum[v1 >> 1]; + *(uint16 *)RomPtr_7E(v2) = v3; + R20_ += v3; + v1 += 2; + v2 += 2; + } while (v2 != ADDR16_OF_RAM(*plm_instruction_timer)); + int v4 = R18_ >> 1; + if (R20_ == kSramChecksum[v4] && (R20_ ^ 0xffff) == kSramChecksumInverted[v4] + || R20_ == kSramChecksumUpper[v4] && (R20_ ^ 0xffff) == kSramChecksumInvertedUpper[v4]) { + for (int i = 94; i >= 0; i -= 2) + *(uint16 *)((char *)&equipped_items + i) = player_data_saved[i >> 1]; + UnpackMapFromSave(); + load_station_index = sram_save_station_index; + area_index = sram_area_index; + return 0; + } else { + R20_ = 0; + uint16 v7 = kOffsetToSaveSlot[R18_ >> 1]; + uint16 v8 = ADDR16_OF_RAM(*player_data_saved); + uint16 v9 = 0; + do { + kSramChecksum[v7 >> 1] = v9; + v9 += R20_; + R20_ = v9; + v7 += 2; + v8 += 2; + } while (v8 != ADDR16_OF_RAM(*plm_instruction_timer)); // 0xDE1C + load_station_index = 0; + area_index = 0; + return 1; + } +} + +void UnpackMapFromSave(void) { // 0x8182E4 + for (int i = 1792; i >= 0; i -= 2) + explored_map_tiles_saved[i >> 1] = 0; + R22_ = 0; + do { + R20_ = swap16(R22_); + R18_ = kPackedBytesPerArea_Count[R22_]; + int v2 = (uint16)(2 * R22_) >> 1; + R0_.addr = kPackedBytesPerArea_UnpackedOffs[v2]; + *(uint16 *)&R0_.bank = 129; + int v3 = kPackedBytesPerArea_PackedOffs[v2]; + R3_.addr = ADDR16_OF_RAM(*explored_map_tiles_saved); + *(uint16 *)&R3_.bank = 126; + do { + uint16 v4 = R20_ + *RomPtr_81(R0_.addr); + IndirWriteByte(&R3_, v4, compressed_map_data[v3]); + ++R0_.addr; + ++v3; + --R18_; + } while (R18_); + ++R22_; + } while (sign16(R22_ - 6)); +} + +void PackMapToSave(void) { // 0x81834B + R26_ = 0; + do { + R22_ = kPackedBytesPerArea_Count[R26_]; + int v0 = R26_; + R0_.addr = kPackedBytesPerArea_UnpackedOffs[v0]; + int v1 = kPackedBytesPerArea_PackedOffs[v0]; + R24_ = swap16(R26_); + R3_.addr = ADDR16_OF_RAM(*explored_map_tiles_saved); + *(uint16 *)&R3_.bank = 126; + do { + int v3 = R24_ + *RomPtr_81(R0_.addr); + compressed_map_data[v1] = *IndirPtr(&R3_, v3); + ++R0_.addr; + ++v1; + --R22_; + } while (R22_); + ++R26_; + } while (sign16(R26_ - 6)); +} + +void DrawSpritemap(uint8 db, uint16 j) { // 0x81879F + int16 v7; + OamEnt *v8; + int16 v10; + int16 v12; + char v13; + char v15; + + uint16 *v2 = (uint16 *)RomPtrWithBank(db, j); + if (*v2) { + R24_ = *v2; + uint16 v3 = j + 2; + uint16 v4 = oam_next_ptr; + if ((oam_next_ptr & 0xFE00) != 0) { + oam_next_ptr = v4; + return; + } + uint16 v5 = oam_next_ptr; + while (1) { + + uint8 *v6 = RomPtrWithBank(db, v3); + v7 = R20_ + *(uint16 *)v6; + v8 = gOamEnt(v5); + *(uint16 *)&v8->xcoord = v7; + if ((v7 & 0x100) != 0) { + int v9 = v5 >> 1; + if (*(int16 *)v6 >= 0) { + R28_ = kOamExtra_Address_And_X8Large[v9]; + v10 = kOamExtra_X8Small_And_Large[v9] | *(uint16 *)RomPtr_RAM(R28_); + } else { + R28_ = kOamExtra_Address_And_X8Large[v9]; + v10 = kOamExtra_Address_And_X8Large[v9 + 1] | *(uint16 *)RomPtr_RAM(R28_); + } + *(uint16 *)RomPtr_RAM(R28_) = v10; + } else if (*(int16 *)v6 < 0) { + int v11 = v5 >> 1; + R28_ = kOamExtra_Address_And_X8Large[v11]; + v12 = kOamExtra_X8Small_And_Large[v11 + 1] | *(uint16 *)RomPtr_RAM(R28_); + *(uint16 *)RomPtr_RAM(R28_) = v12; + } + v13 = v6[2]; + if (v13 >= 0) { + bool v14 = __CFADD__uint8((uint8)R18_, v13); + v15 = R18_ + v13; + if (!v14 && (uint8)v15 < 0xE0u) + goto LABEL_22; + goto LABEL_21; + } + { + bool v14; + v14 = __CFADD__uint8((uint8)R18_, v13); + v15 = R18_ + v13; + if (v14) { + if ((uint8)v15 >= 0xE0u) + goto LABEL_21; + } else if ((uint8)v15 < 0xE0u) { +LABEL_21: + SetXCoordToInvalidPos(v5); + v15 = -32; + } + } + { +LABEL_22: + v8->ycoord = v15; + *(uint16 *)&v8->charnum = R22_ | *(uint16 *)(v6 + 3) & 0xF1FF; + v4 = v5 + 4; + if (((v5 + 4) & 0xFE00) != 0) { + oam_next_ptr = v4; + return; + } + v5 += 4; + v3 += 5; + if (!--R24_) { + oam_next_ptr = v5; + return; + } + } + } + } +} + +void DrawSpritemapOffScreen(uint16 j) { // 0x818853 + int16 v6; + OamEnt *v7; + int16 v9; + int16 v11; + char v12; + char v14; + + uint16 *v1 = (uint16 *)RomPtr_8C(j); + if (*v1) { + R24_ = *v1; + uint16 v2 = j + 2; + uint16 v3 = oam_next_ptr; + if ((oam_next_ptr & 0xFE00) != 0) { +LABEL_25: + oam_next_ptr = v3; + return; + } + uint16 v4 = oam_next_ptr; + while (1) { + uint8 *v5 = RomPtrWithBank(0x8c, v2); + v6 = R20_ + *(uint16 *)v5; + v7 = gOamEnt(v4); + *(uint16 *)&v7->xcoord = v6; + if ((v6 & 0x100) != 0) { + int v8 = v4 >> 1; + if (*(int16 *)v5 >= 0) { + R28_ = kOamExtra_Address_And_X8Large[v8]; + v9 = kOamExtra_X8Small_And_Large[v8] | *(uint16 *)RomPtr_RAM(R28_); + } else { + R28_ = kOamExtra_Address_And_X8Large[v8]; + v9 = kOamExtra_Address_And_X8Large[v8 + 1] | *(uint16 *)RomPtr_RAM(R28_); + } + *(uint16 *)RomPtr_RAM(R28_) = v9; + } else if (*(int16 *)v5 < 0) { + int v10 = v4 >> 1; + R28_ = kOamExtra_Address_And_X8Large[v10]; + v11 = kOamExtra_X8Small_And_Large[v10 + 1] | *(uint16 *)RomPtr_RAM(R28_); + *(uint16 *)RomPtr_RAM(R28_) = v11; + } + v12 = v5[2]; + if (v12 >= 0) { + bool v13 = __CFADD__uint8((uint8)R18_, v12); + v14 = R18_ + v12; + if (v13 || (uint8)v14 >= 0xE0u) + goto LABEL_22; + goto LABEL_21; + } else { + bool v13; + v13 = __CFADD__uint8((uint8)R18_, v12); + v14 = R18_ + v12; + if (v13) { + if ((uint8)v14 < 0xE0u) + goto LABEL_21; + } else if ((uint8)v14 >= 0xE0u) { +LABEL_21: + SetXCoordToInvalidPos(v4); + v14 = -32; + } + } +LABEL_22: + v7->ycoord = v14; + *(uint16 *)&v7->charnum = R22_ | *(uint16 *)(v5 + 3) & 0xF1FF; + v3 = v4 + 4; + if (((v4 + 4) & 0xFE00) != 0) + goto LABEL_25; + v4 += 4; + v2 += 5; + if (!--R24_) { + oam_next_ptr = v4; + return; + } + } + } +} + +void SetXCoordToInvalidPos(uint16 k) { // 0x818907 + int16 v2; + + gOamEnt(k)->xcoord = 0x80; + int v1 = k >> 1; + R28_ = kOamExtra_Address_And_X8Large[v1]; + v2 = kOamExtra_X8Small_And_Large[v1] | *(uint16 *)RomPtr_RAM(R28_); + *(uint16 *)RomPtr_RAM(R28_) = v2; +} + +#define g_off_82C569 ((uint16*)RomPtr(0x82c569)) + +void DrawMenuSpritemap(uint16 a, uint16 k, uint16 j) { // 0x81891F + int16 v8; + OamEnt *v9; + int16 v11; + int16 v13; + + R18_ = j; + R20_ = k; + uint16 v3 = g_off_82C569[a]; + uint16 *v4 = (uint16 *)RomPtr_82(v3); + if (*v4) { + R24_ = *v4; + uint16 v5 = v3 + 2; + uint16 v6 = oam_next_ptr; + do { + uint8 *v7 = RomPtr_82(v5); + v8 = R20_ + *(uint16 *)v7; + v9 = gOamEnt(v6); + *(uint16 *)&v9->xcoord = v8; + if ((v8 & 0x100) != 0) { + int v10 = v6 >> 1; + if (*(int16 *)v7 >= 0) { + R22_ = kOamExtra_Address_And_X8Large[v10]; + v11 = kOamExtra_X8Small_And_Large[v10] | *(uint16 *)RomPtr_RAM(R22_); + } else { + R22_ = kOamExtra_Address_And_X8Large[v10]; + v11 = kOamExtra_Address_And_X8Large[v10 + 1] | *(uint16 *)RomPtr_RAM(R22_); + } + *(uint16 *)RomPtr_RAM(R22_) = v11; + } else if (*(int16 *)v7 < 0) { + int v12 = v6 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v12]; + v13 = kOamExtra_X8Small_And_Large[v12 + 1] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v13; + } + *(uint16 *)&v9->ycoord = R18_ + *((uint16 *)v7 + 1); + *(uint16 *)&v9->charnum = R3_.addr | *(uint16 *)(v7 + 3) & 0xF1FF; + v5 += 5; + v6 = (v6 + 4) & 0x1FF; + --R24_; + } while (R24_); + oam_next_ptr = v6; + } +} + +#define kSamusSpritemapTable ((uint16*)RomPtr(0x92808d)) + +void DrawSamusSpritemap(uint16 a, uint16 k, uint16 j) { // 0x8189AE + int16 v8; + OamEnt *v9; + int16 v11; + int16 v13; + uint16 v15; + + R18_ = j; + R20_ = k; + uint16 v3 = kSamusSpritemapTable[a]; + if (v3 == 0) + return; + uint16 *v4 = (uint16 *)RomPtr_92(v3); + if (*v4) { + R24_ = *v4; + uint16 v5 = v3 + 2; + uint16 v6 = oam_next_ptr; + do { + uint8 *v7 = RomPtr_92(v5); + v8 = R20_ + *(uint16 *)v7; + v9 = gOamEnt(v6); + *(uint16 *)&v9->xcoord = v8; + if ((v8 & 0x100) != 0) { + int v10 = v6 >> 1; + if (*(int16 *)v7 >= 0) { + R22_ = kOamExtra_Address_And_X8Large[v10]; + v11 = kOamExtra_X8Small_And_Large[v10] | *(uint16 *)RomPtr_RAM(R22_); + } else { + R22_ = kOamExtra_Address_And_X8Large[v10]; + v11 = kOamExtra_Address_And_X8Large[v10 + 1] | *(uint16 *)RomPtr_RAM(R22_); + } + *(uint16 *)RomPtr_RAM(R22_) = v11; + } else if (*(int16 *)v7 < 0) { + int v12 = v6 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v12]; + v13 = kOamExtra_X8Small_And_Large[v12 + 1] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v13; + } + *(uint16 *)&v9->ycoord = R18_ + *((uint16 *)v7 + 1); + *(uint16 *)&v9->charnum = *(uint16 *)(v7 + 3); + v5 += 5; + v15 = (v6 + 4) & 0x1FF; + v6 = v15; + --R24_; + } while (R24_); + oam_next_ptr = v15; + } +} + +#define g_off_93A1A1 ((uint16*)RomPtr(0x93a1a1)) + +void DrawBeamGrappleSpritemap(uint16 a) { // 0x818A37 + uint16 v1 = g_off_93A1A1[a]; + R24_ = *(uint16 *)RomPtr_93(v1); + sub_818A5F(v1 + 2); +} + +void DrawProjectileSpritemap(uint16 k) { // 0x818A4B + uint16 v1 = projectile_spritemap_pointers[k >> 1]; + uint16 *v2 = (uint16 *)RomPtr_93(v1); + if (*v2) { + R24_ = *v2; + sub_818A5F(v1 + 2); + } +} + +void sub_818A5F(uint16 j) { // 0x818A5F + uint16 v0 = j; + int16 v3; + OamEnt *v4; + int16 v6; + int16 v8; + uint16 v10; + + uint16 v1 = oam_next_ptr; + do { + uint8 *v2 = RomPtr_93(v0); + v3 = R20_ + *(uint16 *)v2; + v4 = gOamEnt(v1); + *(uint16 *)&v4->xcoord = v3; + if ((v3 & 0x100) != 0) { + int v5 = v1 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v5]; + v6 = kOamExtra_X8Small_And_Large[v5] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v6; + } + if (*(int16 *)v2 < 0) { + int v7 = v1 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v7]; + v8 = kOamExtra_X8Small_And_Large[v7 + 1] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v8; + } + *(uint16 *)&v4->ycoord = R18_ + *((uint16 *)v2 + 1); + *(uint16 *)&v4->charnum = *(uint16 *)(v2 + 3); + v0 += 5; + v10 = (v1 + 4) & 0x1FF; + v1 = v10; + --R24_; + } while (R24_); + oam_next_ptr = v10; +} + +void DrawSpritemapWithBaseTile(uint8 db, uint16 j) { // 0x818AB8 + int16 v5; + OamEnt *v6; + int16 v8; + int16 v10; + uint16 v12; + + if (j == 0) + return; // bug fix + uint16 *v1 = (uint16 *)RomPtrWithBank(db, j); + if (*v1) { + uint16 v2 = j + 2; + R24_ = *v1; + uint16 v3 = oam_next_ptr; + do { + uint8 *v4 = RomPtrWithBank(db, v2); + v5 = R20_ + *(uint16 *)v4; + v6 = gOamEnt(v3); + *(uint16 *)&v6->xcoord = v5; + if ((v5 & 0x100) != 0) { + int v7 = v3 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v7]; + v8 = kOamExtra_X8Small_And_Large[v7] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v8; + } + if (*(int16 *)v4 < 0) { + int v9 = v3 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v9]; + v10 = kOamExtra_X8Small_And_Large[v9 + 1] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v10; + } + v6->ycoord = R18_ + v4[2]; + *(uint16 *)&v6->charnum = R3_.addr | (R0_.addr + *(uint16 *)(v4 + 3)); + bool v11 = 0;// __CFADD__(v2, 5); + v2 += 5; + v12 = (v11 + v3 + 4) & 0x1FF; + v3 = v12; + --R24_; + } while (R24_); + oam_next_ptr = v12; + } +} + +void DrawSpritemapWithBaseTile2(uint8 db, uint16 j) { // 0x818B22 + int16 v6; + OamEnt *v7; + int16 v9; + int16 v11; + + uint16 *v2 = (uint16 *)RomPtrWithBank(db, j); + if (*v2) { + uint16 v3 = j + 2; + R24_ = *v2; + uint16 v4 = oam_next_ptr; + while (1) { + uint8 *v5 = RomPtrWithBank(db, v3); + v6 = R20_ + *(uint16 *)v5; + v7 = gOamEnt(v4); + *(uint16 *)&v7->xcoord = v6; + if ((v6 & 0x100) != 0) { + int v8 = v4 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v8]; + v9 = kOamExtra_X8Small_And_Large[v8] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v9; + } + if (*(int16 *)v5 < 0) { + int v10 = v4 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v10]; + v11 = kOamExtra_X8Small_And_Large[v10 + 1] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v11; + } + int y = v5[2] + LOBYTE(R18_); + if ((v5[2] & 0x80) ? (y & 0x100) == 0 : (y & 0x100) != 0) + y = 0xf0; + v7->ycoord = y; + *(uint16 *)&v7->charnum = R3_.addr | (R0_.addr + *(uint16 *)(v5 + 3)); + v3 += 5; + uint16 v16 = (v4 + 4) & 0x1FF; + v4 = v16; + if (!--R24_) { + oam_next_ptr = v16; + return; + } + } + } +} + +void DrawSpritemapWithBaseTileOffscreen(uint8 db, uint16 j) { // 0x818B96 + int16 v6; + OamEnt *v7; + int16 v9; + int16 v11; + char v12; + + uint16 *v2 = (uint16 *)RomPtrWithBank(db, j); + if (*v2) { + uint16 v3 = j + 2; + R24_ = *v2; + uint16 v4 = oam_next_ptr; + while (1) { + uint8 *v5 = RomPtrWithBank(db, v3); + v6 = R20_ + *(uint16 *)v5; + v7 = gOamEnt(v4); + *(uint16 *)&v7->xcoord = v6; + if ((v6 & 0x100) != 0) { + int v8 = v4 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v8]; + v9 = kOamExtra_X8Small_And_Large[v8] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v9; + } + if (*(int16 *)v5 < 0) { + int v10 = v4 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v10]; + v11 = kOamExtra_X8Small_And_Large[v10 + 1] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v11; + } + v12 = v5[2]; + + bool v13 = __CFADD__uint8((uint8)R18_, v12); + v12 += R18_; + + if (!!sign8(v5[2]) == (v13 != 0)) + v12 = -16; + + v7->ycoord = v12; + *(uint16 *)&v7->charnum = R3_.addr | (R0_.addr + *(uint16 *)(v5 + 3)); + v3 += 5; + uint16 v16 = (v4 + 4) & 0x1FF; + v4 = v16; + if (!--R24_) { + oam_next_ptr = v16; + return; + } + } + } +} + +void DrawEnemyProjectileSpritemapWithBaseTile(uint8 db, uint16 j) { // 0x818C0A + int16 v6; + OamEnt *v7; + int16 v9; + char v10; + char v12; // cf + int16 v14; + + uint16 *v2 = (uint16 *)RomPtrWithBank(db, j); + if (*v2) { + R24_ = *v2; + uint16 v3 = j + 2; + uint16 v4 = oam_next_ptr; + while (1) { + uint8 *v5 = RomPtrWithBank(db, v3); + v6 = R20_ + *(uint16 *)v5; + v7 = gOamEnt(v4); + *(uint16 *)&v7->xcoord = v6; + if ((v6 & 0x100) != 0) { + int v8 = v4 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v8]; + v9 = kOamExtra_X8Small_And_Large[v8] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v9; + } + v10 = v5[2]; + if (v10 >= 0) { + bool v11 = __CFADD__uint8((uint8)R18_, v10); + v10 += R18_; + if (!v11) + goto LABEL_10; + if (v11) + goto LABEL_9; + } + bool v11; + v11 = __CFADD__uint8((uint8)R18_, v10); + v10 += R18_; + if (!v11) + LABEL_9: v10 = -16; +LABEL_10: + v7->ycoord = v10; + v12 = 0; + if (*(int16 *)v5 < 0) { + int v13 = v4 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v13]; + v14 = kOamExtra_X8Small_And_Large[v13 + 1] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v14; + } + *(uint16 *)&v7->charnum = R28_ | (R26_ + v12 + *(uint16 *)(v5 + 3)); + v4 = (v4 + 4) & 0x1FF; + v3 += 5; + if (!--R24_) { + oam_next_ptr = v4; + return; + } + } + } +} + +void DrawEnemyProjectileSpritemapWithBaseTileOffscreen(uint8 db, uint16 j) { // 0x818C7F + int16 v6; + OamEnt *v7; + int16 v9; + char v10; + char v12; // cf + int16 v14; + + uint16 *v2 = (uint16 *)RomPtrWithBank(db, j); + if (*v2) { + R24_ = *v2; + uint16 v3 = j + 2; + uint16 v4 = oam_next_ptr; + while (1) { + uint8 *v5 = RomPtrWithBank(db, v3); + v6 = R20_ + *(uint16 *)v5; + v7 = gOamEnt(v4); + *(uint16 *)&v7->xcoord = v6; + if ((v6 & 0x100) != 0) { + int v8 = v4 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v8]; + v9 = kOamExtra_X8Small_And_Large[v8] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v9; + } + v10 = v5[2]; + if (v10 >= 0) { + bool v11 = __CFADD__uint8((uint8)R18_, v10); + v10 += R18_; + if (v11) + goto LABEL_10; + if (!v11) + goto LABEL_9; + } + bool v11; + v11 = __CFADD__uint8((uint8)R18_, v10); + v10 += R18_; + if (v11) + LABEL_9: + v10 = -16; +LABEL_10: + v7->ycoord = v10; + v12 = 0; + if (*(int16 *)v5 < 0) { + int v13 = v4 >> 1; + R22_ = kOamExtra_Address_And_X8Large[v13]; + v14 = kOamExtra_X8Small_And_Large[v13 + 1] | *(uint16 *)RomPtr_RAM(R22_); + *(uint16 *)RomPtr_RAM(R22_) = v14; + } + *(uint16 *)&v7->charnum = R28_ | (R26_ + v12 + *(uint16 *)(v5 + 3)); + v4 = (v4 + 4) & 0x1FF; + v3 += 5; + if (!--R24_) { + oam_next_ptr = v4; + return; + } + } + } +} + +void GameOverMenu_0_FadeOutConfigGfx(void) { // 0x818D0F + HandleFadeOut(); + if ((reg_INIDISP & 0xF) == 0) { + ScreenOff(); + QueueSfx3_Max6(1u); + DisableHdmaObjects(); + WaitUntilEndOfVblankAndClearHdma(); + uint16 v0 = 0; + do { + ram3000.pause_menu_map_tilemap[v0 + 384] = palette_buffer[v0]; + ++v0; + } while ((int16)(v0 * 2 - 512) < 0); + uint16 v1 = 0; + do { + ram3000.pause_menu_map_tilemap[v1 + 640] = *(uint16 *)(®_INIDISP + v1 * 2); + ++v1; + } while ((int16)(v1 * 2 - 54) < 0); + MapVramForMenu(); + LoadInitialMenuTiles(); + reg_BG1HOFS = 0; + reg_BG2HOFS = 0; + reg_BG3HOFS = 0; + reg_BG1VOFS = 0; + reg_BG2VOFS = 0; + reg_BG3VOFS = 0; + LoadMenuPalettes(); + ++menu_index; + } +} + +void GameOverMenu_24_FadeIn(void) { // 0x818DA6 + HandleFadeIn(); + if ((reg_INIDISP & 0xF) == 15) + ++menu_index; +} + +void MapVramForMenu(void) { // 0x818DBA + reg_TS = 0; + reg_OBSEL = 3; + reg_BG1SC = 81; + reg_BG2SC = 88; + reg_BG3SC = 92; + reg_BG12NBA = 0; + reg_BG34NBA = 4; + reg_TM = 19; +} + +void LoadInitialMenuTiles(void) { // 0x818DDB + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_818DF1 = { 1, 1, 0x18, LONGPTR(0x8e8000), 0x5600 }; + SetupDmaTransfer(&unk_818DF1); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x30u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_818E11 = { 1, 1, 0x18, LONGPTR(0xb68000), 0x2000 }; + SetupDmaTransfer(&unk_818E11); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_818E31 = { 1, 1, 0x18, LONGPTR(0xb6c000), 0x2000 }; + SetupDmaTransfer(&unk_818E31); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x40u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_818E51 = { 1, 1, 0x18, LONGPTR(0x8ed600), 0x0600 }; + SetupDmaTransfer(&unk_818E51); + WriteReg(MDMAEN, 2u); +} + +void LoadMenuPalettes(void) { // 0x818E60 + uint16 v0 = 0; + do { + int v1 = v0 >> 1; + palette_buffer[v1] = kMenuPalettes[v1]; + palette_buffer[v1 + 1] = kMenuPalettes[v1 + 1]; + v0 += 4; + } while ((int16)(v0 - 512) < 0); +} + +void LoadDebugGameOverMenuTilemaps(void) { // 0x818E7F + int v0 = 0; + do + ram3800.cinematic_bg_tilemap[v0++] = 15; + while ((int16)(v0 * 2 - 2048) < 0); + uint16 v1 = vram_write_queue_tail; + VramWriteEntry *v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 2048; + v2->src.addr = 14336; + *(uint16 *)&v2->src.bank = 126; + v2->vram_dst = (reg_BG1SC & 0xFC) << 8; + vram_write_queue_tail = v1 + 7; + uint16 v3 = v1 + 7; + for (int i = 0; ; i += 8) { + uint16 v5 = *(uint16 *)IndirPtr(&R0_, i); + if (v5 == 0xFFFF) + break; + VramWriteEntry *v6 = gVramWriteEntry(v3); + v6->size = v5; + v6->src.addr = *(uint16 *)IndirPtr(&R0_, i + 2); + *(uint16 *)&v6->src.bank = *(uint16 *)IndirPtr(&R0_, i + 4); + v6->vram_dst = *(uint16 *)IndirPtr(&R0_, i + 6); + v3 += 7; + } + vram_write_queue_tail = v3; +} + +void GameOverMenu_3_Main(void) { // 0x819003 + int16 v0; + int16 v1; + + if ((joypad1_newkeys & kButton_Select) != 0 + || (joypad1_newkeys & kButton_Up) != 0 + || (joypad1_newkeys & kButton_Down) != 0) { + file_select_map_area_index ^= 1u; + } else if ((joypad1_newkeys & (uint16)(kButton_B | kButton_Start | kButton_A)) != 0) { + if (file_select_map_area_index) { + ++menu_index; + } else { + SaveToSram(selected_save_slot); + SoftReset(); + } + return; + } + v0 = 30720; + if (file_select_map_area_index) + v0 = -30720; + v1 = v0 | 0x28; + OamEnt *v3 = gOamEnt(oam_next_ptr); + *(uint16 *)&v3->xcoord = v1; + *(uint16 *)&v3->charnum = 182; + oam_next_ptr += 4; +} + +void RestorePalettesAndIoAfterDebugGameover(void) { // 0x81905B + int v0 = 0; + do { + palette_buffer[v0] = ram3000.pause_menu_map_tilemap[v0 + 384]; + ++v0; + } while ((int16)(v0 * 2 - 512) < 0); + int v1 = 0; + do { + *(uint16 *)(®_INIDISP + v1 * 2) = ram3000.pause_menu_map_tilemap[v1 + 640]; + ++v1; + } while ((int16)(v1 * 2 - 54) < 0); +} + +void GameOverMenu_5_Continue(void) { // 0x81907E + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x40u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_819093 = { 1, 1, 0x18, LONGPTR(0x9ab200), 0x2000 }; + SetupDmaTransfer(&unk_819093); + WriteReg(MDMAEN, 2u); + game_state = 16; + file_select_map_area_index = 0; + RestorePalettesAndIoAfterDebugGameover(); +} +static Func_V *const kGameOverMenuFuncs[8] = { // 0x8190AE + GameOverMenu_0_FadeOutConfigGfx, + GameOverMenu_1_Init, + GameOverMenu_2_PlayMusic, + GameOverMenu_3_FadeIn, + GameOverMenu_4_Main, + GameOverMenu_5_FadeOutToGameMap, + GameOverMenu_6_LoadGameMapView, + GameOverMenu_7_FadeOutToSoftReset, +}; +void GameOverMenu(void) { + kGameOverMenuFuncs[menu_index](); +} + +void GameOverMenu_3_FadeIn(void) { // 0x8190CD + HandleGameOverBabyMetroid(); + DrawMenuSelectionMissile(); + HandleFadeIn(); + if ((reg_INIDISP & 0xF) == 15) + ++menu_index; +} + +void GameOverMenu_5_FadeOutToGameMap(void) { // 0x8190E7 + HandleGameOverBabyMetroid(); + DrawMenuSelectionMissile(); + HandleFadeOut(); + if ((reg_INIDISP & 0xF) == 0) + ++menu_index; +} + +void GameOverMenu_7_FadeOutToSoftReset(void) { // 0x8190FE + DrawMenuSelectionMissile(); + HandleGameOverBabyMetroid(); + HandleFadeOut(); + if ((reg_INIDISP & 0xF) == 0) + SoftReset(); +} + +void GameOverMenu_6_LoadGameMapView(void) { // 0x819116 + DisableHdmaObjects(); + WaitUntilEndOfVblankAndClearHdma(); + game_state = kGameState_5_FileSelectMap; + menu_index = 0; +} + +void GameOverMenu_4_Main(void) { // 0x81912B + HandleGameOverBabyMetroid(); + DrawMenuSelectionMissile(); + if ((joypad1_newkeys & kButton_Select) != 0 + || (joypad1_newkeys & kButton_Up) != 0 + || (joypad1_newkeys & kButton_Down) != 0) { + QueueSfx1_Max6(0x37u); + file_select_map_area_index ^= 1u; + } else if ((joypad1_newkeys & kButton_A) != 0) { + enemy_data[0].instruction_timer = 180; + if (file_select_map_area_index) { + menu_index = 7; + } else { + if (loading_game_state == kGameState_31_SetUpNewGame) + game_state = loading_game_state; + else + ++menu_index; + LoadFromSram(selected_save_slot); + } + return; + } + uint16 v0 = 160; + if (file_select_map_area_index) + v0 = 192; + enemy_projectile_id[5] = 40; + enemy_projectile_id[10] = v0; +} + +void GameOverMenu_1_Init(void) { // 0x8191A4 + reg_TM = 17; + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + QueueMusic_Delayed8(0); + QueueMusic_Delayed8(0xFF03u); + enemy_projectile_enable_flag = 1; + enemy_projectile_id[0] = 0; + int v0 = 0; + do { + ((uint16*)ram3000.menu.menu_tilemap)[v0] = 15; + ++v0; + } while ((int16)(v0 * 2 - 2048) < 0); + int v1 = vram_write_queue_tail; + VramWriteEntry *v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 2048; + v2->src.addr = ADDR16_OF_RAM(ram3000.menu.menu_tilemap); + *(uint16 *)&v2->src.bank = 126; + v2->vram_dst = (reg_BG1SC & 0xFC) << 8; + vram_write_queue_tail = v1 + 7; + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x156u, addr_kMenuTilemap_GameOver); + LoadMenuTilemap(0x38Au, addr_kMenuTilemap_FindMetroidLarva); + LoadMenuTilemap(0x414u, addr_kMenuTilemap_TryAgain); + LoadMenuTilemap(0x4CEu, addr_kMenuTilemap_YesReturnToGame); + LoadMenuTilemap(0x5CEu, addr_kMenuTilemap_NoGoToTitle); + enemy_data[0].current_instruction = 0; + enemy_data[0].instruction_timer = 0; + HandleGameOverBabyMetroid(); + *(uint16 *)®_CGWSEL = gameplay_CGWSEL << 8; + DisableHdmaObjects(); + WaitUntilEndOfVblankAndClearHdma(); + EnableHdmaObjects(); + static const SpawnHdmaObject_Args unk_819254 = { 0x00, 0x32, 0x927d }; + static const SpawnHdmaObject_Args unk_81925C = { 0x00, 0x31, 0x928d }; + SpawnHdmaObject(0x81, &unk_819254); + SpawnHdmaObject(0x81, &unk_81925C); + ScreenOn(); + ++menu_index; + screen_fade_delay = 0; + screen_fade_counter = 0; + file_select_map_area_index = 0; + enemy_projectile_id[5] = 40; + enemy_projectile_id[10] = 160; +} + +void GameOverMenu_2_PlayMusic(void) { // 0x8193E8 + if (!(HasQueuedMusic())) { + ++menu_index; + QueueMusic_Delayed8(4u); + } +} + +static Func_V *const kFileSelectMenuFuncs[34] = { // 0x8193FB + FileSelectMenu_0_FadeOutConfigGfx, + FileSelectMenu_1_LoadFileSelectMenuBG2, + FileSelectMenu_2_InitMain, + FileSelectMenu_3_FadeInToMain, + FileSelectMenu_4_Main, + FileSelectMenu_5_FadeOutFromMain, + FileSelectMenu_6_FileCopyInit, + FileSelectMenu_7_FadeInFromMain, + FileSelectMenu_8, + FileSelectMenu_9_InitializeSelectDest, + FileSelectMenu_10_FileCopySelectDest, + FileSelectMenu_11_InitializeConfirm, + FileSelectMenu_12_FileCopyConfirm, + FileSelectMenu_13_FileCopyDoIt, + FileSelectMenu_14_CopyCompleted, + FileSelectMenu_15_FadeOutToMain, + FileSelectMenu_16, + FileSelectMenu_17_FadeInToMain, + FileSelectMenu_18, + FileSelectMenu_5_FadeOutFromMain, + FileSelectMenu_20_FileClearInit, + FileSelectMenu_7_FadeInFromMain, + FileSelectMenu_22_FileClearSelectSlot, + FileSelectMenu_23_FileClearInitConfirm, + FileSelectMenu_24_FileClearConfirm, + FileSelectMenu_25_FileClearDoClear, + FileSelectMenu_26_ClearCompleted, + FileSelectMenu_15_FadeOutToMain, + FileSelectMenu_16, + FileSelectMenu_17_FadeInToMain, + FileSelectMenu_30, + FileSelectMenu_31_TurnSamusHelmet, + FileSelectMenu_32_FadeOutToOptions, + FileSelectMenu_33_FadeOutToTitle, +}; + +void FileSelectMenu(void) { + kFileSelectMenuFuncs[menu_index](); +} + +void FileSelectMenu_0_FadeOutConfigGfx(void) { // 0x81944E + HandleFadeOut(); + if ((reg_INIDISP & 0xF) != 0) + return; + ScreenOff(); + QueueSfx3_Max6(1u); + DisableHdmaObjects(); + WaitUntilEndOfVblankAndClearHdma(); + ++menu_index; + MapVramForMenu(); + LoadInitialMenuTiles(); + reg_BG1HOFS = 0; + reg_BG2HOFS = 0; + reg_BG3HOFS = 0; + reg_BG1VOFS = 0; + reg_BG2VOFS = 0; + reg_BG3VOFS = 0; + LoadFileSelectPalettes(); +} + +void LoadFileSelectPalettes(void) { // 0x819486 + int v0 = 0; + do { + int v1 = v0 >> 1; + palette_buffer[v1] = kMenuPalettes[v1]; + palette_buffer[v1 + 1] = kMenuPalettes[v1 + 1]; + v0 += 4; + } while ((int16)(v0 - 512) < 0); + +} + +void FileSelectMenu_32_FadeOutToOptions(void) { // 0x8194A3 + DrawMenuSelectionMissile(); + DrawBorderAroundSamusData(); + DrawFileSelectSamusHelmets(); + HandleFadeOut(); + if ((reg_INIDISP & 0xF) == 0) { + game_state = kGameState_2_GameOptionsMenu; + menu_index = 0; + int v0 = 0; + do { + *(uint16 *)((char *)&enemy_projectile_enable_flag + v0) = 0; + v0 += 2; + } while ((int16)(v0 - 48) < 0); + } +} + +void FileSelectMenu_33_FadeOutToTitle(void) { // 0x8194D5 + DrawBorderAroundSamusData(); + DrawFileSelectSamusHelmets(); + HandleFadeOut(); + if ((reg_INIDISP & 0xF) == 0) + SoftReset(); +} + +void FileSelectMenu_5_FadeOutFromMain(void) { // 0x8194EE + DrawMenuSelectionMissile(); + FileSelectMenu_15_FadeOutToMain(); +} + +void FileSelectMenu_15_FadeOutToMain(void) { // 0x8194F4 + HandleFadeOut(); + R18_ = *(uint16 *)®_MOSAIC & 0xFF0F; + *(uint16 *)®_MOSAIC = *(uint16 *)®_MOSAIC & 0xFF0F | (16 * (reg_INIDISP & 0xF)) ^ 0xF0; + if ((reg_INIDISP & 0xF) == 0) { + ScreenOff(); + ++menu_index; + } +} + +static const uint16 kMenuSelectionMissileXY[12] = { // 0x81951E + 0x30, 0xe, + 0x58, 0xe, + 0x80, 0xe, + 0xa3, 0xe, + 0xbb, 0xe, + 0xd3, 0xe, +}; + +void FileSelectMenu_17_FadeInToMain(void) { + int v0 = (uint16)(4 * selected_save_slot) >> 1; + enemy_projectile_id[10] = kMenuSelectionMissileXY[v0]; + enemy_projectile_id[5] = kMenuSelectionMissileXY[v0 + 1]; + FileSelectMenu_7_FadeInFromMain(); +} + +void FileSelectMenu_7_FadeInFromMain(void) { // 0x819532 + DrawMenuSelectionMissile(); + HandleFadeIn(); + R18_ = *(uint16 *)®_MOSAIC & 0xFF0F; + *(uint16 *)®_MOSAIC = *(uint16 *)®_MOSAIC & 0xFF0F | (16 * (reg_INIDISP & 0xF)) ^ 0xF0; + if ((reg_INIDISP & 0xF) == 15) + ++menu_index; +} + +void FileSelectMenu_6_FileCopyInit(void) { // 0x819561 + ++menu_index; + FileSelectMenu_Func1(); +} + +void FileSelectMenu_Func1(void) { // 0x819566 + ClearMenuTilemap(); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x52u, addr_kMenuTilemap_DataCopyMode); + LoadMenuTilemap(0x150u, addr_kMenuTilemap_CopyWhichData); + LoadMenuExitTilemap(); + DrawFileCopySaveFileInfo(); + SetInitialFileCopyMenuSelection(); + SetFileCopyMenuSelectionMissilePosition(); + enemy_projectile_id[16] = 0; + enemy_projectile_id[17] = 0; +} + +void sub_819591(void) { // 0x819591 + SetInitialFileCopyMenuSelection(); +} + +void SetInitialFileCopyMenuSelection(void) { // 0x819593 + int v0 = nonempty_save_slots; + int v1 = 0; + do { + if (v0 & 1) + break; + v0 >>= 1; + ++v1; + } while ((int16)(v1 - 3) < 0); + enemy_projectile_id[15] = v1; +} + +void ClearMenuTilemap(void) { // 0x8195A6 + for (int i = 2046; i >= 0; i -= 2) + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[768] + (uint16)i) = 15; +} + +void LoadMenuExitTilemap(void) { // 0x8195B5 + LoadMenuTilemap(0x688u, addr_kMenuTilemap_Exit); +} + +void DrawFileCopySaveFileInfo(void) { // 0x8195BE + LoadFromSram_(0); + enemy_data[0].palette_index = 0; + if ((nonempty_save_slots & 1) == 0) + enemy_data[0].palette_index = 1024; + DrawFileCopySaveSlotAInfo(); + LoadFromSram_(1); + enemy_data[0].palette_index = 0; + if ((nonempty_save_slots & 2) == 0) + enemy_data[0].palette_index = 1024; + DrawFileCopySaveSlotBInfo(); + LoadFromSram_(2); + enemy_data[0].palette_index = 0; + if ((nonempty_save_slots & 4) == 0) + enemy_data[0].palette_index = 1024; + DrawFileCopySaveSlotCInfo(); + QueueTransferOfMenuTilemapToVramBG1(); +} + +void DrawFileCopySaveSlotAInfo(void) { // 0x81960F + DrawFileSelectionHealth((nonempty_save_slots & 1) == 0, 0x218u); + DrawFileSelectionTime((nonempty_save_slots & 1) == 0, 0x272u); + LoadMenuTilemap(0x234u, addr_kMenuTilemap_TIME); + LoadMenuTilemap(0x208u, addr_kMenuTilemap_SamusA); +} + +void DrawFileCopySaveSlotBInfo(void) { // 0x81963F + DrawFileSelectionHealth(~(uint8)nonempty_save_slots & 2, 0x318u); + DrawFileSelectionTime(~(uint8)nonempty_save_slots & 2, 0x372u); + LoadMenuTilemap(0x334u, addr_kMenuTilemap_TIME); + LoadMenuTilemap(0x308u, addr_kMenuTilemap_SamusB); +} + +void DrawFileCopySaveSlotCInfo(void) { // 0x81966F + DrawFileSelectionHealth(~(uint8)nonempty_save_slots & 4, 0x418u); + DrawFileSelectionTime(~(uint8)nonempty_save_slots & 4, 0x472u); + LoadMenuTilemap(0x434u, addr_kMenuTilemap_TIME); + LoadMenuTilemap(0x408u, addr_kMenuTilemap_SamusC); +} + +void QueueTransferOfMenuTilemapToVramBG1(void) { // 0x81969F + uint16 v0 = vram_write_queue_tail; + VramWriteEntry *v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 2048; + v1->src.addr = ADDR16_OF_RAM(ram3000.menu.menu_tilemap); + *(uint16 *)&v1->src.bank = 126; + v1->vram_dst = (reg_BG1SC & 0xFC) << 8; + vram_write_queue_tail = v0 + 7; +} + +static const uint8 kBitShl[3] = { // 0x8196C2 + 1, + 2, + 4, +}; + +void FileSelectMenu_8(void) { + uint8 v0; + + DrawBorderAroundDataCopyMode(); + DrawMenuSelectionMissile(); + if ((joypad1_newkeys & (kButton_Start | kButton_A)) != 0) { + QueueSfx1_Max6(0x37u); + if (enemy_projectile_id[15] == 3) { + menu_index += 7; + } else { + enemy_projectile_id[16] = enemy_projectile_id[15]; + ++menu_index; + } + } else if ((joypad1_newkeys & 0x8000u) != 0) { + menu_index += 7; + QueueSfx1_Max6(0x37u); + } else { + if ((joypad1_newkeys & kButton_Up) != 0) { + v0 = enemy_projectile_id[15]; + while ((--v0 & 0x80) == 0) { + if ((kBitShl[v0] & nonempty_save_slots) != 0) { +LABEL_16: + LOBYTE(enemy_projectile_id[15]) = v0; + QueueSfx1_Max6(0x37u); + SetFileCopyMenuSelectionMissilePosition(); + return; + } + } + } else if ((joypad1_newkeys & kButton_Down) != 0) { + v0 = enemy_projectile_id[15]; + while ((int8)(++v0 - 4) < 0) { + if (v0 == 3 || (kBitShl[v0] & nonempty_save_slots) != 0) + goto LABEL_16; + } + } + SetFileCopyMenuSelectionMissilePosition(); + } +} + +void SetFileCopyMenuSelectionMissilePosition(void) { // 0x81975E + static const uint16 kFileCopyMissileY[4] = { 72, 104, 136, 211 }; + enemy_projectile_id[10] = kFileCopyMissileY[enemy_projectile_id[15]]; + enemy_projectile_id[5] = 22; +} + +void FileSelectMenu_9_InitializeSelectDest(void) { // 0x81977A + DrawBorderAroundDataCopyMode(); + DrawFileCopySelectDestinationSaveFileInfo(); + ++menu_index; + uint16 v0 = 0; + do { + if (v0 != enemy_projectile_id[16]) + break; + ++v0; + } while (sign16(v0 - 3)); + enemy_projectile_id[15] = v0; + SetFileCopyMenuSelectionMissilePosition(); +} + +void DrawFileCopySelectDestinationSaveFileInfo(void) { // 0x819799 + ClearMenuTilemap(); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x52u, addr_kMenuTilemap_DataCopyMode); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x148u, addr_kMenuTilemap_CopySamusToWhere); + ram3000.pause_menu_map_tilemap[944] = enemy_projectile_id[16] + 8298; + LoadMenuExitTilemap(); + LoadFromSram_(0); + uint16 v0 = 1024; + if (enemy_projectile_id[16]) + v0 = 0; + enemy_data[0].palette_index = v0; + DrawFileCopySaveSlotAInfo(); + LoadFromSram_(1); + uint16 v1 = 1024; + if (enemy_projectile_id[16] != 1) + v1 = 0; + enemy_data[0].palette_index = v1; + DrawFileCopySaveSlotBInfo(); + LoadFromSram_(2); + uint16 v2 = 1024; + if (enemy_projectile_id[16] != 2) + v2 = 0; + enemy_data[0].palette_index = v2; + DrawFileCopySaveSlotCInfo(); + QueueTransferOfMenuTilemapToVramBG1(); +} + +void FileSelectMenu_10_FileCopySelectDest(void) { // 0x819813 + static const uint16 kFileCopySelectDest_MissileY[4] = { 72, 104, 136, 212 }; + uint16 v0; + + DrawBorderAroundDataCopyMode(); + DrawMenuSelectionMissile(); + if ((joypad1_newkeys & (kButton_Start | kButton_A)) != 0) { + QueueSfx1_Max6(0x37u); + if (enemy_projectile_id[15] != 3) { + enemy_projectile_id[17] = enemy_projectile_id[15]; + ++menu_index; +LABEL_9: + enemy_projectile_id[10] = kFileCopySelectDest_MissileY[enemy_projectile_id[15]]; + enemy_projectile_id[5] = 22; + return; + } + menu_index += 5; + } else { + if ((joypad1_newkeys & 0x8000u) == 0) { + if ((joypad1_newkeys & kButton_Up) != 0) { + QueueSfx1_Max6(0x37u); + v0 = enemy_projectile_id[15]; + while ((--v0 & 0x8000u) == 0) { + if (v0 != enemy_projectile_id[16]) { +LABEL_8: + enemy_projectile_id[15] = v0; + goto LABEL_9; + } + } + } else if ((joypad1_newkeys & kButton_Down) != 0) { + QueueSfx1_Max6(0x37u); + v0 = enemy_projectile_id[15]; + while (++v0 != 4) { + if (v0 != enemy_projectile_id[16]) + goto LABEL_8; + } + } + goto LABEL_9; + } + menu_index -= 2; + enemy_projectile_id[15] = enemy_projectile_id[16]; + QueueSfx1_Max6(0x37u); + FileSelectMenu_Func1(); + } +} + +void FileSelectMenu_11_InitializeConfirm(void) { // 0x8198B7 + DrawBorderAroundDataCopyMode(); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x144u, addr_kMenuTilemap_CopySamusToSamus); + ram3000.pause_menu_map_tilemap[942] = enemy_projectile_id[16] + 8298; + ram3000.pause_menu_map_tilemap[955] = enemy_projectile_id[17] + 8298; + DrawFileCopyClearConfirmation(); + ++menu_index; + enemy_projectile_id[15] = 0; + enemy_projectile_unk198F = 8; +} + +void DrawFileCopyClearConfirmation(void) { // 0x8198ED + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x514u, addr_kMenuTilemap_IsThisOk); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x59Cu, addr_kMenuTilemap_Yes); + int v0 = 832; + do { + ram3000.pause_menu_map_tilemap[v0 + 768] = 15; + ++v0; + } while ((int16)(v0 * 2 - 1728) < 0); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x65Cu, addr_kMenuTilemap_No); + DrawFileCopyConfirmationSaveFileInfo(); +} + +void DrawFileCopyConfirmationSaveFileInfo(void) { // 0x819922 + LoadFromSram_(0); + int v0 = 0; + if (enemy_projectile_id[16] && enemy_projectile_id[17]) + v0 = 1024; + enemy_data[0].palette_index = v0; + DrawFileCopySaveSlotAInfo(); + LoadFromSram_(1); + int v1 = 0; + if (enemy_projectile_id[16] != 1 && enemy_projectile_id[17] != 1) + v1 = 1024; + enemy_data[0].palette_index = v1; + DrawFileCopySaveSlotBInfo(); + LoadFromSram_(2); + int v2 = 0; + if (enemy_projectile_id[16] != 2 && enemy_projectile_id[17] != 2) + v2 = 1024; + enemy_data[0].palette_index = v2; + DrawFileCopySaveSlotCInfo(); + QueueTransferOfMenuTilemapToVramBG1(); +} + +void FileSelectMenu_12_FileCopyConfirm(void) { // 0x819984 + DrawBorderAroundDataCopyMode(); + DrawMenuSelectionMissile(); + HandleFileCopyArrowPalette(); + DrawFileCopyArrow(); + if ((joypad1_newkeys & (kButton_Up | kButton_Down)) != 0) { + enemy_projectile_id[15] ^= 1u; + QueueSfx1_Max6(0x37u); + } else { + if ((joypad1_newkeys & 0x8000u) != 0) { + menu_index -= 3; + enemy_projectile_id[15] = enemy_projectile_id[17]; + QueueSfx1_Max6(0x37u); + return; + } + if ((joypad1_newkeys & (kButton_Start | kButton_A)) != 0) { + QueueSfx1_Max6(0x38u); + if (enemy_projectile_id[15]) { + menu_index -= 4; + FileSelectMenu_Func1(); + } else { + ++menu_index; + } + return; + } + } + uint16 v0 = 184; + if (enemy_projectile_id[15]) + v0 = 208; + enemy_projectile_id[10] = v0; + enemy_projectile_id[5] = 94; +} + +void HandleFileCopyArrowPalette(void) { // 0x8199FE + if (enemy_projectile_unk198F) { + if (!--enemy_projectile_unk198F) { + enemy_projectile_unk198F = 4; + uint16 v0 = palette_buffer[145]; + uint16 v1 = 0; + do { + palette_buffer[(v1 >> 1) + 145] = palette_buffer[(v1 >> 1) + 146]; + v1 += 2; + } while ((int16)(v1 - 12) < 0); + palette_buffer[151] = v0; + } + } +} + +void FileSelectMenu_13_FileCopyDoIt(void) { // 0x819A2C + static const uint16 kBitShl_16bit[3] = { 1, 2, 4 }; + + DrawBorderAroundDataCopyMode(); + DrawMenuSelectionMissile(); + HandleFileCopyArrowPalette(); + DrawFileCopyArrow(); + *(uint16 *)&R0_.bank = 112; + *(uint16 *)&R3_.bank = 112; + uint16 src_addr = kOffsetToSaveSlot[enemy_projectile_id[16]]; + uint16 dst_addr = kOffsetToSaveSlot[enemy_projectile_id[17]]; + memcpy(&g_sram[dst_addr], &g_sram[src_addr], 1628); + int v2 = enemy_projectile_id[16]; + int v10 = *(uint16 *)(&g_sram[2 * v2 + 0x1FF0]); + int v9 = *(uint16 *)(&g_sram[2 * v2 + 0x1FF8]); + int v8 = *(uint16 *)(&g_sram[2 * v2 + 0]); + int v4 = enemy_projectile_id[17]; + *(uint16 *)(&g_sram[2 * v4 + 8]) = *(uint16 *)&g_sram[2 * v2 + 8]; + *(uint16 *)(&g_sram[2 * v4]) = v8; + *(uint16 *)(&g_sram[2 * v4 + 0x1FF8]) = v9; + *(uint16 *)(&g_sram[2 * v4 + 0x1FF0]) = v10; + ++menu_index; + int v5 = 640; + do { + ram3000.pause_menu_map_tilemap[v5 + 768] = 15; + ++v5; + } while ((int16)(v5 * 2 - 1856) < 0); + nonempty_save_slots |= kBitShl_16bit[enemy_projectile_id[17]]; + int v6 = ((4 * enemy_projectile_id[17] + 9) << 6) + 24; + int v7 = 0; + do { + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[768] + v6) = 15; + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[736] + v6) = 15; + v6 += 2; + v7 += 2; + } while ((int16)(v7 - 22) < 0); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x510u, addr_kMenuTilemap_CopyCompleted); + DrawFileCopyConfirmationSaveFileInfo(); + RtlWriteSram(); +} + +void FileSelectMenu_14_CopyCompleted(void) { // 0x819AFA + DrawBorderAroundDataCopyMode(); + if (joypad1_newkeys) { + QueueSfx1_Max6(0x37u); + ++menu_index; + int slot = sram_save_slot_selected; + if (sign16(slot) || !sign16(sram_save_slot_selected - 3) || + (slot & sram_save_slot_selected_complement)) { + slot = 0; + } + selected_save_slot = slot; + } +} + +void FileSelectMenu_18(void) { // 0x819B28 + menu_index -= 14; +} + +void FileSelectMenu_20_FileClearInit(void) { // 0x819B33 + DrawBorderAroundDataClearMode(); + ++menu_index; + InitFileSelectMenuFileClear(); +} + +void InitFileSelectMenuFileClear(void) { // 0x819B3C + ClearMenuTilemap(); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x50u, addr_kMenuTilemap_DataClearMode); + LoadMenuTilemap(0x140u, addr_kMenuTilemap_ClearWhichData); + LoadMenuExitTilemap(); + DrawFileCopySaveFileInfo(); + enemy_projectile_id[16] = 0; + SetInitialFileCopyMenuSelection(); + SetFileClearMenuMissilePos(); +} + +void FileSelectMenu_22_FileClearSelectSlot(void) { // 0x819B64 + static const uint8 kBitShl_[3] = { 1, 2, 4 }; + uint16 v0; + uint8 v1; + + DrawBorderAroundDataClearMode(); + DrawMenuSelectionMissile(); + HIBYTE(v0) = HIBYTE(joypad1_newkeys); + if ((joypad1_newkeys & (kButton_Start | kButton_A)) != 0) { + QueueSfx1_Max6(0x37u); + if (enemy_projectile_id[15] != 3) { + enemy_projectile_id[16] = enemy_projectile_id[15]; + ++menu_index; + return; + } +LABEL_11: + QueueSfx1_Max6(0x37u); + menu_index += 5; + return; + } + if ((joypad1_newkeys & 0x8000u) != 0) + goto LABEL_11; + if ((joypad1_newkeys & kButton_Up) != 0) { + v1 = enemy_projectile_id[15]; + while ((--v1 & 0x80) == 0) { + if ((kBitShl_[v1] & (uint8)nonempty_save_slots) != 0) { +LABEL_16: + LOBYTE(enemy_projectile_id[15]) = v1; + LOBYTE(v0) = 55; + QueueSfx1_Max6(v0); + SetFileClearMenuMissilePos(); + return; + } + } + } else if ((joypad1_newkeys & kButton_Down) != 0) { + v1 = enemy_projectile_id[15]; + while ((int8)(++v1 - 4) < 0) { + if (v1 == 3 || (kBitShl_[v1] & (uint8)nonempty_save_slots) != 0) + goto LABEL_16; + } + } + SetFileClearMenuMissilePos(); +} + +void SetFileClearMenuMissilePos(void) { // 0x819BEF + static const uint16 kFileClear_MissileY[4] = { 72, 104, 136, 211 }; + enemy_projectile_id[10] = kFileClear_MissileY[enemy_projectile_id[15]]; + enemy_projectile_id[5] = 22; +} + +void FileSelectMenu_23_FileClearInitConfirm(void) { // 0x819C0B + DrawBorderAroundDataClearMode(); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x140u, addr_kMenuTilemap_ClearSamusA); + ram3000.pause_menu_map_tilemap[949] = enemy_projectile_id[16] + 8298; + enemy_projectile_id[17] = 3; + DrawFileCopyClearConfirmation(); + ++menu_index; + enemy_projectile_id[15] = 0; +} + +void FileSelectMenu_24_FileClearConfirm(void) { // 0x819C36 + uint16 v0; + DrawBorderAroundDataClearMode(); + DrawMenuSelectionMissile(); + if ((joypad1_newkeys & (kButton_Up | kButton_Down)) != 0) { + enemy_projectile_id[15] ^= 1u; + QueueSfx1_Max6(0x37u); +LABEL_8: + v0 = 184; + if (enemy_projectile_id[15]) + v0 = 208; + enemy_projectile_id[10] = v0; + enemy_projectile_id[5] = 94; + return; + } + if ((joypad1_newkeys & 0x8000u) != 0) { +LABEL_5: + menu_index -= 2; + enemy_projectile_id[15] = enemy_projectile_id[16]; + QueueSfx1_Max6(0x37u); + InitFileSelectMenuFileClear(); + return; + } + if ((joypad1_newkeys & (kButton_Start | kButton_A)) == 0) + goto LABEL_8; + QueueSfx1_Max6(0x38u); + if (enemy_projectile_id[15]) + goto LABEL_5; + ++menu_index; +} + +void FileSelectMenu_25_FileClearDoClear(void) { // 0x819C9E + static const uint16 kBitShl_Not[3] = { 0xfffe, 0xfffd, 0xfffb }; + + DrawBorderAroundDataClearMode(); + *(uint16 *)&R0_.bank = 112; + int sram_addr = kOffsetToSaveSlot[enemy_projectile_id[16]]; + memset(&g_sram[sram_addr], 0, 1628); + + uint16 v1 = 2 * enemy_projectile_id[16]; + int v2 = (uint16)(2 * enemy_projectile_id[16]) >> 1; + *(uint16 *)(&g_sram[2 * v2]) = 0; + *(uint16 *)(&g_sram[2 * v2 + 8]) = 0; + *(uint16 *)(&g_sram[2 * v2 + 0x1FF0]) = 0; + *(uint16 *)(&g_sram[2 * v2 + 0x1FF8]) = 0; + ++menu_index; + NewSaveFile(); + LoadFromSram(enemy_projectile_id[16]); + area_index = enemy_projectile_id[16]; + LoadMirrorOfExploredMapTiles(); + uint16 v3 = 640; + do { + ram3000.pause_menu_map_tilemap[v3 + 768] = 15; + ++v3; + } while ((int16)(v3 * 2 - 1856) < 0); + nonempty_save_slots &= kBitShl_Not[enemy_projectile_id[16]]; + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x500u, addr_kMenuTilemap_DataCleared); + DrawFileCopyConfirmationSaveFileInfo(); + RtlWriteSram(); +} + +void FileSelectMenu_26_ClearCompleted(void) { // 0x819D26 + DrawBorderAroundDataClearMode(); + if (joypad1_newkeys) { + QueueSfx1_Max6(0x37u); + ++menu_index; + if (!(LoadFromSram(0))) { +LABEL_3: + selected_save_slot = 0; + return; + } + if (LoadFromSram(1)) { + if (LoadFromSram(2)) + goto LABEL_3; + selected_save_slot = 2; + } else { + selected_save_slot = 1; + } + } +} + +void FileSelectMenu_30(void) { // 0x819D68 + DrawBorderAroundSamusData(); + menu_index -= 26; +} + +void FileSelectMenu_31_TurnSamusHelmet(void) { // 0x819D77 + DrawMenuSelectionMissile(); + DrawBorderAroundSamusData(); + DrawFileSelectSlotSamusHelmet(4); + DrawFileSelectSlotSamusHelmet(6); + DrawFileSelectSlotSamusHelmet(8); + if ((joypad1_newkeys & (kButton_Start | kButton_A)) != 0 + || enemy_projectile_id[2] == 7 && !enemy_projectile_index + || enemy_projectile_id[3] == 7 && !enemy_projectile_init_param + || enemy_projectile_id[4] == 7 && !enemy_projectile_unk1995) { + ++menu_index; + } +} + +void DrawFileSelectSamusHelmets(void) { // 0x819DC3 + enemy_projectile_index = 0; + DrawFileSelectSlotSamusHelmet(4); + enemy_projectile_init_param = 0; + DrawFileSelectSlotSamusHelmet(6); + enemy_projectile_unk1995 = 0; + DrawFileSelectSlotSamusHelmet(8); +} + +void DrawFileSelectSlotSamusHelmet(uint16 k) { // 0x819DE4 + uint16 v0 = k; + int16 v1; + + v1 = *(uint16 *)((char *)&enemy_projectile_enable_flag + v0); + if (v1) { + uint16 v2 = v1 - 1; + *(uint16 *)((char *)&enemy_projectile_enable_flag + v0) = v2; + if (!v2) { + *(uint16 *)((char *)&enemy_projectile_enable_flag + v0) = 8; + int v3 = v0 >> 1; + uint16 v4 = enemy_projectile_id[v3] + 1; + if (!sign16(enemy_projectile_id[v3] - 7)) { + *(uint16 *)((char *)&enemy_projectile_enable_flag + v0) = 0; + v4 = 7; + } + enemy_projectile_id[v3] = v4; + } + } + int v5 = v0 >> 1; + uint16 v6 = 2 * enemy_projectile_id[v5]; + R3_.addr = 3584; + static const uint16 kDrawFileSlotHelmet_Spritemaps[9] = { 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x33 }; + DrawMenuSpritemap(kDrawFileSlotHelmet_Spritemaps[v6 >> 1], enemy_projectile_id[v5 + 5], enemy_projectile_id[v5 + 10]); +} +static Func_V *const kFileSelectMapFuncs[23] = { // 0x819E3E + FileSelectMap_0, + FileSelectMap_1, + FileSelectMap_2_LoadAreaSelectForegroundTilemap, + FileSelectMap_3_LoadAreaSelectBackgroundTilemap, + FileSelectMap_4_SetupExpandingSquareTransition, + FileSelectMap_5_ExpandingSquare, + FileSelectMap_6_AreaSelectMap, + FileSelectMap_7_PrepExpandSquareTransToRoomMap, + FileSelectMap_8_ExpandSquareTransToRoomSelectMap, + FileSelectMap_9_InitRoomSelectMap, + FileSelectMap_10_RoomSelectMap, + FileSelectMap_11, + FileSelectMap_11, + FileSelectMap_13, + FileSelectMap_14, + FileSelectMap_15_ClearTileMap, + FileSelectMap_16_LoadPalettes, + FileSelectMap_2_LoadAreaSelectForegroundTilemap, + FileSelectMap_18, + FileSelectMap_4_SetupExpandingSquareTransition, + FileSelectMap_20_SetupExpandingSquare, + FileSelectMap_21_MoveExpandingSquare, + FileSelectMap_22, +}; +void FileSelectMap(void) { + kFileSelectMapFuncs[menu_index](); +} + +void FileSelectMap_22(void) { // 0x819E7B + DrawAreaSelectMapLabels(); + HandleFadeOut(); + if ((reg_INIDISP & 0xF) == 0) { + game_state = kGameState_2_GameOptionsMenu; + menu_index = 0; + } +} + +void FileSelectMenu_1_LoadFileSelectMenuBG2(void) { // 0x819E93 + VramWriteEntry *v2; + + for (int i = 1023; i >= 0; --i) + ram3000.pause_menu_map_tilemap[i + 768] = kZebesAndStarsTilemap[i]; + uint16 v1 = vram_write_queue_tail; + v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 2048; + v2->src.addr = ADDR16_OF_RAM(ram3000.menu.menu_tilemap); + *(uint16 *)&v2->src.bank = 126; + v2->vram_dst = (reg_BG2SC & 0xFC) << 8; + vram_write_queue_tail = v1 + 7; + ++menu_index; + enemy_projectile_enable_flag = 1; + enemy_projectile_id[0] = 0; +} + +void FileSelectMenu_2_InitMain(void) { // 0x819ED6 + uint16 v0; + + if (sign16(sram_save_slot_selected) + || !sign16(sram_save_slot_selected - 3) + || (v0 = sram_save_slot_selected, (sram_save_slot_selected_complement & sram_save_slot_selected) != 0)) { + v0 = 0; + } + selected_save_slot = v0; + FileSelectMenu_16(); +} + +void FileSelectMenu_16(void) { // 0x819EF3 + for (int i = 2046; i >= 0; i -= 2) + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[768] + (uint16)i) = 15; + nonempty_save_slots = -1; + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x56u, addr_kMenuTilemap_SamusData); + LoadMenuTilemap(0x146u, addr_kMenuTilemap_SamusA); + uint8 c = LoadFromSram_(0); + nonempty_save_slots = (nonempty_save_slots >> 1) | (c << 15); + DrawFileSelectionHealth(nonempty_save_slots & 0x8000, 0x15Cu); + DrawFileSelectionTime(nonempty_save_slots & 0x8000, 0x1B4u); + LoadMenuTilemap(0x176u, addr_kMenuTilemap_TIME); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x286u, addr_kMenuTilemap_SamusB); + c = LoadFromSram_(1u); + nonempty_save_slots = (nonempty_save_slots >> 1) | (c << 15); + DrawFileSelectionHealth(nonempty_save_slots & 0x8000, 0x29Cu); + DrawFileSelectionTime(nonempty_save_slots & 0x8000, 0x2F4u); + LoadMenuTilemap(0x2B6u, addr_kMenuTilemap_TIME); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x3C6u, addr_kMenuTilemap_SamusC); + c = LoadFromSram_(2u); + nonempty_save_slots = (nonempty_save_slots >> 1) | (c << 15); + DrawFileSelectionHealth(nonempty_save_slots & 0x8000, 0x3DCu); + DrawFileSelectionTime(nonempty_save_slots & 0x8000, 0x434u); + LoadMenuTilemap(0x3F6u, addr_kMenuTilemap_TIME); + nonempty_save_slots = swap16(~nonempty_save_slots) >> 5; + if (nonempty_save_slots) { + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x508u, addr_kMenuTilemap_DataCopy); + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x5C8u, addr_kMenuTilemap_DataClear); + } + enemy_data[0].palette_index = 0; + LoadMenuTilemap(0x688u, addr_kMenuTilemap_Exit); + QueueTransferOfMenuTilemapToVramBG1(); + enemy_projectile_enable_flag = 1; + enemy_projectile_unk198F = 0; + enemy_projectile_index = 0; + enemy_projectile_init_param = 0; + enemy_projectile_unk1995 = 0; + enemy_projectile_id[0] = 0; + enemy_projectile_id[1] = 0; + enemy_projectile_id[2] = 0; + enemy_projectile_id[3] = 0; + enemy_projectile_id[4] = 0; + enemy_projectile_id[5] = 0; + enemy_projectile_id[10] = 0; + enemy_projectile_id[6] = 0; + enemy_projectile_id[11] = 0; + enemy_projectile_id[7] = 100; + enemy_projectile_id[8] = 100; + enemy_projectile_id[9] = 100; + enemy_projectile_id[12] = 47; + enemy_projectile_id[13] = 87; + enemy_projectile_id[14] = 127; + screen_fade_delay = 1; + screen_fade_counter = 1; + ScreenOn(); + ++menu_index; + enemy_projectile_id[15] = 0; + enemy_projectile_id[16] = 0; + enemy_projectile_id[17] = 0; +} + +uint8 LoadFromSram_(uint16 a) { // 0x81A053 + return LoadFromSram(a); +} + +void FileSelectMenu_3_FadeInToMain(void) { // 0x81A058 + DrawFileSelectSamusHelmets(); + int v0 = (uint16)(4 * selected_save_slot) >> 1; + enemy_projectile_id[10] = kMenuSelectionMissileXY[v0]; + enemy_projectile_id[5] = kMenuSelectionMissileXY[v0 + 1]; + DrawMenuSelectionMissile(); + DrawBorderAroundSamusData(); + HandleFadeIn(); + if ((reg_INIDISP & 0xF) == 15) + ++menu_index; +} + +void DrawFileSelectionHealth(uint16 a, uint16 k) { // 0x81A087 + int16 v2; + int16 v4; + unsigned int v5; + + if (a) { + FileSelectClearRestOfMenuTilemapRow(k); + LoadMenuTilemap(k + 64, addr_kMenuTilemap_NoData); + } else { + R26_ = k; + LoadMenuTilemap(k, addr_kMenuTilemap_Energy); + v2 = R26_ + 8; + + R20_ = samus_health / 100; + R18_ = samus_health % 100; + R22_ = samus_max_health / 100; + R24_ = 7; + uint16 v3 = v2 + 64; + while ((--R22_ & 0x8000u) == 0) { + v4 = 153; + if (R20_) { + --R20_; + v4 = 152; + } + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[768] + v3) = enemy_data[0].palette_index | v4; + v3 += 2; + if (!--R24_) { + v3 -= 78; + R24_ = 8; + } + } + R20_ = R18_ / 10; + R18_ = R18_ % 10; + v5 = R26_; + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[802] + R26_) = enemy_data[0].palette_index | (R18_ + 8288); + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[801] + v5) = enemy_data[0].palette_index | (R20_ + 8288); + } +} + +void DrawFileSelectionTime(uint16 a, uint16 k) { // 0x81A14E + if (!a) { + R26_ = k; + int div_val = game_time_hours / 10; + int mod_val = game_time_hours % 10; + + uint16 v2 = R26_; + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[769] + v2) = enemy_data[0].palette_index | (mod_val + 8288); + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[768] + v2) = enemy_data[0].palette_index | (div_val + 8288); + LoadMenuTilemap(R26_ + 4, addr_word_81B4A8); + + int div_min = game_time_minutes / 10; + int mod_min = game_time_minutes % 10; + + uint16 v3 = R26_; + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[772] + v3) = enemy_data[0].palette_index | (mod_min + 8288); + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[771] + v3) = enemy_data[0].palette_index | (div_min + 8288); + } +} + +void FileSelectMenu_4_Main(void) { // 0x81A1C2 + int16 v0; + uint16 v1, v2; + int v3; + + DrawBorderAroundSamusData(); + DrawMenuSelectionMissile(); + DrawFileSelectSlotSamusHelmet(4); + DrawFileSelectSlotSamusHelmet(6); + DrawFileSelectSlotSamusHelmet(8); + if ((joypad1_newkeys & (kButton_Start | kButton_A)) == 0) { + if ((joypad1_newkeys & kButton_Up) != 0) { + if (nonempty_save_slots) { + v1 = selected_save_slot - 1; + if ((int16)(selected_save_slot - 1) < 0) + v1 = 5; + } else { + v1 = selected_save_slot - 1; + if ((int16)(selected_save_slot - 1) >= 0) { + if (!sign16(selected_save_slot - 5)) + v1 = 2; + } else { + v1 = 5; + } + } + selected_save_slot = v1; + } else { + if ((joypad1_newkeys & kButton_Down) == 0) { + if ((joypad1_newkeys & kButton_B) != 0) { + QueueSfx1_Max6(0x37u); + menu_index = 33; + QueueSfx1_Max6(0x37u); + } + goto LABEL_28; + } + if (nonempty_save_slots) { + v2 = selected_save_slot + 1; + if (!sign16(selected_save_slot - 5)) + v2 = 0; + } else { + v2 = selected_save_slot + 1; + if (!sign16(selected_save_slot - 2)) { + if (sign16(selected_save_slot - 5)) + v2 = 5; + else + v2 = 0; + } + } + selected_save_slot = v2; + } + QueueSfx1_Max6(0x37u); +LABEL_28: + v3 = (uint16)(4 * selected_save_slot) >> 1; + enemy_projectile_id[10] = kMenuSelectionMissileXY[v3]; + enemy_projectile_id[5] = kMenuSelectionMissileXY[v3 + 1]; + return; + } + v0 = selected_save_slot; + if (sign16(selected_save_slot - 3)) { + QueueSfx1_Max6(0x2Au); + menu_index += 27; + *(uint16 *)((char *)&enemy_projectile_enable_flag + (uint16)(2 * (selected_save_slot + 2))) = 1; + *(uint16 *)&g_sram[0x1FEC] = selected_save_slot; + *(uint16 *)&g_sram[0x1FEE] = ~selected_save_slot; + RtlWriteSram(); + if (LoadFromSram(selected_save_slot)) { + NewSaveFile(); + has_area_map = 0; + } else { + LoadMirrorOfExploredMapTiles(); + } + goto LABEL_28; + } + if (selected_save_slot == 3) { + QueueSfx1_Max6(0x37u); + ++menu_index; + *(uint16 *)®_MOSAIC = *(uint16 *)®_MOSAIC & 0xFF0C | 3; + } else { + if (selected_save_slot == 4) { + QueueSfx1_Max6(0x37u); + menu_index += 15; + v0 = *(uint16 *)®_MOSAIC & 0xFF0C | 3; + *(uint16 *)®_MOSAIC = v0; + } + if (v0 == 5) + menu_index = 33; + } +} + +void FileSelectMap_0(void) { // 0x81A32A + VramWriteEntry *v1; + + ClearMenuTilemap(); + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 2048; + v1->src.addr = ADDR16_OF_RAM(ram3000.menu.menu_tilemap); + *(uint16 *)&v1->src.bank = 126; + v1->vram_dst = (reg_BG2SC & 0xFC) << 8; + vram_write_queue_tail = v0 + 7; + palette_change_num = 0; + LoadFileSelectPalettes(); + uint16 v2 = 0; + do { + target_palettes[v2 >> 1] = palette_buffer[v2 >> 1]; + v2 += 2; + } while ((int16)(v2 - 64) < 0); + target_palettes[14] = 0; + target_palettes[30] = 0; + ++menu_index; +} + +void FileSelectMap_1(void) { // 0x81A37C + int16 v1; + int16 v2; + + + if (AdvanceGradualColorChangeOfPalette(0, 0x40u)) { + reg_BG1VOFS = 0; + reg_BG1HOFS = 0; + reg_BG2VOFS = 0; + reg_BG2HOFS = 0; + uint16 v0 = 0; + while (area_index != kFileSelectMap_AreaIndexes[v0 >> 1]) { + v0 += 2; + if ((int16)(v0 - 12) >= 0) { + v0 = 0; + break; + } + } + file_select_map_area_index = v0 >> 1; + v1 = 0; + do { + v2 = v1; + if (v1 == area_index) + LoadActiveAreaMapForegroundColors(v1); + else + LoadInactiveAreaMapForegroundColors(v1); + ++v1; + } while ((int16)(v2 - 5) < 0); + ++menu_index; + g_word_7E0787 = 0; + reg_TM = 2; + } +} + +void sub_81A3D1(uint16 k) { // 0x81A3D1 + LoadActiveAreaMapForegroundColors(k); +} + +static const uint16 kActiveAreaMapForegroundColors[6] = { 0, 0xa, 0x10, 0x16, 0x24, 0x2a }; +static const uint16 kInactiveAreaMapForegroundColors[6] = { // 0x81A3D3 + 0x30, 0x3a, + 0x40, 0x46, + 0x54, 0x5a, +}; + +void LoadActiveAreaMapForegroundColors(uint16 v0) { + LoadAreaMapForegroundColors(kActiveAreaMapForegroundColors[v0]); +} + +void LoadInactiveAreaMapForegroundColors(uint16 v0) { // 0x81A3DC + LoadAreaMapForegroundColors(kInactiveAreaMapForegroundColors[v0]); +} + +void LoadAreaMapForegroundColors(uint16 j) { // 0x81A3E3 + while (1) { + int v1 = j >> 1; + if (kAreaMapForegroundSetDefs[v1] == 0xFFFF) + break; + uint16 v4 = j; + uint16 v2 = kAreaMapForegroundSetDefs[v1 + 1]; + uint16 v3 = kAreaMapForegroundSetDefs[v1]; + R18_ = 5; + do { + palette_buffer[v2 >> 1] = kAreaMapForegroundColors[v3 >> 1]; + v2 += 2; + v3 += 2; + --R18_; + } while (R18_); + j = v4 + 4; + } +} + +void FileSelectMap_2_LoadAreaSelectForegroundTilemap(void) { // 0x81A546 + VramWriteEntry *v1; + + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 2048; + v1->src.addr = addr_kAreaSelectForegroundTilemap; + *(uint16 *)&v1->src.bank = 129; + v1->vram_dst = (reg_BG1SC & 0xFC) << 8; + vram_write_queue_tail = v0 + 7; + *(uint16 *)®_INIDISP = (reg_OBSEL << 8) | 0xF; + ++menu_index; +} + +void FileSelectMap_18(void) { // 0x81A578 + ++menu_index; + LoadAreaSelectBackgroundTilemap(area_index); +} + +void FileSelectMap_3_LoadAreaSelectBackgroundTilemap(void) { // 0x81A582 + ++menu_index; + LoadAreaSelectBackgroundTilemap(area_index); +} + +void LoadAreaSelectBackgroundTilemap(uint16 j) { // 0x81A58A + VramWriteEntry *v2; + int16 v3; + + uint16 v1 = vram_write_queue_tail; + v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 2048; + LOBYTE(v3) = HIBYTE(j); + HIBYTE(v3) = j; + v2->src.addr = 8 * v3 - 16614; + *(uint16 *)&v2->src.bank = 129; + v2->vram_dst = (reg_BG3SC & 0xFC) << 8; + vram_write_queue_tail = v1 + 7; +} + +void FileSelectMap_4_SetupExpandingSquareTransition(void) { // 0x81A5B3 + reg_TS = 4; + WriteReg(TS, 4u); + reg_TSW = 4; + WriteReg(TSW, 4u); + reg_CGWSEL = 2; + WriteReg(CGWSEL, 2u); + reg_CGADSUB = 37; + WriteReg(CGADSUB, 0x25u); + reg_COLDATA[2] = 0x80; + reg_COLDATA[1] = 64; + reg_COLDATA[0] = 32; + SetupInitialExpandingSquareHDMA(); + reg_HDMAEN = 12; + WriteReg(HDMAEN, 0xCu); + ConfigureWindow1ForExpandingSquare(); + hdma_objects_enable_flag = 0; + LOBYTE(menu_index) = menu_index + 1; +} + +void ConfigureWindow1ForExpandingSquare(void) { // 0x81A5F6 + reg_TM = 19; + WriteReg(TM, 0x13u); + reg_TMW = 19; + WriteReg(TMW, 0x13u); + reg_W12SEL = 35; + WriteReg(W12SEL, 0x23u); + reg_W34SEL = 3; + WriteReg(W34SEL, 3u); + reg_WOBJSEL = 35; + WriteReg(WOBJSEL, 0x23u); +} + +void SetupInitialExpandingSquareHDMA(void) { // 0x81A61C + expanding_square_topbottom_margin_right_pos = 0; + expanding_square_topbottom_margin_left_pos = -1; + LOBYTE(expanding_square_left_pos) = 127; + LOBYTE(expanding_square_right_pos) = -127; + hdma_window_1_left_pos[0].field_0 = 111; + hdma_window_1_left_pos[0].field_1 = 34; + hdma_window_1_left_pos[0].field_2 = -98; + hdma_window_1_left_pos[1].field_0 = 1; + hdma_window_1_left_pos[1].field_1 = 50; + hdma_window_1_left_pos[1].field_2 = -98; + hdma_window_1_left_pos[2].field_0 = 1; + hdma_window_1_left_pos[2].field_1 = 50; + hdma_window_1_left_pos[2].field_2 = -98; + hdma_window_1_left_pos[3].field_0 = 111; + hdma_window_1_left_pos[3].field_1 = 32; + hdma_window_1_left_pos[3].field_2 = -98; + WriteReg(DMAP2, 0x40u); + WriteReg(BBAD2, 0x26u); + WriteReg(A1T2L, 0); + WriteReg(A1T2H, 0x9Eu); + WriteReg(A1B2, 0x7Eu); + WriteReg(DAS20, 0x7Eu); + WriteReg(DAS2L, 0); + WriteReg(DAS2H, 0); + WriteReg(A2A2L, 0); + WriteReg(A2A2H, 0); + WriteReg(NTRL2, 0); + hdma_window_1_right_pos[0].field_0 = 111; + hdma_window_1_right_pos[0].field_1 = 32; + hdma_window_1_right_pos[0].field_2 = -98; + hdma_window_1_right_pos[1].field_0 = 1; + hdma_window_1_right_pos[1].field_1 = 54; + hdma_window_1_right_pos[1].field_2 = -98; + hdma_window_1_right_pos[2].field_0 = 1; + hdma_window_1_right_pos[2].field_1 = 54; + hdma_window_1_right_pos[2].field_2 = -98; + hdma_window_1_right_pos[3].field_0 = 111; + hdma_window_1_right_pos[3].field_1 = 32; + hdma_window_1_right_pos[3].field_2 = -98; + WriteReg(DMAP3, 0x40u); + WriteReg(BBAD3, 0x27u); + WriteReg(A1T3L, 0x10u); + WriteReg(A1T3H, 0x9Eu); + WriteReg(A1B3, 0x7Eu); + WriteReg(DAS30, 0x7Eu); + WriteReg(DAS3L, 0); + WriteReg(DAS3H, 0); + WriteReg(A2A3L, 0); + WriteReg(A2A3H, 0); + WriteReg(NTRL3, 0); +} +static const uint8 kExpandingSquareTransitionSpeed = 4; + + +void FileSelectMap_5_ExpandingSquare(void) { // 0x81A725 + VramWriteEntry *v5; + + DrawAreaSelectMapLabels(); + uint8 v0 = hdma_window_1_left_pos[0].field_0 - kExpandingSquareTransitionSpeed; + if ((int8)(hdma_window_1_left_pos[0].field_0 - kExpandingSquareTransitionSpeed) < 0) { + LOBYTE(menu_index) = menu_index + 1; + reg_TM &= ~2u; + reg_TMW = 0; + reg_TSW = 0; + reg_BG2VOFS = 24; + pausemenu_palette_animation_timer = 1; + uint16 v1 = 0; + do { + ram4000.xray_tilemaps[v1] = kBg2RoomSelectMapTilemap[v1]; + ++v1; + } while ((int16)(v1 * 2 - 1600) < 0); + do + ram4000.xray_tilemaps[v1++] = 10241; + while ((int16)(v1 * 2 - 2048) < 0); + + R0_.addr = ADDR16_OF_RAM(ram4000) + 340; + *(uint16 *)&R0_.bank = 126; + DrawRoomSelectMapAreaLabel(); + uint16 v2 = 320; + uint16 v3 = 959; + do { + ram4000.xray_tilemaps[v3--] = kFileSelectExpandingSquareTilemap[v2 >> 1]; + v2 -= 2; + } while (v2); + uint16 v4 = vram_write_queue_tail; + v5 = gVramWriteEntry(vram_write_queue_tail); + v5->size = 2048; + v5->src.addr = ADDR16_OF_RAM(ram4000); + *(uint16 *)&v5->src.bank = 126; + v5->vram_dst = (reg_BG2SC & 0xFC) << 8; + vram_write_queue_tail = v4 + 7; + } else { + hdma_window_1_left_pos[0].field_0 -= kExpandingSquareTransitionSpeed; + hdma_window_1_left_pos[3].field_0 = v0; + hdma_window_1_right_pos[0].field_0 = v0; + hdma_window_1_right_pos[3].field_0 = v0; + hdma_window_1_left_pos[1].field_0 += kExpandingSquareTransitionSpeed; + hdma_window_1_left_pos[2].field_0 = hdma_window_1_left_pos[1].field_0; + hdma_window_1_right_pos[1].field_0 = hdma_window_1_left_pos[1].field_0; + hdma_window_1_right_pos[2].field_0 = hdma_window_1_left_pos[1].field_0; + LOBYTE(expanding_square_left_pos) = expanding_square_left_pos - kExpandingSquareTransitionSpeed; + LOBYTE(expanding_square_right_pos) = kExpandingSquareTransitionSpeed + expanding_square_right_pos; + } +} + +void FileSelectMap_6_AreaSelectMap(void) { // 0x81A800 + int16 v0; + uint16 v2; + uint16 v3; + + v0 = joypad1_newkeys; + if ((joypad1_newkeys & (kButton_Up | kButton_Left)) != 0) { + v0 = enable_debug; + if (enable_debug) { + R24_ = R22_; + uint16 v1 = DecAndWraparoundTo5(file_select_map_area_index); + if (CheckIfFileSelectMapAreaCanBeSelected(v1) + || (v2 = DecAndWraparoundTo5(R28_), CheckIfFileSelectMapAreaCanBeSelected(v2)) + || (v3 = DecAndWraparoundTo5(R28_), CheckIfFileSelectMapAreaCanBeSelected(v3))) { + QueueSfx1_Max6(0x37u); + SwitchActiveFileSelectMapArea(); + DrawAreaSelectMapLabels(); + return; + } + goto LABEL_18; + } +LABEL_6: + if (v0 < 0) { + menu_index = 22; + DrawAreaSelectMapLabels(); + return; + } + if ((v0 & (kButton_Start | kButton_A)) != 0) { + QueueSfx1_Max6(0x38u); + SelectFileSelectMapArea(); + return; + } +LABEL_18: + DrawAreaSelectMapLabels(); + return; + } + if ((joypad1_newkeys & (kButton_Select | kButton_Down | kButton_Right)) == 0) + goto LABEL_6; + v0 = enable_debug; + if (!enable_debug) + goto LABEL_6; + R22_ = 6; + R28_ = file_select_map_area_index; + while (1) { + uint16 v4 = WraparoundFrom6to0(R28_); + if (CheckIfFileSelectMapAreaCanBeSelected(v4)) + break; + if (!--R22_) + goto LABEL_18; + } + SwitchActiveFileSelectMapArea(); + QueueSfx1_Max6(0x37u); + DrawAreaSelectMapLabels(); +} + +uint16 DecAndWraparoundTo5(uint16 a) { // 0x81A898 + uint16 result = a - 1; + if ((result & 0x8000u) != 0) + return 5; + return result; +} + +uint16 WraparoundFrom6to0(uint16 a) { // 0x81A89F + uint16 result = a + 1; + if (!sign16(result - 6)) + return 0; + return result; +} + +void SelectFileSelectMapArea(void) { // 0x81A8A9 + VoidP *v1; + char v2; // cf + int16 v3; + int16 v4; + + ++menu_index; + if (!enable_debug) { + area_index = sram_area_index; + load_station_index = sram_save_station_index; + DrawAreaSelectMapLabels(); + return; + } + area_index = kFileSelectMap_AreaIndexes[file_select_map_area_index]; + R18_ = *(uint16 *)&used_save_stations_and_elevators[(uint16)(2 * area_index)]; + uint16 v0 = 0; + *(uint16 *)&R0_.bank = 130; + R0_.addr = addr_kMapIconDataPointers + 64; + v1 = (VoidP *)IndirPtr(&R0_, 2 * area_index); + while (!*v1) + ; + R0_.addr = *v1; + R20_ = 16; + while (1) { + v2 = R18_ & 1; + R18_ >>= 1; + if (!v2) + goto LABEL_10; + v3 = *(uint16 *)IndirPtr(&R0_, 4 * v0); + if (v3 == -2) + goto LABEL_10; + if (v3 != -1) + break; + v0 = -1; +LABEL_10: + ++v0; + if (!--R20_) { + while (1) { + v4 = *(uint16 *)IndirPtr(&R0_, 4 * v0); + if (v4 != -2) { + if (v4 != -1) + goto LABEL_16; + v0 = -1; + } + ++v0; + if (!--R20_) { + while (1) + ; + } + } + } + } +LABEL_16: + load_station_index = v0; + DrawAreaSelectMapLabels(); +} + +uint16 CheckIfFileSelectMapAreaCanBeSelected(uint16 a) { // 0x81A931 + R28_ = a; + int v1 = 2 * kFileSelectMap_AreaIndexes[a]; + if (*(uint16 *)&used_save_stations_and_elevators[v1]) + return true; + uint16 t = *(uint16 *)((char *)&kMapIconDataPointers[4].crateria + v1) + 64; + return t != 0xffff; +} + +void SwitchActiveFileSelectMapArea(void) { // 0x81A958 + LoadInactiveAreaMapForegroundColors(kFileSelectMap_AreaIndexes[file_select_map_area_index]); + file_select_map_area_index = R28_; + LoadActiveAreaMapForegroundColors(kFileSelectMap_AreaIndexes[R28_]); + LoadAreaSelectBackgroundTilemap(kFileSelectMap_AreaIndexes[file_select_map_area_index]); +} +static const uint16 kAreaSelectMapLabelPositions[12] = { // 0x81A97E + 0x5b, 0x32, + 0x2a, 0x7f, + 0x5e, 0xb5, + 0xce, 0x50, + 0xce, 0x9f, + 0x87, 0x8b, +}; +void DrawAreaSelectMapLabels(void) { + VoidP v0; + int16 v3; + char v4; // cf + int v5; + + R3_.addr = 0; + DrawMenuSpritemap(g_word_82C749[0], 0x80, 0x10u); + R28_ = 0; + do { + v0 = 512; + if (R28_ == file_select_map_area_index) + v0 = 0; + R3_.addr = v0; + uint16 v1 = 2 * kFileSelectMap_AreaIndexes[R28_]; + R36 = *(uint16 *)&used_save_stations_and_elevators[v1]; + uint16 v2 = *(VoidP *)((char *)&kMapIconDataPointers[4].crateria + v1); + g_word_7E001E = 16; + while (1) { + v3 = *(uint16 *)RomPtr_82(v2); + if (v3 == -1) + break; + v4 = R36 & 1; + R36 >>= 1; + if (v4 && v3 != -2) + goto LABEL_11; + v2 += 4; + if (!--g_word_7E001E) { + if (enable_debug && *(uint16 *)RomPtr_82(v2) != 0xFFFF) { +LABEL_11: + v5 = (uint16)(4 * kFileSelectMap_AreaIndexes[R28_]) >> 1; + DrawMenuSpritemap( + g_word_82C749[0] + kFileSelectMap_AreaIndexes[R28_] + 1, + kAreaSelectMapLabelPositions[v5], + kAreaSelectMapLabelPositions[v5 + 1]); + break; + } + break; + } + } + ++R28_; + } while (sign16(R28_ - 6)); +} + + +static const uint16 kRoomSelectMapExpandingSquareTimers[6] = { 0x33, 0x35, 0x2d, 0x33, 0x33, 0x22 }; +#define kExpandingSquareVels ((ExpandingSquareVels*)RomPtr(0x81aa34)) + +void FileSelectMap_7_PrepExpandSquareTransToRoomMap(void) { // 0x81AAAC + VramWriteEntry *v1; + + DrawAreaSelectMapLabels(); + SetupInitialExpandingSquareHDMA(); + reg_TM = 19; + reg_TMW = 19; + reg_W12SEL = 50; + WriteReg(W12SEL, 0x32u); + reg_W34SEL = 2; + WriteReg(W34SEL, 2u); + reg_CGADSUB = 5; + WriteReg(CGADSUB, 5u); + reg_WOBJSEL = 34; + WriteReg(WOBJSEL, 0x22u); + reg_BG12NBA = 48; + hdma_window_1_left_pos[3].field_0 = 0; + hdma_window_1_right_pos[3].field_0 = 0; + R0_.addr = ADDR16_OF_RAM(ram4000) + 340; + *(uint16 *)&R0_.bank = 126; + DrawRoomSelectMapAreaLabel(); + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 512; + v1->src.addr = ADDR16_OF_RAM(ram4000); + *(uint16 *)&v1->src.bank = 126; + v1->vram_dst = (reg_BG2SC & 0xFC) << 8; + vram_write_queue_tail = v0 + 7; + expanding_square_timer = kRoomSelectMapExpandingSquareTimers[area_index]; + int v2 = (uint16)(4 * area_index) >> 1; + expanding_square_left_pos = kAreaSelectMapLabelPositions[v2]; + expanding_square_right_pos = expanding_square_left_pos; + expanding_square_top_pos = kAreaSelectMapLabelPositions[v2 + 1]; + expanding_square_bottom_pos = expanding_square_top_pos; + expanding_square_left_subpos = 0; + expanding_square_right_subpos = 0; + expanding_square_top_subpos = 0; + expanding_square_bottom_subpos = 0; + expanding_square_left_subvel = *(uint16 *)((char *)&kExpandingSquareVels[0].left_subvel + + (uint16)(16 * area_index)); + expanding_square_left_vel = *(uint16 *)((char *)&kExpandingSquareVels[0].left_vel + (uint16)(16 * area_index)); + expanding_square_right_subvel = *(uint16 *)((char *)&kExpandingSquareVels[0].right_subvel + + (uint16)(16 * area_index)); + expanding_square_right_vel = *(uint16 *)((char *)&kExpandingSquareVels[0].right_vel + + (uint16)(16 * area_index)); + expanding_square_top_subvel = *(uint16 *)((char *)&kExpandingSquareVels[0].top_subvel + + (uint16)(16 * area_index)); + expanding_square_top_vel = *(uint16 *)((char *)&kExpandingSquareVels[0].top_vel + (uint16)(16 * area_index)); + expanding_square_bottom_subvel = *(uint16 *)((char *)&kExpandingSquareVels[0].bottom_subvel + + (uint16)(16 * area_index)); + expanding_square_bottom_vel = *(uint16 *)((char *)&kExpandingSquareVels[0].bottom_vel + + (uint16)(16 * area_index)); + SetupRoomSelectMapExpandingSquareTransHDMA(); + reg_HDMAEN = 12; + WriteReg(HDMAEN, 0xCu); + ++menu_index; + QueueSfx1_Max6(0x3Bu); +} + +void SetupRoomSelectMapExpandingSquareTransHDMA(void) { // 0x81ABA7 + uint16 k = 0; + uint16 v0 = expanding_square_top_pos; + AddExpandingSqTransLeftIndirHDMA(v0, k, 0x9E22u); + k = AddExpandingSqTransRightIndirHDMA(v0, k, 0x9E20u); + uint16 v2 = expanding_square_bottom_pos - expanding_square_top_pos; + if ((uint8)expanding_square_bottom_pos == (uint8)expanding_square_top_pos) + v2 = 1; + AddExpandingSqTransLeftIndirHDMA(v2, k, 0x9E32u); + k = AddExpandingSqTransRightIndirHDMA(v2, k, 0x9E36u); + uint16 v4 = -32 - expanding_square_bottom_pos; + if ((uint8)expanding_square_bottom_pos == 0xE0) + v4 = 1; + AddExpandingSqTransLeftIndirHDMA(v4, k, 0x9E22u); + k = AddExpandingSqTransRightIndirHDMA(v4, k, 0x9E20u); + *(&hdma_window_1_left_pos[0].field_0 + k) = 0; + *(&hdma_window_1_right_pos[0].field_0 + k) = 0; +} + +void AddExpandingSqTransLeftIndirHDMA(uint16 a, uint16 k, uint16 j) { // 0x81ABF7 + if ((a & 0x80) != 0) { + *(&hdma_window_1_left_pos[0].field_0 + k) = a - 127; + *(&hdma_window_1_left_pos[1].field_0 + k) = 127; + *(uint16 *)(&hdma_window_1_left_pos[0].field_1 + k) = j; + *(uint16 *)(&hdma_window_1_left_pos[1].field_1 + k) = j; + } else { + *(&hdma_window_1_left_pos[0].field_0 + k) = a; + *(uint16 *)(&hdma_window_1_left_pos[0].field_1 + k) = j; + } +} + +uint16 AddExpandingSqTransRightIndirHDMA(uint16 a, uint16 k, uint16 j) { // 0x81AC2D + if ((a & 0x80) != 0) { + *(&hdma_window_1_right_pos[0].field_0 + k) = a - 127; + *(&hdma_window_1_right_pos[1].field_0 + k) = 127; + *(uint16 *)(&hdma_window_1_right_pos[0].field_1 + k) = j; + *(uint16 *)(&hdma_window_1_right_pos[1].field_1 + k) = j; + return k + 6; + } else { + *(&hdma_window_1_right_pos[0].field_0 + k) = a; + *(uint16 *)(&hdma_window_1_right_pos[0].field_1 + k) = j; + return k + 3; + } +} + +void FileSelectMap_8_ExpandSquareTransToRoomSelectMap(void) { // 0x81AC66 + if ((HandleRoomSelectMapExpandingSquareTrans() & 0x8000u) != 0) { + ++menu_index; + reg_TM = 2; + reg_TMW = 0; + reg_TSW = 0; + reg_TS = 0; + } + DrawAreaSelectMapLabels(); +} + +uint16 HandleRoomSelectMapExpandingSquareTrans(void) { // 0x81AC84 + uint16 v0 = (__PAIR32__(expanding_square_left_vel, expanding_square_left_subvel) + + __PAIR32__(expanding_square_left_pos, expanding_square_left_subpos)) >> 16; + expanding_square_left_subpos += expanding_square_left_subvel; + if (sign16(v0 - 1)) + v0 = 1; + expanding_square_left_pos = v0; + uint16 v1 = (__PAIR32__(expanding_square_right_vel, expanding_square_right_subvel) + + __PAIR32__(expanding_square_right_pos, expanding_square_right_subpos)) >> 16; + expanding_square_right_subpos += expanding_square_right_subvel; + if (!sign16(v1 - 256)) + v1 = 255; + expanding_square_right_pos = v1; + uint16 v2 = (__PAIR32__(expanding_square_top_vel, expanding_square_top_subvel) + + __PAIR32__(expanding_square_top_pos, expanding_square_top_subpos)) >> 16; + expanding_square_top_subpos += expanding_square_top_subvel; + if (sign16(v2 - 1)) + v2 = 1; + expanding_square_top_pos = v2; + uint16 v3 = (__PAIR32__(expanding_square_bottom_vel, expanding_square_bottom_subvel) + + __PAIR32__(expanding_square_bottom_pos, expanding_square_bottom_subpos)) >> 16; + expanding_square_bottom_subpos += expanding_square_bottom_subvel; + if (!sign16(v3 - 224)) + v3 = 224; + expanding_square_bottom_pos = v3; + SetupRoomSelectMapExpandingSquareTransHDMA(); + return --expanding_square_timer; +} + +void FileSelectMap_9_InitRoomSelectMap(void) { // 0x81AD17 + LoadMirrorOfExploredMapTiles(); + DrawRoomSelectMap(); + LoadFromLoadStation(); + DisableHdmaObjects(); + WaitUntilEndOfVblankAndClearHdma(); + RoomDefHeader *RoomDefHeader = get_RoomDefHeader(room_ptr); + LOBYTE(area_index) = RoomDefHeader->area_index_; + LOBYTE(room_x_coordinate_on_map) = RoomDefHeader->x_coordinate_on_map; + LOBYTE(room_y_coordinate_on_map) = RoomDefHeader->y_coordinate_on_map; + SetupMapScrollingForFileSelectMap(); + map_min_y_scroll += 24; + reg_BG2VOFS = 24; + *(uint16 *)®_TM &= ~4u; + ++menu_index; + map_scrolling_direction = 0; + map_scrolling_speed_index = 0; + samus_position_indicator_animation_frame = 0; + samus_position_indicator_animation_timer = 0; + samus_position_indicator_animation_loop_counter = 0; +} + +void FileSelectMap_10_RoomSelectMap(void) { // 0x81AD7F + int16 v1; + VoidP *v2; + int16 v3; + char v4; // cf + int16 v5; + int16 v8; + + DrawFileSelectMapIcons(); + HandleFileSelectMapScrollArrows(); + MapScrolling(); + DisplayMapElevatorDestinations(); + if (enable_debug && (joypad2_new_keys & kButton_Select) != 0) { + QueueSfx1_Max6(0x38u); + R0_.bank = -126; + R24_ = *(uint16 *)&used_save_stations_and_elevators[(uint16)(2 * area_index)]; + v1 = load_station_index; + do { + R24_ >>= 1; + --v1; + } while (v1 >= 0); + v2 = (VoidP *)RomPtr_82(2 * area_index - 14325); + while (!*v2) + ; + R0_.addr = *v2; + v3 = 4 * load_station_index; + R18_ = *(uint16 *)IndirPtr(&R0_, 4 * load_station_index); + R20_ = *(uint16 *)IndirPtr(&R0_, v3 + 2); + if (!sign16(load_station_index - 16)) + goto LABEL_23; + do { + if (!sign16(++load_station_index - 16)) { + while (1) { + v5 = *(uint16 *)IndirPtr(&R0_, 4 * load_station_index); + if (v5 == -1) + break; + if (v5 != -2) + goto LABEL_25; +LABEL_23: + ++load_station_index; + } + load_station_index = 0; + R24_ = *(uint16 *)&used_save_stations_and_elevators[(uint16)(2 * area_index)]; + } + v4 = R24_ & 1; + R24_ >>= 1; + } while (!v4 || *(uint16 *)IndirPtr(&R0_, 4 * load_station_index) >= 0xFFFEu); +LABEL_25:; + uint16 v6 = 4 * load_station_index; + uint8 *v7 = IndirPtr(&R0_, 4 * load_station_index); + if (sign16(*(uint16 *)v7 - reg_BG1HOFS) || !sign16(*(uint16 *)v7 - 256 - reg_BG1HOFS)) { + v8 = reg_BG1HOFS + *(uint16 *)IndirPtr(&R0_, v6) - R18_; + if (v8 >= 0) { + if ((int16)(v8 - map_min_x_scroll) >= 0) + v8 = map_min_x_scroll; + } else { + v8 = 0; + } + reg_BG1HOFS = v8; + } + uint16 v9 = v6 + 2; + uint8 *v10 = IndirPtr(&R0_, v9); + if (sign16(*(uint16 *)v10 - reg_BG1VOFS) || !sign16(*(uint16 *)v10 - 161 - reg_BG1VOFS)) { + uint16 v11 = reg_BG1VOFS + *(uint16 *)IndirPtr(&R0_, v9) - R20_; + if ((int16)(v11 - map_min_y_scroll) >= 0) + v11 = map_min_y_scroll; + reg_BG1VOFS = v11; + } + } else if ((joypad1_newkeys & 0x8000u) != 0) { + menu_index += 5; + uint16 v0 = 0; + while (area_index != kFileSelectMap_AreaIndexes[v0 >> 1]) { + v0 += 2; + if ((int16)(v0 - 12) >= 0) { + file_select_map_area_index = 0; + return; + } + } + file_select_map_area_index = v0 >> 1; + QueueSfx1_Max6(0x3Cu); + } else if ((joypad1_newkeys & (kButton_Start | kButton_A)) != 0) { + ++menu_index; + QueueSfx1_Max6(0x38u); + } +} + +void sub_81AEC8(void) { // 0x81AEC8 + HandleFileSelectMapScrollArrows(); +} + +void HandleFileSelectMapScrollArrows(void) { // 0x81AECA + if (sign16(map_min_x_scroll - 24 - reg_BG1HOFS)) + DrawMapScrollArrowAndCheckToScroll(0x81, addr_kLeftMapScrollArrowData); + if (!sign16(map_max_x_scroll - 232 - reg_BG1HOFS)) + DrawMapScrollArrowAndCheckToScroll(0x81, addr_kRightMapScrollArrowData); + if (sign16(map_min_y_scroll - 64 - reg_BG1VOFS)) + DrawMapScrollArrowAndCheckToScroll(0x81, addr_kUpMapScrollArrowData); + if (sign16(map_max_y_scroll - 145 - reg_BG1VOFS)) { + if (map_scrolling_direction == kDownMapScrollArrowData.map_scroll_dir) { + map_scrolling_gear_switch_timer = 0; + map_scrolling_direction = 0; + map_scrolling_speed_index = 0; + } + } else { + DrawMapScrollArrowAndCheckToScroll(0x81, addr_kDownMapScrollArrowData); + } +} + +void FileSelectMap_11(void) { // 0x81AF5A + DrawFileSelectMapIcons(); + DisplayMapElevatorDestinations(); + ++menu_index; +} + +void FileSelectMap_13(void) { // 0x81AF66 + DrawFileSelectMapIcons(); + DisplayMapElevatorDestinations(); + HandleFadeOut(); + if ((reg_INIDISP & 0xF) == 0) { + ++menu_index; + enemy_data[0].x_pos = 32; + } +} + +void FileSelectMap_14(void) { // 0x81AF83 + if (!--enemy_data[0].x_pos) { + ScreenOff(); + ++game_state; + menu_index = 0; + } +} + +void FileSelectMap_15_ClearTileMap(void) { // 0x81AF97 + reg_TM = 18; + for (int i = 2046; i >= 0; i -= 2) + *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + (uint16)i) = 15; + uint16 v1 = vram_write_queue_tail; + VramWriteEntry *v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 2048; + v2->src.addr = ADDR16_OF_RAM(ram3000.pause_menu_map_tilemap); + *(uint16 *)&v2->src.bank = 126; + v2->vram_dst = (reg_BG1SC & 0xFC) << 8; + vram_write_queue_tail = v1 + 7; + ++menu_index; +} + +void FileSelectMap_16_LoadPalettes(void) { // 0x81AFD3 + int16 v0; + int16 v1; + + LoadMenuPalettes(); + v0 = 0; + do { + v1 = v0; + LoadInactiveAreaMapForegroundColors(v0++); + } while ((int16)(v1 - 5) < 0); + LoadActiveAreaMapForegroundColors(area_index); + LoadAreaSelectBackgroundTilemap(area_index); + ++menu_index; +} + +void FileSelectMap_20_SetupExpandingSquare(void) { // 0x81AFF6 + reg_HDMAEN = 0; + QueueSfx1_Max6(0x3Cu); + expanding_square_timer = kRoomSelectMapExpandingSquareTimers[area_index] - 12; + expanding_square_left_subvel = *(uint16 *)((char *)&kExpandingSquareVels[0].left_subvel + + (uint16)(16 * area_index)); + expanding_square_left_vel = *(uint16 *)((char *)&kExpandingSquareVels[0].left_vel + (uint16)(16 * area_index)); + expanding_square_right_subvel = *(uint16 *)((char *)&kExpandingSquareVels[0].right_subvel + + (uint16)(16 * area_index)); + expanding_square_right_vel = *(uint16 *)((char *)&kExpandingSquareVels[0].right_vel + + (uint16)(16 * area_index)); + expanding_square_top_subvel = *(uint16 *)((char *)&kExpandingSquareVels[0].top_subvel + + (uint16)(16 * area_index)); + expanding_square_top_vel = *(uint16 *)((char *)&kExpandingSquareVels[0].top_vel + (uint16)(16 * area_index)); + expanding_square_bottom_subvel = *(uint16 *)((char *)&kExpandingSquareVels[0].bottom_subvel + + (uint16)(16 * area_index)); + expanding_square_bottom_vel = *(uint16 *)((char *)&kExpandingSquareVels[0].bottom_vel + + (uint16)(16 * area_index)); + expanding_square_left_pos = 8; + expanding_square_right_pos = 248; + expanding_square_top_pos = 8; + expanding_square_bottom_pos = 216; + expanding_square_left_subpos = 0; + expanding_square_right_subpos = 0; + expanding_square_top_subpos = 0; + expanding_square_bottom_subpos = 0; + SetupRoomSelectMapExpandingSquareTransHDMA(); + ++menu_index; + reg_HDMAEN = 12; + WriteReg(HDMAEN, 0xCu); + reg_W12SEL = 50; + WriteReg(W12SEL, 0x32u); + reg_W34SEL = 2; + WriteReg(W34SEL, 2u); + reg_BG12NBA = 48; + reg_WOBJSEL = 34; + hdma_window_1_left_pos[3].field_0 = 0; + hdma_window_1_right_pos[3].field_0 = 0; + reg_BG1VOFS = 0; + reg_BG1HOFS = 0; +} + +void FileSelectMap_21_MoveExpandingSquare(void) { // 0x81B0BB + uint16 v0 = (__PAIR32__(expanding_square_left_pos, expanding_square_left_subpos) + - __PAIR32__(expanding_square_left_vel, expanding_square_left_subvel)) >> 16; + expanding_square_left_subpos -= expanding_square_left_subvel; + expanding_square_left_pos = v0; + uint16 v1 = (__PAIR32__(expanding_square_right_pos, expanding_square_right_subpos) + - __PAIR32__(expanding_square_right_vel, expanding_square_right_subvel)) >> 16; + expanding_square_right_subpos -= expanding_square_right_subvel; + expanding_square_right_pos = v1; + uint16 v2 = (__PAIR32__(expanding_square_top_pos, expanding_square_top_subpos) + - __PAIR32__(expanding_square_top_vel, expanding_square_top_subvel)) >> 16; + expanding_square_top_subpos -= expanding_square_top_subvel; + expanding_square_top_pos = v2; + uint16 v3 = (__PAIR32__(expanding_square_bottom_pos, expanding_square_bottom_subpos) + - __PAIR32__(expanding_square_bottom_vel, expanding_square_bottom_subvel)) >> 16; + expanding_square_bottom_subpos -= expanding_square_bottom_subvel; + expanding_square_bottom_pos = v3; + SetupRoomSelectMapExpandingSquareTransHDMA(); + DrawAreaSelectMapLabels(); + if ((--expanding_square_timer & 0x8000u) != 0) { + menu_index -= 15; + reg_TM = 17; + reg_TMW = 0; + reg_TSW = 0; + } +} + +void NewSaveFile(void) { // 0x81B2CB + samus_max_health = 99; + samus_health = 99; + samus_max_missiles = 0; + samus_missiles = 0; + samus_max_super_missiles = 0; + samus_super_missiles = 0; + samus_max_power_bombs = 0; + samus_power_bombs = 0; + hud_item_index = 0; + collected_beams = 0; + equipped_beams = 0; + collected_items = 0; + equipped_items = 0; + reserve_health_mode = 0; + samus_max_reserve_health = 0; + samus_reserve_health = 0; + samus_reserve_missiles = 0; + button_config_up = kButton_Up; + button_config_down = kButton_Down; + button_config_left = kButton_Left; + button_config_right = kButton_Right; + button_config_jump_a = kButton_A; + button_config_run_b = kButton_B; + button_config_shoot_x = kButton_X; + button_config_itemcancel_y = kButton_Y; + button_config_itemswitch = kButton_Select; + button_config_aim_up_R = kButton_R; + button_config_aim_down_L = kButton_L; + game_time_frames = 0; + game_time_seconds = 0; + game_time_minutes = 0; + game_time_hours = 0; + japanese_text_flag = 0; + moonwalk_flag = 0; + hud_auto_cancel_flag = 0; + debug_flag = 1; + UNUSED_word_7E09E8 = 1; + uint16 v0 = 0; + do { + int v1 = v0 >> 1; + WORD(room_chozo_bits[v0]) = 0; + *(uint16 *)&item_bit_array[v0] = 0; + *(uint16 *)&item_bit_array[v0] = 0; + WORD(opened_door_bit_array[v0]) = 0; + UNUSED_word_7ED8F0[v1] = 0; + *(uint16 *)&map_station_byte_array[v0] = 0; + *(uint16 *)&used_save_stations_and_elevators[v0] = 0; + *(uint16 *)&used_save_stations_and_elevators[v0 + 8] = 0; + v0 += 2; + } while ((int16)(v0 - 8) < 0); + do { + int v2 = v0 >> 1; + WORD(room_chozo_bits[v0]) = 0; + *(uint16 *)&item_bit_array[v0] = 0; + *(uint16 *)&item_bit_array[v0] = 0; + WORD(opened_door_bit_array[v0]) = 0; + v0 += 2; + } while ((int16)(v0 - 64) < 0); + uint16 v3 = 0; + do { + explored_map_tiles_saved[v3 >> 1] = 0; + v3 += 2; + } while ((int16)(v3 - 1792) < 0); +} + +void FileSelectClearRestOfMenuTilemapRow(uint16 v0) { // 0x81B3C5 + R18_ = 32 - ((uint8)(v0 & 0x3F) >> 1); + do { + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[768] + v0) = 15; + v0 += 2; + --R18_; + } while (R18_); +} + +void LoadMenuTilemap(uint16 k, uint16 j) { // 0x81B3E2 + int16 v2; + int k_bak = k; + + while (1) { + while (1) { + v2 = *(uint16 *)RomPtr_81(j); + if (v2 != -2) + break; + j += 2; + k = (k_bak += 64); + } + if (v2 == -1) + break; + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[768] + k) = enemy_data[0].palette_index | v2; + k += 2; + j += 2; + } +} diff --git a/src/sm_82.c b/src/sm_82.c new file mode 100644 index 0000000..3aff73b --- /dev/null +++ b/src/sm_82.c @@ -0,0 +1,5567 @@ +// Top level main game routines + +#include "sm_rtl.h" +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" + +#define kDemoRoomData ((uint16*)RomPtr(0x82876c)) +void CallDemoRoomDataFunc(uint32 ea) { + switch (ea) { + case fnDemoRoom_ChargeBeamRoomScroll21: DemoRoom_ChargeBeamRoomScroll21(); return; + case fnnullsub_291: return; + case fnDemoRoom_SetBG2TilemapBase: DemoRoom_SetBG2TilemapBase(); return; + case fnDemoRoom_SetKraidFunctionTimer: DemoRoom_SetKraidFunctionTimer(); return; + case fnDemoRoom_SetBrinstarBossBits: DemoRoom_SetBrinstarBossBits(); return; + default: Unreachable(); + } +} + +CoroutineRet InitAndLoadGameData_Async(void) { // 0x828000 + int16 v0; + int16 v2; + int16 v4; + int16 v7; + + COROUTINE_BEGIN(coroutine_state_1, 0) + + if (game_state == kGameState_40_TransitionToDemo) { + InitIoForGameplay(); + LoadStdBG3andSpriteTilesClearTilemaps(); + LoadInitialPalette(); + Samus_Initialize(); + LoadDemoRoomData(); + } else { + if (loading_game_state != kLoadingGameState_5_Main) { + if (loading_game_state == kLoadingGameState_1F_StartingAtCeres) { + area_index = 6; + load_station_index = 0; + ClearTimerRam(); + } else if (loading_game_state == kLoadingGameState_22_EscapingCeres) { + area_index = 0; + load_station_index = 18; + LoadMirrorOfExploredMapTiles(); + } + } + InitIoForGameplay(); + LoadStdBG3andSpriteTilesClearTilemaps(); + LoadInitialPalette(); + Samus_Initialize(); + LoadFromLoadStation(); + } + COROUTINE_AWAIT(1, StartGameplay_Async()); + InitializeHud(); + // nullsub_4(); + { + v0 = 32; + uint16 v1 = 0; + do { + target_palettes[(v1 >> 1) + 192] = palette_buffer[(v1 >> 1) + 192]; + v1 += 2; + v0 -= 2; + } while (v0); + } + screen_fade_delay = 1; + screen_fade_counter = 1; + EnableNMI(); + EnableEnemyProjectiles(); + EnablePLMs(); + EnablePaletteFx(); + EnableHdmaObjects(); + EnableAnimtiles(); + SetLiquidPhysicsType(); + if (game_state == kGameState_40_TransitionToDemo) { + loop_counter_transfer_enemies_to_vram = 6; + do { + TransferEnemyTilesToVramAndInit(); + COROUTINE_AWAIT(2, WaitForNMI_Async()); + --loop_counter_transfer_enemies_to_vram; + } while ((loop_counter_transfer_enemies_to_vram & 0x8000u) == 0); + R18_ = 18 * (demo_scene - 1); + R18_ = get_DemoRoomData(R18_ + kDemoRoomData[demo_set])->demo_code_ptr; + CallDemoRoomDataFunc(R18_ | 0x820000); + ++game_state; + v7 = 512; + uint16 v8 = 0; + do { + palette_buffer[v8 >> 1] = target_palettes[v8 >> 1]; + v8 += 2; + v7 -= 2; + } while (v7); + } else if (loading_game_state == kLoadingGameState_22_EscapingCeres) { + QueueMusic_Delayed8(5u); + loop_counter_transfer_enemies_to_vram = 15; + do { + TransferEnemyTilesToVramAndInit(); + COROUTINE_AWAIT(3, WaitForNMI_Async()); + --loop_counter_transfer_enemies_to_vram; + } while ((loop_counter_transfer_enemies_to_vram & 0x8000u) == 0); + ++game_state; + v2 = 512; + uint16 v3 = 0; + do { + palette_buffer[v3 >> 1] = target_palettes[v3 >> 1]; + v3 += 2; + v2 -= 2; + } while (v2); + } else { + loop_counter_transfer_enemies_to_vram = 6; + do { + TransferEnemyTilesToVramAndInit(); + COROUTINE_AWAIT(4, WaitForNMI_Async()); + --loop_counter_transfer_enemies_to_vram; + } while ((loop_counter_transfer_enemies_to_vram & 0x8000u) == 0); + game_state = kGameState_7_MainGameplayFadeIn; + v4 = 512; + uint16 v5 = 0; + do { + palette_buffer[v5 >> 1] = target_palettes[v5 >> 1]; + v5 += 2; + v4 -= 2; + } while (v4); + if (loading_game_state == kLoadingGameState_1F_StartingAtCeres) { + palette_buffer[223] = 0; + CallSomeSamusCode(8u); + } else { + CallSomeSamusCode(9u); + } + } + + COROUTINE_END(0); +} + +void InitIoForGameplay(void) { // 0x82819B + InitCpuForGameplay(); + InitPpuForGameplay(); +} + +void InitCpuForGameplay(void) { // 0x8281A4 + WriteReg(NMITIMEN, 1u); + reg_NMITIMEN = 1; + WriteReg(WRIO, 0); + WriteReg(WRMPYA, 0); + WriteReg(WRMPYB, 0); + WriteReg(WRDIVL, 0); + WriteReg(WRDIVH, 0); + WriteReg(WRDIVB, 0); + WriteReg(HTIMEL, 0); + WriteReg(HTIMEH, 0); + WriteReg(VTIMEL, 0); + WriteReg(VTIMEH, 0); + WriteReg(MDMAEN, 0); + WriteReg(HDMAEN, 0); + reg_HDMAEN = 0; + WriteReg(MEMSEL, 1u); + reg_MEMSEL = 1; +} + +void InitPpuForGameplay(void) { // 0x8281DD + WriteReg(INIDISP, 0x80); + reg_INIDISP = 0x80; + WriteReg(OBSEL, 3u); + reg_OBSEL = 3; + WriteReg(OAMADDL, 0); + LOBYTE(reg_OAMaddr_UNUSED) = 0; + WriteReg(OAMADDH, 0x80); + HIBYTE(reg_OAMaddr_UNUSED) = 0x80; + WriteReg(OAMDATA, 0); + WriteReg(OAMDATA, 0); + WriteReg(BGMODE, 9u); + reg_BGMODE = 9; + WriteReg(MOSAIC, 0); + reg_MOSAIC = 0; + reg_BG12NBA = 0; + WriteReg(BG12NBA, 0); + reg_BG34NBA = 4; + WriteReg(BG34NBA, 4u); + reg_BG1SC = 81; + WriteReg(BG1SC, 0x51u); + reg_BG2SC = 73; + WriteReg(BG2SC, 0x49u); + reg_BG3SC = 90; + WriteReg(BG3SC, 0x5Au); + reg_BG4SC = 0; + WriteReg(BG4SC, 0); + WriteReg(VMAIN, 0); + WriteReg(W12SEL, 0); + reg_W12SEL = 0; + WriteReg(W12SEL, 0); + reg_W12SEL = 0; + WriteReg(W34SEL, 0); + reg_W34SEL = 0; + WriteReg(WOBJSEL, 0); + reg_WOBJSEL = 0; + WriteReg(WH0, 0); + reg_WH0 = 0; + WriteReg(WH1, 0); + reg_WH1 = 0; + WriteReg(WH2, 0); + reg_WH2 = 0; + WriteReg(WH3, 0); + reg_WH3 = 0; + WriteReg(WBGLOG, 0); + reg_WBGLOG = 0; + WriteReg(WOBJLOG, 0); + reg_WOBJLOG = 0; + WriteReg(TM, 0x17u); + reg_TM = 23; + WriteReg(TMW, 0); + reg_TMW = 0; + WriteReg(TS, 0); + reg_TS = 0; + WriteReg(TSW, 0); + reg_TSW = 0; + WriteReg(CGWSEL, 0); + next_gameplay_CGWSEL = 0; + WriteReg(CGADSUB, 0); + next_gameplay_CGADSUB = 0; + WriteReg(COLDATA, 0xE0u); + WriteReg(SETINI, 0); + reg_SETINI = 0; + oam_next_ptr = 0; + memset7E(ADDR16_OF_RAM(ram3000), 0, 0x7FEu); + memset7E(ADDR16_OF_RAM(ram4000), 0x6Fu, 0x7FEu); + memset7E(ADDR16_OF_RAM(ram4000.bg2_tilemap), 0x2C0Fu, 0xFEu); +} + +#define kInitialPalette ((uint16*)RomPtr(0x9a8000)) + +void LoadInitialPalette(void) { // 0x8282C5 + int16 v0; + + v0 = 512; + uint16 v1 = 0; + do { + palette_buffer[v1 >> 1] = kInitialPalette[v1 >> 1]; + v1 += 2; + v0 -= 2; + } while (v0); +} + +void LoadStdBG3andSpriteTilesClearTilemaps(void) { // 0x8282E2 + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x40u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8282F8 = { 1, 1, 0x18, LONGPTR(0x9ab200), 0x2000 }; + SetupDmaTransfer(&unk_8282F8); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_828318 = { 1, 1, 0x18, LONGPTR(0x9ad200), 0x4000 }; + SetupDmaTransfer(&unk_828318); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x50u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_828338 = { 1, 1, 0x18, LONGPTR(0x7e4000), 0x1000 }; + SetupDmaTransfer(&unk_828338); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x58u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_828358 = { 1, 1, 0x18, LONGPTR(0x7e4000), 0x0800 }; + SetupDmaTransfer(&unk_828358); + WriteReg(MDMAEN, 2u); +} + +CoroutineRet GameState_32_MadeItToCeresElevator(void) { // 0x828367 + if (timer_status) + DrawTimer(); + GameState_8_MainGameplay(); + bool v0 = (--reached_ceres_elevator_fade_timer & 0x8000u) != 0; + if (!reached_ceres_elevator_fade_timer || v0) { + ++game_state; + screen_fade_delay = 0; + screen_fade_counter = 0; + } + return kCoroutineNone; +} + +CoroutineRet GameState_33_BlackoutFromCeres(void) { // 0x828388 + if (timer_status) + DrawTimer(); + GameState_8_MainGameplay(); + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + WaitUntilEndOfVblankAndClearHdma(); + DisableIrqInterrupts(); + fx_layer_blending_config_a = 0; + cur_irq_handler = 0; + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = 0; + reg_TM = 16; + reg_TS = 0; + reg_TMW = 0; + reg_TSW = 0; + reg_BGMODE = 9; + screen_fade_delay = 0; + screen_fade_counter = 0; + loading_game_state = kLoadingGameState_22_EscapingCeres; + game_state = 34; + SaveToSram(selected_save_slot); + cinematic_function = FUNC16(CinematicFunctionBlackoutFromCeres); + ceres_status = 0; + timer_status = 0; + QueueMusic_Delayed8(0); + QueueSfx1_Max15(2u); + QueueSfx2_Max15(0x71u); + QueueSfx3_Max15(1u); + } + return kCoroutineNone; +} + +CoroutineRet GameState_35_TimeUp(void) { // 0x828411 + GameState_8_MainGameplay(); + palette_change_denom = 8; + if (AdvancePaletteFadeForAllPalettes()) { + game_state = kGameState_36_WhitingOutFromTimeUp; + screen_fade_delay = 0; + screen_fade_counter = 0; + } + return kCoroutineNone; +} + +CoroutineRet GameState_36_WhitingOutFromTimeUp(void) { // 0x828431 + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + WaitUntilEndOfVblankAndClearHdma(); + DisableIrqInterrupts(); + fx_layer_blending_config_a = 0; + cur_irq_handler = 0; + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = 0; + reg_TM = 16; + reg_TS = 0; + reg_TMW = 0; + reg_TSW = 0; + reg_BGMODE = 9; + screen_fade_delay = 0; + screen_fade_counter = 0; + ceres_status = 0; + timer_status = 0; + QueueSfx1_Max15(2u); + QueueSfx2_Max15(0x71u); + QueueSfx3_Max15(1u); + if (CheckEventHappened(0xEu)) { + game_options_screen_index = 0; + menu_index = 0; + for (int i = 254; i >= 0; i -= 2) + enemy_projectile_y_subpos[(i >> 1) + 15] = 0; + game_state = kGameState_25_SamusNoHealth; + } else { + game_state = kGameState_37_CeresGoesBoomWithSamus; + cinematic_function = FUNC16(CinematicFunctionBlackoutFromCeres); + } + } + return kCoroutineNone; +} + +CoroutineRet GameState_38_SamusEscapesFromZebes(void) { // 0x8284BD + GameState_8_MainGameplay(); + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + WaitUntilEndOfVblankAndClearHdma(); + DisableIrqInterrupts(); + fx_layer_blending_config_a = 0; + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = 0; + reg_TM = 16; + reg_TS = 0; + reg_TMW = 0; + reg_TSW = 0; + reg_BGMODE = 9; + screen_fade_delay = 0; + screen_fade_counter = 0; + game_state = kGameState_39_EndingAndCredits; + cinematic_function = FUNC16(CinematicFunctionEscapeFromCebes); + timer_status = 0; + QueueMusic_Delayed8(0); + QueueSfx1_Max15(2u); + QueueSfx2_Max15(0x71u); + QueueSfx3_Max15(1u); + } + return kCoroutineNone; +} + +CoroutineRet GameState_41_TransitionToDemo(void) { // 0x82852D + GameState_8_MainGameplay(); + HdmaObjectHandler(); + ++game_state; + reg_INIDISP = 15; + return kCoroutineNone; +} + +CoroutineRet GameState_42_PlayingDemo_Async(void) { // 0x828548 + COROUTINE_BEGIN(coroutine_state_3, 0) +// assert(0); + GameState_8_MainGameplay(); + if (joypad1_newkeys) { + substate = 1; + goto LABEL_10; + } + demo_timer--; + if (!demo_timer || (demo_timer & 0x8000u) != 0) { + substate = 0; + my_counter = 90; + while (1) { + COROUTINE_AWAIT(1, WaitForNMI_Async()); + if (joypad1_newkeys) + break; + if (!--my_counter) + goto LABEL_10; + } + substate = 1; + +LABEL_10: + ++game_state; + debug_disable_sounds = 0; + reg_INIDISP = 0x80; + screen_fade_delay = 1; + screen_fade_counter = 1; + } + COROUTINE_END(0); +} + +CoroutineRet GameState_43_TransitionFromDemo(void) { // 0x828593 + if (substate != 1) + CheckForNextDemo(); + EnableNMI(); + ++game_state; + screen_fade_delay = 0; + screen_fade_counter = 0; + WaitUntilEndOfVblankAndClearHdma(); + DisableIrqInterrupts(); + fx_layer_blending_config_a = 0; + cur_irq_handler = 0; + irqhandler_next_handler = 0; + DisablePaletteFx(); + ClearPaletteFXObjects(); + for (int i = 656; i >= 0; i -= 2) + *(uint16 *)((char *)&enemy_projectile_enable_flag + i) = 0; + for (int j = 538; j >= 0; j -= 2) + *(uint16 *)((char *)&hud_item_tilemap_palette_bits + j) = 0; + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = 0; + reg_TM = 16; + reg_TS = 0; + reg_TMW = 0; + reg_TSW = 0; + return kCoroutineNone; +} + +CoroutineRet GameState_44_TransitionFromDemo(void) { // 0x8285FB + game_state = kGameState_1_OpeningCinematic; + if ((substate & 0x8000u) != 0) { + game_state = kGameState_40_TransitionToDemo; + } else if (substate) { + LoadTitleSequenceGraphics(); + enemy_projectile_x_pos[4] = 2; + cinematic_function = FUNC16(CinematicFunctionNone); + } else { + QueueMusic_Delayed8(0); + debug_disable_sounds = 0; + cinematic_function = FUNC16(CinematicFunctionOpening); + } + return kCoroutineNone; +} + +#define kDemoRoomData ((uint16*)RomPtr(0x82876c)) + +void CheckForNextDemo(void) { // 0x828637 + R18_ = 2 * (demo_scene + 8 * demo_scene); + if (*(uint16 *)RomPtr_82(R18_ + kDemoRoomData[demo_set]) == 0xFFFF) { + substate = 0; + uint16 v0 = demo_set + 1; + if ((uint16)(demo_set + 1) >= num_demo_sets) + v0 = 0; + demo_set = v0; + demo_scene = 0; + } else { + substate = 0x8000; + } +} + +void LoadDemoRoomData(void) { // 0x828679 + DemoRoomData *drd; + + door_def_ptr = 0; + R18_ = 18 * demo_scene; + drd = get_DemoRoomData(18 * demo_scene + kDemoRoomData[demo_set]); + room_ptr = drd->room_ptr_; + door_def_ptr = drd->door_ptr; + door_bts = drd->door_slot; + layer1_x_pos = drd->screen_x_pos; + bg1_x_offset = layer1_x_pos; + layer1_y_pos = drd->screen_y_pos; + bg1_y_offset = layer1_y_pos; + samus_y_pos = layer1_y_pos + drd->samus_x_offs; + samus_prev_y_pos = samus_y_pos; + samus_x_pos = drd->samus_y_offs + layer1_x_pos + 128; + samus_prev_x_pos = samus_x_pos; + demo_timer = drd->demo_length; + LOBYTE(area_index) = get_RoomDefHeader(room_ptr)->area_index_; + reg_BG1HOFS = 0; + reg_BG1VOFS = 0; + ++demo_scene; + uint16 v1 = 0; + do { + int v2 = v1 >> 1; + WORD(room_chozo_bits[v1]) = -1; + *(uint16 *)&item_bit_array[v1] = -1; + UNUSED_word_7ED8F0[v2] = -1; + *(uint16 *)&map_station_byte_array[v1] = -1; + *(uint16 *)&used_save_stations_and_elevators[v1] = -1; + *(uint16 *)&used_save_stations_and_elevators[v1 + 8] = -1; + WORD(opened_door_bit_array[v1]) = 0; + WORD(events_that_happened[v1]) = 0; + *(uint16 *)&boss_bits_for_area[v1] = 0; + v1 += 2; + } while ((int16)(v1 - 8) < 0); + do { + int v3 = v1 >> 1; + WORD(room_chozo_bits[v1]) = -1; + *(uint16 *)&item_bit_array[v1] = -1; + WORD(opened_door_bit_array[v1]) = 0; + v1 += 2; + } while ((int16)(v1 - 64) < 0); + uint16 v4 = 0; + do { + explored_map_tiles_saved[v4 >> 1] = 0; + v4 += 2; + } while ((int16)(v4 - 1536) < 0); + samus_max_reserve_health = 0; + samus_reserve_health = 0; + reserve_health_mode = 0; + loading_game_state = kLoadingGameState_0_Intro; + debug_disable_minimap = 0; +} + +void DemoRoom_ChargeBeamRoomScroll21(void) { // 0x82891A + scrolls[33] = 0; +} + +void DemoRoom_SetBG2TilemapBase(void) { // 0x828925 + *(uint16 *)®_BG2SC = 74; +} + +void DemoRoom_SetKraidFunctionTimer(void) { // 0x82892B + enemy_data[0].ai_preinstr = 60; +} + +void DemoRoom_SetBrinstarBossBits(void) { // 0x828932 + boss_bits_for_area[1] = 1; +} + +static Func_V_Coroutine *const kGameStateFuncs[45] = { + GameState_0_Reset_Async, + GameState_1_OpeningCinematic, + GameState_2_GameOptionsMenu, + GameState_3_Null, + GameState_4_FileSelectMenus, + GameState_5_FileSelectMap, + InitAndLoadGameData_Async, + GameState_7_MainGameplayFadeIn, + GameState_8_MainGameplay, + GameState_9_HitDoorBlock, + GameState_10_LoadingNextRoom_Async, + GameState_11_LoadingNextRoom_Async, + GameState_12_Pausing_Darkening_Async, + GameState_13_Pausing_Async, + GameState_14_Paused_Async, + GameState_15_Paused_Async, + GameState_16_Unpausing_Async, + GameState_17_Unpausing_Async, + GameState_18_Unpausing, + GameState_19_SamusNoHealth, + GameState_20_SamusNoHealth_BlackOut, + GameState_21_SamusNoHealth, + GameState_22_SamusNoHealth_Dying, + GameState_23_SamusNoHealth_Flashing, + GameState_24_SamusNoHealth_Explosion, + GameState_25_SamusNoHealth_BlackOut, + GameState_26_GameOverMenu, + GameState_27_ReserveTanksAuto, + GameState_28_Unused, + GameState_29_DebugGameOverMenu, + GameState_37_CeresGoesBoomWithSamus, + InitAndLoadGameData_Async, + GameState_32_MadeItToCeresElevator, + GameState_33_BlackoutFromCeres, + GameState_37_CeresGoesBoomWithSamus, + GameState_35_TimeUp, + GameState_36_WhitingOutFromTimeUp, + GameState_37_CeresGoesBoomWithSamus, + GameState_38_SamusEscapesFromZebes, + GameState_39_EndingAndCredits, + InitAndLoadGameData_Async, + GameState_41_TransitionToDemo, + GameState_42_PlayingDemo_Async, + GameState_43_TransitionFromDemo, + GameState_44_TransitionFromDemo, +}; + +CoroutineRet RunGameStateTrampoline_Async(void) { + // printf("gamestate %d\n", game_state); + return kGameStateFuncs[(uint16)(2 * (uint8)game_state) >> 1](); +} + +CoroutineRet RunOneFrameOfGameInner(void) { + COROUTINE_BEGIN(coroutine_state_0, 1: case 2: case 3); + COROUTINE_AWAIT_ONLY(Vector_RESET_Async()) + COROUTINE_MANUAL_POS(0); + ReadJoypadInputs(); + HdmaObjectHandler(); + NextRandom(); + ClearOamExt(); + oam_next_ptr = 0; + nmi_copy_samus_halves = 0; + nmi_copy_samus_top_half_src = 0; + nmi_copy_samus_bottom_half_src = 0; + COROUTINE_AWAIT(4, RunGameStateTrampoline_Async()); + HandleSoundEffects(); + ClearUnusedOam(); + ShowSpareCpu(); + COROUTINE_END(0); +} + +void RunOneFrameOfGame(void) { // 0x828948 + CoroutineRet ret = RunOneFrameOfGameInner(); + if (ret == 0) + waiting_for_nmi = 1; + + Vector_NMI(); +} + +CoroutineRet GameState_29_DebugGameOverMenu(void) { // 0x8289DB + DebugGameOverMenu(); + return kCoroutineNone; +} + +CoroutineRet GameState_26_GameOverMenu(void) { // 0x8289E0 + GameOverMenu(); + return kCoroutineNone; +} + +CoroutineRet GameState_4_FileSelectMenus(void) { // 0x8289E5 + FileSelectMenu(); + return kCoroutineNone; +} + +CoroutineRet GameState_5_FileSelectMap(void) { // 0x8289EA + FileSelectMap(); + return kCoroutineNone; +} + +static Func_Y_V *const kSfxHandlers[5] = { // 0x8289EF + SfxHandlers_0_SendToApu, + SfxHandlers_1_WaitForAck, + SfxHandlers_2_ClearRequest, + SfxHandlers_3_WaitForAck, + SfxHandlers_4_Reset, +}; + +void HandleSoundEffects(void) { + if ((int8)(sound_handler_downtime - 1) >= 0) { + LOBYTE(sound_handler_downtime) = sound_handler_downtime - 1; + RtlApuWrite(APUI01, 0); + sfx_cur[0] = 0; + RtlApuWrite(APUI02, 0); + sfx_cur[1] = 0; + RtlApuWrite(APUI03, 0); + sfx_cur[2] = 0; + } else { + for (int i = 0; i < 3; ++i) + kSfxHandlers[sfx_state[i]](i); + } +} + +void SfxHandlers_0_SendToApu(uint16 j) { // 0x828A2C + if (sfx_readpos[j] != sfx_writepos[j]) { + uint8 v2 = sfx_readpos[j] + j * 16; + uint8 v3 = sfx1_queue[v2]; + RtlApuWrite((SnesRegs)(j + APUI01), v3); + sfx_cur[j] = v3; + sfx_readpos[j] = (v2 + 1) & 0xF; + ++sfx_state[j]; + } +} + +void SfxHandlers_1_WaitForAck(uint16 j) { // 0x828A55 + // Modified from original + uint8 v1 = sfx_cur[j]; + ++sfx_state[j]; + sfx_clear_delay[j] = 6; +} + +void SfxHandlers_2_ClearRequest(uint16 j) { // 0x828A6C + // Modified from original + if (sfx_clear_delay[j]-- == 1) { + sfx_cur[j] = 0; + ++sfx_state[j]; + } +} + +void SfxHandlers_3_WaitForAck(uint16 j) { // 0x828A7C + // Modified from original + uint8 v1 = sfx_cur[j]; + sfx_state[j] = 0; + SfxHandlers_0_SendToApu(j); +} + +void SfxHandlers_4_Reset(uint16 j) { // 0x828A90 + if (sfx_clear_delay[j]-- == 1) + sfx_state[j] = 0; +} + +void ResetSoundQueues(void) { // 0x828A9A + *(uint16 *)sfx_readpos = 0; + *(uint16 *)&sfx_readpos[2] = 0; + *(uint16 *)&sfx_writepos[1] = 0; + *(uint16 *)sfx_state = 0; + sfx_state[2] = 0; +} + +void ShowSpareCpu(void) { // 0x828AB0 + if ((joypad_dbg_1 & 0x4000) != 0) + debug_spare_cpu_display_flag = debug_spare_cpu_display_flag == 0; + if (debug_spare_cpu_display_flag) + WriteReg(INIDISP, reg_INIDISP & 0xF0 | 5); + joypad1_input_samusfilter = joypad1_lastkeys; +} + +CoroutineRet GameState_0_Reset_Async(void) { // 0x828AE4 + UNUSED_word_7E0DF8 = 0; + UNUSED_word_7E0DFA = 0; + UNUSED_word_7E0DFC = 0; + cinematic_function = FUNC16(CinematicFunctionOpening); + demo_set = 0; + if (num_demo_sets == 4) + demo_set = 3; + ++game_state; + return kCoroutineNone; +} + +CoroutineRet GameState_1_OpeningCinematic(void) { // 0x828B08 + return GameState_1_OpeningCinematic_(); +} + +CoroutineRet GameState_3_Null(void) { + return kCoroutineNone; +} + +CoroutineRet GameState_37_CeresGoesBoomWithSamus(void) { // 0x828B0E + return GameState_37_CeresGoesBoomWithSamus_(); +} + +CoroutineRet GameState_39_EndingAndCredits(void) { // 0x828B13 + return GameState_39_EndingAndCredits_(); +} + +CoroutineRet GameState_7_MainGameplayFadeIn(void) { // 0x828B20 + GameState_8_MainGameplay(); + HandleFadeIn(); + if (reg_INIDISP == 15) { + screen_fade_delay = 0; + screen_fade_counter = 0; + ++game_state; + } + return kCoroutineNone; +} + +CoroutineRet GameState_28_Unused(void) { // 0x828B3F + GameState_28_Unused_(); + return kCoroutineNone; +} + +CoroutineRet GameState_8_MainGameplay(void) { // 0x828B44 + COROUTINE_BEGIN(coroutine_state_1, 0); + DetermineWhichEnemiesToProcess(); + if (1) { // !DebugHandler()) { + PaletteFxHandler(); + HandleControllerInputForGamePhysics(); + if (!debug_disable_sprite_interact) + SamusProjectileInteractionHandler(); + EnemyMain(); + + if (queued_message_box_index) { + COROUTINE_AWAIT(1, DisplayMessageBox_Async(queued_message_box_index)); + queued_message_box_index = 0; + } + + HandleSamusMovementAndPause(); + EprojRunAll(); + COROUTINE_AWAIT(2, PlmHandler_Async()); + + AnimtilesHandler(); + if (!debug_disable_sprite_interact) { + EprojSamusCollDetect(); + EprojProjCollDet(); + ProcessEnemyPowerBombInteraction(); + } + MainScrollingRoutine(); + int debug_scrolling_enabled = 0; + if (debug_scrolling_enabled) + DebugScrollPosSaveLoad(); + DrawSamusEnemiesAndProjectiles(); + QueueEnemyBG2TilemapTransfers(); + } + HandleHudTilemap(); + CalculateLayer2PosAndScrollsWhenScrolling(); + RunRoomMainCode(); + HandleSamusOutOfHealthAndGameTile(); + HandleRoomShaking(); + DecrementSamusTimers(); + COROUTINE_END(0); + +} + +void DeleteAllOptionsMenuObjects_(void) { + for (int i = 14; i >= 0; i -= 2) { + int v1 = i >> 1; + enemy_projectile_y_pos[v1 + 5] = 0; + enemy_projectile_y_vel[v1 + 17] = 0; + } +} + +void CallOptionsEntryFunc(uint32 ea, uint16 j) { + switch (ea) { + case fnsub_82F296: sub_82F296(j); return; + case fnsub_82F34B: sub_82F34B(j); return; + case fnsub_82F353: sub_82F353(j); return; + case fnsub_82F35B: sub_82F35B(j); return; + case fnsub_82F363: sub_82F363(j); return; + case fnsub_82F419: sub_82F419(j); return; + default: Unreachable(); + } +} + +uint8 CreateOptionsMenuObject_(uint16 a, uint16 j) { + options_menu_init_param = a; + uint16 v3 = 14; + while (optionsmenu_instr_ptr[v3 >> 1]) { + v3 -= 2; + if ((v3 & 0x8000u) != 0) + return 1; + } + uint8 *v5 = RomPtr_82(j); + int v6 = v3 >> 1; + optionsmenu_arr1[v6] = *((uint16 *)v5 + 1); + optionsmenu_instr_ptr[v6] = *((uint16 *)v5 + 2); + optionsmenu_instr_timer[v6] = 1; + optionsmenu_cur_data[v6] = 0; + optionsmenu_arr5[v6] = 0; + optionsmenu_arr6[v6] = 0; + optionsmenu_arr7[v6] = 0; + CallOptionsEntryFunc(*(uint16 *)v5 | 0x820000, v3); + return 0; +} + +void OptionsPreInstr_nullsub_57(uint16 k) { // 0x828C10 + ; +} + +void OptionsMenuFunc1(void) { // 0x828C11 + for (int i = 14; i >= 0; i -= 2) { + optionsmenu_index = i; + if (optionsmenu_instr_ptr[i >> 1]) { + OptionsMenuFunc2(i); + i = optionsmenu_index; + } + } +} + +void CallOptionsPreInstr(uint32 ea, uint16 k) { + switch (ea) { + case fnOptionsPreInstr_nullsub_57: OptionsPreInstr_nullsub_57(k); return; + case fnOptionsPreInstr_F2A9: OptionsPreInstr_F2A9(k); return; + case fnOptionsPreInstr_F376: OptionsPreInstr_F376(k); return; + case fnOptionsPreInstr_F3A0: OptionsPreInstr_F3A0(k); return; + case fnOptionsPreInstr_F3E2: OptionsPreInstr_F3E2(k); return; + case fnOptionsPreInstr_F42C: OptionsPreInstr_F42C(k); return; + default: Unreachable(); + } +} + +uint16 CallOptionsInstr(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnOptionsInstr_Destroy: return OptionsInstr_Destroy(k, j); + case fnOptionsInstr_8C64: return OptionsInstr_8C64(k, j); + case fnOptionsInstr_SetPreInstr: return OptionsInstr_SetPreInstr(k, j); + case fnOptionsInstr_8C79: return OptionsInstr_8C79(k, j); + case fnOptionsInstr_Goto: return OptionsInstr_Goto(k, j); + case fnOptionsInstr_8C89: return OptionsInstr_8C89(k, j); + case fnOptionsInstr_8C93: return OptionsInstr_8C93(k, j); + default: return Unreachable(); + } +} + +void OptionsMenuFunc2(uint16 k) { // 0x828C2B + CallOptionsPreInstr(optionsmenu_arr1[k >> 1] | 0x820000, k); + uint16 v1 = optionsmenu_index; + int v2 = optionsmenu_index >> 1; + if (optionsmenu_instr_timer[v2]-- == 1) { + uint16 v4 = optionsmenu_instr_ptr[v2], v6; + while (1) { + uint16 *v5 = (uint16 *)RomPtr_82(v4); + v6 = *v5; + if ((*v5 & 0x8000u) == 0) + break; + R18_ = *v5; + v4 = CallOptionsInstr(v6 | 0x820000, v1, v4 + 2); + if (!v4) + return; + } + int v7 = v1 >> 1; + optionsmenu_instr_timer[v7] = v6; + optionsmenu_cur_data[v7] = *((uint16 *)RomPtr_82(v4) + 1); + optionsmenu_instr_ptr[v7] = v4 + 4; + } +} + +uint16 OptionsInstr_Destroy(uint16 k, uint16 j) { // 0x828C5A + int v2 = k >> 1; + optionsmenu_cur_data[v2] = 0; + optionsmenu_instr_ptr[v2] = 0; + return 0; +} + +uint16 OptionsInstr_8C64(uint16 k, uint16 j) { // 0x828C64 + optionsmenu_instr_ptr[k >> 1] = j - 2; + return 0; +} + +uint16 OptionsInstr_SetPreInstr(uint16 k, uint16 j) { // 0x828C6E + optionsmenu_arr1[k >> 1] = *(uint16 *)RomPtr_82(j); + return j + 2; +} + +uint16 OptionsInstr_8C79(uint16 k, uint16 j) { // 0x828C79 + optionsmenu_arr1[k >> 1] = FUNC16(locret_828C81); + return j; +} + +uint16 OptionsInstr_Goto(uint16 k, uint16 j) { // 0x828C82 + return *(uint16 *)RomPtr_82(j); +} + +uint16 OptionsInstr_8C89(uint16 k, uint16 j) { // 0x828C89 + int v2 = k >> 1; + if (optionsmenu_arr5[v2]-- == 1) + return j + 2; + else + return OptionsInstr_Goto(k, j); +} + +uint16 OptionsInstr_8C93(uint16 k, uint16 j) { // 0x828C93 + optionsmenu_arr5[k >> 1] = *(uint16 *)RomPtr_82(j); + return j + 2; +} + +void DrawOptionsMenuSpritemaps(void) { // 0x828CA1 + for (int i = 14; i >= 0; i -= 2) { + int v1 = i >> 1; + if (optionsmenu_cur_data[v1]) { + uint16 v2 = optionsmenu_cur_data[v1]; + R22_ = optionsmenu_arr10[v1]; + R20_ = optionsmenu_arr8[v1]; + R18_ = optionsmenu_arr9[v1]; + DrawSpritemap(0x82u, v2); + } + } +} + +CoroutineRet GameState_12_Pausing_Darkening_Async(void) { // 0x828CCF + GameState_8_MainGameplay(); + HandleFadeOut(); + if ((reg_INIDISP & 0xF) == 0) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + ++game_state; + } + return kCoroutineNone; +} + +void CallPauseHook(uint32 ea) { + switch (ea) { + case fnPauseHook_Empty: return; + case fnPauseHook_DraygonRoom: PauseHook_DraygonRoom(); return; + case fnUnpauseHook_DraygonRoom: UnpauseHook_DraygonRoom(); return; + case fnUnpauseHook_Kraid_IsDead: UnpauseHook_Kraid_IsDead(); return; + case fnUnpauseHook_Kraid_IsAlive: UnpauseHook_Kraid_IsAlive(); return; + case fnKraid_UnpauseHook_IsSinking: Kraid_UnpauseHook_IsSinking(); return; + case fnPauseHook_Kraid: PauseHook_Kraid(); return; + case fnMotherBrainsBody_UnpauseHook: MotherBrainsBody_UnpauseHook(); return; + default: Unreachable(); + } +} + +CoroutineRet GameState_13_Pausing_Async(void) { // 0x828CEF + DisableHdmaObjects(); + reg_HDMAEN = 0; + WriteReg(HDMAEN, 0); + DisableAnimtiles(); + BackupBG2TilemapForPauseMenu(); + CallPauseHook(Load24(&pause_hook)); + CancelSoundEffects(); + BackupSomeGfxStateForPause(); + LoadPauseMenuTilesAndClearBG2(); + LoadPauseScreenBaseTilemaps(); + LoadPauseMenuMapTilemapAndAreaLabel(); + BackupGameplayPalettesAndLoadForPause(); + ContinueInitPauseMenu(); + screen_fade_delay = 1; + screen_fade_counter = 1; + pausemenu_leftarrow_animation_frame = 0; + pausemenu_palette_animation_timer = 1; + map_scrolling_direction = 0; + map_scrolling_speed_index = 0; + QueueClearingOfFxTilemap(); + ++game_state; + return kCoroutineNone; +} + +void BackupBG2TilemapForPauseMenu(void) { // 0x828D51 + WriteReg(VMADDL, 1u); + WriteReg(VMADDH, reg_BG2SC & 0xFC); + WriteReg(DMAP1, 0x81u); + WriteReg(BBAD1, 0x39u); + WriteReg(A1T1L, 0x5C); + WriteReg(A1T1H, 0xDFu); + WriteReg(A1B1, 0x7Eu); + WriteReg(DAS1L, 0); + WriteReg(DAS1H, 0x10u); + WriteReg(DAS10, 0); + WriteReg(A2A1L, 0); + WriteReg(A2A1H, 0); + WriteReg(NTRL1, 0); + WriteReg(MDMAEN, 2u); +} + +void RestoreBG2TilemapFromPauseScreen(void) { // 0x828D96 + WriteReg(VMADDL, 0); + WriteReg(VMADDH, reg_BG2SC & 0xFC); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_828DAE = { 1, 1, 0x18, LONGPTR(0x7edf5c), 0x1000 }; + SetupDmaTransfer(&unk_828DAE); + WriteReg(MDMAEN, 2u); +} + +void BackupSomeGfxStateForPause(void) { // 0x828DBD + pausemenu_bak_BG1SC = reg_BG1SC; + pausemenu_bak_BG2SC = reg_BG2SC; + pausemenu_bak_BG3SC = reg_BG3SC; + pausemenu_bak_BG12NBA = reg_BG12NBA; + pausemenu_bak_BG34NBA = reg_BG34NBA; + pausemenu_bak_OBSEL = reg_OBSEL; + pausemenu_bak_BG1HOFS = reg_BG1HOFS; + pausemenu_bak_BG2HOFS = reg_BG2HOFS; + pausemenu_bak_BG3HOFS = reg_BG3HOFS; + pausemenu_bak_BG1VOFS = reg_BG1VOFS; + pausemenu_bak_BG2VOFS = reg_BG2VOFS; + pausemenu_bak_BG3VOFS = reg_BG3VOFS; + pausemenu_bak_BGMODE = reg_BGMODE; + pausemenu_bak_layer2_scroll_x = layer2_scroll_x; + pausemenu_bak_layer2_scroll_y = layer2_scroll_y; + pausemenu_bak_MOSAIC = reg_MOSAIC; + pausemenu_bak_CGADSUB = next_gameplay_CGADSUB; +} + +void RestoreSomeGfxStateForPause(void) { // 0x828E19 + layer2_scroll_x = pausemenu_bak_layer2_scroll_x; + layer2_scroll_y = pausemenu_bak_layer2_scroll_y; + reg_BGMODE = pausemenu_bak_BGMODE; + LOBYTE(reg_BG3VOFS) = pausemenu_bak_BG3VOFS; + LOBYTE(reg_BG2VOFS) = pausemenu_bak_BG2VOFS; + LOBYTE(reg_BG1VOFS) = pausemenu_bak_BG1VOFS; + LOBYTE(reg_BG3HOFS) = pausemenu_bak_BG3HOFS; + LOBYTE(reg_BG2HOFS) = pausemenu_bak_BG2HOFS; + LOBYTE(reg_BG1HOFS) = pausemenu_bak_BG1HOFS; + reg_OBSEL = pausemenu_bak_OBSEL; + reg_BG34NBA = pausemenu_bak_BG34NBA; + reg_BG12NBA = pausemenu_bak_BG12NBA; + reg_BG3SC = pausemenu_bak_BG3SC; + reg_BG2SC = pausemenu_bak_BG2SC; + reg_BG1SC = pausemenu_bak_BG1SC; + reg_MOSAIC = pausemenu_bak_MOSAIC; + next_gameplay_CGADSUB = pausemenu_bak_CGADSUB; +} + +void LoadPauseMenuTilesAndClearBG2(void) { // 0x828E75 + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_828E8B = { 1, 1, 0x18, LONGPTR(0xb68000), 0x4000 }; + SetupDmaTransfer(&unk_828E8B); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x20u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_828EAB = { 1, 1, 0x18, LONGPTR(0xb6c000), 0x2000 }; + SetupDmaTransfer(&unk_828EAB); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x40u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_828ECB = { 1, 1, 0x18, LONGPTR(0x9ab200), 0x2000 }; + SetupDmaTransfer(&unk_828ECB); + WriteReg(MDMAEN, 2u); +} + +void LoadPauseScreenBaseTilemaps(void) { // 0x828EDA + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x38u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_828EF0 = { 1, 1, 0x18, LONGPTR(0xb6e000), 0x0800 }; + SetupDmaTransfer(&unk_828EF0); + WriteReg(MDMAEN, 2u); + WriteReg(WMADDL, 0); + WriteReg(WMADDM, 0x34u); + WriteReg(WMADDH, 0x7Eu); + static const StartDmaCopy unk_828F10 = { 1, 0, 0x80, LONGPTR(0xb6e400), 0x0400 }; + SetupDmaTransfer(&unk_828F10); + WriteReg(MDMAEN, 2u); + WriteReg(WMADDL, 0); + WriteReg(WMADDM, 0x38u); + WriteReg(WMADDH, 0x7Eu); + static const StartDmaCopy unk_828F30 = { 1, 0, 0x80, LONGPTR(0xb6e800), 0x0800 }; + SetupDmaTransfer(&unk_828F30); + WriteReg(MDMAEN, 2u); + uint16 v0 = addr_kDummySamusWireframeTilemap; + uint16 v1 = 236; + R20_ = 17; + do { + R18_ = 8; + do { + ram3000.pause_menu_map_tilemap[v1++] = *(uint16 *)RomPtr_82(v0); + v0 += 2; + --R18_; + } while (R18_); + v1 += 8; + --R20_; + } while (R20_); + WriteSamusWireframeTilemap(); + LoadEqupmentScreenReserveHealthTilemap(); +} + +void LoadEqupmentScreenReserveHealthTilemap(void) { // 0x828F70 + if (samus_max_reserve_health) { + R42 = samus_reserve_health / 100; + int rest = samus_reserve_health % 100; + int div10 = rest / 10; + int mod10 = rest % 10; + + ram3800.cinematic_bg_tilemap[394] = mod10 + 2052; + ram3800.cinematic_bg_tilemap[393] = div10 + 2052; + ram3800.cinematic_bg_tilemap[392] = R42 + 2052; + } +} + +#define kPauseScreenPalettes ((uint16*)RomPtr(0xb6f000)) +void BackupGameplayPalettesAndLoadForPause(void) { // 0x828FD4 + int16 v0; + int16 v2; + + v0 = 512; + uint16 v1 = 0; + do { + ram3000.pause_menu_map_tilemap[v1 + 384] = palette_buffer[v1]; + ++v1; + v0 -= 2; + } while (v0); + v2 = 512; + uint16 v3 = 0; + do { + palette_buffer[v3 >> 1] = kPauseScreenPalettes[v3 >> 1]; + v3 += 2; + v2 -= 2; + } while (v2); +} + +void ContinueInitPauseMenu(void) { // 0x829009 + SetupPpuForPauseMenu(); + ResetPauseMenuAnimations(); + LoadEquipmentScreenEquipmentTilemaps(); + SetPauseScreenButtonLabelPalettes_0(); + UpdatePauseMenuLRStartVramTilemap(); + DetermineMapScrollLimits(); + SetupMapScrollingForPauseMenu(0x80); +} + +void SetupMapScrollingForFileSelectMap(void) { // 0x829028 + int16 v0; + int16 v1; + + ResetPauseMenuAnimations(); + DetermineMapScrollLimits(); + reg_BG1HOFS = map_min_x_scroll + ((uint16)(map_max_x_scroll - map_min_x_scroll) >> 1) - 128; + R18_ = 8 * (room_x_coordinate_on_map + (uint8)((uint16)(samus_x_pos & 0xFF00) >> 8)) - reg_BG1HOFS; + v0 = 224 - R18_; + if ((int16)(224 - R18_) >= 0) { + R18_ = 32 - R18_; + if ((R18_ & 0x8000u) == 0) + reg_BG1HOFS -= R18_; + } else { + R18_ = 224 - R18_; + reg_BG1HOFS -= v0; + } + R18_ = map_min_y_scroll + ((uint16)(map_max_y_scroll - map_min_y_scroll) >> 1) + 16; + reg_BG1VOFS = -((112 - R18_) & 0xFFF8); + R18_ = 8 * (room_y_coordinate_on_map + HIBYTE(samus_y_pos) + 1) + ((112 - R18_) & 0xFFF8); + v1 = 64 - R18_; + if ((int16)(64 - R18_) >= 0) { + R18_ = 64 - R18_; + reg_BG1VOFS -= v1; + if (sign16(reg_BG1VOFS + 40)) + reg_BG1VOFS = -40; + } +} + +CoroutineRet GameState_14_Paused_Async(void) { // 0x8290C8 + DrawPauseMenuDuringFadeIn(); + HandleFadeIn(); + if (reg_INIDISP == 15) { + screen_fade_delay = 0; + screen_fade_counter = 0; + ++game_state; + } + return kCoroutineNone; +} + +CoroutineRet GameState_15_Paused_Async(void) { // 0x8290E8 + ReleaseButtonsFilter(3); + MainPauseRoutine(); + HandleHudTilemap(); + HandlePauseScreenPaletteAnimation(); + return kCoroutineNone; +} + +static Func_V *const kPauseMenuFuncs[8] = { // 0x8290FF + PauseMenu_0_MapScreen, + PauseMenu_1_EquipmentScreen, + PauseMenu_2, + PauseMenu_3_MapToEquipment_Load, + PauseMenu_4_MapToEquipment_FadeIn, + PauseMenu_5, + PauseMenu_6_EquipmentToMap_Load, + PauseMenu_7_EquipmentToMap_FadeIn, +}; +void MainPauseRoutine(void) { + kPauseMenuFuncs[menu_index](); +} + +void PauseMenu_0_MapScreen(void) { // 0x829120 + HandlePauseScreenLR(); + HandlePauseScreenStart(); + HandleMapScrollArrows(); + MapScrolling(); + MapScreenDrawSamusPositionIndicator(); + DrawMapIcons(); + DisplayMapElevatorDestinations(); + pause_screen_mode = 0; +} + +void PauseMenu_1_EquipmentScreen(void) { // 0x829142 + reg_BG1HOFS = 0; + reg_BG1VOFS = 0; + EquipmentScreenMain(); + HandlePauseScreenLR(); + HandlePauseScreenStart(); + pause_screen_mode = 1; +} + +void PauseMenu_2(void) { // 0x829156 + DisplayMapElevatorDestinations(); + MapScreenDrawSamusPositionIndicator(); + DrawMapIcons(); + HandlePauseMenuLRPressHighlight(); + pause_screen_mode = 0; + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + ++menu_index; + } +} + +void PauseMenu_5(void) { // 0x829186 + EquipmentScreenDrawItemSelector(); + EquipmentScreenDisplayReserveTankAmount(); + HandlePauseMenuLRPressHighlight(); + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + ++menu_index; + } +} +#define kPauseLrHighlightAnimData ((uint8*)RomPtr(0x82c10c)) +void PauseMenu_3_MapToEquipment_Load(void) { // 0x8291AB + DisplayMapElevatorDestinations(); + EquipmentScreenSetupReserveMode(); + EquipmentScreenTransferBG1Tilemap(); + pause_screen_mode = 1; + SetPauseScreenButtonLabelPalettes(); + pausemenu_lr_animation_frame = 0; + pausemenu_lr_animation_timer = *(uint16 *)kPauseLrHighlightAnimData; + screen_fade_delay = 1; + screen_fade_counter = 1; + ++menu_index; +} + +void PauseMenu_6_EquipmentToMap_Load(void) { // 0x8291D7 + DisplayMapElevatorDestinations(); + LoadPauseMenuMapTilemapAndAreaLabel(); + SetPauseScreenButtonLabelPalettes(); + pausemenu_lr_animation_frame = 0; + pausemenu_lr_animation_timer = *(uint16 *)kPauseLrHighlightAnimData; + screen_fade_delay = 1; + screen_fade_counter = 1; + pause_screen_mode = 0; + ++menu_index; +} + +void PauseMenu_7_EquipmentToMap_FadeIn(void) { // 0x829200 + MapScreenDrawSamusPositionIndicator(); + DrawMapIcons(); + DisplayMapElevatorDestinations(); + pause_screen_mode = 0; + HandleFadeIn(); + if (reg_INIDISP == 15) { + screen_fade_delay = 0; + screen_fade_counter = 0; + uint16 v0 = pausemenu_button_label_mode; + if (pausemenu_button_label_mode) + v0 = 1; + menu_index = v0; + } +} + +void PauseMenu_4_MapToEquipment_FadeIn(void) { // 0x829231 + EquipmentScreenDrawItemSelector(); + EquipmentScreenDisplayReserveTankAmount(); + pause_screen_mode = 1; + HandleFadeIn(); + if (reg_INIDISP == 15) { + screen_fade_delay = 0; + screen_fade_counter = 0; + uint16 v0 = pausemenu_button_label_mode; + if (pausemenu_button_label_mode) + v0 = 1; + menu_index = v0; + } +} + +static Func_V *const kMapScrollingFuncs[5] = { // 0x82925D + MapScrolling_0_None, + MapScrolling_1_Left, + MapScrolling_2_Right, + MapScrolling_3_Up, + MapScrolling_4_Down, +}; +void MapScrolling(void) { + kMapScrollingFuncs[map_scrolling_direction](); +} + +void MapScrolling_0_None(void) { // 0x829278 + map_scrolling_gear_switch_timer = 4; +} + +uint16 MapScrolling_GetSpeedIndex(void) { // 0x82927F + uint16 result = map_scrolling_speed_index; + if (!map_scrolling_gear_switch_timer) + return map_scrolling_speed_index + 32; + return result; +} + +static const uint16 kMapScrollingSpeedTable[32] = { // 0x82928E + 0, 0, 0, 8, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 8, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +void MapScrolling_1_Left(void) { + reg_BG1HOFS -= kMapScrollingSpeedTable[MapScrolling_GetSpeedIndex() >> 1]; + MapScrolling_Common(); +} + +void MapScrolling_Common(void) { // 0x829299 + ++map_scrolling_speed_index; + if ((++map_scrolling_speed_index & 0xF) == 0) { + QueueSfx1_Max6(0x36u); + map_scrolling_direction = 0; + map_scrolling_speed_index = 0; + if (map_scrolling_gear_switch_timer) + --map_scrolling_gear_switch_timer; + } +} + +void MapScrolling_2_Right(void) { // 0x8292BD + reg_BG1HOFS += kMapScrollingSpeedTable[MapScrolling_GetSpeedIndex() >> 1]; + MapScrolling_Common(); +} + +void MapScrolling_3_Up(void) { // 0x8292CA + reg_BG1VOFS -= kMapScrollingSpeedTable[MapScrolling_GetSpeedIndex() >> 1]; + MapScrolling_Common(); +} + +void MapScrolling_4_Down(void) { // 0x8292D7 + reg_BG1VOFS += kMapScrollingSpeedTable[MapScrolling_GetSpeedIndex() >> 1]; + MapScrolling_Common(); +} + +CoroutineRet GameState_16_Unpausing_Async(void) { // 0x829324 + HighlightPauseScreenButton(); + DrawPauseMenuDuringFadeout(); + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + ++game_state; + } + return kCoroutineNone; +} + +void DrawPauseMenuDuringFadeout(void) { // 0x82934B + if (pause_screen_mode == 1) { + EquipmentScreenDrawItemSelector(); + EquipmentScreenDisplayReserveTankAmount(); + HandlePauseMenuLRPressHighlight(); + } else { + DisplayMapElevatorDestinations(); + DrawMapIcons(); + MapScreenDrawSamusPositionIndicator(); + } +} + +CoroutineRet GameState_17_Unpausing_Async(void) { // 0x829367 + ClearSamusBeamTiles(); + ContinueInitGameplayResume(); + ResumeGameplay(); + RestoreSomeGfxStateForPause(); + RestoreBG2TilemapFromPauseScreen(); + screen_fade_delay = 1; + screen_fade_counter = 1; + CallPauseHook(Load24(&unpause_hook)); + EnableHdmaObjects(); + EnableAnimtiles(); + QueueSamusMovementSfx(); + ++game_state; + return kCoroutineNone; +} + +CoroutineRet GameState_18_Unpausing(void) { // 0x8293A1 + GameState_8_MainGameplay(); + HandleFadeIn(); + if (reg_INIDISP == 15) { + screen_fade_delay = 0; + screen_fade_counter = 0; + game_state = kGameState_8_MainGameplay; + } + return kCoroutineNone; +} + +#define kPauseAreaLabelTilemap ((uint16*)RomPtr(0x82965f)) +void LoadPauseMenuMapTilemapAndAreaLabel(void) { // 0x8293C3 + reg_BG1HOFS = reg_BG4HOFS; + reg_BG1VOFS = reg_BG4VOFS; + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x30u); + WriteReg(VMAIN, 0x80); + LoadPauseMenuMapTilemap(); + static const StartDmaCopy unk_8293E9 = { 1, 1, 0x18, LONGPTR(0x7e4000), 0x1000 }; + SetupDmaTransfer(&unk_8293E9); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0xAAu); + WriteReg(VMADDH, 0x38u); + WriteReg(VMAIN, 0x80); + WriteReg(DMAP1, 1u); + WriteReg(BBAD1, 0x18u); + WriteReg(DAS1L, 0x18u); + WriteReg(DAS1H, 0); + uint16 v0 = area_index; + if (!sign16(area_index - 7)) + v0 = 0; + WriteRegWord(A1T1L, kPauseAreaLabelTilemap[v0]); + WriteReg(A1B1, 0x82u); + WriteReg(MDMAEN, 2u); +} + +#define kPauseMenuMapTilemaps ((LongPtr*)RomPtr(0x82964a)) +#define kPauseMenuMapData ((uint16*)RomPtr(0x829717)) +void LoadPauseMenuMapTilemap(void) { // 0x82943D + uint16 v5; + uint16 v6; + int16 v9; + uint16 v13; + + uint16 v0 = area_index; + if (!sign16(area_index - 7)) + v0 = 0; + R18_ = v0; + R0_.addr = *(VoidP *)((char *)&kPauseMenuMapTilemaps[0].addr + (uint16)(3 * v0)); + *(uint16 *)&R0_.bank = *(uint16 *)(&kPauseMenuMapTilemaps[0].bank + (uint16)(3 * v0)); + R3_.addr = ADDR16_OF_RAM(ram4000); + *(uint16 *)&R3_.bank = 126; + R8_ = 130; + R6_ = kPauseMenuMapData[v0]; + if (map_station_byte_array[area_index]) { + uint8 *v4 = IndirPtr(&R6_, 0); + LOBYTE(v5) = HIBYTE(*(uint16 *)v4); + HIBYTE(v5) = *(uint16 *)v4; + R38 = v5; + ++R6_; + ++R6_; + v6 = ADDR16_OF_RAM(*map_tiles_explored); + *(uint16 *)((char *)&R10_ + 1) = 0; + *(uint16 *)((char *)&R8_ + 1) = v6; + uint8 *v7 = IndirPtr((char *)&R8_ + 1, 0); + LOBYTE(v5) = HIBYTE(*(uint16 *)v7); + HIBYTE(v5) = *(uint16 *)v7; + R40 = v5; + ++ *(uint16 *)((char *)&R8_ + 1); + ++ *(uint16 *)((char *)&R8_ + 1); + uint16 v8 = 0; + v9 = 16; + do { + uint16 v10 = *(uint16 *)IndirPtr(&R0_, v8); + bool v11 = R40 >> 15; + R40 *= 2; + if (v11) { + v10 &= ~0x400u; + R38 *= 2; + } else { + v11 = R38 >> 15; + R38 *= 2; + if (!v11) + v10 = 31; + } + IndirWriteWord(&R3_, v8, v10); + if (!--v9) { + v9 = 16; + uint8 *v12 = IndirPtr(&R6_, 0); + LOBYTE(v13) = HIBYTE(*(uint16 *)v12); + HIBYTE(v13) = *(uint16 *)v12; + R38 = v13; + ++R6_; + ++R6_; + uint8 *v14 = IndirPtr((char *)&R8_ + 1, 0); + LOBYTE(v13) = HIBYTE(*(uint16 *)v14); + HIBYTE(v13) = *(uint16 *)v14; + R40 = v13; + ++ *(uint16 *)((char *)&R8_ + 1); + ++ *(uint16 *)((char *)&R8_ + 1); + } + v8 += 2; + } while ((int16)(v8 - 4096) < 0); + } else { + uint16 v1 = 0; + uint16 v2 = 0; + LOBYTE(R18_) = 0; + while (1) { + uint8 t = map_tiles_explored[v2]; + map_tiles_explored[v2] <<= 1; + if (!(t & 0x80)) { + IndirWriteWord(&R3_, v1, 0x1Fu); + } else { + ++map_tiles_explored[v2]; + uint8 *v3 = IndirPtr(&R0_, v1); + IndirWriteWord(&R3_, v1, *(uint16 *)v3 & 0xFBFF); + } + v1 += 2; + LOBYTE(R18_) = R18_ + 1; + if (!sign8(R18_ - 8)) { + LOBYTE(R18_) = 0; + if ((int16)(++v2 - 256) >= 0) + break; + } + } + } +} + +void DrawRoomSelectMap(void) { // 0x829517 + uint16 v3; // r8 + uint16 v6; + unsigned int v7; // kr00_4 + int16 v10; + uint16 v14; + VramWriteEntry *v17; + + reg_BG12NBA = 51; + reg_TM = 19; + reg_BG1VOFS = -40; + uint16 v0 = area_index; + if (!sign16(area_index - 7)) + v0 = 0; + R18_ = v0; + R0_.addr = *(VoidP *)((char *)&kPauseMenuMapTilemaps[0].addr + (uint16)(3 * v0)); + *(uint16 *)&R0_.bank = *(uint16 *)(&kPauseMenuMapTilemaps[0].bank + (uint16)(3 * v0)); + R3_.addr = ADDR16_OF_RAM(ram3000); + R3_.bank = 126; + R8_ = 130; + R6_ = kPauseMenuMapData[v0]; + if (map_station_byte_array[area_index]) { + uint8 *v5 = IndirPtr(&R6_, 0); + LOBYTE(v6) = HIBYTE(*(uint16 *)v5); + HIBYTE(v6) = *(uint16 *)v5; + R38 = v6; + ++R6_; + ++R6_; + v7 = 2039; + *(uint16 *)((char *)&R10_ + 1) = HIWORD(v7); + *(uint16 *)((char *)&R8_ + 1) = v7; + uint8 *v8 = IndirPtr((char *)&R8_ + 1, 0); + LOBYTE(v6) = HIBYTE(*(uint16 *)v8); + HIBYTE(v6) = *(uint16 *)v8; + R40 = v6; + ++ *(uint16 *)((char *)&R8_ + 1); + ++ *(uint16 *)((char *)&R8_ + 1); + uint16 v9 = 0; + v10 = 16; + do { + uint16 v11 = *(uint16 *)IndirPtr(&R0_, v9); + bool v12 = R40 >> 15; + R40 *= 2; + if (v12) { + v11 &= ~0x400u; + R38 *= 2; + } else { + v12 = R38 >> 15; + R38 *= 2; + if (!v12) + v11 = 31; + } + IndirWriteWord(&R3_, v9, v11); + if (!--v10) { + v10 = 16; + uint8 *v13 = IndirPtr(&R6_, 0); + LOBYTE(v14) = HIBYTE(*(uint16 *)v13); + HIBYTE(v14) = *(uint16 *)v13; + R38 = v14; + ++R6_; + ++R6_; + uint8 *v15 = IndirPtr((char *)&R8_ + 1, 0); + LOBYTE(v14) = HIBYTE(*(uint16 *)v15); + HIBYTE(v14) = *(uint16 *)v15; + R40 = v14; + ++ *(uint16 *)((char *)&R8_ + 1); + ++ *(uint16 *)((char *)&R8_ + 1); + } + v9 += 2; + } while ((int16)(v9 - 4096) < 0); + } else { + uint16 v1 = 0; + uint16 v2 = 0; + LOBYTE(R18_) = 0; + while (1) { + Unreachable(); + if (Unreachable()) { + HIBYTE(v3) = HIBYTE(v1); + IndirWriteWord(&R3_, v1, 0xFu); + } else { + ++map_tiles_explored[v2]; + uint8 *v4 = IndirPtr(&R0_, v1); + HIBYTE(v3) = HIBYTE(v1); + IndirWriteWord(&R3_, v1, *(uint16 *)v4 & 0xFBFF); + } + v1 += 2; + LOBYTE(R18_) = R18_ + 1; + LOBYTE(v3) = R18_ - 8; + if (!(uint8)sign8(v3)) { + LOBYTE(R18_) = 0; + if ((++v2 & 0x8000u) == 0) + break; + } + } + } + uint16 v16 = vram_write_queue_tail; + v17 = gVramWriteEntry(vram_write_queue_tail); + v17->size = 4096; + v17->src.addr = ADDR16_OF_RAM(ram3000); + *(uint16 *)&v17->src.bank = 126; + v17->vram_dst = (reg_BG1SC & 0xFC) << 8; + vram_write_queue_tail = v16 + 7; +} + +void DrawRoomSelectMapAreaLabel(void) { // 0x829628 + uint16 v0 = kPauseAreaLabelTilemap[area_index]; + uint16 v1 = 0; + do { + uint8 *v2 = RomPtr_82(v0); + IndirWriteWord(&R0_, v1, *(uint16 *)v2 & 0xEFFF); + v0 += 2; + v1 += 2; + } while ((int16)(v1 - 24) < 0); +} + +void SetupMapScrollingForPauseMenu(uint16 a) { // 0x829E27 + int16 v1; + int16 v2; + + R20_ = a; + reg_BG1HOFS = map_min_x_scroll + ((uint16)(map_max_x_scroll - map_min_x_scroll) >> 1) - 128; + R18_ = 8 * (room_x_coordinate_on_map + (uint8)((uint16)(samus_x_pos & 0xFF00) >> 8)) - reg_BG1HOFS; + v1 = 224 - R18_; + if ((int16)(224 - R18_) >= 0) { + R18_ = 32 - R18_; + if ((R18_ & 0x8000u) == 0) + reg_BG1HOFS -= R18_; + } else { + R18_ = 224 - R18_; + reg_BG1HOFS -= v1; + } + R18_ = map_min_y_scroll + ((uint16)(map_max_y_scroll - map_min_y_scroll) >> 1) + 16; + reg_BG1VOFS = -((R20_ - R18_) & 0xFFF8); + R18_ = 8 * (room_y_coordinate_on_map + HIBYTE(samus_y_pos) + 1) + ((R20_ - R18_) & 0xFFF8); + v2 = 64 - R18_; + if ((int16)(64 - R18_) >= 0) { + R18_ = 64 - R18_; + reg_BG1VOFS -= v2; + if (sign16(reg_BG1VOFS + 40)) + reg_BG1VOFS = -40; + } +} + +void DetermineMapScrollLimits(void) { // 0x829EC4 + if (has_area_map) { + R8_ = 130; + R6_ = addr_kPauseMenuMapData; + R6_ = *(uint16 *)IndirPtr(&R6_, 2 * area_index); + } else { + R8_ = 0; + R6_ = 2039; + } + R0_.bank = R8_; + R0_.addr = R6_; + uint16 v0 = DetermineLeftmostMapColumn(); + map_min_x_scroll = MultiplyBy8(v0); + if (area_index == 4) + map_min_x_scroll -= 24; + R0_.addr = R6_ + 131; + uint16 v1 = DetermineRightmostMapColumn(); + map_max_x_scroll = MultiplyBy8(v1); + R0_.addr = R6_; + uint16 v2 = DetermineTopmostMapColumn(); + map_min_y_scroll = MultiplyBy8(v2); + R0_.addr = R6_ + 124; + uint16 v3 = DetermineBottommostMapColumn(); + map_max_y_scroll = MultiplyBy8(v3); +} + +uint16 MultiplyBy8(uint16 k) { // 0x829F45 + return 8 * k; +} +static const uint8 k0x80Shr[8] = { // 0x829F4A + 0x80, 0x40, 0x20, 0x10, + 8, 4, 2, 1, +}; +static const uint8 k0x80Shr_0[8] = { 0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1 }; +uint16 DetermineLeftmostMapColumn(void) { + uint16 v0; + + HIBYTE(v0) = 0; + uint16 result = 0; +LABEL_2: + LOBYTE(v0) = result & 7; + LOBYTE(R18_) = k0x80Shr[v0]; + uint16 v2 = 0; + while (((uint8)R18_ & *IndirPtr(&R0_, v2)) == 0) { + v2 += 4; + if ((int16)(v2 - 128) >= 0) { + if ((int16)(++result - 64) >= 0) + return 26; + if ((result & 7) == 0) { + R0_.addr += 1; + } + if (result == 32) { + R0_.addr += 123; + } + goto LABEL_2; + } + } + return result; +} + +uint16 DetermineRightmostMapColumn(void) { // 0x829FA9 + uint16 result = 63; +LABEL_2: + LOBYTE(R18_) = k0x80Shr_0[result & 7]; + uint16 v1 = 0; + while (((uint8)R18_ & *IndirPtr(&R0_, v1)) == 0) { + v1 += 4; + if ((int16)(v1 - 128) >= 0) { + if ((--result & 0x8000u) != 0) + return 28; + if ((result & 7) == 7) { + bool v2 = LOBYTE(R0_.addr)-- != 0; + HIBYTE(R0_.addr) -= !v2; + } + if (result == 31) + R0_.addr -= 124; + goto LABEL_2; + } + } + return result; +} + +uint16 DetermineTopmostMapColumn(void) { // 0x82A009 + R3_.addr = R0_.addr + 128; + R3_.bank = R0_.bank; + uint16 result = 0; + uint16 v1 = 0; + while (!*IndirPtr(&R0_, v1) && !*IndirPtr(&R3_, v1)) { + if ((int16)(++v1 - 4) >= 0) { + v1 = 0; + R0_.addr += 4; + R3_.addr += 4; + if ((int16)(++result - 31) >= 0) + return 1; + } + } + return result; +} + +uint16 DetermineBottommostMapColumn(void) { // 0x82A053 + R3_.addr = R0_.addr + 128; + R3_.bank = R0_.bank; + uint16 result = 31; + uint16 v1 = 0; + while (!*IndirPtr(&R0_, v1) && !*IndirPtr(&R3_, v1)) { + if ((int16)(++v1 - 4) >= 0) { + v1 = 0; + R0_.addr -= 4; + R3_.addr -= 4; + if (!--result) + return 11; + } + } + return result; +} + +void SetupPpuForPauseMenu(void) { // 0x82A09A + WriteReg(OBSEL, 1u); + reg_OBSEL = 1; + WriteReg(BGMODE, 9u); + reg_BGMODE = 9; + reg_BG12NBA = 0; + WriteReg(BG12NBA, 0); + reg_BG34NBA = 4; + WriteReg(BG34NBA, 4u); + reg_BG1SC = 49; + WriteReg(BG1SC, 0x31u); + reg_BG2SC = 56; + WriteReg(BG2SC, 0x38u); + reg_BG3SC = 88; + WriteReg(BG3SC, 0x58u); + reg_BG4SC = 0; + WriteReg(BG4SC, 0); + WriteReg(TM, 0x17u); + reg_TM = 23; + WriteReg(MOSAIC, 0); + reg_MOSAIC = 0; + reg_COLDATA[0] &= 0xE0u; + reg_COLDATA[1] &= 0xE0u; + reg_COLDATA[2] &= 0xE0u; + next_gameplay_CGADSUB = 0; +} + +void ResetPauseMenuAnimations(void) { // 0x82A0F7 + pausemenu_reserve_tank_delay_ctr = 0; + reg_BG1HOFS = 0; + reg_BG2HOFS = 0; + reg_BG3HOFS = 0; + reg_BG2VOFS = 0; + reg_BG3VOFS = 0; + pausemenu_button_label_mode = 0; + pausemenu_lr_animation_frame = 0; + UNUSED_word_7E0745 = 0; + samus_position_indicator_animation_frame = 0; + samus_position_indicator_animation_timer = 0; + samus_position_indicator_animation_loop_counter = 0; + pausemenu_lr_animation_timer = *(uint16 *)kPauseLrHighlightAnimData; + pausemenu_palette_animation_timer = 1; + pausemenu_palette_animation_frame = 0; +} +#define kEquipmentTilemaps_Tanks ((uint16*)RomPtr(0x82c088)) +#define kEquipmentTilemaps_Weapons ((uint16*)RomPtr(0x82c08c)) +#define kEquipmentTilemaps_Suits ((uint16*)RomPtr(0x82c096)) +#define kEquipmentTilemaps_Boots ((uint16*)RomPtr(0x82c0a2)) +#define kHyperBeamWeaponsTilemaps ((uint16*)RomPtr(0x82c0a8)) +#define kEquipmentBitmasks_Weapons ((uint16*)RomPtr(0x82c04c)) +#define kEquipmentBitmasks_Suits ((uint16*)RomPtr(0x82c056)) +#define kEquipmentBitmasks_Boots ((uint16*)RomPtr(0x82c062)) +void LoadEquipmentScreenEquipmentTilemaps(void) { // 0x82A12B + if (samus_max_reserve_health) { + R3_.addr = addr_kEquipmentTilemapOffs_Tanks; + *(uint16 *)&R3_.bank = 130; + R0_.addr = *(uint16 *)IndirPtr(&R3_, 0); + R22_ = 14; + Copy_R22_Bytes(kEquipmentTilemaps_Tanks[0]); + R3_.addr = addr_kEquipmentTilemapOffs_Tanks; + *(uint16 *)&R3_.bank = 130; + R0_.addr = *(uint16 *)IndirPtr(&R3_, 2u); + R22_ = 14; + Copy_R22_Bytes(kEquipmentTilemaps_Tanks[1]); + } + uint16 v0 = 0; + R3_.addr = addr_kEquipmentTilemapOffs_Weapons; + *(uint16 *)&R3_.bank = 130; + R0_.addr = *(uint16 *)IndirPtr(&R3_, 0); + if (hyper_beam_flag) { + uint16 v3 = 0; + do { + uint16 v4 = kHyperBeamWeaponsTilemaps[v3 >> 1]; + R22_ = 10; + Copy_R22_Bytes(v4); + v3 += 2; + R0_.addr = *(uint16 *)IndirPtr(&R3_, v3); + } while ((int16)(v3 - 10) < 0); + } else { + do { + int v1 = v0 >> 1; + if ((collected_beams & kEquipmentBitmasks_Weapons[v1]) != 0) { + uint16 v2 = kEquipmentTilemaps_Weapons[v1]; + R22_ = 10; + Copy_R22_Bytes(v2); + if ((equipped_beams & kEquipmentBitmasks_Weapons[v1]) == 0) { + R18_ = 3072; + R22_ = 10; + SetPaletteOfR22TilemapBytesToR18(); + } + } else { + R22_ = 10; + Copy_R22_Bytes(addr_kEquipmentScreenTilemap_Blank); + } + v0 += 2; + R0_.addr = *(uint16 *)IndirPtr(&R3_, v0); + } while ((int16)(v0 - 12) < 0); + } + uint16 v5 = 0; + R3_.addr = addr_kEquipmentTilemapOffs_Suits; + *(uint16 *)&R3_.bank = 130; + R0_.addr = *(uint16 *)IndirPtr(&R3_, 0); + do { + int v6 = v5 >> 1; + if ((collected_items & kEquipmentBitmasks_Suits[v6]) != 0) { + uint16 v7 = kEquipmentTilemaps_Suits[v6]; + R22_ = 18; + Copy_R22_Bytes(v7); + if ((equipped_items & kEquipmentBitmasks_Suits[v6]) == 0) { + R18_ = 3072; + R22_ = 18; + SetPaletteOfR22TilemapBytesToR18(); + } + } else { + R22_ = 18; + Copy_R22_Bytes(addr_kEquipmentScreenTilemap_Blank); + } + v5 += 2; + R0_.addr = *(uint16 *)IndirPtr(&R3_, v5); + } while ((int16)(v5 - 12) < 0); + uint16 v8 = 0; + R3_.addr = addr_kEquipmentTilemapOffs_Boots; + *(uint16 *)&R3_.bank = 130; + R0_.addr = *(uint16 *)IndirPtr(&R3_, 0); + do { + int v9 = v8 >> 1; + if ((collected_items & kEquipmentBitmasks_Boots[v9]) != 0) { + R22_ = 18; + Copy_R22_Bytes(kEquipmentTilemaps_Boots[v9]); + if ((equipped_items & kEquipmentBitmasks_Boots[v9]) == 0) { + R18_ = 3072; + R22_ = 18; + SetPaletteOfR22TilemapBytesToR18(); + } + } else { + R22_ = 18; + Copy_R22_Bytes(addr_kEquipmentScreenTilemap_Blank); + } + v8 += 2; + R0_.addr = *(uint16 *)IndirPtr(&R3_, v8); + } while ((int16)(v8 - 6) < 0); +} + +void Copy_R22_Bytes(uint16 k) { // 0x82A27E + R0_.bank = 126; + uint16 v1 = 0; + do { + uint16 *v2 = (uint16 *)RomPtr_82(k); + IndirWriteWord(&R0_, v1, *v2); + k += 2; + v1 += 2; + --R22_; + --R22_; + } while (R22_); +} + +void SetPaletteOfR22TilemapBytesToR18(void) { // 0x82A29D + R0_.bank = 126; + uint16 v0 = 0; + do { + uint8 *v1 = IndirPtr(&R0_, v0); + IndirWriteWord(&R0_, v0, R18_ | *(uint16 *)v1 & 0xE3FF); + v0 += 2; + --R22_; + --R22_; + } while (R22_); +} + +void ClearSamusBeamTiles(void) { // 0x82A2BE + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_82A2D4 = { 1, 1, 0x18, LONGPTR(0x9ad200), 0x1000 }; + SetupDmaTransfer(&unk_82A2D4); + WriteReg(MDMAEN, 2u); +} + +void ContinueInitGameplayResume(void) { // 0x82A2E3 + int16 v0; + + v0 = 512; + uint16 v1 = 0; + do { + palette_buffer[v1] = ram3000.pause_menu_map_tilemap[v1 + 384]; + ++v1; + v0 -= 2; + } while (v0); + SetupPpuForGameplayResume(); + CalculateBgScrolls_Unpause(); + UpdateBeamTilesAndPalette_Unpause(); + ClearPauseMenuData(); + CallSomeSamusCode(0xCu); +} + +void SetupPpuForGameplayResume(void) { // 0x82A313 + WriteReg(OBSEL, 3u); + reg_OBSEL = 3; + WriteReg(BGMODE, 9u); + reg_BGMODE = 9; + reg_BG12NBA = 0; + WriteReg(BG12NBA, 0); + reg_BG34NBA = 4; + WriteReg(BG34NBA, 4u); + reg_BG1SC = 81; + WriteReg(BG1SC, 0x51u); + reg_BG2SC = 73; + WriteReg(BG2SC, 0x49u); + reg_BG3SC = 90; + WriteReg(BG3SC, 0x5Au); + reg_BG4SC = 0; + WriteReg(BG4SC, 0); +} + +void CalculateBgScrolls_Unpause(void) { // 0x82A34E + reg_BG1HOFS = bg1_x_offset + layer1_x_pos; + reg_BG1VOFS = bg1_y_offset + layer1_y_pos; + reg_BG2HOFS = bg2_x_scroll + layer2_x_pos; + reg_BG2VOFS = bg2_y_scroll + layer2_y_pos; +} + +void UpdateBeamTilesAndPalette_Unpause(void) { // 0x82A377 + UpdateBeamTilesAndPalette(); +} + +void ClearPauseMenuData(void) { // 0x82A380 + menu_index = 0; + pausemenu_start_lr_pressed_highlight_timer = 0; + pausemenu_lr_animation_timer = 0; + pausemenu_item_selector_animation_timer = 0; + pausemenu_reserve_tank_animation_timer = 0; + UNUSED_word_7E0731 = 0; + pausemenu_uparrow_animation_timer = 0; + pausemenu_downarrow_animation_timer = 0; + pausemenu_rightarrow_animation_timer = 0; + pausemenu_leftarrow_animation_timer = 0; + UNUSED_word_7E073D = 0; + pausemenu_lr_animation_frame = 0; + pausemenu_item_selector_animation_frame = 0; + pausemenu_reserve_tank_animation_frame = 0; + UNUSED_word_7E0745 = 0; + pausemenu_uparrow_animation_frame = 0; + pausemenu_downarrow_animation_frame = 0; + pausemenu_rightarrow_animation_frame = 0; + pausemenu_leftarrow_animation_frame = 0; + pausemenu_shoulder_button_highlight = 0; + pausemenu_button_label_mode = 0; + pausemenu_equipment_category_item = 0; + pausemenu_reserve_tank_delay_ctr = 0; + UNUSED_word_7E0759 = 0; + UNUSED_word_7E075B = 0; + UNUSED_word_7E075D = 0; + UNUSED_word_7E075F = 0; + UNUSED_word_7E0761 = 0; +} + + +void sub_82A425(void) { // 0x82A425 + ; +} + +void sub_82A42A(void) { // 0x82A42A + if (samus_pose == kPose_81_FaceR_Screwattack || samus_pose == kPose_82_FaceL_Screwattack) { + if ((equipped_items & 8) != 0) + return; + goto LABEL_8; + } + if ((samus_pose == kPose_1B_FaceR_SpaceJump || samus_pose == kPose_1C_FaceL_SpaceJump) + && (equipped_items & 0x20) == 0) { +LABEL_8: + if (samus_pose_x_dir == 4) + samus_pose = kPose_1A_FaceL_SpinJump; + else + samus_pose = kPose_19_FaceR_SpinJump; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + } +} + +void sub_82A47B(void) { // 0x82A47B + if ((equipped_items & 4) == 0) { + if (samus_pose_x_dir == 4) + samus_pose = kPose_41_FaceL_Morphball_Ground; + else + samus_pose = kPose_1D_FaceR_Morphball_Ground; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + } +} + +void sub_82A4A9(void) { // 0x82A4A9 + if ((equipped_items & 2) != 0) { + if (samus_pose_x_dir == 4) + samus_pose = kPose_7A_FaceL_Springball_Ground; + else + samus_pose = kPose_79_FaceR_Springball_Ground; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + } +} + +void HandlePauseScreenLR(void) { // 0x82A505 + HandlePauseScreenLrInput(); + DrawLrHighlight(); +} + +void HandlePauseScreenLrInput(void) { // 0x82A50C + if ((newly_held_down_timed_held_input & kButton_L) != 0) { + if (!pausemenu_button_label_mode) + return; + pausemenu_start_lr_pressed_highlight_timer = 5; + menu_index = 5; + pausemenu_shoulder_button_highlight = 1; + pausemenu_button_label_mode = 0; + SetPauseScreenButtonLabelPalettes(); + goto LABEL_7; + } + if ((newly_held_down_timed_held_input & kButton_R) != 0 && pausemenu_button_label_mode != 2) { + pausemenu_start_lr_pressed_highlight_timer = 5; + menu_index = 2; + pausemenu_shoulder_button_highlight = 2; + pausemenu_button_label_mode = 2; + SetPauseScreenButtonLabelPalettes(); +LABEL_7: + QueueSfx1_Max6(0x38u); + } +} +static const uint16 kPauseLrButtonPressedHighlight_Spritemap[2] = { 0x28, 0x29 }; +static const uint16 kPauseLrButtonPressedHighlight_Y[2] = { 0x18, 0xe8 }; +static const uint16 kPauseLrButtonPressedHighlight_X[2] = { 0xd0, 0xd0 }; +void HandlePauseMenuLRPressHighlight(void) { // 0x82A56D + if (pausemenu_start_lr_pressed_highlight_timer) { + --pausemenu_start_lr_pressed_highlight_timer; + if (pausemenu_shoulder_button_highlight) { + R3_.addr = 0; + int v0 = pausemenu_shoulder_button_highlight - 1; + DrawMenuSpritemap( + kPauseLrButtonPressedHighlight_Spritemap[v0], + kPauseLrButtonPressedHighlight_Y[v0], + kPauseLrButtonPressedHighlight_X[v0] - 1); + } + } +} + +void DrawLrHighlight(void) { // 0x82A59A + DrawPauseScreenSpriteAnim(2u, 0x18u, 0xD0u); + DrawPauseScreenSpriteAnim(2u, 0xE8u, 0xD0u); +} + +void HandlePauseScreenStart(void) { // 0x82A5B7 + if ((newly_held_down_timed_held_input & kButton_Start) != 0) { + QueueSfx1_Max6(0x38u); + screen_fade_delay = 1; + screen_fade_counter = 1; + uint16 v0 = pausemenu_button_label_mode; + pausemenu_button_label_mode = 1; + SetPauseScreenButtonLabelPalettes(); + pausemenu_button_label_mode = v0; + pausemenu_start_lr_pressed_highlight_timer = 11; + ++game_state; + } + UpdatePauseMenuLRStartVramTilemap(); +} + +void HighlightPauseScreenButton(void) { // 0x82A5F1 + if (pausemenu_start_lr_pressed_highlight_timer) { + --pausemenu_start_lr_pressed_highlight_timer; + R3_.addr = 0; + DrawMenuSpritemap(0x2Bu, 0x90u, 0xD0u); + } +} +static Func_V *const kSetPauseScreenButtonLabelPalettes_Funcs[3] = { // 0x82A615 + SetPauseScreenButtonLabelPalettes_0, + SetPauseScreenButtonLabelPalettes_1, + SetPauseScreenButtonLabelPalettes_2, +}; +void SetPauseScreenButtonLabelPalettes(void) { + kSetPauseScreenButtonLabelPalettes_Funcs[pausemenu_button_label_mode](); +} + +void SetPauseScreenButtonLabelPalettes_2(void) { // 0x82A628 + int16 v0; + int16 v2; + int16 v4; + int16 v6; + int16 v8; + int16 v10; + + v0 = 10; + uint16 v1 = 0; + do { + ram3000.pause_menu_map_tilemap[v1 + 805] = ram3000.pause_menu_map_tilemap[v1 + 805] & 0xE3FF | 0x800; + ++v1; + v0 -= 2; + } while (v0); + v2 = 10; + uint16 v3 = 0; + do { + ram3000.pause_menu_map_tilemap[v3 + 837] = ram3000.pause_menu_map_tilemap[v3 + 837] & 0xE3FF | 0x800; + ++v3; + v2 -= 2; + } while (v2); + v4 = 8; + uint16 v5 = 0; + do { + ram3000.pause_menu_map_tilemap[v5 + 812] = ram3000.pause_menu_map_tilemap[v5 + 812] & 0xE3FF | 0x800; + ++v5; + v4 -= 2; + } while (v4); + v6 = 8; + uint16 v7 = 0; + do { + ram3000.pause_menu_map_tilemap[v7 + 844] = ram3000.pause_menu_map_tilemap[v7 + 844] & 0xE3FF | 0x800; + ++v7; + v6 -= 2; + } while (v6); + v8 = 10; + uint16 v9 = 0; + do { + ram3000.pause_menu_map_tilemap[v9 + 822] = ram3000.pause_menu_map_tilemap[v9 + 822] & 0xE3FF | 0x1400; + ++v9; + v8 -= 2; + } while (v8); + v10 = 10; + uint16 v11 = 0; + do { + ram3000.pause_menu_map_tilemap[v11 + 854] = ram3000.pause_menu_map_tilemap[v11 + 854] & 0xE3FF | 0x1400; + ++v11; + v10 -= 2; + } while (v10); +} + +void SetPauseScreenButtonLabelPalettes_1(void) { // 0x82A6DF + int16 v0; + int16 v2; + int16 v4; + int16 v6; + int16 v8; + int16 v10; + + v0 = 8; + uint16 v1 = 0; + do { + ram3000.pause_menu_map_tilemap[v1 + 812] = ram3000.pause_menu_map_tilemap[v1 + 812] & 0xE3FF | 0x800; + ++v1; + v0 -= 2; + } while (v0); + v2 = 8; + uint16 v3 = 0; + do { + ram3000.pause_menu_map_tilemap[v3 + 844] = ram3000.pause_menu_map_tilemap[v3 + 844] & 0xE3FF | 0x800; + ++v3; + v2 -= 2; + } while (v2); + v4 = 10; + uint16 v5 = 0; + do { + ram3000.pause_menu_map_tilemap[v5 + 805] = ram3000.pause_menu_map_tilemap[v5 + 805] & 0xE3FF | 0x1400; + ++v5; + v4 -= 2; + } while (v4); + v6 = 10; + uint16 v7 = 0; + do { + ram3000.pause_menu_map_tilemap[v7 + 837] = ram3000.pause_menu_map_tilemap[v7 + 837] & 0xE3FF | 0x1400; + ++v7; + v6 -= 2; + } while (v6); + v8 = 10; + uint16 v9 = 0; + do { + ram3000.pause_menu_map_tilemap[v9 + 822] = ram3000.pause_menu_map_tilemap[v9 + 822] & 0xE3FF | 0x1400; + ++v9; + v8 -= 2; + } while (v8); + v10 = 10; + uint16 v11 = 0; + do { + ram3000.pause_menu_map_tilemap[v11 + 854] = ram3000.pause_menu_map_tilemap[v11 + 854] & 0xE3FF | 0x1400; + ++v11; + v10 -= 2; + } while (v10); +} + +void SetPauseScreenButtonLabelPalettes_0(void) { // 0x82A796 + int16 v0; + int16 v2; + int16 v4; + int16 v6; + int16 v8; + int16 v10; + + v0 = 10; + uint16 v1 = 0; + do { + ram3000.pause_menu_map_tilemap[v1 + 822] = ram3000.pause_menu_map_tilemap[v1 + 822] & 0xE3FF | 0x800; + ++v1; + v0 -= 2; + } while (v0); + v2 = 10; + uint16 v3 = 0; + do { + ram3000.pause_menu_map_tilemap[v3 + 854] = ram3000.pause_menu_map_tilemap[v3 + 854] & 0xE3FF | 0x800; + ++v3; + v2 -= 2; + } while (v2); + v4 = 8; + uint16 v5 = 0; + do { + ram3000.pause_menu_map_tilemap[v5 + 812] = ram3000.pause_menu_map_tilemap[v5 + 812] & 0xE3FF | 0x800; + ++v5; + v4 -= 2; + } while (v4); + v6 = 8; + uint16 v7 = 0; + do { + ram3000.pause_menu_map_tilemap[v7 + 844] = ram3000.pause_menu_map_tilemap[v7 + 844] & 0xE3FF | 0x800; + ++v7; + v6 -= 2; + } while (v6); + v8 = 10; + uint16 v9 = 0; + do { + ram3000.pause_menu_map_tilemap[v9 + 805] = ram3000.pause_menu_map_tilemap[v9 + 805] & 0xE3FF | 0x1400; + ++v9; + v8 -= 2; + } while (v8); + v10 = 10; + uint16 v11 = 0; + do { + ram3000.pause_menu_map_tilemap[v11 + 837] = ram3000.pause_menu_map_tilemap[v11 + 837] & 0xE3FF | 0x1400; + ++v11; + v10 -= 2; + } while (v10); +} + +void UpdatePauseMenuLRStartVramTilemap(void) { // 0x82A84D + uint16 v0 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 128; + v0 += 2; + gVramWriteEntry(v0)->size = 0x3640; + v0 += 2; + LOBYTE(gVramWriteEntry(v0++)->size) = 126; + gVramWriteEntry(v0)->size = ((reg_BG2SC & 0xFC) << 8) + 800; + vram_write_queue_tail = v0 + 2; +} + +#define kPauseScreenSpriteAnimationData_0 (*(PauseScreenSpriteAnimationData*)RomPtr(0x82c0b2)) +#define kPauseScreenSpriteAnimationData_1 (*(PauseScreenSpriteAnimationData*)RomPtr(0x82c0c4)) +#define kPauseScreenSpriteAnimationData_2 (*(PauseScreenSpriteAnimationData*)RomPtr(0x82c0d6)) +#define kPauseScreenSpriteAnimationData_3 (*(PauseScreenSpriteAnimationData*)RomPtr(0x82c0e8)) +#define kPAuseSpritePaletteIndexValues ((uint16*)RomPtr(0x82c0fa)) +#define kPausePtsToAnimationSpritemapBaseIds ((uint16*)RomPtr(0x82c1e4)) + +void DrawPauseScreenSpriteAnim(uint16 a, uint16 k, uint16 j) { // 0x82A881 + int16 v9; + int16 v10; + int16 v12; + + R18_ = k; + R20_ = j; + uint16 v3 = 2 * (a - 1); + uint16 v4 = *(VoidP *)((char *)&kPauseScreenSpriteAnimationData_0.unused + v3); + uint8 *v5 = RomPtr_RAM(v4); + bool v6 = *(uint16 *)v5 == 1; + bool v7 = (int16)-- * (uint16 *)v5 < 0; + if (v6 || v7) { + R24_ = v4; + uint8 *v8 = RomPtr_RAM(*(VoidP *)((char *)&kPauseScreenSpriteAnimationData_1.unused + v3)); + v9 = *(uint16 *)v8 + 1; + *(uint16 *)v8 = v9; + R22_ = *(uint16 *)v8 + 2 * v9; + v10 = *RomPtr_82(R22_ + *(VoidP *)((char *)&kPauseScreenSpriteAnimationData_3.unused + v3)); + if (v10 == 255) { + *(uint16 *)RomPtr_RAM(*(VoidP *)((char *)&kPauseScreenSpriteAnimationData_1.unused + v3)) = 0; + v10 = *RomPtr_82(*(VoidP *)((char *)&kPauseScreenSpriteAnimationData_3.unused + v3)); + } + *(uint16 *)RomPtr_RAM(R24_) = v10; + } + R24_ = 3 * *(uint16 *)RomPtr_RAM(*(VoidP *)((char *)&kPauseScreenSpriteAnimationData_1.unused + v3)); + v12 = R24_ + *(VoidP *)((char *)&kPauseScreenSpriteAnimationData_3.unused + v3) + 1; + R3_.addr = kPAuseSpritePaletteIndexValues[3]; + R24_ = *RomPtr_82(v12 + 1); + R26_ = 2 * *RomPtr_RAM(*(VoidP *)((char *)&kPauseScreenSpriteAnimationData_2.unused + v3)); + uint8 *v11 = RomPtr_82(R26_ + kPausePtsToAnimationSpritemapBaseIds[v3 >> 1]); + DrawMenuSpritemap(R24_ + *(uint16 *)v11, R18_, R20_ - 1); +} +#define kPauseAnimatedPalette ((uint16*)RomPtr(0x82a987)) +void HandlePauseScreenPaletteAnimation(void) { // 0x82A92B + uint16 v2; + uint16 j; + uint8 v1; + + if ((uint8)pausemenu_palette_animation_timer) { + LOBYTE(pausemenu_palette_animation_timer) = pausemenu_palette_animation_timer - 1; + if (!(uint8)pausemenu_palette_animation_timer) { + for (int i = pausemenu_palette_animation_frame + 1; ; i = 0) { + LOBYTE(pausemenu_palette_animation_frame) = i; + v1 = kPauseLrHighlightAnimData[(uint8)(3 * i)]; + if (v1 != 0xFF) + break; + QueueSfx3_Max6(0x2Au); + } + LOBYTE(pausemenu_palette_animation_timer) = v1; + LOBYTE(v2) = 0; + HIBYTE(v2) = pausemenu_palette_animation_frame; + uint16 v3 = (v2 >> 3) + 30; + for (j = 30; (j & 0x8000u) == 0; j -= 2) { + palette_buffer[(j >> 1) + 176] = kPauseAnimatedPalette[v3 >> 1]; + v3 -= 2; + } + } + } +} +#define kPauseReserveTankAnimationData ((uint8*)RomPtr(0x82c165)) +void EquipmentScreenSetupReserveMode(void) { // 0x82AB47 + VoidP v0; + int16 v3; + int16 v5; + int16 v7; + int16 v8; + + reg_BG4HOFS = reg_BG1HOFS; + reg_BG4VOFS = reg_BG1VOFS; + reg_BG1HOFS = 0; + reg_BG1VOFS = 0; + if (samus_max_reserve_health && reserve_health_mode) { + v0 = addr_kEquipmentScreenTilemap_AUTO; + if (reserve_health_mode != 1) + v0 = addr_kEquipmentScreenTilemap_MANUAL; + *(uint16 *)&R0_.bank = 130; + R0_.addr = v0; + R18_ = 4; + uint16 v1 = 0; + uint16 v2 = 0; + do { + v3 = ram3800.cinematic_bg_tilemap[v1 + 327] & 0xFC00; + ram3800.cinematic_bg_tilemap[v1 + 327] = *(uint16 *)IndirPtr(&R0_, v2) | v3; + v2 += 2; + ++v1; + --R18_; + } while (R18_); + } + pausemenu_item_selector_animation_frame = 0; + pausemenu_item_selector_animation_timer = kPauseLrHighlightAnimData[0]; + pausemenu_reserve_tank_animation_frame = 0; + pausemenu_reserve_tank_animation_timer = kPauseReserveTankAnimationData[0]; + if (samus_max_reserve_health) { + pausemenu_equipment_category_item = 0; + } else if (hyper_beam_flag) { +LABEL_15:; + uint16 v6 = 0; + do { + if ((kEquipmentBitmasks_Suits[v6 >> 1] & collected_items) != 0) { + LOBYTE(v7) = (uint16)(v6 >> 1) >> 8; + HIBYTE(v7) = v6 >> 1; + pausemenu_equipment_category_item = v7 | 2; + goto LABEL_21; + } + v6 += 2; + } while ((int16)(v6 - 12) < 0); + v8 = 0; + do + v8 += 2; + while ((int16)(v8 - 6) < 0); + } else { + uint16 v4 = 0; + while ((kEquipmentBitmasks_Weapons[v4 >> 1] & collected_beams) == 0) { + v4 += 2; + if ((int16)(v4 - 10) >= 0) + goto LABEL_15; + } + LOBYTE(v5) = (uint16)(v4 >> 1) >> 8; + HIBYTE(v5) = v4 >> 1; + pausemenu_equipment_category_item = v5 | 1; + } +LABEL_21: + if (samus_reserve_health) { + EquipmentScreenGlowingArrowSolidOn(); + WriteSamusWireframeTilemapAndQueue(); + } +} + +void EquipmentScreenTransferBG1Tilemap(void) { // 0x82AC22 + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x30u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_82AC3B = { 1, 1, 0x18, LONGPTR(0x7e3800), 0x0800 }; + SetupDmaTransfer(&unk_82AC3B); + WriteReg(MDMAEN, 2u); + reg_BG1VOFS = 0; +} +static Func_V *const kEquipmentScreenCategories[4] = { // 0x82AC4F + EquipmentScreenCategory_Tanks, + EquipmentScreenCategory_Weapons, + EquipmentScreenCategory_Suit, + EquipmentScreenCategory_Boots, +}; +void EquipmentScreenMain(void) { + kEquipmentScreenCategories[(uint16)(2 * (uint8)pausemenu_equipment_category_item) >> 1](); + EquipmentScreenDrawItemSelector(); + EquipmentScreenDisplayReserveTankAmount(); + WriteSamusWireframeTilemapAndQueue(); +} +static Func_V *const kEquipmentScreenCategory_TanksFuncs[2] = { // 0x82AC70 + EquipmentScreenCategory_Tanks_0, + EquipmentScreenCategory_Tanks_1, +}; +void EquipmentScreenCategory_Tanks(void) { + kEquipmentScreenCategory_TanksFuncs[(uint16)(2 * HIBYTE(pausemenu_equipment_category_item)) >> 1](); + EquipmentScreenHandleDpad(); + EquipmentScreenGlowingArrow(); +} + +void EquipmentScreenHandleDpad(void) { // 0x82AC8B + R18_ = pausemenu_equipment_category_item; + if ((joypad1_newkeys & kButton_Right) != 0) { + if ((joypad1_newkeys & kButton_Down) != 0 || EquipmentScreenMoveLowerOnSuitsMisc(0) == 0xFFFF) + EquipmentScreenMoveToHighJumpOrLowerInBoots(0); + } else if ((joypad1_newkeys & kButton_Up) != 0) { + if ((pausemenu_equipment_category_item & 0xFF00) != 0) { + QueueSfx1_Max6(0x37u); + pausemenu_equipment_category_item -= 256; + } + } else if ((joypad1_newkeys & kButton_Down) != 0) { + if ((pausemenu_equipment_category_item & 0xFF00) == 256 + || reserve_health_mode == 1 + || (pausemenu_equipment_category_item += 256, !samus_reserve_health)) { + EquipmentScreenMoveToBeams(0); + } else { + QueueSfx1_Max6(0x37u); + } + } +} +static Func_V *const kEquipmentScreenGlowingArrowFuncs[2] = { // 0x82AD0A + EquipmentScreenGlowingArrowAnimated, + EquipmentScreenGlowingArrowSolidOn, +}; + +void EquipmentScreenGlowingArrow(void) { + if ((uint8)pausemenu_equipment_category_item) + EquipmentScreenGlowingArrowSolidOff(); + else + kEquipmentScreenGlowingArrowFuncs[0](); +} + +static const uint16 kEquipmentScreenGlowingArrowPalettes0[32] = { 0x39e, 0x77d, 0xb5c, 0xf5b, 0x133a, 0x171a, 0x1f19, 0x22f8, 0x26d7, 0x2ad6, 0x2eb6, 0x3695, 0x3a94, 0x3e73, 0x4253, 0x4a52, 0x4a52, 0x4253, 0x3e73, 0x3a94, 0x3695, 0x2eb6, 0x2ad6, 0x26d7, 0x22f8, 0x1f19, 0x171a, 0x133a, 0xf5b, 0xb5c, 0x77d, 0x39e }; +static const uint16 kEquipmentScreenGlowingArrowPalettes1[32] = { 0x156, 0x155, 0x554, 0x954, 0xd53, 0xd52, 0x1152, 0x1551, 0x1970, 0x1d70, 0x1d6f, 0x216e, 0x256e, 0x296d, 0x296c, 0x318c, 0x318c, 0x296c, 0x296d, 0x256e, 0x216e, 0x1d6f, 0x1d70, 0x1970, 0x1551, 0x1152, 0xd52, 0xd53, 0x954, 0x554, 0x155, 0x156 }; + +void EquipmentScreenGlowingArrowAnimated(void) { // 0x82AD29 + if (reserve_health_mode == 1) { + int v0 = nmi_frame_counter_byte & 0x1F; + palette_buffer[102] = kEquipmentScreenGlowingArrowPalettes0[v0]; + palette_buffer[107] = kEquipmentScreenGlowingArrowPalettes1[v0]; + EquipmentScreenEnergyArrowGlow_On(); + } else { + palette_buffer[107] = 926; + palette_buffer[102] = 342; + EquipmentScreenEnergyArrowGlow_Off(); + } +} + +void EquipmentScreenGlowingArrowSolidOn(void) { // 0x82ADDD + palette_buffer[107] = 926; + palette_buffer[102] = 342; + EquipmentScreenEnergyArrowGlow_On(); +} + +void EquipmentScreenGlowingArrowSolidOff(void) { // 0x82ADEF + palette_buffer[107] = 926; + palette_buffer[102] = 342; + EquipmentScreenEnergyArrowGlow_Off(); +} + +void EquipmentScreenEnergyArrowGlow_On(void) { // 0x82AE01 + int16 v0; + int16 v2; + + v0 = 16; + uint16 v1 = 0; + do { + ram3800.cinematic_bg_tilemap[v1 + 129] = ram3800.cinematic_bg_tilemap[v1 + 129] & 0xE3FF | 0x1800; + v1 += 32; + v0 -= 2; + } while (v0); + v2 = 4; + uint16 v3 = 0; + do { + ram3800.cinematic_bg_tilemap[v3 + 385] = ram3800.cinematic_bg_tilemap[v3 + 385] & 0xE3FF | 0x1800; + ++v3; + v2 -= 2; + } while (v2); +} + +void EquipmentScreenEnergyArrowGlow_Off(void) { // 0x82AE46 + int16 v0; + int16 v2; + + v0 = 16; + uint16 v1 = 0; + do { + ram3800.cinematic_bg_tilemap[v1 + 129] = ram3800.cinematic_bg_tilemap[v1 + 129] & 0xE3FF | 0x1C00; + v1 += 32; + v0 -= 2; + } while (v0); + v2 = 4; + uint16 v3 = 0; + do { + ram3800.cinematic_bg_tilemap[v3 + 385] = ram3800.cinematic_bg_tilemap[v3 + 385] & 0xE3FF | 0x1C00; + ++v3; + v2 -= 2; + } while (v2); +} +static const uint16 kEquipmentScreenTilemap_MODE_MANUAL[7] = { 0x2519, 0x251a, 0x251b, 0x3d46, 0x3d47, 0x3d48, 0x3d49 }; +static const uint16 kEquipmentScreenTilemap_RESERVE_TANK[7] = { 0x3c80, 0x3c81, 0x3c82, 0x3c83, 0x3c84, 0x3c85, 0x3c86 }; +static const uint16 kEquipmentScreenTilemap_MANUAL[4] = { 0x3d46, 0x3d47, 0x3d48, 0x3d49 }; +static const uint16 kEquipmentScreenTilemap_AUTO[4] = { 0x3d56, 0x3d57, 0x3d58, 0x3d59 }; +static const uint16 kEquipmentScreenTilemap_CHARGE[5] = { 0x8ff, 0x8d8, 0x8d9, 0x8da, 0x8e7 }; +static const uint16 kEquipmentScreenTilemap_ICE[5] = { 0x8ff, 0x8db, 0x8dc, 0x8d4, 0x8d4 }; +static const uint16 kEquipmentScreenTilemap_WAVE[5] = { 0x8ff, 0x8dd, 0x8de, 0x8df, 0x8d4 }; +static const uint16 kEquipmentScreenTilemap_SPAZER[5] = { 0x8ff, 0x8e8, 0x8e9, 0x8ea, 0x8eb }; +static const uint16 kEquipmentScreenTilemap_PLASMA[5] = { 0x8ff, 0x8ec, 0x8ed, 0x8ee, 0x8ef }; +static const uint16 kEquipmentScreenTilemap_VARIASUIT[9] = { // 0x82AE8B + 0x8ff, 0x900, 0x901, 0x902, 0x903, 0x904, 0x905, 0x8d4, + 0x8d4, +}; +static const uint16 kEquipmentScreenTilemap_GRAVITYSUIT[9] = { + 0x8ff, 0x8d0, 0x8d1, 0x8d2, 0x8d3, 0x903, 0x904, 0x905, + 0x8d4, +}; +static const uint16 kEquipmentScreenTilemap_MORPHINGBALL[9] = { + 0x8ff, 0x920, 0x921, 0x922, 0x923, 0x917, 0x918, 0x90f, + 0x91f, +}; +static const uint16 kEquipmentScreenTilemap_BOMBS[9] = { + 0x8ff, 0x8d5, 0x8d6, 0x8d7, 0x8d4, 0x8d4, 0x8d4, 0x8d4, + 0x8d4, +}; +static const uint16 kEquipmentScreenTilemap_SPRING_BALL[9] = { + 0x8ff, 0x910, 0x911, 0x912, 0x913, 0x914, 0x915, 0x916, + 0x8d4, +}; +static const uint16 kEquipmentScreenTilemap_SCREW_ATTACK[9] = { + 0x8ff, 0x8e0, 0x8e1, 0x8e2, 0x8e3, 0x8e4, 0x8e5, 0x8e6, + 0x8d4, +}; +static const uint16 kEquipmentScreenTilemap_HIJUMP_BOOTS[9] = { + 0x8ff, 0x930, 0x931, 0x932, 0x933, 0x934, 0x935, 0x936, + 0x8d4, +}; +static const uint16 kEquipmentScreenTilemap_SPACE_JUMP[9] = { + 0x8ff, 0x8f0, 0x8f1, 0x8f2, 0x8f3, 0x8f4, 0x8f5, 0x8d4, + 0x8d4, +}; +static const uint16 kEquipmentScreenTilemap_SPEED_BOOSTER[9] = { + 0x8ff, 0x924, 0x925, 0x926, 0x927, 0x928, 0x929, 0x92a, + 0x92b, +}; +static const uint16 kEquipmentScreenTilemap_HYPER[9] = { + 0x8ff, 0x937, 0x938, 0x939, 0x92f, 0x8d4, 0x8d4, 0x8d4, + 0x8d4, +}; +static const uint16 kEquipmentScreenTilemap_Blank[9] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; +void EquipmentScreenCategory_Tanks_0(void) { + int16 v0; + int16 v2; + + if ((joypad1_newkeys & kButton_A) != 0 && samus_max_reserve_health) { + QueueSfx1_Max6(0x37u); + if (reserve_health_mode == 1) { + reserve_health_mode = 2; + EquipmentScreenHudReserveAutoTilemap_Off(); + v0 = 8; + uint16 v1 = 0; + do { + ram3800.cinematic_bg_tilemap[v1 + 327] = kEquipmentScreenTilemap_MANUAL[v1] | ram3800.cinematic_bg_tilemap[v1 + 327] & 0xFC00; + ++v1; + v0 -= 2; + } while (v0); + } else { + reserve_health_mode = 1; + EquipmentScreenHudReserveAutoTilemap_On_BUGGY(); + v2 = 8; + uint16 v3 = 0; + do { + ram3800.cinematic_bg_tilemap[v3 + 327] = kEquipmentScreenTilemap_AUTO[v3] | ram3800.cinematic_bg_tilemap[v3 + 327] & 0xFC00; + ++v3; + v2 -= 2; + } while (v2); + } + } +} + +void EquipmentScreenHudReserveAutoTilemap_On_BUGGY(void) { // 0x82AEFD + uint16 v0 = -26229; + if (!samus_reserve_health) + v0 = -26217; + uint16 *v1 = (uint16 *)RomPtr_82(v0); + hud_tilemap[8] = *v1; + hud_tilemap[9] = v1[1]; + hud_tilemap[40] = v1[2]; + hud_tilemap[41] = v1[3]; + hud_tilemap[72] = v1[4]; + hud_tilemap[73] = v1[5]; +} + +void EquipmentScreenHudReserveAutoTilemap_Off(void) { // 0x82AF33 + hud_tilemap[8] = 11279; + hud_tilemap[9] = 11279; + hud_tilemap[40] = 11279; + hud_tilemap[41] = 11279; + hud_tilemap[72] = 11279; + hud_tilemap[73] = 11279; +} +static const uint16 kReserveTankEnergyTransferPerFrame = 1; +void EquipmentScreenCategory_Tanks_1(void) { // 0x82AF4F + if (!pausemenu_reserve_tank_delay_ctr) { + if ((joypad1_newkeys & kButton_A) == 0) + return; + pausemenu_reserve_tank_delay_ctr = (samus_reserve_health + 7) & 0xFFF8; + } + if ((--pausemenu_reserve_tank_delay_ctr & 7) == 7) + QueueSfx3_Max6(0x2Du); + samus_health += kReserveTankEnergyTransferPerFrame; + if ((int16)(samus_health - samus_max_health) < 0) { + bool v0 = (int16)(samus_reserve_health - kReserveTankEnergyTransferPerFrame) < 0; + samus_reserve_health -= kReserveTankEnergyTransferPerFrame; + if (samus_reserve_health) { + if (!v0) + return; + samus_health += samus_reserve_health; + } + } else { + samus_health = samus_max_health; + } + samus_reserve_health = 0; + pausemenu_reserve_tank_delay_ctr = 0; + EquipmentScreenEnergyArrowGlow_Off(); + pausemenu_equipment_category_item = 0; +} + +void EquipmentScreenCategory_Weapons(void) { // 0x82AFBE + EquipmentScreenCategory_Weapons_MoveButtons(); + R36 = equipped_beams; + if (collected_beams) { + R24_ = 10; + EquipmentScreenCategory_ButtonResponse(); + EquipmentScreenCategory_Weapons_PlazmaSpazerCheck(); + } +} + +void EquipmentScreenCategory_Weapons_MoveButtons(void) { // 0x82AFDB + R18_ = pausemenu_equipment_category_item; + if ((joypad1_newkeys & 0x100) != 0) { + if ((joypad1_newkeys & 0x800) != 0) { + EquipmentScreenMoveLowerOnSuitsMisc(0); + } else if (EquipmentScreenMoveLowerOnSuitsMisc(4u)) { + EquipmentScreenMoveToHighJumpOrLowerInBoots(0); + } + } else if ((joypad1_newkeys & 0x400) != 0) { + if (!hyper_beam_flag && pausemenu_equipment_category_item != 1025) { + pausemenu_equipment_category_item += 256; + EquipmentScreenMoveToBeams(2 * HIBYTE(pausemenu_equipment_category_item)); + } + } else if ((joypad1_newkeys & 0x800) != 0) { + if ((pausemenu_equipment_category_item & 0xFF00) == 0 + || (pausemenu_equipment_category_item -= 256, + EquipmentScreenMoveToBottomOfBeams(2 * HIBYTE(pausemenu_equipment_category_item)) == 0xFFFF)) { + if (!EquipmentScreenMoveToReserveTanks()) + pausemenu_equipment_category_item = R18_; + } + } +} +#define kEquipmentTilemapOffs_Tanks ((uint16*)RomPtr(0x82c068)) +#define kEquipmentTilemapOffs_Weapons ((uint16*)RomPtr(0x82c06c)) +#define kEquipmentTilemapOffs_Suits ((uint16*)RomPtr(0x82c076)) +#define kEquipmentTilemapOffs_Boots ((uint16*)RomPtr(0x82c082)) +#define kEquipmentTilemaps_Tanks ((uint16*)RomPtr(0x82c088)) +#define kEquipmentTilemaps_Weapons ((uint16*)RomPtr(0x82c08c)) +#define kEquipmentTilemaps_Suits ((uint16*)RomPtr(0x82c096)) +#define kEquipmentTilemaps_Boots ((uint16*)RomPtr(0x82c0a2)) +void EquipmentScreenCategory_Weapons_PlazmaSpazerCheck(void) { // 0x82B068 + if (((uint8)equipped_beams & (uint8)~(uint8)R36 & 4) != 0) { + if ((R36 & 4) == 0 && (equipped_beams & 8) != 0) { + equipped_beams &= ~8; + R0_.addr = kEquipmentTilemapOffs_Weapons[4]; + goto LABEL_9; + } + } else if (((uint8)equipped_beams & (uint8)~(uint8)R36 & 8) != 0 + && (R36 & 8) == 0 + && (equipped_beams & 4) != 0) { + equipped_beams &= ~4; + R0_.addr = kEquipmentTilemapOffs_Weapons[3]; +LABEL_9: + R18_ = 3072; + R22_ = 10; + SetPaletteOfR22TilemapBytesToR18(); + } +} + +void EquipmentScreenCategory_Suit(void) { // 0x82B0C2 + EquipmentScreenCategory_Suit_MoveResponse(); + R24_ = 18; + EquipmentScreenCategory_ButtonResponse(); +} + +void EquipmentScreenCategory_Suit_MoveResponse(void) { // 0x82B0D2 + R18_ = pausemenu_equipment_category_item; + if ((joypad1_newkeys & kButton_Left) != 0) { + if ((joypad1_newkeys & kButton_Down) == 0) { + if (EquipmentScreenMoveToReserveTanks()) + return; + pausemenu_equipment_category_item = R18_; + } + EquipmentScreenMoveToBeams(0); + } else if ((joypad1_newkeys & kButton_Up) != 0) { + if ((pausemenu_equipment_category_item & 0xFF00) != 0) { + pausemenu_equipment_category_item -= 256; + EquipmentScreenMoveToScrewOrHigherOnSuits(2 * HIBYTE(pausemenu_equipment_category_item)); + } + } else if ((joypad1_newkeys & kButton_Down) != 0) { + if ((pausemenu_equipment_category_item & 0xFF00) == 1280 + || (pausemenu_equipment_category_item += 256, + EquipmentScreenMoveLowerOnSuitsMisc(2 * HIBYTE(pausemenu_equipment_category_item)) == 0xFFFF)) { + EquipmentScreenMoveToHighJumpOrLowerInBoots(0); + } + } +} + +void EquipmentScreenCategory_Boots(void) { // 0x82B150 + EquipmentScreenCategory_Boots_MoveResponse(); + R24_ = 18; + EquipmentScreenCategory_ButtonResponse(); +} + +void EquipmentScreenCategory_Boots_MoveResponse(void) { // 0x82B160 + R18_ = pausemenu_equipment_category_item; + if ((joypad1_newkeys & kButton_Left) != 0) { + if (((joypad1_newkeys & kButton_Up) != 0 || EquipmentScreenMoveToBottomOfBeams(8u) == 0xFFFF) + && !EquipmentScreenMoveToReserveTanks()) { + pausemenu_equipment_category_item = R18_; + } + } else if ((joypad1_newkeys & kButton_Down) != 0) { + if (pausemenu_equipment_category_item != 515) { + pausemenu_equipment_category_item += 256; + EquipmentScreenMoveToHighJumpOrLowerInBoots(2 * HIBYTE(pausemenu_equipment_category_item)); + } + } else if ((joypad1_newkeys & kButton_Up) != 0) { + if ((pausemenu_equipment_category_item & 0xFF00) == 0 + || (pausemenu_equipment_category_item -= 256, + EquipmentScreenCategory_Boots_MoveUpInBoots(2 * HIBYTE(pausemenu_equipment_category_item)) == 0xFFFF)) { + EquipmentScreenMoveToScrewOrHigherOnSuits(0xAu); + } + } +} + +void WriteSamusWireframeTilemapAndQueue(void) { // 0x82B1E0 + WriteSamusWireframeTilemap(); + uint16 v0 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 1280; + v0 += 2; + gVramWriteEntry(v0)->size = ADDR16_OF_RAM(ram3800) + 256; + v0 += 2; + LOBYTE(gVramWriteEntry(v0++)->size) = 126; + gVramWriteEntry(v0)->size = 0x3080; + vram_write_queue_tail = v0 + 2; +} + +#define kEquipmentScreenWireframeCmp ((uint16*)RomPtr(0x82b257)) +#define kEquipmentScreenWireframePtrs ((uint16*)RomPtr(0x82b25f)) + +void WriteSamusWireframeTilemap(void) { // 0x82B20C + uint16 i; + + for (i = 0; (equipped_items & 0x101) != kEquipmentScreenWireframeCmp[i >> 1]; i += 2) + ; + R0_.addr = kEquipmentScreenWireframePtrs[i >> 1]; + *(uint16 *)&R0_.bank = 130; + R20_ = 17; + uint16 v1 = 0; + uint16 v2 = 472; + do { + uint16 v3 = v2; + R18_ = 8; + do { + *(uint16 *)((char *)ram3800.cinematic_bg_tilemap + v2) = *(uint16 *)IndirPtr(&R0_, v1); + v2 += 2; + v1 += 2; + --R18_; + } while (R18_); + v2 = v3 + 64; + --R20_; + } while (R20_); +} + +#define kEquipmentScreenPtrsToItemXYpos ((uint16*)RomPtr(0x82c18e)) + +void EquipmentScreenDrawItemSelector(void) { // 0x82B267 + if (samus_max_reserve_health | (uint16)(collected_items | collected_beams)) { + R18_ = kEquipmentScreenPtrsToItemXYpos[(uint16)(2 * (uint8)pausemenu_equipment_category_item) >> 1]; + uint16 v0 = *(uint16 *)RomPtr_82(R18_ + 4 * HIBYTE(pausemenu_equipment_category_item)) - 1; + uint16 v1 = *(uint16 *)RomPtr_82(R18_ + 4 * HIBYTE(pausemenu_equipment_category_item) + 2); + DrawPauseScreenSpriteAnim(3u, v0, v1); + } +} + +void EquipmentScreenDisplayReserveTankAmount(void) { // 0x82B2A2 + EquipmentScreenDisplayReserveTankAmount_(); +} +static const uint16 kEquipmentScreenReserveTank_X[6] = { // 0x82B2AA + 0x18, 0x20, + 0x28, 0x30, + 0x38, 0x40, +}; +static const uint16 kEquipmentScreenReserveTank_Y = 0x60; +static const uint16 kPartialReserveTankSpritemapIds[16] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 }; + +void EquipmentScreenDisplayReserveTankAmount_(void) { + uint16 a; + + R3_.addr = 0; + EquipmentScreenDisplayReserves_PaletteSetup(); + bg3_tilemap_offset = 0; + if (samus_max_reserve_health) { + R44 = samus_max_reserve_health / 100; + + int mod_value = samus_reserve_health % 100; + R50 = mod_value; + R42 = samus_reserve_health / 100; + + R48 = R42; + R46 = R42; + if (R42) { + uint16 v0 = 0; + do { + a = v0; + DrawMenuSpritemap(0x1Bu, kEquipmentScreenReserveTank_X[v0 >> 1], kEquipmentScreenReserveTank_Y - 1); + v0 += 2; + --R46; + } while (R46); + bg3_tilemap_offset = a + 2; + } + uint16 RegWord = mod_value; + if (RegWord) { + uint16 v2 = 2 * (RegWord / 14); + if (sign16(v2 - 7) && RegWord % 14 && (nmi_frame_counter_byte & 4) == 0) + v2 += 2; + if (!sign16(samus_reserve_health - 100)) + v2 += 16; + DrawMenuSpritemap( + kPartialReserveTankSpritemapIds[v2 >> 1], + kEquipmentScreenReserveTank_X[bg3_tilemap_offset >> 1], + kEquipmentScreenReserveTank_Y - 1); + ++R48; + ++bg3_tilemap_offset; + ++bg3_tilemap_offset; + } + while (sign16(R48 - R44)) { + DrawMenuSpritemap( + 0x20u, + kEquipmentScreenReserveTank_X[bg3_tilemap_offset >> 1], + kEquipmentScreenReserveTank_Y - 1); + ++bg3_tilemap_offset; + ++bg3_tilemap_offset; + ++R48; + } + DrawMenuSpritemap( + 0x1Fu, + kEquipmentScreenReserveTank_X[bg3_tilemap_offset >> 1], + kEquipmentScreenReserveTank_Y - 1); + int div_val = R50 / 10; + int mod_val = R50 % 10; + ram3800.cinematic_bg_tilemap[394] = mod_val + 2052; + ram3800.cinematic_bg_tilemap[393] = div_val + 2052; + ram3800.cinematic_bg_tilemap[392] = R42 + 2052; + } +} + +void EquipmentScreenDisplayReserves_PaletteSetup(void) { // 0x82B3F9 + R3_.addr = 1536; + if (samus_reserve_health) { + bool v0 = (--pausemenu_reserve_tank_animation_timer & 0x8000u) != 0; + if (!pausemenu_reserve_tank_animation_timer || v0) { + ++pausemenu_reserve_tank_animation_frame; + uint16 v1 = kPauseReserveTankAnimationData[(uint16)(2 * pausemenu_reserve_tank_animation_frame)]; + if (v1 == 255) { + pausemenu_reserve_tank_animation_frame = 0; + v1 = kPauseReserveTankAnimationData[0]; + } + pausemenu_reserve_tank_animation_timer = v1; + } + R3_.addr = kPAuseSpritePaletteIndexValues[3]; + } +} + +uint16 EquipmentScreenMoveToReserveTanks(void) { // 0x82B43F + uint16 result = samus_max_reserve_health; + if (samus_max_reserve_health) { + pausemenu_equipment_category_item = 0; + QueueSfx1_Max6(0x37u); + return 1; + } + return result; +} + +void EquipmentScreenMoveToBeams(uint16 v0) { // 0x82B456 + int16 v1; + + if (hyper_beam_flag) { +LABEL_4: + pausemenu_equipment_category_item = R18_; + } else { + while ((kEquipmentBitmasks_Weapons[v0 >> 1] & collected_beams) == 0) { + v0 += 2; + if ((int16)(v0 - 10) >= 0) + goto LABEL_4; + } + LOBYTE(v1) = (uint16)(v0 >> 1) >> 8; + HIBYTE(v1) = v0 >> 1; + pausemenu_equipment_category_item = v1 & 0xFF00 | 1; + QueueSfx1_Max6(0x37u); + } +} + +uint16 EquipmentScreenMoveToBottomOfBeams(uint16 k) { // 0x82B489 + int16 v2; + + if (hyper_beam_flag) + return -1; + while ((kEquipmentBitmasks_Weapons[k >> 1] & collected_beams) == 0) { + k -= 2; + if ((k & 0x8000u) != 0) + return -1; + } + QueueSfx1_Max6(0x37u); + LOBYTE(v2) = (uint16)(k >> 1) >> 8; + HIBYTE(v2) = k >> 1; + uint16 result = v2 & 0xFF00 | 1; + pausemenu_equipment_category_item = result; + return result; +} + +uint16 EquipmentScreenMoveLowerOnSuitsMisc(uint16 v0) { // 0x82B4B7 + int16 v1; + + while ((kEquipmentBitmasks_Suits[v0 >> 1] & collected_items) == 0) { + v0 += 2; + if ((int16)(v0 - 10) >= 0) + return -1; + } + QueueSfx1_Max6(0x37u); + LOBYTE(v1) = (uint16)(v0 >> 1) >> 8; + HIBYTE(v1) = v0 >> 1; + pausemenu_equipment_category_item = v1 & 0xFF00 | 2; + return 0; +} + +void EquipmentScreenMoveToScrewOrHigherOnSuits(uint16 v0) { // 0x82B4E6 + int16 v1; + + while ((kEquipmentBitmasks_Suits[v0 >> 1] & collected_items) == 0) { + v0 -= 2; + if ((v0 & 0x8000u) != 0) { + pausemenu_equipment_category_item = R18_; + return; + } + } + QueueSfx1_Max6(0x37u); + LOBYTE(v1) = (uint16)(v0 >> 1) >> 8; + HIBYTE(v1) = v0 >> 1; + pausemenu_equipment_category_item = v1 & 0xFF00 | 2; +} + +void EquipmentScreenMoveToHighJumpOrLowerInBoots(uint16 v0) { // 0x82B511 + int16 v1; + + while ((kEquipmentBitmasks_Boots[v0 >> 1] & collected_items) == 0) { + v0 += 2; + if ((int16)(v0 - 6) >= 0) { + pausemenu_equipment_category_item = R18_; + return; + } + } + QueueSfx1_Max6(0x37u); + LOBYTE(v1) = (uint16)(v0 >> 1) >> 8; + HIBYTE(v1) = v0 >> 1; + pausemenu_equipment_category_item = v1 & 0xFF00 | 3; +} + +uint16 EquipmentScreenCategory_Boots_MoveUpInBoots(uint16 k) { // 0x82B53F + int16 v2; + + while ((kEquipmentBitmasks_Boots[k >> 1] & collected_items) == 0) { + k -= 2; + if ((k & 0x8000u) != 0) + return -1; + } + QueueSfx1_Max6(0x37u); + LOBYTE(v2) = (uint16)(k >> 1) >> 8; + HIBYTE(v2) = k >> 1; + uint16 result = v2 & 0xFF00 | 3; + pausemenu_equipment_category_item = result; + return result; +} +#define kEquipmentPtrsToRamTilemapOffsets ((uint16*)RomPtr(0x82c02c)) +#define kEquipmentPtrsToBitmasks ((uint16*)RomPtr(0x82c034)) +#define kEquipmentPtrsToBitsets ((uint16*)RomPtr(0x82c03c)) +#define kEquipmentPtrsToEquipmentTilemaps ((uint16*)RomPtr(0x82c044)) +void EquipmentScreenCategory_ButtonResponse(void) { // 0x82B568 + if ((joypad1_newkeys & kButton_A) != 0) { + QueueSfx1_Max6(0x38u); + R26_ = 2 * (uint8)pausemenu_equipment_category_item; + R18_ = 2 * HIBYTE(pausemenu_equipment_category_item); + int v0 = R26_ >> 1; + R0_.addr = *(uint16 *)RomPtr_82(R18_ + kEquipmentPtrsToRamTilemapOffsets[v0]); + uint16 v1 = kEquipmentPtrsToBitsets[v0]; + uint16 v2 = R18_ + kEquipmentPtrsToBitmasks[v0]; + uint8 *v3 = RomPtr_RAM(v1); + uint8 *v4 = RomPtr_82(v2); + if ((*(uint16 *)v4 & *(uint16 *)v3) != 0) { + R18_ = ~*(uint16 *)RomPtr_82(v2); + uint8 *v6 = RomPtr_RAM(v1); + *(uint16 *)v6 &= R18_; + R18_ = 3072; + R22_ = R24_; + SetPaletteOfR22TilemapBytesToR18(); + } else { + *(uint16 *)v3 |= *(uint16 *)v4; + R22_ = R24_; + uint16 v5 = *(uint16 *)RomPtr_82(R18_ + kEquipmentPtrsToEquipmentTilemaps[R26_ >> 1]); + Copy_R22_Bytes(v5); + } + } +} + + +void DrawPauseMenuDuringFadeIn(void) { // 0x82B62B + if (menu_index) { + EquipmentScreenDrawItemSelector(); + EquipmentScreenDisplayReserveTankAmount(); + } else { + MapScreenDrawSamusPositionIndicator(); + DrawMapIcons(); + DisplayMapElevatorDestinations(); + } +} + +void UNKNOWN_sub_82B650(void) { // 0x82B650 + if (pausemenu_button_label_mode) { + DisplayMapElevatorDestinations(); + MapScreenDrawSamusPositionIndicator(); + DrawMapIcons(); + } else { + EquipmentScreenDrawItemSelector(); + EquipmentScreenDisplayReserveTankAmount(); + } +} +static const uint16 kMap_Criteria_SavePoints[16] = { 0xd8, 0x28, 0x90, 0x38, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe }; +void DrawMapIcons(void) { // 0x82B672 + DrawBossMapIcons(9u, addr_kMapIconDataPointers); + R3_.addr = 3584; + DrawSimpleMapIcons(0xBu, addr_kMapIconDataPointers + 0x10); + DrawSimpleMapIcons(0xAu, addr_kMapIconDataPointers + 0x20); + DrawSimpleMapIcons(0x4Eu, addr_kMapIconDataPointers + 0x30); + R3_.addr = 1024; + DrawSaveStationMapIcon(8u, 0xC80B); + if (enable_debug) + DrawSimpleMapIcons(8u, 0xC82B); + if (!area_index) { + R3_.addr = 3584; + DrawMenuSpritemap( + 0x63u, + kMap_Criteria_SavePoints[0] - reg_BG1HOFS, + kMap_Criteria_SavePoints[1] - reg_BG1VOFS); + } +} +#define kMapIconDataPointers ((MapIconDataPointers*)RomPtr(0x82c7cb)) +void DrawFileSelectMapIcons(void) { // 0x82B6DD + int16 v0; + + HandlePauseScreenPaletteAnimation(); + DrawBossMapIcons(9u, 0xC7CBu); + R3_.addr = 3584; + DrawSimpleMapIcons(0xBu, 0xC7DBu); + DrawSimpleMapIcons(0xAu, 0xC7EBu); + DrawSimpleMapIcons(0x4Eu, 0xC7FBu); + R3_.addr = 3584; + uint16 a = UpdateSamusPositionIndicatorAnimation(); + *(uint16 *)&R0_.bank = 130; + R0_.addr = *(VoidP *)((char *)&kMapIconDataPointers[4].crateria + (uint16)(2 * area_index)); + v0 = 4 * load_station_index; + uint16 v1 = *(uint16 *)IndirPtr(&R0_, 4 * load_station_index) - reg_BG1HOFS; + uint16 v2 = *(uint16 *)IndirPtr(&R0_, v0 + 2) - reg_BG1VOFS; + if ((samus_position_indicator_animation_loop_counter & 1) == 0) + DrawMenuSpritemap(0x12u, v1, v2); + DrawMenuSpritemap(a, v1, v2); + if (enable_debug) { + R3_.addr = 1536; + DrawDebugSaveMapIcons(0xCu, 0xC80B); + DrawDebugElevatorMapIcons(0x17u, 0xC81B); + DrawSimpleMapIcons(0xCu, 0xC82B); + } + if (!area_index) { + R3_.addr = 3584; + DrawMenuSpritemap( + 0x63u, + kMap_Criteria_SavePoints[0] - reg_BG1HOFS, + kMap_Criteria_SavePoints[1] - reg_BG1VOFS); + } +} + +void DrawSaveStationMapIcon(uint16 a, uint16 k) { // 0x82B798 + static const uint8 kShlBit[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80 }; + + + R32 = k; + R34 = a; + if (area_index == sram_area_index) { + R36 = *(uint16 *)&used_save_stations_and_elevators[(uint16)(2 * area_index)]; + LOBYTE(R36) = R36 & kShlBit[load_station_index]; + uint16 v2 = *(uint16 *)RomPtr_82(R32 + 2 * area_index); + if (v2) + DrawMapIconsOfType(v2); + } +} + +void DrawDebugSaveMapIcons(uint16 a, uint16 k) { // 0x82B7D1 + R32 = k; + R34 = a; + R36 = *(uint16 *)&used_save_stations_and_elevators[(uint16)(2 * area_index)]; + uint16 v2 = *(uint16 *)RomPtr_82(k + 2 * area_index); + if (v2) + DrawMapIconsOfType(v2); +} + +void DrawDebugElevatorMapIcons(uint16 a, uint16 k) { // 0x82B7EB + R32 = k; + R34 = a; + R36 = *(uint16 *)&used_save_stations_and_elevators[(uint16)(2 * area_index) + 1]; + uint16 v2 = *(uint16 *)RomPtr_82(k + 2 * area_index); + if (v2) + DrawMapIconsOfType(v2); +} + +void DrawSimpleMapIcons(uint16 a, uint16 k) { // 0x82B805 + R32 = k; + R34 = a; + R36 = -1; + uint16 v2 = *(uint16 *)RomPtr_82(k + 2 * area_index); + if (v2) + DrawMapIconsOfType(v2); +} + +void DrawMapIconsOfType(uint16 a) { // 0x82B81C + char v3; // cf + int16 v4; + + while (1) { + uint16 *v2 = (uint16 *)RomPtr_82(a); + if ((*v2 & 0x8000u) != 0) + break; + v3 = R36 & 1; + R36 >>= 1; + if (v3) { + v4 = CheckIfMapPositionIsExplored(*v2, v2[1]); + if (v4) { + uint8 *v5 = RomPtr_82(a); + DrawMenuSpritemap(R34, *(uint16 *)v5 - reg_BG1HOFS, *((uint16 *)v5 + 1) - reg_BG1VOFS); + } + } + a += 4; + } +} + +uint16 CheckIfMapPositionIsExplored(uint16 k, uint16 j) { // 0x82B855 + static const uint8 kBits0x80Shr[8] = { 0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1 }; + uint16 v2; + uint16 v4; // dx + + R18_ = (uint16)(k & 0xFF00) >> 1; + R18_ += (uint8)k >> 6; + R18_ += (uint16)(j & 0xFFF8) >> 1; + uint16 v3 = (k >> 3) & 7; + HIBYTE(v2) = HIBYTE(v3); + LOBYTE(v2) = map_tiles_explored[R18_]; + HIBYTE(v4) = HIBYTE(v3); + LOBYTE(v4) = kBits0x80Shr[v3]; + return (v4 & v2) != 0; +} + +void DrawBossMapIcons(uint16 a, uint16 k) { // 0x82B892 + int16 v4; + char v5; // cf + + R32 = k; + R34 = a; + R36 = boss_bits_for_area[area_index]; + uint8 *v2 = RomPtr_82(k + 2 * area_index); + if (*(uint16 *)v2) { + for (int i = *(uint16 *)v2; ; i += 4) { + v4 = *(uint16 *)RomPtr_82(i); + if (v4 == -1) + return; + if (v4 != -2) { + R3_.addr = 3584; + v5 = R36 & 1; + R36 >>= 1; + if (v5) { + { + uint8 *v7 = RomPtr_82(i); + DrawMenuSpritemap(0x62u, *(uint16 *)v7 - reg_BG1HOFS, *((uint16 *)v7 + 1) - reg_BG1VOFS); + R3_.addr = 3072; + } +LABEL_7:; + uint8 *v6 = RomPtr_82(i); + DrawMenuSpritemap(R34, *(uint16 *)v6 - reg_BG1HOFS, *((uint16 *)v6 + 1) - reg_BG1VOFS); + continue; + } + if (has_area_map) + goto LABEL_7; + } + R36 >>= 1; + } + } +} + +void DrawMapScrollArrowAndCheckToScroll(uint8 db, uint16 k) { // 0x82B90A + uint16 *v1 = (uint16 *)RomPtrWithBank(db, k); + DrawPauseScreenSpriteAnim(v1[2], *v1, v1[1]); + uint8 *v2 = RomPtrWithBank(db, k); + if ((joypad1_lastkeys & *((uint16 *)v2 + 3)) != 0 && !map_scrolling_direction) + map_scrolling_direction = *((uint16 *)v2 + 4); +} + +void sub_82B932(void) { // 0x82B932 + HandleMapScrollArrows(); +} + +#define g_stru_82B9A0 ((MapScrollArrowData*)RomPtr(0x82b9a0)) +#define g_stru_82B9AA ((MapScrollArrowData*)RomPtr(0x82b9aa)) +#define g_stru_82B9B4 ((MapScrollArrowData*)RomPtr(0x82b9b4)) +#define g_stru_82B9BE (*(MapScrollArrowData*)RomPtr(0x82b9be)) + +void HandleMapScrollArrows(void) { // 0x82B934 + if (sign16(map_min_x_scroll - 24 - reg_BG1HOFS)) + DrawMapScrollArrowAndCheckToScroll(0x82, addr_stru_82B9A0); + if (!sign16(map_max_x_scroll - 232 - reg_BG1HOFS)) + DrawMapScrollArrowAndCheckToScroll(0x82, addr_stru_82B9AA); + if (sign16(map_min_y_scroll - 56 - reg_BG1VOFS)) + DrawMapScrollArrowAndCheckToScroll(0x82, addr_stru_82B9B4); + if (sign16(map_max_y_scroll - 177 - reg_BG1VOFS)) { + if (map_scrolling_direction == g_stru_82B9BE.map_scroll_dir) { + map_scrolling_gear_switch_timer = 0; + map_scrolling_direction = 0; + map_scrolling_speed_index = 0; + } + } else { + DrawMapScrollArrowAndCheckToScroll(0x82, addr_stru_82B9BE); + } +} + +void MapScreenDrawSamusPositionIndicator(void) { // 0x82B9C8 + R3_.addr = 3584; + uint16 a = UpdateSamusPositionIndicatorAnimation(); + DrawMenuSpritemap( + a, + 8 * (room_x_coordinate_on_map + HIBYTE(samus_x_pos)) - reg_BG1HOFS, + 8 * (room_y_coordinate_on_map + HIBYTE(samus_y_pos) + 1) - reg_BG1VOFS); +} + +static const uint16 kMap_SamusPositionIndicator_Delays[4] = { 8, 4, 8, 4 }; +static const uint16 kMap_SamusPositionIndicator_SpritemapIds[4] = { 0x5f, 0x60, 0x61, 0x60 }; + +uint16 UpdateSamusPositionIndicatorAnimation(void) { // 0x82B9FC + uint16 v0 = samus_position_indicator_animation_timer; + if (!v0) { + uint16 v1 = samus_position_indicator_animation_frame + 2; + if ((int16)(v1 - 8) >= 0) { + ++samus_position_indicator_animation_loop_counter; + v1 = 0; + } + samus_position_indicator_animation_frame = v1; + v0 = kMap_SamusPositionIndicator_Delays[v1 >> 1]; + samus_position_indicator_animation_timer = v0; + } + samus_position_indicator_animation_timer = v0 - 1; + return kMap_SamusPositionIndicator_SpritemapIds[samus_position_indicator_animation_frame >> 1]; +} + +void DrawBorderAroundSamusData(void) { // 0x82BA35 + R3_.addr = 3584; + DrawMenuSpritemap(0x48u, 0x80, 0x10u); +} + +void DrawBorderAroundDataCopyMode(void) { // 0x82BA48 + R3_.addr = 3584; + DrawMenuSpritemap(0x49u, 0x80, 0x10u); +} + +void DrawBorderAroundDataClearMode(void) { // 0x82BA5B + R3_.addr = 3584; + DrawMenuSpritemap(0x4Au, 0x7Cu, 0x10u); +} +static const uint16 kDrawMenuSelectionMissile_Enable[4] = { 8, 8, 8, 8 }; +static const uint16 kDrawMenuSelectionMissile_SpriteMap[4] = { 0x37, 0x36, 0x35, 0x34 }; +void DrawMenuSelectionMissile(void) { // 0x82BA6E + if (enemy_projectile_enable_flag) { + if (!--enemy_projectile_enable_flag) { + enemy_projectile_id[0] = (LOBYTE(enemy_projectile_id[0]) + 1) & 3; + enemy_projectile_enable_flag = kDrawMenuSelectionMissile_Enable[enemy_projectile_id[0]]; + } + } + R3_.addr = 3584; + DrawMenuSpritemap( + kDrawMenuSelectionMissile_SpriteMap[enemy_projectile_id[0]], + enemy_projectile_id[5], + enemy_projectile_id[10]); +} +#define file_copy_arrow_stuff ((FileCopyArrowStuff*)RomPtr(0x82bb0c)) +void DrawFileCopyArrow(void) { // 0x82BABA + uint16 v0; + if ((int16)(enemy_projectile_id[16] - enemy_projectile_id[17]) >= 0) { + v0 = 3; + if (sign16(enemy_projectile_id[16] - enemy_projectile_id[17] - 2)) { + v0 = 4; + if (enemy_projectile_id[16] != 1) + v0 = 5; + } + } else { + v0 = 0; + if (sign16(enemy_projectile_id[17] - enemy_projectile_id[16] - 2)) { + v0 = 1; + if (enemy_projectile_id[16]) + v0 = 2; + } + } + R3_.addr = 512; + DrawMenuSpritemap( + file_copy_arrow_stuff[v0].spritemap, + file_copy_arrow_stuff[v0].xpos, + file_copy_arrow_stuff[v0].ypos); +} +#define kMapElevatorDests ((uint16*)RomPtr(0x82c74d)) +void DisplayMapElevatorDestinations(void) { // 0x82BB30 + R3_.addr = 0; + if (map_station_byte_array[area_index]) { + for (int i = kMapElevatorDests[area_index]; ; i += 6) { + uint8 *v1 = RomPtr_82(i); + if (*(uint16 *)v1 == 0xFFFF) + break; + DrawMenuSpritemap(*((uint16 *)v1 + 2), *(uint16 *)v1 - reg_BG1HOFS, *((uint16 *)v1 + 1) - reg_BG1VOFS); + } + } +} + +void HandleGameOverBabyMetroid(void) { // 0x82BB75 + if (enemy_data[0].instruction_timer) + sub_82BB7F(enemy_data[0].instruction_timer); + else + sub_82BBDD(); +} + +void CallBabyMetroidPlaySfx(uint32 ea) { + switch (ea) { + case fnBabyMetroidPlaySfx0x23: BabyMetroidPlaySfx0x23(); return; + case fnBabyMetroidPlaySfx0x26: BabyMetroidPlaySfx0x26(); return; + case fnBabyMetroidPlaySfx0x27: BabyMetroidPlaySfx0x27(); return; + default: Unreachable(); + } +} + +void sub_82BB7F(uint16 a) { // 0x82BB7F + uint16 current_instruction = enemy_data[0].current_instruction; + enemy_data[0].instruction_timer = a - 1; + if (a == 1) { + uint8 *v2 = RomPtr_82(enemy_data[0].current_instruction); + if (*((uint16 *)v2 + 3) == 0xFFFF) { + sub_82BBDD(); + } else if ((int16)(*((uint16 *)v2 + 3) + 1) >= 0) { + enemy_data[0].instruction_timer = *((uint16 *)v2 + 3); + enemy_data[0].current_instruction += 6; + DrawBabyMetroid(current_instruction + 6); + } else { + R18_ = *((uint16 *)v2 + 3); + CallBabyMetroidPlaySfx(R18_ | 0x820000); + } + } else { + DrawBabyMetroid(enemy_data[0].current_instruction); + } +} + +void sub_82BBDD(void) { // 0x82BBDD + enemy_data[0].current_instruction = addr_kgameOverBabyMetridInstructionList; + enemy_data[0].instruction_timer = 10; + sub_82BB7F(0xAu); +} + +void DrawBabyMetroid(uint16 k) { // 0x82BB9E + uint16 v1 = *((uint16 *)RomPtr_82(k) + 2); + uint16 v2 = 0; + do { + palette_buffer[(v2 >> 1) + 192] = *(uint16 *)RomPtr_82(v1); + v1 += 2; + v2 += 2; + } while ((int16)(v2 - 32) < 0); + R3_.addr = 2048; + uint8 *v3 = RomPtr_82(k); + DrawMenuSpritemap(*((uint16 *)v3 + 1), 0x7Cu, 0x50u); + R3_.addr = 2560; + DrawMenuSpritemap(0x64u, 0x7Cu, 0x50u); +} + +void FinishProcessingGameOverBabyMetroidAsm(void) { // 0x82BBF0 + uint16 current_instruction = enemy_data[0].current_instruction; + enemy_data[0].instruction_timer = *((uint16 *)RomPtr_82(enemy_data[0].current_instruction) + 4); + enemy_data[0].current_instruction += 8; + if (*(uint16 *)RomPtr_82(current_instruction + 8) == 0xFFFF) + sub_82BBDD(); + else + DrawBabyMetroid(enemy_data[0].current_instruction); +} + +void BabyMetroidPlaySfx0x23(void) { // 0x82BC0C + QueueSfx3_Max6(0x23u); + FinishProcessingGameOverBabyMetroidAsm(); +} + +void BabyMetroidPlaySfx0x26(void) { // 0x82BC15 + QueueSfx3_Max6(0x26u); + FinishProcessingGameOverBabyMetroidAsm(); +} + +void BabyMetroidPlaySfx0x27(void) { // 0x82BC1E + QueueSfx3_Max6(0x27u); + FinishProcessingGameOverBabyMetroidAsm(); +} + +void CancelSoundEffects(void) { // 0x82BE17 + QueueSfx1_Max6(2u); + QueueSfx2_Max6(0x71u); + QueueSfx3_Max6(1u); +} + +void QueueSamusMovementSfx(void) { // 0x82BE2F + if ((speed_boost_counter & 0xFF00) == 1024) + QueueSfx3_Max6(0x2Bu); + if (!sign16(flare_counter - 16)) + QueueSfx1_Max6(0x41u); + CallSomeSamusCode(0x14u); +} + + +uint8 AdvancePaletteFadeForAllPalettes_0xc(void) { // 0x82D961 + palette_change_denom = 12; + return AdvancePaletteFadeForAllPalettes(); +} + +uint8 AdvancePaletteFade_BgPalette6(void) { // 0x82D96C + palette_change_denom = 12; + if (palette_change_num <= 0xDu) { + for (int i = 192; i < 0xE0u; i += 2) + palette_buffer[i >> 1] = CalculateNthTransitionColorFromXtoY( + palette_change_num, + palette_buffer[i >> 1], + target_palettes[i >> 1]); + ++palette_change_num; + return 0; + } else { + palette_change_num = 0; + return 1; + } +} + +uint8 AdvanceGradualColorChangeOfPalette(uint16 k, uint16 j) { // 0x82D9B8 + palette_change_denom = 15; + if ((int16)(15 - palette_change_num) >= 0) { + R34 = j; + do { + palette_buffer[k >> 1] = CalculateNthTransitionColorFromXtoY( + palette_change_num + 1, + palette_buffer[k >> 1], + target_palettes[k >> 1]); + k += 2; + } while (k < R34); + ++palette_change_num; + return 0; + } else { + palette_change_num = 0; + return 1; + } +} + +uint8 AdvancePaletteFadeForAllPalettes(void) { // 0x82DA02 + if ((uint16)(palette_change_denom + 1) >= palette_change_num) { + for (int i = 0; i < 0x200u; i += 2) { + g_word_7EC404 = i; + int v2 = i >> 1; + if (target_palettes[v2] != palette_buffer[v2]) { + uint16 v3 = CalculateNthTransitionColorFromXtoY(palette_change_num, palette_buffer[v2], target_palettes[v2]); + i = g_word_7EC404; + palette_buffer[g_word_7EC404 >> 1] = v3; + } + } + ++palette_change_num; + return 0; + } else { + palette_change_num = 0; + return 1; + } +} + +uint16 CalculateNthTransitionColorFromXtoY(uint16 a, uint16 k, uint16 j) { // 0x82DA4A + int16 v3; + char v4; // t0 + int16 v8; + + uint16 v7 = CalculateNthTransitionColorComponentFromXtoY(a, k & 0x1F, j & 0x1F); + v8 = v7 | (32 * CalculateNthTransitionColorComponentFromXtoY(a, (k >> 5) & 0x1F, (j >> 5) & 0x1F)); + v3 = 4 + * CalculateNthTransitionColorComponentFromXtoY( + a, + ((uint16)(k >> 2) >> 8) & 0x1F, + ((uint16)(j >> 2) >> 8) & 0x1F); + v4 = v3; + LOBYTE(v3) = HIBYTE(v3); + HIBYTE(v3) = v4; + return v8 | v3; +} + +uint16 CalculateNthTransitionColorComponentFromXtoY(uint16 a, uint16 k, uint16 j) { // 0x82DAA6 + int16 v4; + char v6; // t0 + int16 v8; + + if (!a) + return k; + v4 = a - 1; + if (v4 == palette_change_denom) + return j; + R20_ = v4 + 1; + R18_ = j - k; + uint16 v5 = abs16(j - k); + v6 = v5; + LOBYTE(v5) = HIBYTE(v5); + HIBYTE(v5) = v6; + uint16 RegWord = SnesDivide(v5 & 0xFF00, palette_change_denom - R20_ + 1); + R18_ = sign16(R18_) ? -RegWord : RegWord; + LOBYTE(v8) = HIBYTE(k); + HIBYTE(v8) = k; + return (uint16)(R18_ + v8) >> 8; +} + +uint8 sub_82DAF7(uint16 a) { // 0x82DAF7 + palette_change_denom = 12; + return sub_82DB0C(a); +} + +uint8 sub_82DB0C(uint16 a) { // 0x82DB0C + if ((uint16)(palette_change_denom + 1) >= palette_change_num) { + g_word_7EC404 = 0; + while (a) { + if (!(a & 1)) + g_word_7EC404 += 32; + else + sub_82DB41(); + a >>= 1; + } + ++palette_change_num; + return 0; + } else { + palette_change_num = 0; + return 1; + } +} + + +void sub_82DB41(void) { // 0x82DB41 + uint16 v0 = g_word_7EC404; + do { + int v1 = v0 >> 1; + if (target_palettes[v1] != palette_buffer[v1]) { + uint16 v2 = CalculateNthTransitionColorFromXtoY(palette_change_num, palette_buffer[v1], target_palettes[v1]); + v0 = g_word_7EC404; + palette_buffer[g_word_7EC404 >> 1] = v2; + } + v0 += 2; + g_word_7EC404 = v0; + } while ((v0 & 0x1F) != 0); +} + +void HandleSamusOutOfHealthAndGameTile(void) { // 0x82DB69 + if ((int16)samus_health <= 0) { + if ((reserve_health_mode & 1) != 0 && samus_reserve_health) { + time_is_frozen_flag = 0x8000; + game_state = kGameState_27_ReserveTanksAuto; + CallSomeSamusCode(0x1Bu); + } else { + if (game_state != kGameState_8_MainGameplay) + return; + time_is_frozen_flag = 0x8000; + CallSomeSamusCode(0x11u); + game_state = kGameState_19_SamusNoHealth; + } + } + if (!sign16(++game_time_frames - 60)) { + game_time_frames = 0; + if (!sign16(++game_time_seconds - 60)) { + game_time_seconds = 0; + if (!sign16(++game_time_minutes - 60)) { + game_time_minutes = 0; + ++game_time_hours; + } + } + } + if (!sign16(game_time_hours - 100)) { + game_time_frames = 59; + game_time_seconds = 59; + game_time_minutes = 59; + game_time_hours = 99; + } +} + +CoroutineRet GameState_27_ReserveTanksAuto(void) { // 0x82DC10 + if (RefillHealthFromReserveTanks()) { + time_is_frozen_flag = 0; + game_state = kGameState_8_MainGameplay; + CallSomeSamusCode(0x10u); + } + GameState_8_MainGameplay(); + Samus_LowHealthCheck_0(); + return kCoroutineNone; +} + +uint8 RefillHealthFromReserveTanks(void) { // 0x82DC31 + if (samus_reserve_health) { + if ((nmi_frame_counter_word & 7) == 0) + QueueSfx3_Max3(0x2Du); + if ((int16)(++samus_health - samus_max_health) >= 0) { + samus_health = samus_max_health; +LABEL_9: + samus_reserve_health = 0; + return samus_reserve_health == 0; + } + bool v0 = (--samus_reserve_health & 0x8000u) != 0; + if (!samus_reserve_health) + goto LABEL_9; + if (v0) { + samus_health += samus_reserve_health; + goto LABEL_9; + } + } + return samus_reserve_health == 0; +} + +CoroutineRet GameState_19_SamusNoHealth(void) { // 0x82DC80 + uint16 j; + uint16 k; + uint16 m; + + GameState_8_MainGameplay(); + for (int i = 255; i >= 0; --i) + ram3000.pause_menu_map_tilemap[i + 384] = palette_buffer[i]; + for (j = 382; (j & 0x8000u) == 0; j -= 2) + target_palettes[j >> 1] = 0; + for (k = 94; (k & 0x8000u) == 0; k -= 2) + target_palettes[(k >> 1) + 208] = 0; + for (m = 30; (m & 0x8000u) == 0; m -= 2) + target_palettes[(m >> 1) + 192] = palette_buffer[(m >> 1) + 192]; + game_options_screen_index = 3; + g_word_7E0DE4 = 0; + g_word_7E0DE6 = 0; + g_word_7E0DE8 = 0; + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + ++game_state; + + return kCoroutineNone; +} + +CoroutineRet GameState_20_SamusNoHealth_BlackOut(void) { // 0x82DCE0 + GameState_8_MainGameplay(); + palette_change_denom = 6; + if (AdvancePaletteFadeForAllPalettes()) { + WaitUntilEndOfVblankAndClearHdma(); + DisableIrqInterrupts(); + fx_layer_blending_config_a = 0; + cur_irq_handler = 0; + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = 0; + reg_TM = 16; + reg_TS = 0; + reg_TMW = 0; + reg_TSW = 0; + reg_BGMODE = 9; + game_options_screen_index = 0; + screen_fade_delay = 0; + screen_fade_counter = 0; + for (int i = 254; i >= 0; i -= 2) + enemy_projectile_y_subpos[(i >> 1) + 15] = 0; + g_word_7E0DE8 = 16; + game_options_screen_index = 3; + g_word_7E0DE4 = 0; + g_word_7E0DE6 = 0; + ++game_state; + power_bomb_explosion_status = 0; + QueueSfx1_Max15(2u); + QueueSfx2_Max15(0x71u); + QueueSfx3_Max15(1u); + QueueMusic_Delayed8(0); + QueueMusic_Delayed8(0xFF39u); + QueueMusic_DelayedY(5u, 0xEu); + } + return kCoroutineNone; +} + +CoroutineRet GameState_21_SamusNoHealth(void) { // 0x82DD71 + Samus_DrawWhenNotAnimatingOrDying(); + if (!HasQueuedMusic()) { + StartSamusDeathAnimation(); + ++game_state; + } + return kCoroutineNone; +} + +CoroutineRet GameState_22_SamusNoHealth_Dying(void) { // 0x82DD87 + DrawSamusStartingDeathAnim_(); + bool v0 = (--g_word_7E0DE8 & 0x8000u) != 0; + if (!g_word_7E0DE8 || v0) + ++game_state; + return kCoroutineNone; +} + +CoroutineRet GameState_23_SamusNoHealth_Flashing(void) { // 0x82DD9A + if (HandleSamusDeathSequence()) + ++game_state; + else + Samus_DrawDuringDeathAnim(); + return kCoroutineNone; +} + +CoroutineRet GameState_24_SamusNoHealth_Explosion(void) { // 0x82DDAF + if (GameState_24_SamusNoHealth_Explosion_Helper()) { + screen_fade_delay = 1; + screen_fade_counter = 1; + ++game_state; + } + return kCoroutineNone; +} + +CoroutineRet GameState_25_SamusNoHealth_BlackOut(void) { // 0x82DDC7 + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + ++game_state; + menu_index = 0; + debug_disable_sounds = 0; + } + return kCoroutineNone; +} + +void LoaadDesinationRoomCreBitset(void) { // 0x82DDF1 + uint16 room_definition_ptr = get_DoorDef(door_def_ptr)->room_definition_ptr; + previous_cre_bitset = cre_bitset; + cre_bitset = get_RoomDefHeader(room_definition_ptr)->cre_bitset_; +} + +void LoadDoorHeader(void) { // 0x82DE12 + DoorDef *DoorDef; + int16 samus_distance_from_door; + + DoorDef = get_DoorDef(door_def_ptr); + room_ptr = DoorDef->room_definition_ptr; + elevator_door_properties_orientation = *(uint16 *)&DoorDef->door_bitflags; + elevator_flags = elevator_door_properties_orientation & 0x80; + door_direction = DoorDef->door_orientation; + door_destination_x_pos = DoorDef->x_pos_in_room << 8; + door_destination_y_pos = DoorDef->y_pos_in_room << 8; + R18_ = 0; + R20_ = 0; + samus_distance_from_door = DoorDef->samus_distance_from_door; + if (samus_distance_from_door < 0) { + if ((door_direction & 2) != 0) + samus_distance_from_door = 384; + else + samus_distance_from_door = 200; + } + *(uint16 *)((char *)&R18_ + 1) = samus_distance_from_door; + samus_door_transition_subspeed = R18_; + samus_door_transition_speed = R20_; +} + +void LoadRoomHeader(void) { // 0x82DE6F + RoomDefHeader *RoomDefHeader; + + RoomDefHeader = get_RoomDefHeader(room_ptr); + room_index = RoomDefHeader->semiunique_room_number; + area_index = RoomDefHeader->area_index_; + room_x_coordinate_on_map = RoomDefHeader->x_coordinate_on_map; + room_y_coordinate_on_map = RoomDefHeader->y_coordinate_on_map; + room_width_in_scrolls = RoomDefHeader->width; + room_width_in_blocks = 16 * room_width_in_scrolls; + room_height_in_scrolls = RoomDefHeader->height; + room_height_in_blocks = 16 * room_height_in_scrolls; + up_scroller = RoomDefHeader->up_scroller_; + down_scroller = RoomDefHeader->down_scroller_; + door_list_pointer = RoomDefHeader->ptr_to_doorout; + HandleRoomDefStateSelect(room_ptr); + uint16 prod = Mult8x8(room_width_in_blocks, room_height_in_blocks); + room_size_in_blocks = 2 * prod; +} +#define kStateHeaderGraphicsSets ((uint16*)RomPtr(0x8fe7a7)) +void LoadStateHeader(void) { // 0x82DEF2 + StateHeaderTiles *StateHeaderTiles; // r10 + RoomDefRoomstate *RoomDefRoomstate; // r11 + + int v0 = (uint16)(2 * get_RoomDefRoomstate(roomdefroomstate_ptr)->graphics_set) >> 1; + StateHeaderTiles = get_StateHeaderTiles(kStateHeaderGraphicsSets[v0]); + copy24(&tileset_tile_table_pointer, &StateHeaderTiles->tile_table_ptr); + copy24(&tileset_tiles_pointer, &StateHeaderTiles->tiles_ptr); + copy24(&tileset_compr_palette_ptr, &StateHeaderTiles->palette_ptr); + RoomDefRoomstate = get_RoomDefRoomstate(roomdefroomstate_ptr); + copy24(&room_compr_level_data_ptr, &RoomDefRoomstate->compressed_room_map_ptr); + room_music_data_index = RoomDefRoomstate->music_track; + room_music_track_index = RoomDefRoomstate->music_control; + room_layer3_asm_ptr = RoomDefRoomstate->room_layer3_fx_ptr; + room_enemy_population_ptr = RoomDefRoomstate->enemy_population_ptr_; + room_enemy_tilesets_ptr = RoomDefRoomstate->enemy_tilesets_ptr; + *(uint16 *)&layer2_scroll_x = RoomDefRoomstate->vertical_screen_nudge_limit; + room_main_code_ptr = RoomDefRoomstate->main_code_ptr; +} + +void WaitUntilEndOfVblankAndEnableIrq(void) { // 0x82DF69 + if ((reg_NMITIMEN & 0x30) != 0x30) + EnableIrqInterruptsNow(); +} + +void PointlessFunctionStupidToo(void) { // 0x82DF80 +} + +void SaveMapExploredifElevator(void) { // 0x82DF99 + if ((elevator_door_properties_orientation & 0xF) != 0) + SetElevatorsAsUsed(); + if ((get_DoorDef(door_def_ptr)->door_bitflags & 0x40) != 0) + SaveExploredMapTilesToSaved(); +} + +void LoadMapExploredIfElevator(void) { // 0x82DFB6 + if ((get_DoorDef(door_def_ptr)->door_bitflags & 0x40) != 0) + LoadMirrorOfExploredMapTiles(); +} + +void EnsureSamusDrawnEachFrame(void) { // 0x82DFC7 + if (!elevator_flags) + Samus_DrawWhenNotAnimatingOrDying(); +} + +void LoadEnemyGfxToVram(void) { // 0x82DFD1 + EnemyDef_A2 *EnemyDef_A2; + + R18_ = 28672; + uint16 v0 = room_enemy_tilesets_ptr; + if (room_enemy_tilesets_ptr) { + for (int i = room_enemy_tilesets_ptr; ; v0 = i) { + uint16 enemy_def = get_EnemyTileset(v0)->enemy_def; + if (enemy_def == 0xFFFF) + break; + EnemyDef_A2 = get_EnemyDef_A2(enemy_def); + copy24(&door_transition_vram_update_src, &EnemyDef_A2->tile_data); + if ((EnemyDef_A2->tile_data_size & 0x8000u) != 0) { + door_transition_vram_update_size = EnemyDef_A2->tile_data_size & 0x7FFF; + door_transition_vram_update_dst = ((uint16)(get_EnemyTileset(i)->vram_dst & 0xF000) >> 4) | 0x6000; + } else { + door_transition_vram_update_size = EnemyDef_A2->tile_data_size; + door_transition_vram_update_dst = R18_; + R18_ += EnemyDef_A2->tile_data_size >> 1; + } + WaitForIrqDoorTransitionVramUpdate(); + i += 4; + } + } +} + +void CopyToVramAtNextInterrupt(const void *p) { // 0x82E039 + const CopyToVramAtNextInterruptArgs *pp = (const CopyToVramAtNextInterruptArgs *)p; + door_transition_vram_update_src = pp->source; + door_transition_vram_update_dst = pp->dest; + door_transition_vram_update_size = pp->size; + WaitForIrqDoorTransitionVramUpdate(); +} + +void LoadRoomMusic(void) { // 0x82E071 + if (game_state < kGameState_40_TransitionToDemo && room_music_data_index && room_music_data_index != music_data_index) { + QueueMusic_Delayed8(0); + QueueMusic_Delayed8((uint8)room_music_data_index | 0xFF00); + } +} + +void UpdateMusicTrackIndex(void) { // 0x82E09B + if (game_state < kGameState_40_TransitionToDemo && room_music_track_index) { + R18_ = (uint8)room_music_data_index << 8; + R18_ |= room_music_track_index; + R20_ = (uint8)music_data_index << 8; + R20_ |= music_track_index; + if (R18_ != R20_) + music_track_index = room_music_track_index; + } +} + +void LoadNewMusicTrackIfChanged(void) { // 0x82E0D5 + if (game_state < 0x28u && room_music_track_index) { + R18_ = (uint8)room_music_data_index << 8; + R18_ |= room_music_track_index; + R20_ = (uint8)music_data_index << 8; + R20_ |= music_track_index; + if (R18_ != R20_) + QueueMusic_DelayedY(room_music_track_index, 6u); + } +} + +void NullFunc(void) { // 0x82E113 + ; +} + +void PlayRoomMusicTrackAfterAFrames(uint16 a) { // 0x82E118 + if (game_state < kGameState_40_TransitionToDemo) { + QueueMusic_DelayedY(0, a); + QueueMusic_Delayed8(music_track_index); + } +} + +#define kCommonSpritesPalette1 ((uint16*)RomPtr(0x9afc00)) +void LoadColorsForSpritesBeamsAndEnemies(void) { // 0x82E139 + uint16 j; + uint16 k; + + for (int i = 30; i >= 0; i -= 2) + target_palettes[(i >> 1) + 208] = kInitialPalette[(i >> 1) + 208]; + for (j = 30; (j & 0x8000u) == 0; j -= 2) + target_palettes[(j >> 1) + 224] = palette_buffer[(j >> 1) + 224]; + for (k = 30; (k & 0x8000u) == 0; k -= 2) + target_palettes[(k >> 1) + 128] = kCommonSpritesPalette1[k >> 1]; +} + +CoroutineRet CallDoorTransitionFunction_Async(uint32 ea) { + switch (ea) { + case fnDoorTransitionFunction_HandleElevator: return DoorTransitionFunction_HandleElevator(); + case fnDoorTransitionFunction_Wait48frames: return DoorTransitionFunction_Wait48frames(); + case fnDoorTransitionFunction_WaitForSoundsToFinish: return DoorTransitionFunction_WaitForSoundsToFinish(); + case fnDoorTransitionFunction_FadeOutScreen: return DoorTransitionFunction_FadeOutScreen(); + case fnDoorTransitionFunction_LoadDoorHeaderEtc: return DoorTransitionFunction_LoadDoorHeaderEtc(); + case fnDoorTransitionFunction_ScrollScreenToAlignment: return DoorTransitionFunction_ScrollScreenToAlignment(); + case fnDoorTransitionFunction_FixDoorsMovingUp: return DoorTransitionFunction_FixDoorsMovingUp(); + case fnDoorTransitionFunction_SetupNewRoom: return DoorTransitionFunction_SetupNewRoom(); + case fnDoorTransitionFunction_SetupScrolling: return DoorTransitionFunction_SetupScrolling(); + case fnDoorTransitionFunction_PlaceSamusLoadTiles: return DoorTransitionFunction_PlaceSamusLoadTiles(); + case fnDoorTransitionFunction_LoadMoreThings_Async: return DoorTransitionFunction_LoadMoreThings_Async(); + case fnDoorTransition_C_HandleAnimTiles: return DoorTransition_C_HandleAnimTiles(); + case fnDoorTransition_WaitForMusicToClear: return DoorTransition_WaitForMusicToClear(); + case fnDoorTransition_HandleTransition: return DoorTransition_HandleTransition(); + case fnDoorTransition_FadeInScreenAndFinish: return DoorTransition_FadeInScreenAndFinish(); + default: return Unreachable(); + } +} + +CoroutineRet GameState_9_HitDoorBlock(void) { // 0x82E169 + return CallDoorTransitionFunction_Async(door_transition_function | 0x820000); +} + +CoroutineRet DoorTransitionFunction_HandleElevator(void) { // 0x82E17D + if (!elevator_flags) { + ++game_state; + return GameState_10_LoadingNextRoom_Async(); + } + CallSomeSamusCode(0); + if ((elevator_direction & 0x8000u) != 0) { + ++game_state; + return GameState_10_LoadingNextRoom_Async(); + } + downwards_elevator_delay_timer = 48; + door_transition_function = FUNC16(DoorTransitionFunction_Wait48frames); + return DoorTransitionFunction_Wait48frames(); +} + +CoroutineRet DoorTransitionFunction_Wait48frames(void) { // 0x82E19F + if ((--downwards_elevator_delay_timer & 0x8000u) != 0) { + ++game_state; + return GameState_10_LoadingNextRoom_Async(); + } else { + DetermineWhichEnemiesToProcess(); + EnemyMain(); + DrawSamusEnemiesAndProjectiles(); + EnsureSamusDrawnEachFrame(); + } + return kCoroutineNone; +} + +CoroutineRet GameState_10_LoadingNextRoom_Async(void) { // 0x82E1B7 + door_transition_flag_enemies = 1; + door_transition_flag_elevator_zebetites = 1; + debug_disable_minimap = 0; + save_station_lockout_flag = 0; + DetermineWhichEnemiesToProcess(); + EnemyMain(); + DrawSamusEnemiesAndProjectiles(); + EnsureSamusDrawnEachFrame(); + LoaadDesinationRoomCreBitset(); + for (int i = 254; i >= 0; i -= 2) { + int v1 = i >> 1; + target_palettes[v1] = 0; + target_palettes[v1 + 128] = 0; + } + target_palettes[9] = palette_buffer[9]; + target_palettes[10] = palette_buffer[10]; + target_palettes[13] = palette_buffer[13]; + target_palettes[14] = palette_buffer[14]; + target_palettes[17] = palette_buffer[17]; + target_palettes[18] = palette_buffer[18]; + target_palettes[19] = palette_buffer[19]; + target_palettes[29] = palette_buffer[29]; + if (((previous_cre_bitset | cre_bitset) & 1) == 0) { + target_palettes[20] = palette_buffer[20]; + target_palettes[21] = palette_buffer[21]; + target_palettes[22] = palette_buffer[22]; + target_palettes[23] = palette_buffer[23]; + target_palettes[28] = palette_buffer[28]; + if (timer_status) { + target_palettes[209] = palette_buffer[209]; + target_palettes[210] = palette_buffer[210]; + target_palettes[212] = palette_buffer[212]; + target_palettes[221] = palette_buffer[221]; + DrawTimer(); + } + } + ClearSoundsWhenGoingThroughDoor(); + QueueSfx2_Max15(0x71u); + debug_disable_sounds = -1; + door_transition_function = FUNC16(DoorTransitionFunction_WaitForSoundsToFinish); + ++game_state; + return kCoroutineNone; +} + +CoroutineRet GameState_11_LoadingNextRoom_Async(void) { // 0x82E288 + COROUTINE_AWAIT_ONLY(CallDoorTransitionFunction_Async(door_transition_function | 0x820000)); + if (timer_status) + DrawTimer(); + return kCoroutineNone; +} + +CoroutineRet DoorTransitionFunction_WaitForSoundsToFinish(void) { // 0x82E29E + DetermineWhichEnemiesToProcess(); + EnemyMain(); + DrawSamusEnemiesAndProjectiles(); + EnsureSamusDrawnEachFrame(); + if (((sfx_writepos[0] - sfx_readpos[0]) & 0xF) == 0 + && ((sfx_writepos[1] - sfx_readpos[1]) & 0xF) == 0 + && ((sfx_writepos[2] - sfx_readpos[2]) & 0xF) == 0) { + door_transition_function = FUNC16(DoorTransitionFunction_FadeOutScreen); + } + return kCoroutineNone; +} + +CoroutineRet DoorTransitionFunction_FadeOutScreen(void) { // 0x82E2DB + if (AdvancePaletteFadeForAllPalettes_0xc()) { + door_transition_function = FUNC16(DoorTransitionFunction_LoadDoorHeaderEtc); + } else { + DetermineWhichEnemiesToProcess(); + EnemyMain(); + DrawSamusEnemiesAndProjectiles(); + EnsureSamusDrawnEachFrame(); + } + return kCoroutineNone; +} + +CoroutineRet DoorTransitionFunction_LoadDoorHeaderEtc(void) { // 0x82E2F7 + LoadDoorHeader(); + sub_8882AC(); + hdma_objects_enable_flag &= ~0x8000u; + irqhandler_next_handler = 8; + door_transition_function = FUNC16(DoorTransitionFunction_ScrollScreenToAlignment); + return kCoroutineNone; +} + +CoroutineRet DoorTransitionFunction_ScrollScreenToAlignment(void) { // 0x82E310 + if ((door_direction & 2) != 0) { + if ((uint8)layer1_x_pos) { + if ((layer1_x_pos & 0x80) != 0) + ++layer1_x_pos; + else + --layer1_x_pos; + goto LABEL_10; + } + } else if ((uint8)layer1_y_pos) { + if ((layer1_y_pos & 0x80) != 0) + ++layer1_y_pos; + else + --layer1_y_pos; +LABEL_10: + CalculateLayer2PosAndScrollsWhenScrolling(); + return kCoroutineNone; + } + CalculateLayer2PosAndScrollsWhenScrolling(); + door_transition_function = FUNC16(DoorTransitionFunction_FixDoorsMovingUp); + return kCoroutineNone; +} + +CoroutineRet DoorTransitionFunction_FixDoorsMovingUp(void) { // 0x82E353 + if ((door_direction & 3) == 3) + FixDoorsMovingUp(); + door_transition_function = FUNC16(DoorTransitionFunction_SetupNewRoom); + return kCoroutineNone; +} + +CoroutineRet DoorTransitionFunction_SetupNewRoom(void) { // 0x82E36E + SaveMapExploredifElevator(); + LoadRoomHeader(); + LoadStateHeader(); + LoadMapExploredIfElevator(); + InitializeSpecialEffectsForNewRoom(); + LoadLevelScrollAndCre(); + door_transition_function = FUNC16(DoorTransitionFunction_SetupScrolling); + return kCoroutineNone; +} + +CoroutineRet DoorTransitionFunction_SetupScrolling(void) { // 0x82E38E + reg_BG2HOFS = 0; + reg_BG2VOFS = 0; + scrolling_finished_hook = 0; + if ((door_direction & 3) == 2) + ++reg_BG1VOFS; + if ((door_direction & 3) != 3) + door_transition_frame_counter = 0; + DoorTransitionScrollingSetup(); + door_transition_function = FUNC16(DoorTransitionFunction_PlaceSamusLoadTiles); + return kCoroutineNone; +} + +CoroutineRet DoorTransitionFunction_PlaceSamusLoadTiles(void) { // 0x82E3C0 + static const LongPtr unk_82E421 = LONGPTR(0x7e7000); + static const LongPtr unk_82E432 = LONGPTR(0x7e2000); + static const LongPtr unk_82E443 = LONGPTR(0x7ec200); + static const CopyToVramAtNextInterruptArgs unk_82E449 = { LONGPTR(0x7e2000), 0x0000, 0x2000 }; + static const CopyToVramAtNextInterruptArgs unk_82E453 = { LONGPTR(0x7e4000), 0x1000, 0x2000 }; + static const CopyToVramAtNextInterruptArgs unk_82E45D = { LONGPTR(0x7e6000), 0x2000, 0x1000 }; + static const CopyToVramAtNextInterruptArgs unk_82E477 = { LONGPTR(0x7e7000), 0x2800, 0x1000 }; + static const CopyToVramAtNextInterruptArgs unk_82E481 = { LONGPTR(0x7e8000), 0x3000, 0x2000 }; + static const CopyToVramAtNextInterruptArgs unk_82E48B = { LONGPTR(0x9ab200), 0x4000, 0x1000 }; + uint16 v0; + + samus_x_pos = layer1_x_pos + (uint8)samus_x_pos; + samus_prev_x_pos = samus_x_pos; + samus_y_pos = layer1_y_pos + (uint8)samus_y_pos; + samus_prev_y_pos = samus_y_pos; + door_transition_flag = 0; + door_transition_vram_update_enabled = 0; + if ((door_direction & 3) == 2) + v0 = 16; + else + v0 = 22; + irqhandler_next_handler = v0; + WaitUntilEndOfVblankAndEnableIrq(); + if ((cre_bitset & 2) != 0 && door_def_ptr != (uint16)addr_kDoorDef_947a) { + mov24(&decompress_src, 0xb98000); + DecompressToMem_IpArg(&unk_82E421); + } + copy24(&decompress_src, &tileset_tiles_pointer); + DecompressToMem_IpArg(&unk_82E432); + copy24(&decompress_src, &tileset_compr_palette_ptr); + DecompressToMem_IpArg(&unk_82E443); + CopyToVramAtNextInterrupt(&unk_82E449); + CopyToVramAtNextInterrupt(&unk_82E453); + CopyToVramAtNextInterrupt(&unk_82E45D); + if ((cre_bitset & 6) != 0 && door_def_ptr != (uint16)addr_kDoorDef_947a) { + CopyToVramAtNextInterrupt(&unk_82E477); + CopyToVramAtNextInterrupt(&unk_82E481); + CopyToVramAtNextInterrupt(&unk_82E48B); + } + if ((door_direction & 3) == 3) + irqhandler_next_handler = 16; + door_transition_function = FUNC16(DoorTransitionFunction_LoadMoreThings_Async); + return kCoroutineNone; +} + +static Func_Y_Y *const kUpdateBackgroundCommands[8] = { + UpdateBackgroundCommand_0_Finish, + UpdateBackgroundCommand_2_TransferToVram, + UpdateBackgroundCommand_4_Decompression, + UpdateBackgroundCommand_6_ClearFxTilemap, + UpdateBackgroundCommand_8_TransferToVramAndSetBg3, + UpdateBackgroundCommand_A_ClearBg2Tilemap, + UpdateBackgroundCommand_C_ClearKraidBg2Tilemap, + UpdateBackgroundCommand_E_DoorDependentTransferToVRAM, +}; + +CoroutineRet DoorTransitionFunction_LoadMoreThings_Async(void) { + int16 bg_data_ptr; + + COROUTINE_BEGIN(coroutine_state_1, 0); + + LoadEnemyGfxToVram(); + LoadRoomMusic(); + ClearEnemyProjectiles(); + ClearAnimtiles(); + ClearPaletteFXObjects(); + ClearPLMs(); + CreatePlmsExecuteDoorAsmRoomSetup(); + LoadFXHeader(); + SpawnDoorClosingPLM(); + UpdateBeamTilesAndPalette(); + LoadColorsForSpritesBeamsAndEnemies(); + LoadEnemies(); + InitializeEnemies(); + ResetProjectileData(); + Samus_LoadSuitTargetPalette(); + ClearFxTilemap(); + *(VoidP *)((char *)&door_transition_vram_update_src.addr + 1) = -30208; + if (fx_tilemap_ptr) { + door_transition_vram_update_src.addr = fx_tilemap_ptr; + door_transition_vram_update_dst = addr_unk_605BE0; + door_transition_vram_update_size = 2112; + WaitForIrqDoorTransitionVramUpdate(); + } + bg_data_ptr = get_RoomDefRoomstate(roomdefroomstate_ptr)->bg_data_ptr; + if (bg_data_ptr < 0) { + do { + int v1 = *(uint16 *)RomPtr_8F(bg_data_ptr) >> 1; + bg_data_ptr = kUpdateBackgroundCommands[v1](bg_data_ptr + 2); + } while (bg_data_ptr); + } + // Wait until the screen has finished scrolling as a result of the door opening + while ((door_transition_flag & 0x8000u) == 0) { + COROUTINE_AWAIT(1, WaitForNMI_Async()); + } + palette_buffer[196] = 15328; + SpawnBG3ScrollHdmaObject(); + hdma_objects_enable_flag |= 0x8000; + COROUTINE_AWAIT(2, PlmHandler_Async()); + + if ((door_direction & 2) == 0) { + if ((door_direction & 3) != 0) + samus_x_pos &= 0xFFF8u; + else + samus_x_pos |= 7u; + } + door_transition_function = FUNC16(DoorTransition_C_HandleAnimTiles); + COROUTINE_END(0); +} + +static const CopyToVramAtNextInterruptArgs unk_82E5B5 = { LONGPTR(0x7e4000), 0x4000, 0x1000 }; +static const CopyToVramAtNextInterruptArgs unk_82E5BF = { LONGPTR(0x7e4000), 0x4800, 0x1000 }; +static const CopyToVramAtNextInterruptArgs unk_82E57B = { LONGPTR(0x7e4000), 0x5880, 0x0f00 }; +static const CopyToVramAtNextInterruptArgs unk_82E598 = { LONGPTR(0x7e4000), 0x4800, 0x1000 }; + +void ClearFxTilemap(void) { // 0x82E566 + for (int i = 959; i >= 0; --i) { + ram4000.xray_tilemaps[i] = 6222; + ram4000.xray_tilemaps[i + 960] = 6222; + } + CopyToVramAtNextInterrupt(&unk_82E57B); +} + +void ClearBg2Tilemap(void) { // 0x82E583 + for (int i = 1023; i >= 0; --i) { + ram4000.xray_tilemaps[i] = 824; + ram4000.xray_tilemaps[i + 1024] = 824; + } + CopyToVramAtNextInterrupt(&unk_82E598); +} + +void ClearKraidBg2Tilemap(void) { // 0x82E5A0 + for (int i = 1023; i >= 0; --i) { + ram4000.xray_tilemaps[i] = 824; + ram4000.xray_tilemaps[i + 1024] = 824; + } + CopyToVramAtNextInterrupt(&unk_82E5B5); + CopyToVramAtNextInterrupt(&unk_82E5BF); +} + +uint16 UpdateBackgroundCommand_0_Finish(uint16 y) { // 0x82E5D7 + return 0; +} + +uint16 UpdateBackgroundCommand_E_DoorDependentTransferToVRAM(uint16 j) { // 0x82E5D9 + if (door_def_ptr == *(uint16 *)RomPtr_8F(j)) + return UpdateBackgroundCommand_2_TransferToVram(j + 2); + else + return j + 9; +} + +uint16 UpdateBackgroundCommand_2_TransferToVram(uint16 j) { // 0x82E5EB + uint8 *v1 = RomPtr_8F(j); + door_transition_vram_update_dst = *(uint16 *)(v1 + 3); + copy24(&door_transition_vram_update_src, (LongPtr *)v1); + door_transition_vram_update_size = *(uint16 *)(v1 + 5); + WaitForIrqDoorTransitionVramUpdate(); + return j + 7; +} + +uint16 UpdateBackgroundCommand_4_Decompression(uint16 j) { // 0x82E616 + LongPtr *v1; + + v1 = (LongPtr *)RomPtr_8F(j); + copy24(&decompress_src, v1); + *(VoidP *)((char *)&decompress_dst.addr + 1) = 32256; + decompress_dst.addr = v1[1].addr; + DecompressToMem(); + return j + 5; +} + +uint16 UpdateBackgroundCommand_6_ClearFxTilemap(uint16 j) { // 0x82E637 + ClearFxTilemap(); + return j; +} + +uint16 UpdateBackgroundCommand_8_TransferToVramAndSetBg3(uint16 j) { // 0x82E63E + j = UpdateBackgroundCommand_2_TransferToVram(j); + reg_BG34NBA = 2; + return j; +} + +uint16 UpdateBackgroundCommand_A_ClearBg2Tilemap(uint16 j) { // 0x82E64B + ClearBg2Tilemap(); + return j; +} + +uint16 UpdateBackgroundCommand_C_ClearKraidBg2Tilemap(uint16 j) { // 0x82E652 + ClearKraidBg2Tilemap(); + return j; +} + +CoroutineRet DoorTransition_C_HandleAnimTiles(void) { // 0x82E659 + AnimtilesHandler(); + door_transition_function = FUNC16(DoorTransition_WaitForMusicToClear); + return kCoroutineNone; +} + +CoroutineRet DoorTransition_WaitForMusicToClear(void) { // 0x82E664 + if (!HasQueuedMusic()) { + door_transition_function = FUNC16(DoorTransition_HandleTransition); + LoadNewMusicTrackIfChanged(); + } + return kCoroutineNone; +} + +CoroutineRet DoorTransition_HandleTransition(void) { // 0x82E6A2 + if ((samus_x_pos & 0xF0) == 16) { + samus_x_pos = (samus_x_pos | 0xF) + 8; + } else if ((samus_x_pos & 0xF0) == 224) { + samus_x_pos = (samus_x_pos & 0xFFF0) - 8; + } + if ((samus_y_pos & 0xF0) == 16) + samus_y_pos = (samus_y_pos | 0xF) + 8; + for (int i = 510; i >= 0; i -= 2) { + *(uint16 *)&mother_brain_indirect_hdma[i] = 0; + *(uint16 *)(&hdma_window_1_left_pos[0].field_0 + i) = 0; + } + uint16 v1 = room_loading_irq_handler; + if (!room_loading_irq_handler) + v1 = 4; + irqhandler_next_handler = v1; + PointlessFunctionStupidToo(); + if (elevator_flags) { + if ((elevator_direction & 0x8000u) == 0) + CallSomeSamusCode(7u); + else + CallSomeSamusCode(0); + } + SetLiquidPhysicsType(); + door_transition_function = FUNC16(DoorTransition_FadeInScreenAndFinish); + *(uint16 *)®_INIDISP |= 0x1Fu; + return kCoroutineNone; +} + +CoroutineRet DoorTransition_FadeInScreenAndFinish(void) { // 0x82E737 + AnimtilesHandler(); + DetermineWhichEnemiesToProcess(); + EnemyMain(); + EprojRunAll(); + DrawSamusEnemiesAndProjectiles(); + EnsureSamusDrawnEachFrame(); + QueueEnemyBG2TilemapTransfers(); + if (AdvancePaletteFadeForAllPalettes_0xc()) { + debug_disable_sounds = 0; + PlaySpinJumpSoundIfSpinJumping(); + door_transition_flag_elevator_zebetites = 0; + door_transition_flag_enemies = 0; + game_state = kGameState_8_MainGameplay; + } + return kCoroutineNone; +} + +void LoadDestinationRoomThings(void) { // 0x82E76B + LoaadDesinationRoomCreBitset(); + LoadDoorHeader(); + LoadRoomHeader(); + LoadStateHeader(); + LoadCRETilesTilesetTilesAndPalette(); +} + +void LoadCRETilesTilesetTilesAndPalette(void) { // 0x82E783 + elevator_flags = 0; + WriteRegWord(VMAIN, 0x80); + mov24(&decompress_src, 0xb98000); + decompress_dst.addr = addr_unk_605000; + WriteRegWord(VMADDL, 0x2800u); + DecompressToVRAM(); + copy24(&decompress_src, &tileset_tiles_pointer); + WriteRegWord(VMADDL, 0); + decompress_dst.addr = 0; + DecompressToVRAM(); + *(VoidP *)((char *)&decompress_src.addr + 1) = *(VoidP *)((char *)&tileset_compr_palette_ptr.addr + 1); + decompress_src.addr = tileset_compr_palette_ptr.addr; + static const LongPtr unk_82E7CD = LONGPTR(0x7ec200); + DecompressToMem_IpArg(&unk_82E7CD); +} + +void LoadLevelDataAndOtherThings(void) { // 0x82E7D3 + uint16 j; + int16 v3; + uint16 k; + RoomDefRoomstate *v12; + RoomDefRoomstate *RoomDefRoomstate; + int16 rdf_scroll_ptr; + uint16 m; + char v10; + char v11; + + uint16 n; + char v14; + + static const LongPtr unk_82E849 = LONGPTR(0x7ea000); + static const LongPtr unk_82E85A = LONGPTR(0x7ea800); + static const LongPtr unk_82E86D = LONGPTR(0x7ea000); + + for (int i = 25598; i >= 0; i -= 2) + level_data[i >> 1] = 0x8000; + copy24(&decompress_src, &room_compr_level_data_ptr); + static const DecompressToParams unk_82E7F8 = { LONGPTR(0x7f0000) }; + DecompressToMem_IpArg(&unk_82E7F8); + uint16 v1 = ram7F_start; + for (j = ram7F_start + ram7F_start + (ram7F_start >> 1); ; custom_background[v1 >> 1] = level_data[j >> 1]) { + j -= 2; + v1 -= 2; + if ((v1 & 0x8000u) != 0) + break; + } + v3 = ram7F_start >> 1; + for (k = ram7F_start + (ram7F_start >> 1); ; *(uint16 *)&BTS[(uint16)v3] = level_data[k >> 1]) { + k -= 2; + v3 -= 2; + if (v3 < 0) + break; + } + if (area_index == 6) { + copy24(&decompress_src, &tileset_tile_table_pointer); + DecompressToMem_IpArg(&unk_82E86D); + } else { + mov24(&decompress_src, 0xb9a09d); + DecompressToMem_IpArg(&unk_82E849); + copy24(&decompress_src, &tileset_tile_table_pointer); + DecompressToMem_IpArg(&unk_82E85A); + } + RoomDefRoomstate = get_RoomDefRoomstate(roomdefroomstate_ptr); + rdf_scroll_ptr = RoomDefRoomstate->rdf_scroll_ptr; + if (rdf_scroll_ptr >= 0) { + R18_ = RoomDefRoomstate->rdf_scroll_ptr; + LOBYTE(R20_) = room_height_in_scrolls - 1; + uint8 v8 = 2; + uint8 v9 = 0; + v10 = 0; + do { + if (v10 == (uint8)R20_) + v8 = R18_ + 1; + v14 = v10; + v11 = 0; + do { + scrolls[v9++] = v8; + ++v11; + } while (v11 != (uint8)room_width_in_scrolls); + v10 = v14 + 1; + } while (v14 + 1 != (uint8)room_height_in_scrolls); + } else { + for (m = 0; m != 50; m += 2) { + *(uint16 *)&scrolls[m] = *(uint16 *)RomPtr_8F(rdf_scroll_ptr); + rdf_scroll_ptr += 2; + } + } + v12 = get_RoomDefRoomstate(roomdefroomstate_ptr); + if (v12->room_plm_header_ptr) { + for (n = v12->room_plm_header_ptr; get_RoomPlmEntry(n)->plm_header_ptr_; n += 6) + SpawnRoomPLM(n); + } + RunDoorSetupCode(); + RunRoomSetupCode(); + if (elevator_flags) + elevator_status = 2; +} + +void SpawnDoorClosingPLM(void) { // 0x82E8EB + if (!CheckIfColoredDoorCapSpawned()) { + uint16 *v0 = (uint16 *)RomPtr_8F(2 * door_direction - 6518); + if (*v0) { + R18_ = *v0; + R20_ = *(uint16 *)&get_DoorDef(door_def_ptr)->x_pos_plm; + //SpawnRoomPLM(0x12u); // WTF? + } + } +} + +uint8 CheckIfColoredDoorCapSpawned(void) { // 0x82E91C + DoorDef *DoorDef; + int16 x_pos_plm; + int16 v2; + int16 v6; + + DoorDef = get_DoorDef(door_def_ptr); + uint16 prod = Mult8x8(DoorDef->y_pos_plm, room_width_in_blocks); + x_pos_plm = DoorDef->x_pos_plm; + v2 = 2 * (prod + x_pos_plm); + uint16 v3 = 78; + while (v2 != plm_block_indices[v3 >> 1]) { + v3 -= 2; + if ((v3 & 0x8000u) != 0) + return 0; + } + int v5 = v3 >> 1; + if (!plm_header_ptr[v5]) + return 0; + v6 = plm_room_arguments[v5]; + if (v6 >= 0) { + int idx = PrepareBitAccess(v6); + if ((bitmask & opened_door_bit_array[idx]) != 0) + return 0; + } + int v7 = v3 >> 1; + plm_instruction_timer[v7] = 1; + uint16 v8 = plm_header_ptr[v7]; + if (!v8) + return 0; + plm_instr_list_ptrs[v3 >> 1] = get_PlmHeader_Size4(v8)[1].func_ptr; + return 1; +} + +static Func_Y_Y *const kLoadLibraryBackgroundFuncs[8] = { // 0x82E97C + LoadLibraryBackgroundFunc_0_DONE, + LoadLibraryBackgroundFunc_2_TransferToVram, + LoadLibraryBackgroundFunc_4_Decompress, + LoadLibraryBackgroundFunc_6_ClearFxTilemap, + LoadLibraryBackgroundFunc_8_TransferToVramAndSetBg3, + LoadLibraryBackgroundFunc_A_ClearBG2Tilemap, + LoadLibraryBackgroundFunc_C_ClearKraidLayer2, + LoadLibraryBackgroundFunc_E_DoorDependentTransferToVram, +}; + +void LoadLibraryBackground(void) { + int16 bg_data_ptr; + + ClearFXTilemap(); + if (fx_tilemap_ptr) { + WriteRegWord(A1T1L, fx_tilemap_ptr); + WriteRegWord(VMADDL, addr_unk_605BE0); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1B1, 0x8Au); + WriteRegWord(DAS1L, 0x840u); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 2u); + } + bg_data_ptr = get_RoomDefRoomstate(roomdefroomstate_ptr)->bg_data_ptr; + if (bg_data_ptr < 0) { + do { + uint16 v1 = *(uint16 *)RomPtr_8F(bg_data_ptr); + bg_data_ptr += 2; + bg_data_ptr = kLoadLibraryBackgroundFuncs[v1 >> 1](bg_data_ptr); + } while (bg_data_ptr); + } +} + +uint16 LoadLibraryBackgroundFunc_0_DONE(uint16 j) { // 0x82E9E5 + return 0; +} + +uint16 LoadLibraryBackgroundFunc_E_DoorDependentTransferToVram(uint16 j) { // 0x82E9E7 + if (door_def_ptr == get_LoadBg_E(j)->field_0) + return LoadLibraryBackgroundFunc_2_TransferToVram(j + 2); + else + return j + 9; +} + +uint16 LoadLibraryBackgroundFunc_2_TransferToVram(uint16 j) { // 0x82E9F9 + uint16 *LoadBg_28 = (uint16 *)get_LoadBg_28(j); + WriteRegWord(VMADDL, *(uint16 *)((char *)LoadBg_28 + 3)); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1T1L, *LoadBg_28); + WriteRegWord(A1B1, LoadBg_28[1]); + WriteRegWord(DAS1L, *(uint16 *)((char *)LoadBg_28 + 5)); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 2u); + return j + 7; +} + +uint16 LoadLibraryBackgroundFunc_4_Decompress(uint16 j) { // 0x82EA2D + LongPtr *LoadBg_28; + + LoadBg_28 = (LongPtr *)get_LoadBg_28(j); + copy24(&decompress_src, LoadBg_28); + *(VoidP *)((char *)&decompress_dst.addr + 1) = 32256; + decompress_dst.addr = LoadBg_28[1].addr; + DecompressToMem(); + return j + 5; +} + +uint16 LoadLibraryBackgroundFunc_6_ClearFxTilemap(uint16 j) { // 0x82EA4E + ClearFXTilemap(); + return j; +} + +uint16 LoadLibraryBackgroundFunc_A_ClearBG2Tilemap(uint16 j) { // 0x82EA56 + ClearBG2Tilemap(); + return j; +} + +uint16 LoadLibraryBackgroundFunc_C_ClearKraidLayer2(uint16 j) { // 0x82EA5E + ClearBG2Tilemap(); + return j; +} + +uint16 LoadLibraryBackgroundFunc_8_TransferToVramAndSetBg3(uint16 j) { // 0x82EA66 + j = LoadLibraryBackgroundFunc_2_TransferToVram(j); + reg_BG34NBA = 2; + return j; +} + +void LoadLevelScrollAndCre(void) { // 0x82EA73 + uint16 j; + int16 v3; + uint16 k; + RoomDefRoomstate *RoomDefRoomstate; + int16 rdf_scroll_ptr; + uint16 m; + char v10; + char v11; + char v12; + + static const LongPtr unk_82EAA0 = LONGPTR(0x7f0000); + static const LongPtr unk_82EAF9 = LONGPTR(0x7ea000); + static const LongPtr unk_82EB0A = LONGPTR(0x7ea800); + static const LongPtr unk_82EB1D = LONGPTR(0x7ea000); + + for (int i = 6398; i >= 0; i -= 2) { + level_data[i >> 1] = 0x8000; + level_data[(i >> 1) + 3200 * 1] = 0x8000; + level_data[(i >> 1) + 3200 * 2] = 0x8000; + level_data[(i >> 1) + 3200 * 3] = 0x8000; + } + copy24(&decompress_src, &room_compr_level_data_ptr); + DecompressToMem_IpArg(&unk_82EAA0); + uint16 v1 = ram7F_start; + for (j = ram7F_start + ram7F_start + (ram7F_start >> 1); ; custom_background[v1 >> 1] = level_data[j >> 1]) { + j -= 2; + v1 -= 2; + if ((v1 & 0x8000u) != 0) + break; + } + v3 = ram7F_start >> 1; + for (k = ram7F_start + (ram7F_start & 1) + (ram7F_start >> 1); + ; + *(uint16 *)&BTS[(uint16)v3] = level_data[k >> 1]) { + k -= 2; + v3 -= 2; + if (v3 < 0) + break; + } + if (area_index == 6) { + copy24(&decompress_src, &tileset_tile_table_pointer); + DecompressToMem_IpArg(&unk_82EB1D); + } else { + if ((cre_bitset & 2) != 0) { + mov24(&decompress_src, 0xb9a09d); + DecompressToMem_IpArg(&unk_82EAF9); + } + copy24(&decompress_src, &tileset_tile_table_pointer); + DecompressToMem_IpArg(&unk_82EB0A); + } + RoomDefRoomstate = get_RoomDefRoomstate(roomdefroomstate_ptr); + rdf_scroll_ptr = RoomDefRoomstate->rdf_scroll_ptr; + if (rdf_scroll_ptr >= 0) { + R18_ = RoomDefRoomstate->rdf_scroll_ptr; + LOBYTE(R20_) = room_height_in_scrolls - 1; + uint8 v8 = 2; + uint8 v9 = 0; + v10 = 0; + do { + if (v10 == (uint8)R20_) + v8 = R18_ + 1; + v12 = v10; + v11 = 0; + do { + scrolls[v9++] = v8; + ++v11; + } while (v11 != (uint8)room_width_in_scrolls); + v10 = v12 + 1; + } while (v12 + 1 != (uint8)room_height_in_scrolls); + } else { + for (m = 0; m != 50; m += 2) { + *(uint16 *)&scrolls[m] = *(uint16 *)RomPtr_8F(rdf_scroll_ptr); + rdf_scroll_ptr += 2; + } + } +} + +void CreatePlmsExecuteDoorAsmRoomSetup(void) { // 0x82EB6C + RoomDefRoomstate *RoomDefRoomstate; + RoomDefRoomstate = get_RoomDefRoomstate(roomdefroomstate_ptr); + if (RoomDefRoomstate->room_plm_header_ptr) { + for (int i = RoomDefRoomstate->room_plm_header_ptr; get_PlmHeader_Size6(i)->func_ptr; i += 6) + SpawnRoomPLM(i); + } + RunDoorSetupCode(); + RunRoomSetupCode(); + if (elevator_flags) + elevator_status = 2; +} + +static Func_V *const kGameOptionsMenuFuncs[13] = { // 0x82EB9F + GameOptionsMenuFunc_0, + GameOptionsMenu_1_LoadingOptionsScreen, + GameOptionsMenu_2_FadeInOptionsScreen, + GameOptionsMenu_3_OptionsScreen, + GameOptionsMenu_4_StartGame, + GameOptionsMenu_5_DissolveOutScreen, + GameOptionsMenu_6_DissolveInScreen, + GameOptionsMenu_7_ControllerSettings, + GameOptionsMenu_8_SpecialSettings, + GameOptionsMenu_9_ScrollControllerSettingsDown, + GameOptionsMenu_A_ScrollControllerSettingsUp, + GameOptionsMenu_B_TransitionBackToFileSelect, + GameOptionsMenu_C_FadeOutOptionsScreenToStart, +}; + +CoroutineRet GameState_2_GameOptionsMenu(void) { + kGameOptionsMenuFuncs[game_options_screen_index](); + OptionsMenuFunc1(); + DrawOptionsMenuSpritemaps(); + if (!sign16(game_options_screen_index - 2)) + OptionsMenu_AddToVramQueue(); + return kCoroutineNone; +} + +void GameOptionsMenuFunc_0(void) { // 0x82EBDB + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + ++game_options_screen_index; + } else if (reg_INIDISP == 14) { + uint16 v0 = reg_TS; + if ((reg_TS & 4) == 0) + CreateOptionsMenuObject_(v0, addr_stru_82F4D6); + } +} + +#define kMenuPalettes ((uint16*)RomPtr(0x8ee400)) +void GameOptionsMenu_1_LoadingOptionsScreen(void) { // 0x82EC11 + uint16 j; + + static const DecompressToParams unk_82EC74 = { LONGPTR(0x7fc000) }; + static const DecompressToParams unk_82EC85 = { LONGPTR(0x7fc800) }; + static const DecompressToParams unk_82EC96 = { LONGPTR(0x7fd000) }; + static const DecompressToParams unk_82ECA7 = { LONGPTR(0x7fd800) }; + static const DecompressToParams unk_82ECB8 = { LONGPTR(0x7fe000) }; + + reg_BG12NBA = 0; + reg_TM = 19; + reg_TS = 0; + reg_TMW = 0; + reg_TSW = 0; + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x58u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_82EC3D = { 1, 1, 0x18, LONGPTR(0x8edc00), 0x0800 }; + SetupDmaTransfer(&unk_82EC3D); + WriteReg(MDMAEN, 2u); + reg_BG1HOFS = 0; + reg_BG1VOFS = 0; + reg_BG2HOFS = 0; + reg_BG2VOFS = 0; + debug_invincibility = 0; + for (int i = 510; i >= 0; i -= 2) + palette_buffer[i >> 1] = kMenuPalettes[i >> 1]; + mov24(&decompress_src, 0x978DF4u); + DecompressToMem_IpArg(&unk_82EC74); + mov24(&decompress_src, 0x978FCDu); + DecompressToMem_IpArg(&unk_82EC85); + mov24(&decompress_src, 0x9791C4u); + DecompressToMem_IpArg(&unk_82EC96); + mov24(&decompress_src, 0x97938Du); + DecompressToMem_IpArg(&unk_82ECA7); + mov24(&decompress_src, 0x97953Au); + DecompressToMem_IpArg(&unk_82ECB8); + for (j = 1023; (j & 0x8000u) == 0; --j) + ram3000.pause_menu_map_tilemap[j] = custom_background[j + 5375]; + menu_option_index = 0; + DeleteAllOptionsMenuObjects_(); + CreateOptionsMenuObject_(0, addr_stru_82F4B8); + CreateOptionsMenuObject_(0, addr_stru_82F4C4); + ++game_options_screen_index; + OptionsMenuFunc4(); +} + +void GameOptionsMenu_2_FadeInOptionsScreen(void) { // 0x82ECE4 + HandleFadeIn(); + if (reg_INIDISP == 15) { + screen_fade_delay = 0; + screen_fade_counter = 0; + ++game_options_screen_index; + } +} + +void OptionsMenu_AddToVramQueue(void) { // 0x82ECFF + uint16 v0 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 2048; + v0 += 2; + gVramWriteEntry(v0)->size = 12288; + v0 += 2; + LOBYTE(gVramWriteEntry(v0++)->size) = 126; + gVramWriteEntry(v0)->size = 20480; + vram_write_queue_tail = v0 + 2; +} + +void OptionsMenuFunc5(uint16 a, uint16 k, uint16 j) { // 0x82ED28 + R18_ = a; + do { + *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + k) = R18_ | *(uint16 *)((uint8 *)ram3000.pause_menu_map_tilemap + + k) & 0xE3FF; + k += 2; + j -= 2; + } while (j); +} +static Func_V *const kGameOptionsMenuItemFuncs[5] = { // 0x82ED42 + GameOptionsMenuItemFunc_0, + GameOptionsMenuItemFunc_2_ToggleJapanese, + GameOptionsMenuItemFunc_2_ToggleJapanese, + GameOptionsMenuItemFunc_4, + GameOptionsMenuItemFunc_4, +}; +void GameOptionsMenu_3_OptionsScreen(void) { + if ((joypad1_newkeys & kButton_Up) != 0) { + QueueSfx1_Max6(0x37u); + if ((--menu_option_index & 0x8000u) != 0) + menu_option_index = 4; + } else if ((joypad1_newkeys & kButton_Down) != 0) { + QueueSfx1_Max6(0x37u); + if (++menu_option_index == 5) + menu_option_index = 0; + } + if ((joypad1_newkeys & 0x8000u) != 0) { + game_options_screen_index = 11; + } else if ((joypad1_newkeys & kButton_A) != 0 || (joypad1_newkeys & kButton_Start) != 0) { + QueueSfx1_Max6(0x38u); + kGameOptionsMenuItemFuncs[menu_option_index](); + } +} + +void GameOptionsMenuItemFunc_0(void) { // 0x82EDB1 + if (enable_debug && (joypad1_lastkeys & kButton_L) == 0 || loading_game_state == kGameState_5_FileSelectMap) { + game_options_screen_index = 4; + } else { + screen_fade_delay = 0; + screen_fade_counter = 0; + game_options_screen_index = 12; + } +} + +void GameOptionsMenuItemFunc_2_ToggleJapanese(void) { // 0x82EDDA + menu_option_index = 0; + japanese_text_flag = japanese_text_flag == 0; + OptionsMenuFunc4(); +} + +void OptionsMenuFunc4(void) { // 0x82EDED + if (japanese_text_flag) { + OptionsMenuFunc5(0x400u, 0x288u, 0x18u); + OptionsMenuFunc5(0x400u, 0x2C8u, 0x18u); + OptionsMenuFunc5(0, 0x348u, 0x32u); + OptionsMenuFunc5(0, 0x388u, 0x32u); + } else { + OptionsMenuFunc5(0, 0x288u, 0x18u); + OptionsMenuFunc5(0, 0x2C8u, 0x18u); + OptionsMenuFunc5(0x400u, 0x348u, 0x32u); + OptionsMenuFunc5(0x400u, 0x388u, 0x32u); + } +} + +void GameOptionsMenuItemFunc_4(void) { // 0x82EE55 + reg_MOSAIC = 3; + screen_fade_delay = 0; + screen_fade_counter = 0; + game_options_screen_index = 5; +} + +void GameOptionsMenu_B_TransitionBackToFileSelect(void) { // 0x82EE6A + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + game_state = kGameState_4_FileSelectMenus; + menu_index = 0; + game_options_screen_index = 0; + } +} + +void GameOptionsMenu_C_FadeOutOptionsScreenToStart(void) { // 0x82EE92 + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + game_options_screen_index = 4; + } +} + +void GameOptionsMenu_4_StartGame(void) { // 0x82EEB4 + game_options_screen_index = 0; + if (enable_debug && (joypad1_lastkeys & 0x20) == 0) { + game_state = kGameState_5_FileSelectMap; + if (loading_game_state != kLoadingGameState_5_Main) { + loading_game_state = kGameState_5_FileSelectMap; + SaveToSram(selected_save_slot); + } + } else if (loading_game_state) { + game_state = loading_game_state; + if (loading_game_state == kGameState_34_CeresGoesBoom) + cinematic_function = FUNC16(CinematicFunctionBlackoutFromCeres); + menu_option_index = 0; + game_options_screen_index = 0; + } else { + game_state = kGameState_30_IntroCinematic; + cinematic_function = FUNC16(CinematicFunction_Intro_Initial); + menu_option_index = 0; + screen_fade_delay = 0; + screen_fade_counter = 0; + } +} + +void GameOptionsMenu_5_DissolveOutScreen(void) { // 0x82EF18 + uint16 m; + uint16 k; + uint16 j; + uint16 n; + uint16 v1; + + HandleFadeOut(); + if (reg_MOSAIC != 0xF3) + reg_MOSAIC += 16; + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + reg_BG1VOFS = 0; + ++game_options_screen_index; + if (menu_option_index) { + if ((menu_option_index & 4) != 0) { + if (japanese_text_flag) { + for (int i = 1023; i >= 0; --i) + ram3000.pause_menu_map_tilemap[i] = custom_background[i + 9471]; + } else { + for (j = 1023; (j & 0x8000u) == 0; --j) + ram3000.pause_menu_map_tilemap[j] = custom_background[j + 8447]; + } + menu_option_index = 0; + OptionsMenuFunc7(); + menu_option_index = 1; + OptionsMenuFunc7(); + menu_option_index = 4; + CreateOptionsMenuObject_(4u, addr_stru_82F4D0); + } else { + if (japanese_text_flag) { + for (k = 1023; (k & 0x8000u) == 0; --k) { + v1 = custom_background[k + 7423]; + ram3000.pause_menu_map_tilemap[k] = v1; + } + } else { + for (m = 1023; (m & 0x8000u) == 0; --m) { + v1 = custom_background[m + 6399]; + ram3000.pause_menu_map_tilemap[m] = v1; + } + } + CreateOptionsMenuObject_(v1, addr_stru_82F4CA); + LoadControllerOptionsFromControllerBindings(); + OptionsMenuFunc6(); + } + } else { + for (n = 1023; (n & 0x8000u) == 0; --n) + ram3000.pause_menu_map_tilemap[n] = custom_background[n + 5375]; + OptionsMenuFunc4(); + uint16 v6 = 0; // bug + CreateOptionsMenuObject_(v6, addr_stru_82F4C4); + } + } +} + +void GameOptionsMenu_6_DissolveInScreen(void) { // 0x82EFDB + HandleFadeIn(); + if (reg_MOSAIC != 3) + reg_MOSAIC -= 16; + if (reg_INIDISP == 15) { + reg_MOSAIC = 0; + screen_fade_delay = 0; + screen_fade_counter = 0; + if (menu_option_index) { + if ((menu_option_index & 4) != 0) + game_options_screen_index = 8; + else + game_options_screen_index = 7; + menu_option_index = 0; + } else { + game_options_screen_index = 3; + } + } +} +static Func_V *const kGameOptionsMenuSpecialSettings[3] = { // 0x82F024 + GameOptionsMenuSpecialSettings_0, + GameOptionsMenuSpecialSettings_0, + GameOptionsMenuSpecialSettings_2, +}; +void GameOptionsMenu_8_SpecialSettings(void) { + if ((joypad1_newkeys & kButton_Up) != 0) { + QueueSfx1_Max6(0x37u); + if ((--menu_option_index & 0x8000u) != 0) + menu_option_index = 2; + } else if ((joypad1_newkeys & kButton_Down) != 0) { + QueueSfx1_Max6(0x37u); + if (++menu_option_index == 3) + menu_option_index = 0; + } + if ((joypad1_newkeys & 0x8000u) == 0) { + if ((joypad1_newkeys & (kButton_Start | kButton_Left | kButton_Right | kButton_A)) != 0) { + QueueSfx1_Max6(0x38u); + kGameOptionsMenuSpecialSettings[menu_option_index](); + } + } else { + QueueSfx1_Max6(0x38u); + menu_option_index = 0; + GameOptionsMenuItemFunc_4(); + } +} +#define kOptionsMenuSpecialPtrs ((uint16*)RomPtr(0x82f0ae)) +void GameOptionsMenuSpecialSettings_0(void) { // 0x82F08E + uint8 *v0 = RomPtr_RAM(kOptionsMenuSpecialPtrs[menu_option_index]); + if (*(uint16 *)v0) + *(uint16 *)v0 = 0; + else + *(uint16 *)v0 = 1; + OptionsMenuFunc7(); +} + +void GameOptionsMenuSpecialSettings_2(void) { // 0x82F0B2 + menu_option_index = 0; + GameOptionsMenuItemFunc_4(); +} + +static const uint16 g_word_82F149[4] = { // 0x82F0B9 + 0x1e0, 0x220, + 0x360, 0x3a0, +}; +static const uint16 g_word_82F151[4] = { + 0x1ee, 0x22e, + 0x36e, 0x3ae, +}; +void OptionsMenuFunc7(void) { + + uint16 v0 = 4 * menu_option_index; + if (*(uint16 *)RomPtr_RAM(kOptionsMenuSpecialPtrs[menu_option_index])) { + OptionsMenuFunc5(0, g_word_82F149[(uint16)(4 * menu_option_index) >> 1], 0xCu); + OptionsMenuFunc5(0, g_word_82F149[(v0 >> 1) + 1], 0xCu); + OptionsMenuFunc5(0x400u, g_word_82F151[v0 >> 1], 0xCu); + OptionsMenuFunc5(0x400u, g_word_82F151[(v0 >> 1) + 1], 0xCu); + } else { + OptionsMenuFunc5(0x400u, g_word_82F149[(uint16)(4 * menu_option_index) >> 1], 0xCu); + OptionsMenuFunc5(0x400u, g_word_82F149[(v0 >> 1) + 1], 0xCu); + OptionsMenuFunc5(0, g_word_82F151[v0 >> 1], 0xCu); + OptionsMenuFunc5(0, g_word_82F151[(v0 >> 1) + 1], 0xCu); + } +} + +static const uint16 word_82F204[16] = { // 0x82F159 + 0x20, 0x20, 0x20, 0x20, + 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x4000, 0x40, + 0x40, 0x80, 0x80, 0x80, +}; + +void GameOptionsMenu_7_ControllerSettings(void) { + + if ((joypad1_newkeys & kButton_Up) != 0) { + QueueSfx1_Max6(0x37u); + uint16 v0 = --menu_option_index; + if ((menu_option_index & 0x8000u) == 0) { + if (v0 != 6) + return; + game_options_screen_index = 10; + return; + } + menu_option_index = 8; + game_options_screen_index = 9; + return; + } + if ((joypad1_newkeys & kButton_Down) != 0) { + QueueSfx1_Max6(0x37u); + uint16 v1 = menu_option_index + 1; + menu_option_index = v1; + if (v1 == 7) { + game_options_screen_index = 9; + return; + } + if (v1 == 9) { + menu_option_index = 0; + game_options_screen_index = 10; + return; + } + } else if (joypad1_newkeys) { + QueueSfx1_Max6(0x38u); + static Func_V *const kOptionsMenuControllerFuncs[9] = { + OptionsMenuControllerFunc_0, + OptionsMenuControllerFunc_0, + OptionsMenuControllerFunc_0, + OptionsMenuControllerFunc_0, + OptionsMenuControllerFunc_0, + OptionsMenuControllerFunc_0, + OptionsMenuControllerFunc_0, + OptionsMenuControllerFunc_7, + OptionsMenuControllerFunc_8, + }; + kOptionsMenuControllerFuncs[menu_option_index](); + } else if (joypad2_new_keys && menu_option_index == 8 && sign16(debug_invincibility - 16)) { + if ((word_82F204[debug_invincibility] & joypad2_new_keys) == word_82F204[debug_invincibility]) + ++debug_invincibility; + else + debug_invincibility = 0; + } +} + +void OptionsMenuControllerFunc_8(void) { // 0x82F224 + if ((joypad1_newkeys & (kButton_Start | kButton_A)) != 0) { + button_config_shoot_x = 64; + button_config_jump_a = 128; + button_config_run_b = 0x8000; + button_config_itemcancel_y = 0x4000; + button_config_itemswitch = 0x2000; + button_config_aim_up_R = 16; + button_config_aim_down_L = 32; + LoadControllerOptionsFromControllerBindings(); + OptionsMenuFunc6(); + } +} + +void OptionsMenuControllerFunc_7(void) { // 0x82F25D + if ((joypad1_newkeys & (kButton_Start | kButton_A)) != 0 && !OptionsMenuFunc8()) { + menu_option_index = 0; + GameOptionsMenuItemFunc_4(); + } +} + +void GameOptionsMenu_9_ScrollControllerSettingsDown(void) { // 0x82F271 + reg_BG1VOFS += 2; + if (reg_BG1VOFS == 32) + game_options_screen_index = 7; +} + +void GameOptionsMenu_A_ScrollControllerSettingsUp(void) { // 0x82F285 + reg_BG1VOFS -= 2; + if (!reg_BG1VOFS) + game_options_screen_index = 7; +} + +void sub_82F296(uint16 j) { // 0x82F296 + int v1 = j >> 1; + enemy_projectile_y_pos[v1 + 13] = 24; + enemy_projectile_x_vel[v1 + 3] = 56; + enemy_projectile_x_vel[v1 + 11] = 3584; +} +#define off_82F2ED ((uint16*)RomPtr(0x82f2ed)) +void OptionsPreInstr_F2A9(uint16 v0) { // 0x82F2A9 + if (game_state == kGameState_2_GameOptionsMenu) { + int v2 = game_options_screen_index; + uint16 v3 = off_82F2ED[v2]; + if (v3) { + R18_ = off_82F2ED[v2]; + uint16 *v4 = (uint16 *)RomPtr_82(v3 + 4 * menu_option_index); + int v5 = v0 >> 1; + enemy_projectile_y_pos[v5 + 13] = *v4; + enemy_projectile_x_vel[v5 + 3] = v4[1]; + } else { + int v6 = v0 >> 1; + enemy_projectile_y_pos[v6 + 13] = 384; + enemy_projectile_x_vel[v6 + 3] = 16; + } + } else { + int v1 = v0 >> 1; + enemy_projectile_E[v1 + 15] = 1; + enemy_projectile_y_vel[v1 + 17] = addr_off_82F4B6; + } +} + +void sub_82F34B(uint16 j) { // 0x82F34B + enemy_projectile_y_pos[(j >> 1) + 13] = 124; + sub_82F369(j); +} +void sub_82F353(uint16 j) { // 0x82F353 + enemy_projectile_y_pos[(j >> 1) + 13] = 132; + sub_82F369(j); +} +void sub_82F35B(uint16 j) { // 0x82F35B + enemy_projectile_y_pos[(j >> 1) + 13] = 128; + sub_82F369(j); +} +void sub_82F363(uint16 j) { // 0x82F363 + enemy_projectile_y_pos[(j >> 1) + 13] = 128; + sub_82F369(j); +} + +void sub_82F369(uint16 j) { // 0x82F369 + int v1 = j >> 1; + enemy_projectile_x_vel[v1 + 3] = 16; + enemy_projectile_x_vel[v1 + 11] = 3584; +} + + +void OptionsPreInstr_F376(uint16 k) { // 0x82F376 + if (game_state != kGameState_2_GameOptionsMenu || game_options_screen_index == 6 && reg_INIDISP == 0x80) { + int v1 = k >> 1; + enemy_projectile_E[v1 + 15] = 1; + enemy_projectile_y_vel[v1 + 17] = addr_off_82F4B6; + } +} + +void OptionsPreInstr_F3A0(uint16 k) { // 0x82F3A0 + switch (game_options_screen_index) { + case 6u: + if (reg_INIDISP == 0x80) { + int v1 = k >> 1; + enemy_projectile_E[v1 + 15] = 1; + enemy_projectile_y_vel[v1 + 17] = -2890; + } + break; + case 9u: + enemy_projectile_x_vel[(k >> 1) + 3] -= 2; + break; + case 0xAu: + enemy_projectile_x_vel[(k >> 1) + 3] += 2; + break; + } +} + +void OptionsPreInstr_F3E2(uint16 k) { // 0x82F3E2 + if (game_options_screen_index == 6 && reg_INIDISP == 0x80) { + int v1 = k >> 1; + enemy_projectile_E[v1 + 15] = 1; + enemy_projectile_y_vel[v1 + 17] = -2890; + } +} + +void sub_82F404(uint16 k) { // 0x82F404 + if (game_options_screen_index == 1) { + int v1 = k >> 1; + enemy_projectile_E[v1 + 15] = 1; + enemy_projectile_y_vel[v1 + 17] = -2890; + } +} + +void sub_82F419(uint16 j) { // 0x82F419 + int v1 = j >> 1; + enemy_projectile_y_pos[v1 + 13] = 216; + enemy_projectile_x_vel[v1 + 3] = 16; + enemy_projectile_x_vel[v1 + 11] = 3584; +} + +void OptionsPreInstr_F42C(uint16 k) { // 0x82F42C + if (game_state != 2) { + int v1 = k >> 1; + enemy_projectile_E[v1 + 15] = 1; + enemy_projectile_y_vel[v1 + 17] = addr_off_82F4B6; + } +} +#define off_82F54A ((uint16*)RomPtr(0x82f54a)) +void LoadControllerOptionsFromControllerBindings(void) { // 0x82F4DC + int16 v2; + + uint16 v0 = 0; + do { + int v1 = v0 >> 1; + v2 = *(uint16 *)RomPtr_7E(off_82F54A[v1]); + if ((v2 & kButton_X) != 0) { +LABEL_9: + enemy_projectile_F[v1 + 13] = 0; + goto LABEL_16; + } + if ((v2 & kButton_A) != 0) { + enemy_projectile_F[v1 + 13] = 1; + } else if (v2 < 0) { + enemy_projectile_F[v1 + 13] = 2; + } else if ((v2 & kButton_Select) != 0) { + enemy_projectile_F[v1 + 13] = 3; + } else if ((v2 & kButton_Y) != 0) { + enemy_projectile_F[v1 + 13] = 4; + } else if ((v2 & kButton_L) != 0) { + enemy_projectile_F[v1 + 13] = 5; + } else { + if ((v2 & kButton_R) == 0) + goto LABEL_9; + enemy_projectile_F[v1 + 13] = 6; + } +LABEL_16: + v0 += 2; + } while ((int16)(v0 - 14) < 0); +} +static const Buttons word_82F575[9] = { // 0x82F558 + kButton_X, + kButton_A, + kButton_B, + kButton_Select, + kButton_Y, + kButton_L, + kButton_R, + kButton_Left, + kButton_Right, +}; +uint8 OptionsMenuFunc8(void) { + + uint16 v0 = 0, v2; + do { + v2 = v0; + *(uint16 *)RomPtr_7E(off_82F54A[v0 >> 1]) = word_82F575[(uint16)(2 * enemy_projectile_F[(v0 >> 1) + 13]) >> 1]; + v0 += 2; + } while ((int16)(v2 - 12) < 0); + return 0; +} +#define g_word_82F639 ((uint16*)RomPtr(0x82f639)) +#define g_off_82F647 ((uint16*)RomPtr(0x82f647)) +static const uint16 g_word_82F6AD[6] = { // 0x82F587 + 0, + 0xe, + 0xe, + 0x10, + 0x1f, + 0x1f, +}; + +void OptionsMenuFunc6(void) { + uint16 v0 = 0, v4; + do { + v4 = v0; + int v1 = v0 >> 1; + uint16 v2 = g_word_82F639[v1]; + uint16 *v3 = (uint16 *)RomPtr_82(g_off_82F647[(uint16)(2 * enemy_projectile_F[v1 + 13]) >> 1]); + *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + v2) = *v3; + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[1] + v2) = v3[1]; + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[2] + v2) = v3[2]; + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[32] + v2) = v3[3]; + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[33] + v2) = v3[4]; + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[34] + v2) = v3[5]; + v0 = v4 + 2; + } while ((int16)(v4 - 12) < 0); + if (enemy_projectile_instr_list_ptr[0] != 5 && enemy_projectile_instr_list_ptr[0] != 6) { + *(uint32 *)&ram3000.menu.backup_of_io_registers_in_gameover[46] = *(uint32 *)g_word_82F6AD; + ram3000.pause_menu_map_tilemap[665] = g_word_82F6AD[2]; + *(uint32 *)&ram3000.menu.field_536[56] = *(uint32 *)&g_word_82F6AD[3]; + ram3000.pause_menu_map_tilemap[697] = g_word_82F6AD[5]; + } + if (enemy_projectile_instr_list_ptr[1] != 5 && enemy_projectile_instr_list_ptr[1] != 6) { + *(uint32 *)&ram3000.menu.field_536[184] = *(uint32 *)g_word_82F6AD; + ram3000.pause_menu_map_tilemap[761] = g_word_82F6AD[2]; + *(uint32 *)&ram3000.menu.menu_tilemap[46] = *(uint32 *)&g_word_82F6AD[3]; + ram3000.pause_menu_map_tilemap[793] = g_word_82F6AD[5]; + } +} + +void OptionsMenuControllerFunc_0(void) { // 0x82F6B9 + uint16 v0 = 12; + while ((word_82F575[v0 >> 1] & joypad1_newkeys) == 0) { + v0 -= 2; + if ((v0 & 0x8000u) != 0) + return; + } + R18_ = v0 >> 1; + uint16 v1 = 2 * menu_option_index + 2; + if (!sign16(2 * menu_option_index - 12)) + v1 = 0; + uint16 v2 = v1; + for (int i = 5; i >= 0; --i) { + if (enemy_projectile_F[(v2 >> 1) + 13] == R18_) + break; + v2 += 2; + if ((int16)(v2 - 14) >= 0) + v2 = 0; + } + int v4 = menu_option_index; + R20_ = enemy_projectile_F[v4 + 13]; + enemy_projectile_F[v4 + 13] = R18_; + enemy_projectile_F[(v2 >> 1) + 13] = R20_; + OptionsMenuFunc6(); +} diff --git a/src/sm_84.c b/src/sm_84.c new file mode 100644 index 0000000..d084fe7 --- /dev/null +++ b/src/sm_84.c @@ -0,0 +1,3473 @@ +// PLMs +#include "ida_types.h" +#include "variables.h" +#include "sm_rtl.h" +#include "funcs.h" + +void CallPlmPreInstr(uint32 ea, uint16 k); +uint16 CallPlmInstr(uint32 ea, uint16 j, uint16 k); + +#define kGoldenTorizoPalette1 ((uint16*)RomPtr(0x848032)) +#define kGoldenTorizoPalette2 ((uint16*)RomPtr(0x848132)) +#define kXrayBlockDrawingInstrs ((uint16*)RomPtr(0x84839d)) +#define kGrayDoorPreInstrs ((uint16*)RomPtr(0x84be4b)) +#define kDowardGatePlmListPtrs ((uint16*)RomPtr(0x84c70a)) +#define kDowardGateLeftBlockBts ((uint16*)RomPtr(0x84c71a)) +#define kDowardGateRightBlockBts ((uint16*)RomPtr(0x84c72a)) +#define kUpwardGatePlmListPtrs ((uint16*)RomPtr(0x84c764)) +#define kUpwardGateLeftBlockBts ((uint16*)RomPtr(0x84c774)) +#define kUpwardGateRightBlockBts ((uint16*)RomPtr(0x84c784)) +#define off_84DB28 ((uint16*)RomPtr(0x84db28)) +#define off_84E05F ((uint16*)RomPtr(0x84e05f)) +#define off_84E077 ((uint16*)RomPtr(0x84e077)) + +void SetGoldenTorizoPalette(uint16 a) { // 0x848000 + int16 v1; + + v1 = HIBYTE(a) & 0x78; + if ((v1 & 0x40) != 0) + v1 = 56; + uint16 v2 = (4 * v1) | 0x1E; + for (int i = 30; i >= 0; i -= 2) { + int v4 = v2 >> 1; + int v5 = i >> 1; + palette_buffer[v5 + 160] = kGoldenTorizoPalette2[v4]; + palette_buffer[v5 + 144] = kGoldenTorizoPalette1[v4]; + v2 -= 2; + } +} + +void LoadRoomPlmGfx(void) { // 0x848232 + plm_item_gfx_index = 0; + uint16 v0 = 0, v1; + do { + v1 = v0; + if (plm_item_gfx_ptrs[v0 >> 1]) // bugfix + PlmInstr_LoadItemPlmGfx(plm_item_gfx_ptrs[v0 >> 1], v0); + v0 += 2; + } while (v1 != 6); +} + +void ClearSoundsWhenGoingThroughDoor(void) { // 0x848250 + CallSomeSamusCode(0x1Du); +} + +void UNUSED_sub_848258(void) { // 0x848258 + if (samus_movement_type << 8 == 768 || samus_movement_type << 8 == 5120) + QueueSfx1_Max15(0x32u); +} + +void PlaySpinJumpSoundIfSpinJumping(void) { // 0x848270 + CallSomeSamusCode(0x1Cu); +} + +void UNUSED_sub_848278(void) { // 0x848278 + if (samus_movement_type << 8 == 768 || samus_movement_type << 8 == 5120) + QueueSfx1_Max15(0x30u); +} + +void CalculatePlmBlockCoords(uint16 k) { // 0x848290 + uint16 t = plm_block_indices[k >> 1] >> 1; + plm_y_block = SnesDivide(t, room_width_in_blocks); + plm_x_block = SnesModulus(t, room_width_in_blocks); +} + +void WriteLevelDataBlockTypeAndBts(uint16 k, uint16 a) { // 0x8482B4 + R18_ = a; + uint8 *v2 = RomPtr_7F(k); + v2[3] = HIBYTE(a) | v2[3] & 0xF; + BTS[k >> 1] = R18_; +} + +void WriteRowOfLevelDataBlockAndBTS(uint16 k, uint16 arg0, uint16 arg1, uint16 arg2) { // 0x8482D6 + uint16 v1 = k; + + R18_ = arg0; + R20_ = arg1; + R22_ = arg2; + uint16 v2 = plm_block_indices[v1 >> 1]; + uint16 v8 = v2 >> 1; + uint16 v3 = R18_; + uint16 v4 = R22_; + do { + level_data[v2 >> 1] = v3; + v2 += 2; + --v4; + } while (v4); + uint16 v5 = v8; + uint8 v6 = R20_; + uint16 v7 = R22_; + do { + BTS[v5++] = v6; + --v7; + } while (v7); +} + +void LoadXrayBlocks(void) { // 0x84831A + RoomDefRoomstate *RoomDefRoomstate; + uint16 j; + int16 v7; + + for (int i = 78; i >= 0; i -= 2) { + int v1 = i >> 1; + if (plm_header_ptr[v1] >= (uint16)FUNC16(PlmPreInstr_GotoLinkIfTriggered)) { + uint16 k = i; + uint16 v2 = item_bit_array[PrepareBitAccess(plm_room_arguments[v1])]; + i = k; + if ((bitmask & v2) == 0) { + CalculatePlmBlockCoords(k); + uint8 *v3 = RomPtr_84(kXrayBlockDrawingInstrs[plm_variables[k >> 1] >> 1]); + LoadBlockToXrayTilemap(*((uint16 *)v3 + 1) & 0xFFF, plm_x_block, plm_y_block); + i = k; + } + } + } + RoomDefRoomstate = get_RoomDefRoomstate(roomdefroomstate_ptr); + if (RoomDefRoomstate->xray_special_casing_ptr) { + for (j = RoomDefRoomstate->xray_special_casing_ptr; ; j += 4) { + uint8 *v6 = RomPtr_8F(j); + v7 = *(uint16 *)v6; + if (!*(uint16 *)v6) + break; + R18_ = (uint8)v7; + R20_ = v6[1]; + LoadBlockToXrayTilemap(*((uint16 *)v6 + 1), (uint8)v7, R20_); + } + } +} + +void EnablePLMs(void) { // 0x8483AD + plm_flag |= 0x8000u; +} + +void DisablePLMs(void) { // 0x8483B8 + plm_flag &= ~0x8000u; +} + +void ClearPLMs(void) { // 0x8483C3 + for (int i = 78; i >= 0; i -= 2) + plm_header_ptr[i >> 1] = 0; + plm_item_gfx_index = 0; +} + +uint8 CallPlmHeaderFunc(uint32 ea, uint16 j) { + switch (ea) { + case fnnullsub_67: + case fnnullsub_290: + case fnnullsub_68: + case fnnullsub_84BAFA: + case fnnullsub_71: + case fnnullsub_72: + case fnnullsub_69: return 0; + case fnPlmSetup_CrumbleBotwoonWall: return PlmSetup_CrumbleBotwoonWall(j); + case fnPlmSetup_SetrupWreckedShipEntrance: return PlmSetup_SetrupWreckedShipEntrance(j); + case fnPlmSetup_BTS_Brinstar_0x80_Floorplant: return PlmSetup_BTS_Brinstar_0x80_Floorplant(j); + case fnPlmSetup_BTS_Brinstar_0x81_Ceilingplant: return PlmSetup_BTS_Brinstar_0x81_Ceilingplant(j); + case fnPlmSetup_B6D3_MapStation: return PlmSetup_B6D3_MapStation(j); + case fnPlmSetup_Bts47_MapStationRightAccess: return PlmSetup_Bts47_MapStationRightAccess(j); + case fnPlmSetup_Bts4_MapStationLeftAccess: return PlmSetup_Bts4_MapStationLeftAccess(j); + case fnPlmSetup_PlmB6DF_EnergyStation: return PlmSetup_PlmB6DF_EnergyStation(j); + case fnPlmSetup_PlmB6EB_EnergyStation: return PlmSetup_PlmB6EB_EnergyStation(j); + case fnPlmSetup_B6E3_EnergyStationRightAccess: return PlmSetup_B6E3_EnergyStationRightAccess(j); + case fnPlmSetup_B6E7_EnergyStationLeftAccess: return PlmSetup_B6E7_EnergyStationLeftAccess(j); + case fnPlmSetup_B6EF_MissileStationRightAccess: return PlmSetup_B6EF_MissileStationRightAccess(j); + case fnPlmSetup_B6F3_MissileStationLeftAccess: return PlmSetup_B6F3_MissileStationLeftAccess(j); + case fnPlmSetup_B638_Rightwards_Extension: return PlmSetup_B638_Rightwards_Extension(j); + case fnPlmSetup_B63F_Leftwards_Extension: return PlmSetup_B63F_Leftwards_Extension(j); + case fnPlmSetup_B643_Downwards_Extension: return PlmSetup_B643_Downwards_Extension(j); + case fnPlmSetup_B647_Upwards_Extension: return PlmSetup_B647_Upwards_Extension(j); + case fnPlmSetup_B703_ScrollPLM: return PlmSetup_B703_ScrollPLM(j); + case fnPlmSetup_B707_SolidScrollPLM: return PlmSetup_B707_SolidScrollPLM(j); + case fnPlmSetup_B6FF_ScrollBlockTouch: return PlmSetup_B6FF_ScrollBlockTouch(j); + case fnPlmSetup_DeactivatePlm: return PlmSetup_DeactivatePlm(j); + case fnPlmSetup_ReturnCarryClear: return PlmSetup_ReturnCarryClear(j); + case fnPlmSetup_ReturnCarrySet: return PlmSetup_ReturnCarrySet(j); + case fnPlmSetup_D094_EnemyBreakableBlock: return PlmSetup_D094_EnemyBreakableBlock(j); + case fnUNUSED_sub_84B3E3: return UNUSED_sub_84B3E3(j); + case fnPlmSetup_B70F_IcePhysics: return PlmSetup_B70F_IcePhysics(j); + case fnPlmSetup_QuicksandSurface: return PlmSetup_QuicksandSurface(j); + case fnPlmSetup_B71F_SubmergingQuicksand: return PlmSetup_B71F_SubmergingQuicksand(j); + case fnPlmSetup_B723_SandfallsSlow: return PlmSetup_B723_SandfallsSlow(j); + case fnPlmSetup_B727_SandFallsFast: return PlmSetup_B727_SandFallsFast(j); + case fnPlmSetup_QuicksandSurfaceB: return PlmSetup_QuicksandSurfaceB(j); + case fnPlmSetup_B737_SubmergingQuicksand: return PlmSetup_B737_SubmergingQuicksand(j); + case fnPlmSetup_B73B_B73F_SandFalls: return PlmSetup_B73B_B73F_SandFalls(j); + case fnPlmSetup_ClearShitroidInvisibleWall: return PlmSetup_ClearShitroidInvisibleWall(j); + case fnPlmSetup_B767_ClearShitroidInvisibleWall: return PlmSetup_B767_ClearShitroidInvisibleWall(j); + case fnPlmSetup_B76B_SaveStationTrigger: return PlmSetup_B76B_SaveStationTrigger(j); + case fnPlmSetup_B76F_SaveStation: return PlmSetup_B76F_SaveStation(j); + case fnPlmSetup_MotherBrainRoomEscapeDoor: return PlmSetup_MotherBrainRoomEscapeDoor(j); + case fnPlmSetup_B7EB_EnableSoundsIn32Frames: return PlmSetup_B7EB_EnableSoundsIn32Frames(j); + case fnPlmSetup_SpeedBoosterEscape: return PlmSetup_SpeedBoosterEscape(j); + case fnPlmSetup_ShaktoolsRoom: return PlmSetup_ShaktoolsRoom(j); + case fnPlmSetup_B974: return PlmSetup_B974(j); + case fnPlmSetup_B9C1_CrittersEscapeBlock: return PlmSetup_B9C1_CrittersEscapeBlock(j); + case fnPlmSetup_B9ED_CrittersEscapeBlock: return PlmSetup_B9ED_CrittersEscapeBlock(j); + case fnsub_84B9F1: return sub_84B9F1(j); + case fnPlmSetup_BB30_CrateriaMainstreetEscape: return PlmSetup_BB30_CrateriaMainstreetEscape(j); + case fnPlmSetup_C806_LeftGreenGateTrigger: return PlmSetup_C806_LeftGreenGateTrigger(j); + case fnPlmSetup_C80A_RightGreenGateTrigger: return PlmSetup_C80A_RightGreenGateTrigger(j); + case fnPlmSetup_C80E_LeftRedGateTrigger: return PlmSetup_C80E_LeftRedGateTrigger(j); + case fnPlmSetup_C812_RightRedGateTrigger: return PlmSetup_C812_RightRedGateTrigger(j); + case fnPlmSetup_C81E_LeftYellowGateTrigger: return PlmSetup_C81E_LeftYellowGateTrigger(j); + case fnPlmSetup_C822_RightYellowGateTrigger: return PlmSetup_C822_RightYellowGateTrigger(j); + case fnPlmSetup_C816_LeftBlueGateTrigger: return PlmSetup_C816_LeftBlueGateTrigger(j); + case fnPlmSetup_C81A_RightBlueGateTrigger: return PlmSetup_C81A_RightBlueGateTrigger(j); + case fnPlmSetup_C82A_DownwardsClosedGate: return PlmSetup_C82A_DownwardsClosedGate(j); + case fnPlmSetup_C832_UpwardsClosedGate: return PlmSetup_C832_UpwardsClosedGate(j); + case fnPlmSetup_C826_DownwardsOpenGate: return PlmSetup_C826_DownwardsOpenGate(j); + case fnPlmSetup_C82E_UpwardsOpenGate: return PlmSetup_C82E_UpwardsOpenGate(j); + case fnPlmSetup_C836_DownwardsGateShootblock: return PlmSetup_C836_DownwardsGateShootblock(j); + case fnPlmSetup_C73A_UpwardsGateShootblock: return PlmSetup_C73A_UpwardsGateShootblock(j); + case fnPlmSetup_C794_GreyDoor: return PlmSetup_C794_GreyDoor(j); + case fnPlmSetup_Door_Colored: return PlmSetup_Door_Colored(j); + case fnPlmSetup_Door_Blue: return PlmSetup_Door_Blue(j); + case fnPlmSetup_Door_Strange: return PlmSetup_Door_Strange(j); + case fnPlmSetup_D028_D02C_Unused: return PlmSetup_D028_D02C_Unused(j); + case fnPlmSetup_RespawningSpeedBoostBlock: return PlmSetup_RespawningSpeedBoostBlock(j); + case fnPlmSetup_RespawningCrumbleBlock: return PlmSetup_RespawningCrumbleBlock(j); + case fnPlmSetup_RespawningShotBlock: return PlmSetup_RespawningShotBlock(j); + case fnPlmSetup_RespawningBombBlock: return PlmSetup_RespawningBombBlock(j); + case fnPlmSetup_RespawningBombBlock2: return PlmSetup_RespawningBombBlock2(j); + case fnPlmSetup_RespawningPowerBombBlock: return PlmSetup_RespawningPowerBombBlock(j); + case fnPlmSetup_D08C_SuperMissileBlockRespawning: return PlmSetup_D08C_SuperMissileBlockRespawning(j); + case fnPlmSetup_D08C_CrumbleBlock: return PlmSetup_D08C_CrumbleBlock(j); + case fnPlmSetup_D0DC_BreakableGrappleBlock: return PlmSetup_D0DC_BreakableGrappleBlock(j); + case fnPlmSetup_D0D8_SetVFlag: return PlmSetup_D0D8_SetVFlag(j); + case fnPlmSetup_D0D8_ClearVflag: return PlmSetup_D0D8_ClearVflag(j); + case fnPlmSetup_D0E8_GiveSamusDamage: return PlmSetup_D0E8_GiveSamusDamage(j); + case fnPlmSetup_D113_LowerNorfairChozoRoomPlug: return PlmSetup_D113_LowerNorfairChozoRoomPlug(j); + case fnPlmSetup_D127: return PlmSetup_D127(j); + case fnPlmSetup_D138: return PlmSetup_D138(j); + case fnPlmSetup_D6DA_LowerNorfairChozoHandTrigger: return PlmSetup_D6DA_LowerNorfairChozoHandTrigger(j); + case fnPlmSetup_MotherBrainGlass: return PlmSetup_MotherBrainGlass(j); + case fnPlmSetup_DeletePlmIfAreaTorizoDead: return PlmSetup_DeletePlmIfAreaTorizoDead(j); + case fnPlmSetup_MakeBllockChozoHandTrigger: return PlmSetup_MakeBllockChozoHandTrigger(j); + case fnPlmSetup_D6F2_WreckedShipChozoHandTrigger: return PlmSetup_D6F2_WreckedShipChozoHandTrigger(j); + case fnPlmSetup_D700_MakePlmAirBlock_Unused: return PlmSetup_D700_MakePlmAirBlock_Unused(j); + case fnPlmSetup_D704_AlteranateLowerNorfairChozoHand_Unused: return PlmSetup_D704_AlteranateLowerNorfairChozoHand_Unused(j); + case fnPlmSetup_D708_LowerNorfairChozoBlockUnused: return PlmSetup_D708_LowerNorfairChozoBlockUnused(j); + case fnPlmSetup_D70C_NoobTube: return PlmSetup_D70C_NoobTube(j); + case fnPlmSetup_EyeDoorEye: return PlmSetup_EyeDoorEye(j); + case fnPlmSetup_EyeDoor: return PlmSetup_EyeDoor(j); + case fnPlmSetup_SetMetroidRequiredClearState: return PlmSetup_SetMetroidRequiredClearState(j); + case fnPlmSetup_DraygonCannonFacingRight: return PlmSetup_DraygonCannonFacingRight(j); + case fnPlmSetup_DraygonCannonFacingDiagonalRight: return PlmSetup_DraygonCannonFacingDiagonalRight(j); + case fnPlmSetup_DraygonCannonFacingLeft: return PlmSetup_DraygonCannonFacingLeft(j); + case fnPlmSetup_DraygonCannonFacingDiagonalLeft: return PlmSetup_DraygonCannonFacingDiagonalLeft(j); + case fnPlmSetup_DraygonCannon: return PlmSetup_DraygonCannon(j); + case fnsub_84EE4D: return sub_84EE4D(j); + case fnsub_84EE52: return sub_84EE52(j); + case fnsub_84EE57: return sub_84EE57(j); + case fnsub_84EE5C: return sub_84EE5C(j); + case fnsub_84EE64: return sub_84EE64(j); + case fnsub_84EE77: return sub_84EE77(j); + case fnsub_84EE7C: return sub_84EE7C(j); + case fnsub_84EE81: return sub_84EE81(j); + case fnsub_84EE86: return sub_84EE86(j); + case fnsub_84EE8E: return sub_84EE8E(j); + case fnsub_84EEAB: return sub_84EEAB(j); + default: return Unreachable(); + } +} + +void SpawnHardcodedPlm(const void *p) { // 0x8483D7 + SpawnHardcodedPlmArgs *pp = (SpawnHardcodedPlmArgs *)p; + int16 v2; + PlmHeader_Size4 *PlmHeader_Size4; + + uint16 v1 = 78; + while (plm_header_ptr[v1 >> 1]) { + v1 -= 2; + if ((v1 & 0x8000u) != 0) { + return; + } + } + uint16 prod = Mult8x8(pp->field_1, room_width_in_blocks); + v2 = pp->field_0; + plm_block_indices[v1 >> 1] = 2 * (prod + v2); + uint16 v3 = pp->field_2; + plm_header_ptr[v1 >> 1] = v3; + int v4 = v1 >> 1; + plm_room_arguments[v4] = 0; + plm_variables[v4] = 0; + plm_pre_instrs[v4] = 0x8469; + plm_instr_list_ptrs[v4] = get_PlmHeader_Size4(v3)->instr_list_ptr; + plm_instruction_timer[v4] = 1; + plm_instruction_draw_ptr[v4] = addr_kDefaultPlmDrawInstruction; + plm_timers[v4] = 0; + plm_id = v1; + PlmHeader_Size4 = get_PlmHeader_Size4(v3); + CallPlmHeaderFunc(PlmHeader_Size4->func_ptr | 0x840000, v1); +} + +void SpawnRoomPLM(uint16 k) { // 0x84846A + RoomPlmEntry *rpe; + int16 x_block; + PlmHeader_Size4 *PlmHeader_Size4; + + uint16 v1 = 78; + while (plm_header_ptr[v1 >> 1]) { + v1 -= 2; + if ((v1 & 0x8000u) != 0) + return; + } + rpe = get_RoomPlmEntry(k); + uint16 prod = Mult8x8(rpe->y_block, room_width_in_blocks); + x_block = rpe->x_block; + int v4 = v1 >> 1; + plm_block_indices[v4] = 2 * (prod + x_block); + plm_room_arguments[v4] = rpe->plm_room_argument; + uint16 pp = rpe->plm_header_ptr_; + plm_header_ptr[v4] = rpe->plm_header_ptr_; + plm_variables[v4] = 0; + plm_pre_instrs[v4] = FUNC16(PlmPreInstr_Empty2); + plm_instr_list_ptrs[v4] = get_PlmHeader_Size4(pp)->instr_list_ptr; + plm_instruction_timer[v4] = 1; + plm_instruction_draw_ptr[v4] = addr_kDefaultPlmDrawInstruction; + plm_timers[v4] = 0; + plm_id = v1; + PlmHeader_Size4 = get_PlmHeader_Size4(pp); + CallPlmHeaderFunc(PlmHeader_Size4->func_ptr | 0x840000, v1); +} + +void PlmPreInstr_Empty2(void) { // 0x8484E6 + ; +} + +// returns bit 0 set if carry, 0x40 if ovf +uint8 SpawnPLM(uint16 a) { // 0x8484E7 + PlmHeader_Size4 *PlmHeader_Size4; + + uint16 v1 = 78; + while (plm_header_ptr[v1 >> 1]) { + v1 -= 2; + if ((v1 & 0x8000u) != 0) + return 0; + } + int v3 = v1 >> 1; + plm_block_indices[v3] = 2 * cur_block_index; + plm_header_ptr[v3] = a; + plm_pre_instrs[v3] = FUNC16(PlmPreInstr_Empty3); + plm_instr_list_ptrs[v3] = get_PlmHeader_Size4(a)->instr_list_ptr; + plm_instruction_timer[v3] = 1; + plm_instruction_draw_ptr[v3] = addr_kDefaultPlmDrawInstruction; + plm_timers[v3] = 0; + plm_room_arguments[v3] = 0; + plm_variables[v3] = 0; + plm_id = v1; + PlmHeader_Size4 = get_PlmHeader_Size4(a); + return CallPlmHeaderFunc(PlmHeader_Size4->func_ptr | 0x840000, v1); +} + +CoroutineRet PlmHandler_Async(void) { // 0x8485B4 + COROUTINE_BEGIN(coroutine_state_2, 0); + if ((plm_flag & 0x8000) == 0) + return kCoroutineNone; + plm_draw_tilemap_index = 0; + for (plm_id = 78; (plm_id & 0x8000) == 0; plm_id -= 2) { + if (!plm_header_ptr[plm_id >> 1]) + continue; + CallPlmPreInstr(plm_pre_instrs[plm_id >> 1] | 0x840000, plm_id); + if (--plm_instruction_timer[plm_id >> 1]) + continue; + uint16 v4, *v5; + v4 = plm_instr_list_ptrs[plm_id >> 1]; + while (1) { + v5 = (uint16 *)RomPtr_84(v4); + if ((*v5 & 0x8000u) == 0) + break; + R18_ = *v5; + v4 = CallPlmInstr(*v5 | 0x840000, v4 + 2, plm_id); + if (!v4) + goto NEXT_PLM; + // If the plm handler wanted to display a message, then display it. + if (queued_message_box_index != 0) { + plm_instr_list_ptrs[plm_id >> 1] = v4; + COROUTINE_AWAIT(1, DisplayMessageBox_Async(queued_message_box_index)); + queued_message_box_index = 0; + v4 = plm_instr_list_ptrs[plm_id >> 1]; + } + } + int v7; + v7 = plm_id >> 1; + plm_instruction_timer[v7] = v5[0]; + plm_instruction_draw_ptr[v7] = v5[1]; + plm_instr_list_ptrs[v7] = v4 + 4; + ProcessPlmDrawInstruction(plm_id); + CalculatePlmBlockCoords(plm_id); + DrawPlm(plm_id); +NEXT_PLM:; + } + plm_id = 0; + COROUTINE_END(0); +} + +#define fnPlmPreInstr_Empty4 0x848AA6 +void CallPlmPreInstr(uint32 ea, uint16 k) { + switch (ea) { + case fnPlmPreInstr_nullsub_60: return; + case fnPlmPreInstr_nullsub_301: return; + case fnPlmPreInstr_Empty: return; + case fnPlmPreInstr_Empty2: return; + case fnPlmPreInstr_Empty3: return; + case fnPlmPreInstr_Empty4: return; + case fnPlmPreInstr_Empty5: return; + case fnnullsub_351: return; + case fnnullsub_84BAFA: return; + case fnPlmSetup_BTS_Brinstar_0x80_Floorplant: PlmSetup_BTS_Brinstar_0x80_Floorplant(k); return; + case fnPlmSetup_BTS_Brinstar_0x81_Ceilingplant: PlmSetup_BTS_Brinstar_0x81_Ceilingplant(k); return; + case fnPlmPreInstr_B7EB_DecTimerEnableSoundsDeletePlm: PlmPreInstr_B7EB_DecTimerEnableSoundsDeletePlm(k); return; + case fnPlmPreInstr_WakeAndLavaIfBoosterCollected: PlmPreInstr_WakeAndLavaIfBoosterCollected(k); return; + case fnPlmPreInstr_WakePLMAndStartFxMotionSamusFarLeft: PlmPreInstr_WakePLMAndStartFxMotionSamusFarLeft(k); return; + case fnPlmPreInstr_AdvanceLavaSamusMovesLeft: PlmPreInstr_AdvanceLavaSamusMovesLeft(k); return; + case fnPlmPreInstr_ShaktoolsRoom: PlmPreInstr_ShaktoolsRoom(k); return; + case fnPlmPreInstr_OldTourianEscapeShaftEscape: PlmPreInstr_OldTourianEscapeShaftEscape(k); return; + case fnPlmPreInstr_EscapeRoomBeforeOldTourianEscapeShaft: PlmPreInstr_EscapeRoomBeforeOldTourianEscapeShaft(k); return; + case fnPlmPreInstr_WakePlmIfTriggered: PlmPreInstr_WakePlmIfTriggered(k); return; + case fnPlmPreInstr_WakePlmIfTriggeredOrSamusBelowPlm: PlmPreInstr_WakePlmIfTriggeredOrSamusBelowPlm(k); return; + case fnPlmPreInstr_WakePlmIfTriggeredOrSamusAbovePlm: PlmPreInstr_WakePlmIfTriggeredOrSamusAbovePlm(k); return; + case fnPlmPreInstr_DeletePlmAndSpawnTriggerIfBlockDestroyed: PlmPreInstr_DeletePlmAndSpawnTriggerIfBlockDestroyed(k); return; + case fnPlmPreInstr_IncrementRoomArgIfShotBySuperMissile: PlmPreInstr_IncrementRoomArgIfShotBySuperMissile(k); return; + case fnPlmPreInstr_WakePlmIfSamusHasBombs: PlmPreInstr_WakePlmIfSamusHasBombs(k); return; + case fnPlmPreInstr_WakePlmIfRoomArgumentDoorIsSet: PlmPreInstr_WakePlmIfRoomArgumentDoorIsSet(k); return; + case fnPlmPreInstr_GotoLinkIfShotWithSuperMissile: PlmPreInstr_GotoLinkIfShotWithSuperMissile(k); return; + case fnPlmPreInstr_GotoLinkIfTriggered: PlmPreInstr_GotoLinkIfTriggered(k); return; + case fnPlmPreInstr_WakeIfTriggered: PlmPreInstr_WakeIfTriggered(k); return; + case fnPlmPreInstr_GoToLinkInstrIfShot: PlmPreInstr_GoToLinkInstrIfShot(k); return; + case fnPlmPreInstr_GoToLinkInstrIfShotWithPowerBomb: PlmPreInstr_GoToLinkInstrIfShotWithPowerBomb(k); return; + case fnPlmPreInstr_GoToLinkInstrIfShotWithAnyMissile: PlmPreInstr_GoToLinkInstrIfShotWithAnyMissile(k); return; + case fnPlmPreInstr_GoToLinkInstrIfShotWithSuperMissile: PlmPreInstr_GoToLinkInstrIfShotWithSuperMissile(k); return; + case fnPlmPreInstr_GoToLinkInstruction: PlmPreInstr_GoToLinkInstruction(k); return; + case fnPlmPreInstr_PlayDudSound: PlmPreInstr_PlayDudSound(k); return; + case fnPlmPreInstr_GotoLinkIfBoss1Dead: PlmPreInstr_GotoLinkIfBoss1Dead(k); return; + case fnPlmPreInstr_GotoLinkIfMiniBossDead: PlmPreInstr_GotoLinkIfMiniBossDead(k); return; + case fnPlmPreInstr_GotoLinkIfTorizoDead: PlmPreInstr_GotoLinkIfTorizoDead(k); return; + case fnPlmPreInstr_GotoLinkIfEnemyDeathQuotaOk: PlmPreInstr_GotoLinkIfEnemyDeathQuotaOk(k); return; + case fnPlmPreInstr_GotoLinkIfTourianStatueFinishedProcessing: PlmPreInstr_GotoLinkIfTourianStatueFinishedProcessing(k); return; + case fnPlmPreInstr_GotoLinkIfCrittersEscaped: PlmPreInstr_GotoLinkIfCrittersEscaped(k); return; + case fnPlmPreInstr_PositionSamusAndInvincible: PlmPreInstr_PositionSamusAndInvincible(k); return; + case fnPlmPreInstr_WakeOnKeyPress: PlmPreInstr_WakeOnKeyPress(k); return; + case fnnullsub_359: return; + case fnnullsub_73: + case fnnullsub_74: + case fnnullsub_75: + case fnnullsub_76: + case fnnullsub_77: + case fnnullsub_78: + case fnnullsub_79: + case fnnullsub_80: + case fnnullsub_81: return; + case fnPlmPreInstr_SetMetroidsClearState_Ev0x10: PlmPreInstr_SetMetroidsClearState_Ev0x10(k); return; + case fnPlmPreInstr_SetMetroidsClearState_Ev0x11: PlmPreInstr_SetMetroidsClearState_Ev0x11(k); return; + case fnPlmPreInstr_SetMetroidsClearState_Ev0x12: PlmPreInstr_SetMetroidsClearState_Ev0x12(k); return; + case fnPlmPreInstr_SetMetroidsClearState_Ev0x13: PlmPreInstr_SetMetroidsClearState_Ev0x13(k); return; + default: Unreachable(); + } +} + +uint16 CallPlmInstr(uint32 ea, uint16 j, uint16 k) { + switch (ea) { + case fnPlmInstr_Sleep: return PlmInstr_Sleep(j, k); + case fnPlmInstr_Delete: return PlmInstr_Delete(j, k); + case fnPlmInstr_PreInstr: return PlmInstr_PreInstr(j, k); + case fnPlmInstr_ClearPreInstr: return PlmInstr_ClearPreInstr(j, k); + case fnPlmInstr_CallFunction: return PlmInstr_CallFunction(j, k); + case fnPlmInstr_Goto: return PlmInstr_Goto(j, k); + case fnPlmInstr_DecrementAndBranchNonzero: return PlmInstr_DecrementAndBranchNonzero(j, k); + case fnPlmInstr_SetTimer: return PlmInstr_SetTimer(j, k); + case fnPlmInstr_LoadItemPlmGfx: return PlmInstr_LoadItemPlmGfx(j, k); + case fnPlmInstr_CopyFromRamToVram: return PlmInstr_CopyFromRamToVram(j, k); + case fnPlmInstr_GotoIfBossBitSet: return PlmInstr_GotoIfBossBitSet(j, k); + case fnPlmInstr_GotoIfEventSet: return PlmInstr_GotoIfEventSet(j, k); + case fnPlmInstr_SetEvent: return PlmInstr_SetEvent(j, k); + case fnPlmInstr_GotoIfChozoSet: return PlmInstr_GotoIfChozoSet(j, k); + case fnPlmInstr_SetRoomChozoBit: return PlmInstr_SetRoomChozoBit(j, k); + case fnPlmInstr_GotoIfItemBitSet: return PlmInstr_GotoIfItemBitSet(j, k); + case fnPlmInstr_SetItemBit: return PlmInstr_SetItemBit(j, k); + case fnPlmInstr_PickupBeamAndShowMessage: return PlmInstr_PickupBeamAndShowMessage(j, k); + case fnPlmInstr_PickupEquipmentAndShowMessage: return PlmInstr_PickupEquipmentAndShowMessage(j, k); + case fnPlmInstr_PickupEquipmentAddGrappleShowMessage: return PlmInstr_PickupEquipmentAddGrappleShowMessage(j, k); + case fnPlmInstr_PickupEquipmentAddXrayShowMessage: return PlmInstr_PickupEquipmentAddXrayShowMessage(j, k); + case fnPlmInstr_CollectHealthEnergyTank: return PlmInstr_CollectHealthEnergyTank(j, k); + case fnPlmInstr_CollectHealthReserveTank: return PlmInstr_CollectHealthReserveTank(j, k); + case fnPlmInstr_CollectAmmoMissileTank: return PlmInstr_CollectAmmoMissileTank(j, k); + case fnPlmInstr_CollectAmmoSuperMissileTank: return PlmInstr_CollectAmmoSuperMissileTank(j, k); + case fnPlmInstr_CollectAmmoPowerBombTank: return PlmInstr_CollectAmmoPowerBombTank(j, k); + case fnPlmInstr_SetLinkReg: return PlmInstr_SetLinkReg(j, k); + case fnPlmInstr_Call: return PlmInstr_Call(j, k); + case fnPlmInstr_Return: return PlmInstr_Return(j, k); + case fnPlmInstr_GotoIfDoorBitSet: return PlmInstr_GotoIfDoorBitSet(j, k); + case fnPlmInstr_IncrementDoorHitCounterAndJGE: return PlmInstr_IncrementDoorHitCounterAndJGE(j, k); + case fnPlmInstr_IncrementArgumentAndJGE: return PlmInstr_IncrementArgumentAndJGE(j, k); + case fnPlmInstr_SetBTS: return PlmInstr_SetBTS(j, k); + case fnPlmInstr_DrawPlmBlock: return PlmInstr_DrawPlmBlock(j, k); + case fnPlmInstr_DrawPlmBlock_: return PlmInstr_DrawPlmBlock_(j, k); + case fnPlmInstr_ProcessAirScrollUpdate: return PlmInstr_ProcessAirScrollUpdate(j, k); + case fnPlmInstr_ProcessSolidScrollUpdate: return PlmInstr_ProcessSolidScrollUpdate(j, k); + case fnPlmInstr_QueueMusic: return PlmInstr_QueueMusic(j, k); + case fnPlmInstr_ClearMusicQueueAndQueueTrack: return PlmInstr_ClearMusicQueueAndQueueTrack(j, k); + case fnPlmInstr_QueueSfx1_Max6: return PlmInstr_QueueSfx1_Max6(j, k); + case fnPlmInstr_QueueSfx2_Max6: return PlmInstr_QueueSfx2_Max6(j, k); + case fnPlmInstr_QueueSfx3_Max6: return PlmInstr_QueueSfx3_Max6(j, k); + case fnPlmInstr_QueueSfx1_Max15: return PlmInstr_QueueSfx1_Max15(j, k); + case fnPlmInstr_QueueSfx2_Max15: return PlmInstr_QueueSfx2_Max15(j, k); + case fnPlmInstr_QueueSfx3_Max15: return PlmInstr_QueueSfx3_Max15(j, k); + case fnPlmInstr_QueueSfx1_Max3: return PlmInstr_QueueSfx1_Max3(j, k); + case fnPlmInstr_QueueSfx2_Max3: return PlmInstr_QueueSfx2_Max3(j, k); + case fnPlmInstr_QueueSfx_Max3: return PlmInstr_QueueSfx_Max3(j, k); + case fnPlmInstr_QueueSfx1_Max9: return PlmInstr_QueueSfx1_Max9(j, k); + case fnPlmInstr_QueueSfx2_Max9: return PlmInstr_QueueSfx2_Max9(j, k); + case fnPlmInstr_QueueSfx3_Max9: return PlmInstr_QueueSfx3_Max9(j, k); + case fnPlmInstr_QueueSfx1_Max1: return PlmInstr_QueueSfx1_Max1(j, k); + case fnPlmInstr_QueueSfx2_Max1: return PlmInstr_QueueSfx2_Max1(j, k); + case fnPlmInstr_QueueSfx3_Max1: return PlmInstr_QueueSfx3_Max1(j, k); + case fnPlmInstr_ActivateMapStation: return PlmInstr_ActivateMapStation(j, k); + case fnPlmInstr_ActivateEnergyStation: return PlmInstr_ActivateEnergyStation(j, k); + case fnPlmInstr_ActivateMissileStation: return PlmInstr_ActivateMissileStation(j, k); + case fnPlmInstr_ActivateSaveStationAndGotoIfNo: return PlmInstr_ActivateSaveStationAndGotoIfNo(j, k); + case fnPlmInstr_GotoIfSamusNear: return PlmInstr_GotoIfSamusNear(j, k); + case fnPlmInstr_MovePlmDownOneBlock: return PlmInstr_MovePlmDownOneBlock(j, k); + case fnPlmInstr_Scroll_0_1_Blue: return PlmInstr_Scroll_0_1_Blue(j, k); + case fnPlmInstr_MovePlmDownOneBlock_0: return PlmInstr_MovePlmDownOneBlock_0(j, k); + case fnPlmInstr_DealDamage_2: return PlmInstr_DealDamage_2(j, k); + case fnPlmInstr_GiveInvincibility: return PlmInstr_GiveInvincibility(j, k); + case fnPlmInstr_Draw0x38FramesOfRightTreadmill: return PlmInstr_Draw0x38FramesOfRightTreadmill(j, k); + case fnPlmInstr_Draw0x38FramesOfLeftTreadmill: return PlmInstr_Draw0x38FramesOfLeftTreadmill(j, k); + case fnPlmInstr_GotoIfSamusHealthFull: return PlmInstr_GotoIfSamusHealthFull(j, k); + case fnPlmInstr_GotoIfMissilesFull: return PlmInstr_GotoIfMissilesFull(j, k); + case fnPlmInstr_PlaceSamusOnSaveStation: return PlmInstr_PlaceSamusOnSaveStation(j, k); + case fnPlmInstr_DisplayGameSavedMessageBox: return PlmInstr_DisplayGameSavedMessageBox(j, k); + case fnPlmInstr_EnableMovementAndSetSaveStationUsed: return PlmInstr_EnableMovementAndSetSaveStationUsed(j, k); + case fnPlmInstr_JumpIfSamusHasNoBombs: return PlmInstr_JumpIfSamusHasNoBombs(j, k); + case fnPlmInstr_MovePlmRight4Blocks: return PlmInstr_MovePlmRight4Blocks(j, k); + case fnPlmInstr_ClearTrigger: return PlmInstr_ClearTrigger(j, k); + case fnPlmInstr_SpawnEnemyProjectile: return PlmInstr_SpawnEnemyProjectile(j, k); + case fnPlmInstr_WakeEnemyProjectileAtPlmPos: return PlmInstr_WakeEnemyProjectileAtPlmPos(j, k); + case fnPlmInstr_SetGreyDoorPreInstr: return PlmInstr_SetGreyDoorPreInstr(j, k); + case fnPlmInstr_FxBaseYPos_0x2D2: return PlmInstr_FxBaseYPos_0x2D2(j, k); + case fnPlmInstr_GotoIfRoomArgLess: return PlmInstr_GotoIfRoomArgLess(j, k); + case fnPlmInstr_SpawnFourMotherBrainGlass: return PlmInstr_SpawnFourMotherBrainGlass(j, k); + case fnPlmInstr_SpawnTorizoStatueBreaking: return PlmInstr_SpawnTorizoStatueBreaking(j, k); + case fnPlmInstr_QueueSong1MusicTrack: return PlmInstr_QueueSong1MusicTrack(j, k); + case fnPlmInstr_TransferWreckedShipChozoSpikesToSlopes: return PlmInstr_TransferWreckedShipChozoSpikesToSlopes(j, k); + case fnPlmInstr_TransferWreckedShipSlopesToChozoSpikes: return PlmInstr_TransferWreckedShipSlopesToChozoSpikes(j, k); + case fnPlmInstr_EnableWaterPhysics: return PlmInstr_EnableWaterPhysics(j, k); + case fnPlmInstr_SpawnN00bTubeCrackEnemyProjectile: return PlmInstr_SpawnN00bTubeCrackEnemyProjectile(j, k); + case fnPlmInstr_DiagonalEarthquake: return PlmInstr_DiagonalEarthquake(j, k); + case fnPlmInstr_Spawn10shardsAnd6n00bs: return PlmInstr_Spawn10shardsAnd6n00bs(j, k); + case fnPlmInstr_ShootEyeDoorProjectileWithProjectileArg: return PlmInstr_ShootEyeDoorProjectileWithProjectileArg(j, k); + case fnPlmInstr_SpawnEyeDoorSweatEnemyProjectile: return PlmInstr_SpawnEyeDoorSweatEnemyProjectile(j, k); + case fnPlmInstr_SpawnTwoEyeDoorSmoke: return PlmInstr_SpawnTwoEyeDoorSmoke(j, k); + case fnPlmInstr_SpawnEyeDoorSmokeProjectile: return PlmInstr_SpawnEyeDoorSmokeProjectile(j, k); + case fnPlmInstr_MoveUpAndMakeBlueDoorFacingRight: return PlmInstr_MoveUpAndMakeBlueDoorFacingRight(j, k); + case fnPlmInstr_MoveUpAndMakeBlueDoorFacingLeft: return PlmInstr_MoveUpAndMakeBlueDoorFacingLeft(j, k); + case fnPlmInstr_DamageDraygonTurret: return PlmInstr_DamageDraygonTurret(j, k); + case fnPlmInstr_DamageDraygonTurretFacingDownRight: return PlmInstr_DamageDraygonTurretFacingDownRight(j, k); + case fnPlmInstr_DamageDraygonTurretFacingUpRight: return PlmInstr_DamageDraygonTurretFacingUpRight(j, k); + case fnPlmInstr_DamageDraygonTurret2: return PlmInstr_DamageDraygonTurret2(j, k); + case fnPlmInstr_DamageDraygonTurretFacingDownLeft: return PlmInstr_DamageDraygonTurretFacingDownLeft(j, k); + case fnPlmInstr_DamageDraygonTurretFacingUpLeft: return PlmInstr_DamageDraygonTurretFacingUpLeft(j, k); + case fnPlmInstr_DrawItemFrame0: return PlmInstr_DrawItemFrame0(j, k); + case fnPlmInstr_DrawItemFrame1: return PlmInstr_DrawItemFrame1(j, k); + case fnPlmInstr_DrawItemFrame_Common: return PlmInstr_DrawItemFrame_Common(j, k); + case fnPlmInstr_ClearChargeBeamCounter: return PlmInstr_ClearChargeBeamCounter(j, k); + case fnPlmInstr_ABD6: return PlmInstr_ABD6(j, k); + case fnPlmInstr_E63B: return PlmInstr_E63B(j, k); + case fnPlmInstr_SetBtsTo1: return PlmInstr_SetBtsTo1(j, k); + case fnPlmInstr_DisableSamusControls: return PlmInstr_DisableSamusControls(j, k); + case fnPlmInstr_EnableSamusControls: return PlmInstr_EnableSamusControls(j, k); + default: return Unreachable(); + } +} + +static inline uint8_t *RomPtr_84orRAM(uint16_t addr) { + if (addr & 0x8000) { + return RomPtr(0x840000 | addr); + } else { + assert(addr < 0x2000); + return RomPtr_RAM(addr); + } +} + +void ProcessPlmDrawInstruction(uint16 v0) { // 0x84861E + int16 v4; + int16 v8; + int16 v9; + int16 v10; + uint16 v5; + + int v1 = v0 >> 1; + uint16 v2 = plm_instruction_draw_ptr[v1]; + R18_ = plm_block_indices[v1]; + uint16 v3 = R18_; + while (1) { + v4 = *(uint16 *)RomPtr_84orRAM(v2); + if (v4 < 0) { + R22_ = (uint8)v4; + v5 = v2 + 2; + do { + level_data[v3 >> 1] = *(uint16 *)RomPtr_84orRAM(v5); + v5 += 2; + v3 += room_width_in_blocks + room_width_in_blocks; + --R22_; + } while (R22_); + } else { + R22_ = (uint8)v4; + v5 = v2 + 2; + do { + level_data[v3 >> 1] = *(uint16 *)RomPtr_84orRAM(v5); + v5 += 2; + v3 += 2; + --R22_; + } while (R22_); + } + if (!*(uint16 *)RomPtr_84orRAM(v5)) + break; + uint16 v6 = v5 - 1; + uint8 *v7 = RomPtr_84orRAM(v6); + v8 = (int8)HIBYTE(*(uint16 *)v7); + R20_ = R18_ + 2 * v8; + LOBYTE(v8) = HIBYTE(*(uint16 *)(v7 + 1)); + if ((v8 & 0x80) == 0) { + v8 = (uint8)v8; + if ((uint8)v8) { + v10 = (uint8)v8; + v8 = 0; + do { + v8 += room_width_in_blocks; + --v10; + } while (v10); + } + } else { + v9 = -(v8 | 0xFF00); + v8 = 0; + do { + v8 -= room_width_in_blocks; + --v9; + } while (v9); + } + v3 = R20_ + 2 * v8; + v2 = v6 + 3; + } +} + +uint16 PlmInstr_Sleep(uint16 j, uint16 k) { // 0x8486B4 + plm_instr_list_ptrs[k >> 1] = j - 2; + return 0; +} + +uint16 PlmInstr_Delete(uint16 j, uint16 k) { // 0x8486BC + plm_header_ptr[k >> 1] = 0; + return 0; +} + +uint16 PlmInstr_PreInstr(uint16 j, uint16 k) { // 0x8486C1 + plm_pre_instrs[k >> 1] = *(uint16 *)RomPtr_84(j); + return j + 2; +} + +uint16 PlmInstr_ClearPreInstr(uint16 j, uint16 k) { // 0x8486CA + plm_pre_instrs[k >> 1] = FUNC16(PlmPreInstr_Empty); + return j; +} + +void CallPlmInstrFunc(uint32 ea) { + switch (ea) { + case fnVariaSuitPickup: VariaSuitPickup(); return; + case fnGravitySuitPickup: GravitySuitPickup(); return; + default: Unreachable(); + } +} + +uint16 PlmInstr_CallFunction(uint16 j, uint16 k) { // 0x84870B + uint8 *v2 = RomPtr_84(j); + copy24((LongPtr *)&R18_, (LongPtr *)v2); + CallPlmInstrFunc(Load24(&R18_)); + return j + 3; +} + +uint16 PlmInstr_Goto(uint16 j, uint16 k) { // 0x848724 + return *(uint16 *)RomPtr_84(j); +} + + +uint16 PlmInstr_DecrementAndBranchNonzero(uint16 j, uint16 k) { // 0x84873F + int v2 = k >> 1; + if (plm_timers[v2]-- == 1) + return j + 2; + else + return PlmInstr_Goto(j, k); +} + +uint16 PlmInstr_SetTimer(uint16 j, uint16 k) { // 0x84874E + *((uint8 *)plm_timers + k) = *RomPtr_84(j); + return j + 1; +} + +#define kPlmVramAddresses ((uint16*)RomPtr(0x8487cd)) +#define kPlmTileDataOffs ((uint16*)RomPtr(0x8487d5)) +#define kPlmStartingTileNumber ((uint16*)RomPtr(0x8487dd)) + +uint16 PlmInstr_LoadItemPlmGfx(uint16 j, uint16 k) { // 0x848764 + VramWriteEntry *v5; // r10 + + uint16 v2 = plm_item_gfx_index; + plm_variables[k >> 1] = plm_item_gfx_index; + plm_item_gfx_index = ((uint8)v2 + 2) & 6; + int v3 = v2 >> 1; + R18_ = kPlmVramAddresses[v3]; + R20_ = kPlmTileDataOffs[v3]; + R22_ = kPlmStartingTileNumber[v3]; + plm_item_gfx_ptrs[v3] = j; + uint16 v4 = vram_write_queue_tail; + v5 = gVramWriteEntry(vram_write_queue_tail); + v5->size = 256; + v5->src.addr = *(uint16 *)RomPtr_84(j); + *(uint16 *)&v5->src.bank = 137; + v5->vram_dst = R18_; + vram_write_queue_tail = v4 + 7; + uint16 result = j + 2; + uint16 v7 = R20_; + R24_ = R20_ + 16; + do { + *(uint16 *)((char *)&tile_table.tables[0].top_left + v7) = R22_ + (*RomPtr_84(result) << 10); + ++R22_; + ++result; + v7 += 2; + } while (v7 != R24_); + return result; +} + +uint16 PlmInstr_CopyFromRamToVram(uint16 j, uint16 k) { // 0x8487E5 + VramWriteEntry *v4; + + uint16 v2 = vram_write_queue_tail; + uint8 *v3 = RomPtr_84(j); + v4 = gVramWriteEntry(vram_write_queue_tail); + v4->size = *(uint16 *)v3; + v4->src.addr = *((uint16 *)v3 + 1); + *(VoidP *)((char *)&v4->src.addr + 1) = *(uint16 *)(v3 + 3); + v4->vram_dst = *(uint16 *)(v3 + 5); + vram_write_queue_tail = v2 + 7; + return j + 7; +} + +uint16 PlmInstr_GotoIfBossBitSet(uint16 j, uint16 k) { // 0x84880E + uint8 *v2 = RomPtr_84(j); + uint16 v3 = j + 1; + if (CheckBossBitForCurArea((uint8) * (uint16 *)v2)) + return PlmInstr_Goto(v3, k); + else + return v3 + 2; +} + +uint16 PlmInstr_GotoIfEventSet(uint16 j, uint16 k) { // 0x84882D + uint16 *v2 = (uint16 *)RomPtr_84(j); + uint16 v3 = j + 2; + if (CheckEventHappened(*v2)) + return PlmInstr_Goto(v3, k); + else + return v3 + 2; +} + +uint16 PlmInstr_SetEvent(uint16 j, uint16 k) { // 0x84883E + uint16 *v2 = (uint16 *)RomPtr_84(j); + SetEventHappened(*v2); + return j + 2; +} + +uint16 PlmInstr_GotoIfChozoSet(uint16 j, uint16 k) { // 0x848848 + int16 v3; + + int v2 = k >> 1; + v3 = plm_room_arguments[v2]; + int idx = PrepareBitAccess(v3); + if (v3 >= 0 && ((bitmask & room_chozo_bits[idx]) != 0)) + return PlmInstr_Goto(j, k); + else + return j + 2; +} + +uint16 PlmInstr_SetRoomChozoBit(uint16 j, uint16 k) { // 0x848865 + int16 v3; + + int v2 = k >> 1; + v3 = plm_room_arguments[v2]; + if (v3 >= 0) { + int idx = PrepareBitAccess(v3); + room_chozo_bits[idx] |= bitmask; + } + return j; +} + +uint16 PlmInstr_GotoIfItemBitSet(uint16 j, uint16 k) { // 0x84887C + int16 v2; + + v2 = plm_room_arguments[k >> 1]; + int idx = PrepareBitAccess(v2); + if (v2 >= 0 && (bitmask & item_bit_array[idx]) != 0) + return PlmInstr_Goto(j, k); + else + return j + 2; +} + +uint16 PlmInstr_SetItemBit(uint16 j, uint16 k) { // 0x848899 + int16 v2; + + v2 = plm_room_arguments[k >> 1]; + if (v2 >= 0) { + uint16 v3 = PrepareBitAccess(v2); + item_bit_array[v3] |= bitmask; + } + return j; +} + +uint16 PlmInstr_PickupBeamAndShowMessage(uint16 j, uint16 k) { // 0x8488B0 + uint8 *v2 = RomPtr_84(j); + collected_beams |= *(uint16 *)v2; + equipped_beams |= *(uint16 *)v2; + equipped_beams &= ~((2 * (uint8) * (uint16 *)v2) & 8); + equipped_beams &= ~((*(uint16 *)v2 >> 1) & 4); + UpdateBeamTilesAndPalette(); + PlayRoomMusicTrackAfterAFrames(0x168u); + uint8 *v3 = RomPtr_84(j); + DisplayMessageBox(v3[2]); + return j + 3; +} + +uint16 PlmInstr_PickupEquipmentAndShowMessage(uint16 j, uint16 k) { // 0x8488F3 + uint8 *v2 = RomPtr_84(j); + equipped_items |= *(uint16 *)v2; + collected_items |= *(uint16 *)v2; + PlayRoomMusicTrackAfterAFrames(0x168u); + DisplayMessageBox(v2[2]); + return j + 3; +} + +uint16 PlmInstr_PickupEquipmentAddGrappleShowMessage(uint16 j, uint16 k) { // 0x84891A + uint8 *v2 = RomPtr_84(j); + equipped_items |= *(uint16 *)v2; + collected_items |= *(uint16 *)v2; + AddGrappleToHudTilemap(); + PlayRoomMusicTrackAfterAFrames(0x168u); + DisplayMessageBox(5u); + return j + 2; +} + +uint16 PlmInstr_PickupEquipmentAddXrayShowMessage(uint16 j, uint16 k) { // 0x848941 + uint8 *v2 = RomPtr_84(j); + equipped_items |= *(uint16 *)v2; + collected_items |= *(uint16 *)v2; + AddXrayToHudTilemap(); + PlayRoomMusicTrackAfterAFrames(0x168u); + DisplayMessageBox(6u); + return j + 2; +} + +uint16 PlmInstr_CollectHealthEnergyTank(uint16 j, uint16 k) { // 0x848968 + samus_max_health += *(uint16 *)RomPtr_84(j); + samus_health = samus_max_health; + PlayRoomMusicTrackAfterAFrames(0x168u); + DisplayMessageBox(1u); + return j + 2; +} + +uint16 PlmInstr_CollectHealthReserveTank(uint16 j, uint16 k) { // 0x848986 + samus_max_reserve_health += *(uint16 *)RomPtr_84(j); + if (!reserve_health_mode) + ++reserve_health_mode; + PlayRoomMusicTrackAfterAFrames(0x168u); + DisplayMessageBox(0x19u); + return j + 2; +} + +uint16 PlmInstr_CollectAmmoMissileTank(uint16 j, uint16 k) { // 0x8489A9 + uint8 *v2 = RomPtr_84(j); + samus_max_missiles += *(uint16 *)v2; + samus_missiles += *(uint16 *)v2; + AddMissilesToHudTilemap(); + PlayRoomMusicTrackAfterAFrames(0x168u); + DisplayMessageBox(2u); + return j + 2; +} + +uint16 PlmInstr_CollectAmmoSuperMissileTank(uint16 j, uint16 k) { // 0x8489D2 + uint8 *v2 = RomPtr_84(j); + samus_max_super_missiles += *(uint16 *)v2; + samus_super_missiles += *(uint16 *)v2; + AddSuperMissilesToHudTilemap(); + PlayRoomMusicTrackAfterAFrames(0x168u); + DisplayMessageBox(3u); + return j + 2; +} + +uint16 PlmInstr_CollectAmmoPowerBombTank(uint16 j, uint16 k) { // 0x8489FB + uint8 *v2 = RomPtr_84(j); + samus_max_power_bombs += *(uint16 *)v2; + samus_power_bombs += *(uint16 *)v2; + AddPowerBombsToHudTilemap(); + PlayRoomMusicTrackAfterAFrames(0x168u); + DisplayMessageBox(4u); + return j + 2; +} + +uint16 PlmInstr_SetLinkReg(uint16 j, uint16 k) { // 0x848A24 + plm_instruction_list_link_reg[k >> 1] = *(uint16 *)RomPtr_84(j); + return j + 2; +} + +uint16 PlmInstr_Call(uint16 j, uint16 k) { // 0x848A2E + plm_instruction_list_link_reg[k >> 1] = j + 2; + return *(uint16 *)RomPtr_84(j); +} + +uint16 PlmInstr_Return(uint16 j, uint16 k) { // 0x848A3A + return plm_instruction_list_link_reg[k >> 1]; +} + +uint16 PlmInstr_GotoIfDoorBitSet(uint16 j, uint16 k) { // 0x848A72 + int16 v2; + + v2 = plm_room_arguments[k >> 1]; + if (sign16(v2)) + return j + 2; + int idx = PrepareBitAccess(v2); + if (v2 >= 0 && (bitmask & opened_door_bit_array[idx]) != 0) + return *(uint16 *)RomPtr_84(j); + else + return j + 2; +} + +uint16 PlmInstr_IncrementDoorHitCounterAndJGE(uint16 j, uint16 k) { // 0x848A91 + int16 v5; + + int v2 = k >> 1; + uint16 v3 = plm_variables[v2] + 1; + plm_variables[v2] = v3; + if ((uint8)v3 < *RomPtr_84(j)) + return j + 3; + v5 = plm_room_arguments[v2]; + if (v5 >= 0) { + int idx = PrepareBitAccess(v5); + v5 = bitmask | opened_door_bit_array[idx]; + opened_door_bit_array[idx] = v5; + v5 = WORD(opened_door_bit_array[idx]); + } + int v6 = k >> 1; + plm_room_arguments[v6] = v5 | 0x8000; + plm_pre_instrs[v6] = addr_PlmPreInstr_Empty4; + return PlmInstr_Goto(j + 1, k); +} + +uint16 PlmInstr_IncrementArgumentAndJGE(uint16 j, uint16 k) { // 0x848ACD + uint8 v2 = *((uint8 *)plm_room_arguments + k) + 1; + if (v2 >= *RomPtr_84(j)) { + int v4 = k >> 1; + plm_room_arguments[v4] = -1; + plm_pre_instrs[v4] = addr_locret_848AE0; + return PlmInstr_Goto(j + 1, k); + } else { + plm_room_arguments[k >> 1] = v2; + return j + 3; + } +} + +uint16 PlmInstr_SetBTS(uint16 j, uint16 k) { // 0x848AF1 + BTS[plm_block_indices[k >> 1] >> 1] = *RomPtr_84(j); + return j + 1; +} + +uint16 PlmInstr_DrawPlmBlock(uint16 j, uint16 k) { // 0x848B05 + return PlmInstr_DrawPlmBlock_(j, k); +} + +uint16 PlmInstr_DrawPlmBlock_(uint16 j, uint16 k) { // 0x848B17 + int v2 = k >> 1; + uint16 v3 = plm_variable[v2]; + level_data[plm_block_indices[v2] >> 1] = v3; + custom_draw_instr_plm_block = v3; + custom_draw_instr_num_blocks = 1; + custom_draw_instr_zero_terminator = 0; + plm_instruction_timer[v2] = 1; + plm_instruction_draw_ptr[v2] = ADDR16_OF_RAM(custom_draw_instr_num_blocks); + plm_instr_list_ptrs[v2] = j; + ProcessPlmDrawInstruction(k); + uint16 v4 = plm_id; + CalculatePlmBlockCoords(plm_id); + DrawPlm(v4); + return 0; +} + +uint16 PlmInstr_ProcessAirScrollUpdate(uint16 j, uint16 k) { // 0x848B55 + uint16 v4; + char *v5; + + int v2 = k >> 1; + plm_variable[v2] = 0; + uint16 v3 = plm_room_arguments[v2]; + HIBYTE(v4) = 0; + while (1) { + v5 = (char *)RomPtr_8F(v3); + if (*v5 < 0) + break; + LOBYTE(v4) = *v5; + scrolls[v4] = v5[1]; + v3 += 2; + } + uint16 result = j; + int v7 = plm_block_indices[k >> 1] >> 1; + level_data[v7] = level_data[v7] & 0xFFF | 0x3000; + return result; +} + +uint16 PlmInstr_ProcessSolidScrollUpdate(uint16 j, uint16 k) { // 0x848B93 + uint16 v4; + char *v5; + + int v2 = k >> 1; + plm_variable[v2] = 0; + uint16 v3 = plm_room_arguments[v2]; + HIBYTE(v4) = 0; + while (1) { + v5 = (char *)RomPtr_8F(v3); + if (*v5 < 0) + break; + LOBYTE(v4) = *v5; + scrolls[v4] = v5[1]; + v3 += 2; + } + uint16 result = j; + int v7 = plm_block_indices[k >> 1] >> 1; + level_data[v7] = level_data[v7] & 0xFFF | 0xB000; + return result; +} + +uint16 PlmInstr_QueueMusic(uint16 j, uint16 k) { // 0x848BD1 + uint8 *v2 = RomPtr_84(j); + QueueMusic_Delayed8(*v2); + return j + 1; +} + +uint16 PlmInstr_ClearMusicQueueAndQueueTrack(uint16 j, uint16 k) { // 0x848BDD + for (int i = 14; i >= 0; i -= 2) { + int v3 = i >> 1; + music_queue_track[v3] = 0; + music_queue_delay[v3] = 0; + } + music_queue_read_pos = music_queue_write_pos; + music_timer = 0; + music_entry = 0; + uint8 *v4 = RomPtr_84(j); + QueueMusic_Delayed8(*v4); + return j + 1; +} + +uint16 PlmInstr_QueueSfx1_Max6(uint16 j, uint16 k) { // 0x848C07 + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx1_Max6(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx2_Max6(uint16 j, uint16 k) { // 0x848C10 + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx2_Max6(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx3_Max6(uint16 j, uint16 k) { // 0x848C19 + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx3_Max6(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx1_Max15(uint16 j, uint16 k) { // 0x848C22 + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx1_Max15(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx2_Max15(uint16 j, uint16 k) { // 0x848C2B + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx2_Max15(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx3_Max15(uint16 j, uint16 k) { // 0x848C34 + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx3_Max15(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx1_Max3(uint16 j, uint16 k) { // 0x848C3D + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx1_Max3(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx2_Max3(uint16 j, uint16 k) { // 0x848C46 + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx2_Max3(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx_Max3(uint16 j, uint16 k) { // 0x848C4F + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx3_Max3(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx1_Max9(uint16 j, uint16 k) { // 0x848C58 + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx1_Max9(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx2_Max9(uint16 j, uint16 k) { // 0x848C61 + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx2_Max9(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx3_Max9(uint16 j, uint16 k) { // 0x848C6A + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx3_Max9(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx1_Max1(uint16 j, uint16 k) { // 0x848C73 + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx1_Max1(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx2_Max1(uint16 j, uint16 k) { // 0x848C7C + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx2_Max1(*v2); + return j + 1; +} + +uint16 PlmInstr_QueueSfx3_Max1(uint16 j, uint16 k) { // 0x848C85 + uint16 *v2 = (uint16 *)RomPtr_84(j); + QueueSfx3_Max1(*v2); + return j + 1; +} + +uint16 PlmInstr_ActivateMapStation(uint16 j, uint16 k) { // 0x848C8F + *(uint16 *)&map_station_byte_array[area_index] |= 0xFFu; + DisplayMessageBox(0x14u); + has_area_map = 1; + return j; +} + +uint16 PlmInstr_ActivateEnergyStation(uint16 j, uint16 k) { // 0x848CAF + if (samus_max_health != samus_health) { + DisplayMessageBox(0x15u); + samus_health = samus_max_health; + } + CallSomeSamusCode(1u); + return j; +} + +uint16 PlmInstr_ActivateMissileStation(uint16 j, uint16 k) { // 0x848CD0 + if (samus_max_missiles != samus_missiles) { + DisplayMessageBox(0x16u); + samus_missiles = samus_max_missiles; + } + CallSomeSamusCode(1u); + return j; +} + +uint16 PlmInstr_ActivateSaveStationAndGotoIfNo(uint16 j, uint16 k) { // 0x848CF1 + int r = DisplayMessageBox_Poll(23); + if (r < 0) + return j - 2; // restart plm instr + + if (r == 2) + return *(uint16 *)RomPtr_84(j); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_SaveStationElectricity, 0); + load_station_index = plm_room_arguments[plm_id >> 1] & 7; + PrepareBitAccess(load_station_index); + used_save_stations_and_elevators[(uint16)(2 * area_index)] |= bitmask; + SaveToSram(selected_save_slot); + return j + 2; +} + +uint16 PlmInstr_GotoIfSamusNear(uint16 j, uint16 k) { // 0x848D41 + uint8 v4; + + CalculatePlmBlockCoords(k); + uint8 v2 = abs16((samus_x_pos >> 4) - plm_x_block); + uint8 *v3 = RomPtr_84(j); + if ((v2 < *v3 || v2 == *v3) && (v4 = abs16((samus_y_pos >> 4) - plm_y_block), v4 < v3[1] || v4 == v3[1])) + return *((uint16 *)v3 + 1); + else + return j + 4; +} + +void DrawPlm(uint16 k) { // 0x848DAA + int16 v2; + int16 v5; + int16 v8; + VramWriteEntry *v10; + VoidP v12; + VoidP v13; + VramWriteEntry *v15; + int16 v18; + int16 v20; + bool v23; // sf + VramWriteEntry *v25; + int16 v28; + int16 v31; + int16 v33; + uint16 v35; + uint16 a; + + *(uint16 *)((char *)&R8_ + 1) = addr_unk_605000; + R12_ = addr_unk_6053E0; + uint16 v1 = plm_instruction_draw_ptr[k >> 1]; + g_word_7E001E = plm_x_block; + R32 = plm_y_block; +LABEL_2: + R26_ = layer1_y_pos >> 4; + if (!sign16((layer1_y_pos >> 4) + 15 - R32)) { + v2 = *(uint16 *)RomPtr_84orRAM(v1); + if (v2 < 0) { + R20_ = v2 & 0x7FFF; + if (layer1_x_pos >> 4 == g_word_7E001E || (int16)((layer1_x_pos >> 4) - g_word_7E001E) < 0) { + v20 = (layer1_x_pos >> 4) + 17; + if (v20 != g_word_7E001E && (int16)(v20 - g_word_7E001E) >= 0) { + R24_ = g_word_7E001E; + R18_ = 0; + R22_ = R26_ + 16; + if ((int16)(R26_ - R32) < 0) { + R26_ = R32; + } else { + R18_ = R26_ - R32; + if (sign16(R32 + R20_ - R26_)) + return; + bool v21 = R20_ == R18_; + bool v22 = (int16)(R20_ - R18_) < 0; + R20_ -= R18_; + while (v22) + ; + if (v21) + return; + } + R22_ = R20_ + R26_ - R22_; + if ((R22_ & 0x8000u) != 0 || (v23 = (int16)(R20_ - R22_) < 0, (R20_ -= R22_) != 0) && !v23) { + v35 = k; + uint16 v24; + v24 = vram_write_queue_tail; + if ((int16)(vram_write_queue_tail - 240) < 0 + && !sign16(((uint16)(512 - plm_draw_tilemap_index) >> 3) - R20_)) { + R28_ = 0x8000; + CalculatePlmDrawTilemapVramDst(vram_write_queue_tail); + v25 = gVramWriteEntry(v24); + v25[1].vram_dst = v25->vram_dst + 1; + vram_write_queue_tail = v24 + 14; + R18_ *= 2; + R3_.addr = R18_ + v1 + 2; + uint16 v26; + v26 = 0; + while (1) { + g_word_7E001E = *(uint16 *)RomPtr_84orRAM(R3_.addr); + uint16 v27, v29; + v27 = g_word_7E001E & 0x3FF; + v28 = g_word_7E001E & 0xC00; + if ((g_word_7E001E & 0xC00) != 0) { + if (v28 == 1024) { + IndirWriteWord(&R0_, v26, tile_table.tables[v27].top_right ^ 0x4000); + IndirWriteWord(&R6_, v26, tile_table.tables[v27].top_left ^ 0x4000); + v29 = v26 + 2; + IndirWriteWord(&R0_, v29, tile_table.tables[v27].bottom_right ^ 0x4000); + IndirWriteWord(&R6_, v29, tile_table.tables[v27].bottom_left ^ 0x4000); + } else if (v28 == 2048) { + IndirWriteWord(&R0_, v26, tile_table.tables[v27].bottom_left ^ 0x8000); + IndirWriteWord(&R6_, v26, tile_table.tables[v27].bottom_right ^ 0x8000); + v29 = v26 + 2; + IndirWriteWord(&R0_, v29, tile_table.tables[v27].top_left ^ 0x8000); + IndirWriteWord(&R6_, v29, tile_table.tables[v27].top_right ^ 0x8000); + } else { + IndirWriteWord(&R0_, v26, tile_table.tables[v27].bottom_right ^ 0xC000); + IndirWriteWord(&R6_, v26, tile_table.tables[v27].bottom_left ^ 0xC000); + v29 = v26 + 2; + IndirWriteWord(&R0_, v29, tile_table.tables[v27].top_right ^ 0xC000); + IndirWriteWord(&R6_, v29, tile_table.tables[v27].top_left ^ 0xC000); + } + } else { + IndirWriteWord(&R0_, v26, tile_table.tables[v27].top_left); + IndirWriteWord(&R6_, v26, tile_table.tables[v27].top_right); + v29 = v26 + 2; + IndirWriteWord(&R0_, v29, tile_table.tables[v27].bottom_left); + IndirWriteWord(&R6_, v29, tile_table.tables[v27].bottom_right); + } + v26 = v29 + 2; + ++R3_.addr; + ++R3_.addr; + plm_draw_tilemap_index += 8; + if (!sign16(plm_draw_tilemap_index - 512)) + break; + if (!--R20_) { +LABEL_70: + k = v35; + uint16 addr = R3_.addr; + if ((R22_ & 0x8000u) == 0) + addr = R3_.addr + 2 * R22_; + v31 = *(uint16 *)RomPtr_84orRAM(addr); + if (v31) { + v31 = (uint8)v31; + if ((v31 & 0x80) != 0) + v31 |= 0xFF00u; + g_word_7E001E = plm_x_block + v31; + uint16 v32 = addr + 1; + v33 = *RomPtr_84orRAM(v32); + if ((v33 & 0x80) != 0) + v33 |= 0xFF00u; + R32 = plm_y_block + v33; + v1 = v32 + 1; + goto LABEL_2; + } + return; + } + } + } + } + } + } + } else { + R20_ = v2 & 0x7FFF; + R28_ = 0; + if (sign16(R32 - R26_)) + return; + R26_ = R32; + R18_ = 0; + R24_ = g_word_7E001E; + R22_ = ((uint16)(layer1_x_pos + 15) >> 4) - 1; + if ((int16)(R22_ - g_word_7E001E) >= 0 && R22_ != g_word_7E001E) { + R18_ = R22_ - g_word_7E001E; + if (g_word_7E001E + R20_ == R22_ || (int16)(g_word_7E001E + R20_ - R22_) < 0) + return; + R20_ -= R18_; + R24_ = R22_; + } + R22_ += 17; + if (!sign16(R22_ - g_word_7E001E)) { + R22_ = R20_ + R24_ - 1 - R22_; + if ((R22_ & 0x8000u) != 0 || (R20_ -= R22_) != 0) { + v35 = k; + uint16 v3 = vram_write_queue_tail; + if ((int16)(vram_write_queue_tail - 480) < 0 + && !sign16(((uint16)(512 - plm_draw_tilemap_index) >> 3) - R20_)) { + uint16 prod = (R26_ & 0xF) * 0x40; + uint16 v4 = R24_ & 0x1F; + if (v4 >= 0x10u) { + v8 = R12_ + 2 * v4; + a = prod + v8; + if ((bg1_x_offset & 0x100) != 0) + a -= 1024; + } else { + v5 = *(uint16 *)((char *)&R8_ + 1) + 2 * v4; + uint16 RegWord = prod; + a = RegWord + v5; + if ((bg1_x_offset & 0x100) != 0) + a += 1024; + } + g_word_7E001E = 2 * R20_; + R34 = a & 0x1F; + if (((2 * R20_ + (a & 0x1F) - 1) & 0xFFE0) != 0) { + if ((int16)(v3 - 228) >= 0 || (int16)(32 - R34) < 0) + return; + uint16 v9 = 2 * (32 - R34); + v10 = gVramWriteEntry(v3); + v10->size = v9; + v10[2].size = v9; + v10->vram_dst = a; + v10[1].vram_dst = a & 0xFFE0 ^ 0x400; + v10[3].vram_dst = v10[1].vram_dst + 32; + v10[2].vram_dst = v10->vram_dst + 32; + g_word_7E001E = 4 * R20_; + uint16 v11 = 4 * R20_ - v10->size; + v10[1].size = v11; + v10[3].size = v11; + v12 = plm_draw_tilemap_index - 14648; + v10->src.addr = plm_draw_tilemap_index - 14648; + R0_.addr = v12; + v13 = v10->size + v12; + v10[1].src.addr = v13; + uint16 v14 = v10[1].size + v13; + v10[2].src.addr = v14; + R6_ = v14; + v10[3].src.addr = v10[2].size + v14; + v10->src.bank = 126; + R0_.bank = 126; + v10[1].src.bank = 126; + LOBYTE(R8_) = 126; + v10[2].src.bank = 126; + v10[3].src.bank = 126; + vram_write_queue_tail = v3 + 28; + } else { + PartiallyQueueVramForSingleScreenPlm(a, v3); + v15 = gVramWriteEntry(v3); + v15[1].vram_dst = v15->vram_dst + 32; + vram_write_queue_tail = v3 + 14; + } + R18_ *= 2; + R3_.addr = R18_ + v1 + 2; + uint16 v16 = 0; + while (1) { + g_word_7E001E = *(uint16 *)RomPtr_84orRAM(R3_.addr); + uint16 v17 = g_word_7E001E & 0x3FF, v19; + v18 = g_word_7E001E & 0xC00; + if ((g_word_7E001E & 0xC00) != 0) { + if (v18 == 1024) { + IndirWriteWord(&R0_, v16, tile_table.tables[v17].top_right ^ 0x4000); + IndirWriteWord(&R6_, v16, tile_table.tables[v17].bottom_right ^ 0x4000); + v19 = v16 + 2; + IndirWriteWord(&R0_, v19, tile_table.tables[v17].top_left ^ 0x4000); + IndirWriteWord(&R6_, v19, tile_table.tables[v17].bottom_left ^ 0x4000); + } else if (v18 == 2048) { + IndirWriteWord(&R0_, v16, tile_table.tables[v17].bottom_left ^ 0x8000); + IndirWriteWord(&R6_, v16, tile_table.tables[v17].top_left ^ 0x8000); + v19 = v16 + 2; + IndirWriteWord(&R0_, v19, tile_table.tables[v17].bottom_right ^ 0x8000); + IndirWriteWord(&R6_, v19, tile_table.tables[v17].top_right ^ 0x8000); + } else { + IndirWriteWord(&R0_, v16, tile_table.tables[v17].bottom_right ^ 0xC000); + IndirWriteWord(&R6_, v16, tile_table.tables[v17].top_right ^ 0xC000); + v19 = v16 + 2; + IndirWriteWord(&R0_, v19, tile_table.tables[v17].bottom_left ^ 0xC000); + IndirWriteWord(&R6_, v19, tile_table.tables[v17].top_left ^ 0xC000); + } + } else { + IndirWriteWord(&R0_, v16, tile_table.tables[v17].top_left); + IndirWriteWord(&R6_, v16, tile_table.tables[v17].bottom_left); + v19 = v16 + 2; + IndirWriteWord(&R0_, v19, tile_table.tables[v17].top_right); + IndirWriteWord(&R6_, v19, tile_table.tables[v17].bottom_right); + } + v16 = v19 + 2; + ++R3_.addr; + ++R3_.addr; + plm_draw_tilemap_index += 8; + if (!sign16(plm_draw_tilemap_index - 512)) + break; + if (!--R20_) + goto LABEL_70; + } + } + } + } + } + } +} + + +void CalculatePlmDrawTilemapVramDst(uint16 k) { // 0x8491DC + int16 v2; + int16 v5; + uint16 a; + + uint16 prod = (R26_ & 0xF) * 0x40; + uint16 v1 = R24_ & 0x1F; + if (v1 >= 0x10u) { + v5 = R12_ + 2 * v1; + uint16 RegWord = prod; + a = RegWord + v5; + if ((bg1_x_offset & 0x100) != 0) + a -= 1024; + } else { + v2 = *(uint16 *)((char *)&R8_ + 1) + 2 * v1; + uint16 v3 = prod; + a = v3 + v2; + if ((bg1_x_offset & 0x100) != 0) + a += 1024; + } + PartiallyQueueVramForSingleScreenPlm(a, k); +} + +void PartiallyQueueVramForSingleScreenPlm(uint16 a, uint16 k) { // 0x849220 + VramWriteEntry *v2; + VoidP v4; + + v2 = gVramWriteEntry(k); + v2->vram_dst = R28_ | a; + uint16 v3 = 4 * R20_; + v2->size = 4 * R20_; + v2[1].size = v3; + v4 = plm_draw_tilemap_index - 14648; + v2->src.addr = plm_draw_tilemap_index - 14648; + R0_.addr = v4; + uint16 v5 = v2->size + v4; + v2[1].src.addr = v5; + R6_ = v5; + v2->src.bank = 126; + v2[1].src.bank = 126; + R0_.bank = 126; + LOBYTE(R8_) = 126; +} + +uint16 PlmInstr_MovePlmDownOneBlock(uint16 j, uint16 k) { // 0x84AB00 + plm_block_indices[k >> 1] += 2 * room_width_in_blocks; + return j; +} + +uint8 PlmSetup_CrumbleBotwoonWall(uint16 j) { // 0x84AB28 + plm_instruction_timer[j >> 1] = 64; + return 0; +} + +uint16 PlmInstr_Scroll_0_1_Blue(uint16 j, uint16 k) { // 0x84AB51 + *(uint16 *)scrolls = 257; + return j; +} + +uint16 PlmInstr_MovePlmDownOneBlock_0(uint16 j, uint16 k) { // 0x84AB59 + plm_block_indices[k >> 1] += room_width_in_blocks + + room_width_in_blocks; + return j; +} + +uint16 PlmInstr_ABD6(uint16 j, uint16 k) { // 0x84ABD6 + int v1 = k >> 1; + ++plm_block_indices[v1]; + ++plm_block_indices[v1]; + return j; +} + +void PlmPreInstr_PositionSamusAndInvincible(uint16 k) { // 0x84AC89 + int v1 = k >> 1; + samus_x_pos = plm_variable[v1]; + samus_y_pos = plm_variables[v1]; + samus_invincibility_timer |= 0x10u; +} + +uint16 PlmInstr_DealDamage_2(uint16 j, uint16 k) { // 0x84AC9D + samus_periodic_damage += 2; + return j; +} + +uint16 PlmInstr_GiveInvincibility(uint16 j, uint16 k) { // 0x84ACB1 + samus_invincibility_timer = 48; + return j; +} + +uint16 PlmInstr_Draw0x38FramesOfRightTreadmill(uint16 j, uint16 k) { // 0x84AD43 + WriteRowOfLevelDataBlockAndBTS(k, 0x30ff, 0x8, 0x38); + return j; +} + +uint16 PlmInstr_Draw0x38FramesOfLeftTreadmill(uint16 j, uint16 k) { // 0x84AD58 + WriteRowOfLevelDataBlockAndBTS(k, 0x30ff, 0x9, 0x38); + return j; +} + +uint16 PlmInstr_GotoIfSamusHealthFull(uint16 j, uint16 k) { // 0x84AE35 + if (samus_max_health != samus_health) + return j + 2; + CallSomeSamusCode(1u); + return *(uint16 *)RomPtr_84(j); +} + +uint16 PlmInstr_GotoIfMissilesFull(uint16 j, uint16 k) { // 0x84AEBF + if (samus_max_missiles != samus_missiles) + return j + 2; + CallSomeSamusCode(1u); + return *(uint16 *)RomPtr_84(j); +} + +uint16 PlmInstr_PlaceSamusOnSaveStation(uint16 j, uint16 k) { // 0x84B00E + samus_x_pos = (samus_x_pos + 8) & 0xFFF0; + MakeSamusFaceForward(); + return j; +} + +uint16 PlmInstr_DisplayGameSavedMessageBox(uint16 j, uint16 k) { // 0x84B024 + DisplayMessageBox(0x18u); + return j; +} + +uint16 PlmInstr_EnableMovementAndSetSaveStationUsed(uint16 j, uint16 k) { // 0x84B030 + CallSomeSamusCode(1u); + save_station_lockout_flag = 1; + return j; +} + +uint8 PlmSetup_SetrupWreckedShipEntrance(uint16 j) { // 0x84B04A + int16 v2; + + uint16 v1 = plm_block_indices[j >> 1]; + v2 = 56; + do { + level_data[v1 >> 1] = 255; + v1 += 2; + --v2; + } while (v2); + return 0; +} + +uint8 PlmSetup_BTS_Brinstar_0x80_Floorplant(uint16 j) { // 0x84B0DC + if ((((uint8)samus_y_radius + (uint8)samus_y_pos - 1) & 0xF) == 15) { + int v1 = plm_block_indices[j >> 1] >> 1; + level_data[v1] &= 0x8FFFu; + int v2 = j >> 1; + plm_variable[v2] = samus_x_pos; + plm_variables[v2] = samus_y_pos - 1; + } else { + plm_header_ptr[j >> 1] = 0; + } + return 0; +} + +uint8 PlmSetup_BTS_Brinstar_0x81_Ceilingplant(uint16 j) { // 0x84B113 + if ((((uint8)samus_y_pos - (uint8)samus_y_radius) & 0xF) != 0) { + plm_header_ptr[j >> 1] = 0; + } else { + int v1 = plm_block_indices[j >> 1] >> 1; + level_data[v1] &= 0x8FFFu; + int v2 = j >> 1; + plm_variable[v2] = samus_x_pos; + plm_variables[v2] = samus_y_pos + 1; + } + return 0; +} + +uint8 ActivateStationIfSamusCannonLinedUp(uint16 a, uint16 j) { // 0x84B146 + uint16 v2 = 78; + while (a != plm_block_indices[v2 >> 1]) { + v2 -= 2; + if ((v2 & 0x8000u) != 0) + goto LABEL_7; + } + CalculatePlmBlockCoords(plm_id); + if (((uint16)(16 * plm_y_block) | 0xB) == samus_y_pos) { + int v3 = v2 >> 1; + plm_instr_list_ptrs[v3] = plm_instruction_list_link_reg[v3]; + plm_instruction_timer[v3] = 1; + CallSomeSamusCode(6u); + return 1; + } +LABEL_7: + plm_header_ptr[j >> 1] = 0; + return 1; +} + +uint8 PlmSetup_B6D3_MapStation(uint16 j) { // 0x84B18B + int v1 = j >> 1; + int v2 = plm_block_indices[v1] >> 1; + level_data[v2] = level_data[v2] & 0xFFF | 0x8000; + if (map_station_byte_array[area_index]) { + plm_instr_list_ptrs[v1] = addr_word_84AD76; + } else { + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] + 2, 0xB047u); + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] - 4, 0xB048u); + } + return 0; +} + +uint8 PlmSetup_Bts47_MapStationRightAccess(uint16 j) { // 0x84B1C8 + if ((samus_collision_direction & 0xF) == 0 && samus_pose == kPose_8A_FaceL_Ranintowall && (samus_pose_x_dir & 4) != 0) + return ActivateStationIfSamusCannonLinedUp(plm_block_indices[j >> 1] - 2, j); + plm_header_ptr[j >> 1] = 0; + return 1; +} + +uint8 PlmSetup_Bts4_MapStationLeftAccess(uint16 j) { // 0x84B1F0 + if ((samus_collision_direction & 0xF) == 1 && samus_pose == kPose_89_FaceR_Ranintowall && (samus_pose_x_dir & 8) != 0) + return ActivateStationIfSamusCannonLinedUp(plm_block_indices[j >> 1] + 4, j); + plm_header_ptr[j >> 1] = 0; + return 1; +} + +uint8 PlmSetup_PlmB6DF_EnergyStation(uint16 j) { // 0x84B21D + int v1 = j >> 1; + int v2 = plm_block_indices[v1] >> 1; + level_data[v2] = level_data[v2] & 0xFFF | 0x8000; + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] + 2, 0xB049u); + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] - 2, FUNC16(PlmSetup_SetrupWreckedShipEntrance)); + return 0; +} + +uint8 PlmSetup_PlmB6EB_EnergyStation(uint16 j) { // 0x84B245 + int v1 = j >> 1; + int v2 = plm_block_indices[v1] >> 1; + level_data[v2] = level_data[v2] & 0xFFF | 0x8000; + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] + 2, 0xB04Bu); + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] - 2, 0xB04Cu); + return 0; +} + +uint8 PlmSetup_B6E3_EnergyStationRightAccess(uint16 j) { // 0x84B26D + if ((samus_collision_direction & 0xF) != 0 + || samus_pose != kPose_8A_FaceL_Ranintowall + || (samus_pose_x_dir & 4) == 0 + || samus_health == samus_max_health) { + plm_header_ptr[j >> 1] = 0; + return 1; + } else { + return ActivateStationIfSamusCannonLinedUp(plm_block_indices[j >> 1] - 2, j); + } +} + +uint8 PlmSetup_B6E7_EnergyStationLeftAccess(uint16 j) { // 0x84B29D + if ((samus_collision_direction & 0xF) == 1 + && samus_pose == kPose_89_FaceR_Ranintowall + && (samus_pose_x_dir & 8) != 0 + && samus_health != samus_max_health) { + return ActivateStationIfSamusCannonLinedUp(plm_block_indices[j >> 1] + 2, j); + } + plm_header_ptr[j >> 1] = 0; + return 1; +} + +uint8 PlmSetup_B6EF_MissileStationRightAccess(uint16 j) { // 0x84B2D0 + if ((samus_collision_direction & 0xF) != 0 + || samus_pose != kPose_8A_FaceL_Ranintowall + || (samus_pose_x_dir & 4) == 0 + || samus_missiles == samus_max_missiles) { + plm_header_ptr[j >> 1] = 0; + return 1; + } + return ActivateStationIfSamusCannonLinedUp(plm_block_indices[j >> 1] - 2, j); +} + +uint8 PlmSetup_B6F3_MissileStationLeftAccess(uint16 j) { // 0x84B300 + if ((samus_collision_direction & 0xF) == 1 + && samus_pose == kPose_89_FaceR_Ranintowall + && (samus_pose_x_dir & 8) != 0 + && samus_missiles != samus_max_missiles) { + return ActivateStationIfSamusCannonLinedUp(plm_block_indices[j >> 1] + 2, j); + } else { + plm_header_ptr[j >> 1] = 0; + return 1; + } +} + +void DeletePlm(uint16 j) { // 0x84B333 + plm_header_ptr[j >> 1] = 0; +} + +uint8 PlmSetup_B638_Rightwards_Extension(uint16 j) { // 0x84B33A + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0x50FFu); + DeletePlm(j); + return 0; +} + +uint8 PlmSetup_B63F_Leftwards_Extension(uint16 j) { // 0x84B345 + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0x5001u); + DeletePlm(j); + return 0; +} + +uint8 PlmSetup_B643_Downwards_Extension(uint16 j) { // 0x84B350 + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0xD0FFu); + DeletePlm(j); + return 0; +} + +uint8 PlmSetup_B647_Upwards_Extension(uint16 j) { // 0x84B35B + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0xD001u); + DeletePlm(j); + return 0; +} + +void SkipDebugDrawInstructionsForScrollPlms(uint16 j) { // 0x84B366 + plm_instr_list_ptrs[j >> 1] += 4; +} + +uint8 PlmSetup_B703_ScrollPLM(uint16 j) { // 0x84B371 + int v1 = j >> 1; + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1], 0x3046u); + plm_variable[v1] = 0; + SkipDebugDrawInstructionsForScrollPlms(j); + return 0; +} + +uint8 PlmSetup_B707_SolidScrollPLM(uint16 j) { // 0x84B382 + int v1 = j >> 1; + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1], 0xB046u); + plm_variable[v1] = 0; + SkipDebugDrawInstructionsForScrollPlms(j); + return 0; +} + +uint8 PlmSetup_B6FF_ScrollBlockTouch(uint16 j) { // 0x84B393 + int v1 = j >> 1; + uint16 v2 = plm_block_indices[v1]; + plm_block_indices[v1] = 0; + uint16 v3 = 78; + while (v2 != plm_block_indices[v3 >> 1]) { + v3 -= 2; + if ((v3 & 0x8000u) != 0) { + while (1) + ; + } + } + int v4 = v3 >> 1; + if ((plm_variable[v4] & 0x8000u) == 0) { + plm_variable[v4] = 0x8000; + ++plm_instr_list_ptrs[v4]; + ++plm_instr_list_ptrs[v4]; + plm_instruction_timer[v4] = 1; + } + return 0; +} + +uint8 PlmSetup_DeactivatePlm(uint16 j) { // 0x84B3C1 + int v1 = plm_block_indices[j >> 1] >> 1; + level_data[v1] &= 0x8FFFu; + return 0; +} + +uint8 PlmSetup_ReturnCarryClear(uint16 j) { // 0x84B3D0 + return 0; +} + +uint8 PlmSetup_ReturnCarrySet(uint16 j) { // 0x84B3D2 + return 1; +} + +uint8 PlmSetup_D094_EnemyBreakableBlock(uint16 j) { // 0x84B3D4 + int v1 = plm_block_indices[j >> 1] >> 1; + level_data[v1] &= 0xFFFu; + return 0; +} + +uint8 UNUSED_sub_84B3E3(uint16 j) { // 0x84B3E3 + assert(0); + return 0; +} + +uint8 PlmSetup_B70F_IcePhysics(uint16 j) { // 0x84B3EB + if ((((uint8)samus_y_radius + (uint8)samus_y_pos - 1) & 0xF) == 7 + || (((uint8)samus_y_radius + (uint8)samus_y_pos - 1) & 0xF) == 15) { + *(uint16 *)&samus_x_decel_mult = 16; + } + return 0; +} + +static Func_Y_V *const kPlmSetup_QuicksandSurface[4] = { // 0x84B408 + PlmSetup_QuicksandSurface_0, + PlmSetup_QuicksandSurface_1, + PlmSetup_QuicksandSurface_2, + PlmSetup_QuicksandSurface_0, +}; + +static const uint16 g_word_84B48B[2] = { 0x200, 0x200 }; +static const uint16 g_word_84B48F[2] = { 0x120, 0x100 }; +static const uint16 g_word_84B493[2] = { 0x280, 0x380 }; + +uint8 PlmSetup_QuicksandSurface(uint16 j) { + + samus_has_momentum_flag = 0; + speed_boost_counter = 0; + samus_echoes_sound_flag = 0; + samus_x_extra_run_subspeed = 0; + samus_x_extra_run_speed = 0; + samus_x_base_subspeed &= ~0x8000u; + samus_x_base_speed = 0; + uint16 v1 = 0; + if ((equipped_items & 0x20) != 0) + v1 = 2; + if (!inside_block_reaction_samus_point) + kPlmSetup_QuicksandSurface[samus_y_dir & 3](v1); + return 0; +} + +void PlmSetup_QuicksandSurface_0(uint16 j) { // 0x84B447 + samus_y_subspeed = 0; + samus_y_speed = 0; + extra_samus_y_subdisplacement = 0; + extra_samus_y_displacement = 0; + *(uint16 *)((char *)&extra_samus_y_subdisplacement + 1) = g_word_84B48F[j >> 1]; +} + +void PlmSetup_QuicksandSurface_1(uint16 j) { // 0x84B45A + int v1 = j >> 1; + if (g_word_84B493[v1] < *(uint16 *)((char *)&samus_y_subspeed + 1)) { + samus_y_subspeed = 0; + samus_y_speed = 0; + *(uint16 *)((char *)&samus_y_subspeed + 1) = g_word_84B493[v1]; + } + extra_samus_y_subdisplacement = 0; + extra_samus_y_displacement = 0; + *(uint16 *)((char *)&extra_samus_y_subdisplacement + 1) = g_word_84B48B[v1]; +} + +void PlmSetup_QuicksandSurface_2(uint16 j) { // 0x84B47B + extra_samus_y_subdisplacement = 0; + extra_samus_y_displacement = 0; + *(uint16 *)((char *)&extra_samus_y_subdisplacement + 1) = g_word_84B48B[j >> 1]; + autojump_timer = 0; +} + +uint8 PlmSetup_B71F_SubmergingQuicksand(uint16 j) { // 0x84B497 + autojump_timer = 0; + extra_samus_y_subdisplacement = 0x2000; + extra_samus_y_displacement = 1; + return 0; +} + +uint8 PlmSetup_B723_SandfallsSlow(uint16 j) { // 0x84B4A8 + extra_samus_y_subdisplacement = 0x4000; + extra_samus_y_displacement = 1; + return 0; +} + +uint8 PlmSetup_B727_SandFallsFast(uint16 j) { // 0x84B4B6 + extra_samus_y_subdisplacement = -16384; + extra_samus_y_displacement = 1; + return 0; +} + +static Func_Y_U8 *const kPlmSetup_QuicksandSurfaceB[4] = { // 0x84B4C4 + PlmSetup_QuicksandSurfaceB_0, + PlmSetup_QuicksandSurfaceB_1, + PlmSetup_QuicksandSurfaceB_2, + PlmSetup_QuicksandSurfaceB_0, +}; + +uint8 PlmSetup_QuicksandSurfaceB(uint16 j) { + + if ((samus_collision_direction & 2) == 0) + return 0; + + uint16 v1 = 0; + if ((equipped_items & 0x20) != 0) + v1 = 2; + uint16 v2 = R18_; + R18_ = R20_; + R20_ = v2; + uint8 rv = kPlmSetup_QuicksandSurfaceB[samus_y_dir & 3](v1); + uint16 v3 = R18_; + R18_ = R20_; + R20_ = v3; + return rv; +} + +uint8 PlmSetup_QuicksandSurfaceB_0(uint16 j) { // 0x84B500 + static const uint16 word_84B53D[2] = { + 0x30, + 0x30, + }; + if ((samus_collision_direction & 0xF) == 3) { + if (samus_contact_damage_index == 1) { + R18_ = 0; + R20_ = 0; + return 1; + } else { + if (word_84B53D[j >> 1] < *(uint16 *)((char *)&R18_ + 1)) + *(uint16 *)((char *)&R18_ + 1) = word_84B53D[j >> 1]; + ++flag_samus_in_quicksand; + } + } + return 0; +} + +uint8 PlmSetup_QuicksandSurfaceB_1(uint16 j) { // 0x84B528 + return 0; +} + +uint8 PlmSetup_QuicksandSurfaceB_2(uint16 j) { // 0x84B52A + if (samus_contact_damage_index == 1) { + R18_ = 0; + R20_ = 0; + return 1; + } else { + flag_samus_in_quicksand++; + return 0; + } +} + + +uint8 PlmSetup_B737_SubmergingQuicksand(uint16 j) { // 0x84B541 + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_subaccel = 0; + samus_y_accel = 0; + return 0; +} + +uint8 PlmSetup_B73B_B73F_SandFalls(uint16 j) { // 0x84B54F + return 0; +} + +uint8 PlmSetup_ClearShitroidInvisibleWall(uint16 j) { // 0x84B551 + int16 v2; + + uint16 v1 = plm_block_indices[j >> 1]; + v2 = 10; + do { + level_data[v1 >> 1] &= 0xFFFu; + v1 += room_width_in_blocks + room_width_in_blocks; + --v2; + } while (v2); + return 0; +} + +uint8 PlmSetup_B767_ClearShitroidInvisibleWall(uint16 j) { // 0x84B56F + int16 v2; + + uint16 v1 = plm_block_indices[j >> 1]; + v2 = 10; + do { + level_data[v1 >> 1] = level_data[v1 >> 1] & 0xFFF | 0x8000; + v1 += room_width_in_blocks + room_width_in_blocks; + --v2; + } while (v2); + return 0; +} + +uint8 PlmSetup_B76B_SaveStationTrigger(uint16 j) { // 0x84B590 + if (!power_bomb_explosion_status + && (samus_pose == kPose_01_FaceR_Normal || samus_pose == kPose_02_FaceL_Normal) + && !save_station_lockout_flag + && (samus_collision_direction & 0xF) == 3) { + CalculatePlmBlockCoords(j); + if ((uint16)(samus_x_pos - 8) >> 4 == plm_x_block) { + int v1 = j >> 1; + uint16 v2 = plm_block_indices[v1]; + plm_block_indices[v1] = 0; + plm_header_ptr[v1] = 0; + uint16 v3 = 78; + while (v2 != plm_block_indices[v3 >> 1]) { + v3 -= 2; + if ((v3 & 0x8000u) != 0) + return 1; + } + int v4 = v3 >> 1; + ++plm_instr_list_ptrs[v4]; + ++plm_instr_list_ptrs[v4]; + plm_instruction_timer[v4] = 1; + } + } + return 1; +} + +uint8 PlmSetup_B76F_SaveStation(uint16 j) { // 0x84B5EE + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0xB04Du); + return 0; +} + +uint8 PlmSetup_MotherBrainRoomEscapeDoor(uint16 j) { // 0x84B5F8 + uint16 v1 = plm_block_indices[j >> 1]; + WriteLevelDataBlockTypeAndBts(v1, 0x9001u); + uint16 v2 = room_width_in_blocks + room_width_in_blocks + v1; + WriteLevelDataBlockTypeAndBts(v2, 0xD0FFu); + uint16 v3 = room_width_in_blocks + room_width_in_blocks + v2; + WriteLevelDataBlockTypeAndBts(v3, 0xD0FFu); + WriteLevelDataBlockTypeAndBts( + room_width_in_blocks + room_width_in_blocks + v3, + 0xD0FFu); + return 0; +} + +uint8 PlmSetup_B7EB_EnableSoundsIn32Frames(uint16 j) { // 0x84B7C3 + uint16 v1; + if (area_index == 6) + v1 = 32; + else + v1 = 240; + int v2 = j >> 1; + plm_timers[v2] = v1; + plm_pre_instrs[v2] = FUNC16(PlmPreInstr_B7EB_DecTimerEnableSoundsDeletePlm); + return 0; +} + +void PlmPreInstr_B7EB_DecTimerEnableSoundsDeletePlm(uint16 k) { // 0x84B7DD + int v2 = k >> 1; + if (plm_timers[v2]-- == 1) { + debug_disable_sounds = 0; + plm_header_ptr[v2] = 0; + } +} + +void PlmPreInstr_WakeAndLavaIfBoosterCollected(uint16 k) { // 0x84B7EF + if ((collected_items & 0x2000) != 0) { + if ((fx_target_y_pos & 0x8000u) != 0) { + plm_header_ptr[k >> 1] = 0; + } else { + fx_y_vel = -128; + int v1 = k >> 1; + plm_instruction_timer[v1] = 1; + ++plm_instr_list_ptrs[v1]; + ++plm_instr_list_ptrs[v1]; + plm_timers[v1] = 0; + } + } else { + fx_target_y_pos = -1; + fx_y_vel = 0; + fx_timer = 0; + earthquake_timer = 0; + plm_header_ptr[k >> 1] = 0; + } +} + +void PlmPreInstr_WakePLMAndStartFxMotionSamusFarLeft(uint16 k) { // 0x84B82A + if (samus_x_pos <= 0xAE0u) { + fx_timer = 1; + int v1 = k >> 1; + plm_instruction_timer[v1] = 1; + ++plm_instr_list_ptrs[v1]; + ++plm_instr_list_ptrs[v1]; + plm_timers[v1] = 0; + } +} + +void PlmPreInstr_AdvanceLavaSamusMovesLeft(uint16 k) { // 0x84B846 + static const uint16 g_word_84B876[10] = { + 0x72b, 0x1bf, + 0xff50, 0x50a, + 0x167, 0xff20, + 0x244, 0x100, + 0xff20, 0x8000, + }; + + + int v1 = k >> 1; + uint16 v2 = plm_timers[v1]; + int v3 = v2 >> 1; + uint16 v4 = g_word_84B876[v3]; + if ((v4 & 0x8000u) != 0) { + SetEventHappened(0x15u); + } else if (v4 >= samus_x_pos) { + if (g_word_84B876[v3 + 1] < fx_base_y_pos) + fx_base_y_pos = g_word_84B876[v3 + 1]; + fx_y_vel = g_word_84B876[v3 + 2]; + plm_timers[v1] = v2 + 6; + } +} + +uint8 PlmSetup_SpeedBoosterEscape(uint16 j) { // 0x84B89C + if (CheckEventHappened(0x15u)) + plm_header_ptr[j >> 1] = 0; + return 0; +} + +void PlmPreInstr_ShaktoolsRoom(uint16 k) { // 0x84B8B0 + if (power_bomb_explosion_status) { + *(uint16 *)scrolls = 257; + *(uint16 *)&scrolls[2] = 257; + } + if (samus_x_pos > 0x348u) { + SetEventHappened(0xDu); + plm_header_ptr[k >> 1] = 0; + } +} + +uint8 PlmSetup_ShaktoolsRoom(uint16 j) { // 0x84B8DC + *(uint16 *)scrolls = 1; + *(uint16 *)&scrolls[2] = 0; + return 0; +} + +uint8 WakePlmIfSamusIsBelowAndRightOfTarget(uint16 k) { // 0x84B8FD + uint8 v1 = R18_ >= samus_x_pos; + if (R18_ < samus_x_pos) { + v1 = R20_ >= samus_y_pos; + if (R20_ < samus_y_pos) { + v1 = k & 1; + int v2 = k >> 1; + ++plm_instr_list_ptrs[v2]; + ++plm_instr_list_ptrs[v2]; + plm_instruction_timer[v2] = 1; + } + } + return v1; +} + +void PlmPreInstr_OldTourianEscapeShaftEscape(uint16 k) { // 0x84B927 + R18_ = 240; + R20_ = 2080; + if (!WakePlmIfSamusIsBelowAndRightOfTarget(k)) + SpawnEnemyProjectileWithRoomGfx(0xB4B1u, 0); +} + +void PlmPreInstr_EscapeRoomBeforeOldTourianEscapeShaft(uint16 k) { // 0x84B948 + R18_ = 240; + R20_ = 1344; + if (!WakePlmIfSamusIsBelowAndRightOfTarget(k)) { + fx_y_vel = -104; + fx_timer = 16; + } +} + +uint8 PlmSetup_B974(uint16 j) { // 0x84B96C + R38 = 0; + R40 = -1; + return 0; +} + +uint8 PlmSetup_B9C1_CrittersEscapeBlock(uint16 j) { // 0x84B978 + if (projectile_type[projectile_index >> 1]) { + int v1 = j >> 1; + int v2 = plm_block_indices[v1] >> 1; + uint16 v3 = level_data[v2] & 0xF000 | 0x9F; + plm_variable[v1] = v3; + level_data[v2] = v3 & 0x8FFF; + } else { + plm_header_ptr[j >> 1] = 0; + } + return 0; +} + +uint16 PlmInstr_SetCrittersEscapedEvent(uint16 j, uint16 k) { // 0x84B9B9 + SetEventHappened(0xFu); + return j; +} + +uint8 PlmSetup_B9ED_CrittersEscapeBlock(uint16 j) { // 0x84B9C5 + uint16 v1 = plm_block_indices[j >> 1]; + WriteLevelDataBlockTypeAndBts(v1, 0xC04Fu); + uint16 v2 = room_width_in_blocks + room_width_in_blocks + v1; + WriteLevelDataBlockTypeAndBts(v2, 0xD0FFu); + WriteLevelDataBlockTypeAndBts( + room_width_in_blocks + room_width_in_blocks + v2, + 0xD0FFu); + return 0; +} + +uint8 sub_84B9F1(uint16 j) { // 0x84B9F1 + uint16 v1 = plm_block_indices[j >> 1]; + level_data[v1 >> 1] = level_data[v1 >> 1] & 0xFFF | 0x8000; + uint16 v2 = room_width_in_blocks + room_width_in_blocks + v1; + level_data[v2 >> 1] = level_data[v2 >> 1] & 0xFFF | 0x8000; + uint16 v3 = room_width_in_blocks + room_width_in_blocks + v2; + level_data[v3 >> 1] = level_data[v3 >> 1] & 0xFFF | 0x8000; + int v4 = (uint16)(room_width_in_blocks + room_width_in_blocks + v3) >> 1; + level_data[v4] = level_data[v4] & 0xFFF | 0x8000; + return 0; +} + +uint16 PlmInstr_JumpIfSamusHasNoBombs(uint16 j, uint16 k) { // 0x84BA6F + if ((collected_items & 0x1000) != 0) + return j + 2; + else + return *(uint16 *)RomPtr_84(j); +} + +void UNUSED_sub_84BAD1(uint16 j) { // 0x84BAD1 + int v1 = j >> 1; + plm_variable[v1] = 4; + plm_room_arguments[v1] = plm_room_arguments[v1] & 0x3FF | 0x8000; + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1], 0xC044u); +} + +uint8 PlmSetup_BB30_CrateriaMainstreetEscape(uint16 j) { // 0x84BB09 + if (!CheckEventHappened(0xFu)) + plm_header_ptr[j >> 1] = 0; + return 0; +} + +uint16 PlmInstr_MovePlmRight4Blocks(uint16 j, uint16 k) { // 0x84BB25 + plm_block_indices[k >> 1] += 8; + return j; +} + +void PlmPreInstr_WakePlmIfTriggered(uint16 k) { // 0x84BB52 + int v1 = k >> 1; + if (plm_timers[v1]) { + ++plm_instr_list_ptrs[v1]; + ++plm_instr_list_ptrs[v1]; + plm_instruction_timer[v1] = 1; + plm_pre_instrs[v1] = addr_locret_84BB6A; + } +} + +void PlmPreInstr_WakePlmIfTriggeredOrSamusBelowPlm(uint16 k) { // 0x84BB6B + CalculatePlmBlockCoords(k); + if (samus_x_pos >> 4 == plm_x_block && (uint16)((samus_y_pos >> 4) - plm_y_block) < 5u + || plm_timers[k >> 1]) { + int v1 = k >> 1; + ++plm_instr_list_ptrs[v1]; + ++plm_instr_list_ptrs[v1]; + plm_instruction_timer[v1] = 1; + plm_pre_instrs[v1] = FUNC16(PlmPreInstr_Empty5); + } +} + +void PlmPreInstr_WakePlmIfTriggeredOrSamusAbovePlm(uint16 k) { // 0x84BBA4 + CalculatePlmBlockCoords(k); + if (samus_x_pos >> 4 == plm_x_block && (uint16)((samus_y_pos >> 4) - plm_y_block) >= 0xFFFCu + || plm_timers[k >> 1]) { + int v1 = k >> 1; + ++plm_instr_list_ptrs[v1]; + ++plm_instr_list_ptrs[v1]; + plm_instruction_timer[v1] = 1; + plm_pre_instrs[v1] = addr_locret_84BBDC; + } +} + +uint16 PlmInstr_ClearTrigger(uint16 j, uint16 k) { // 0x84BBDD + plm_timers[k >> 1] = 0; + return j; +} + +uint16 PlmInstr_SpawnEnemyProjectile(uint16 j, uint16 k) { // 0x84BBE1 + uint16 *v2 = (uint16 *)RomPtr_84(j); + SpawnEnemyProjectileWithRoomGfx(*v2, *v2); + return j + 2; +} + +uint16 PlmInstr_WakeEnemyProjectileAtPlmPos(uint16 j, uint16 k) { // 0x84BBF0 + int i; + + uint16 v2 = plm_block_indices[k >> 1]; + for (i = 34; i >= 0; i -= 2) { + if (v2 == enemy_projectile_E[i >> 1]) + break; + } + int v4 = i >> 1; + enemy_projectile_instr_timers[v4] = 1; + ++enemy_projectile_instr_list_ptr[v4]; + ++enemy_projectile_instr_list_ptr[v4]; + return j + 2; +} + +void PlmPreInstr_GoToLinkInstrIfShot(uint16 k) { // 0x84BD0F + int v2 = k >> 1; + if (plm_timers[v2]) { + plm_timers[v2] = 0; + plm_instr_list_ptrs[v2] = plm_instruction_list_link_reg[v2]; + plm_instruction_timer[v2] = 1; + } +} + +void PlmPreInstr_GoToLinkInstrIfShotWithPowerBomb(uint16 k) { // 0x84BD26 + int v2 = k >> 1; + uint16 v3 = plm_timers[v2]; + if (v3) { + if ((v3 & 0xF00) == 768) { + plm_timers[v2] = 0; + plm_instr_list_ptrs[v2] = plm_instruction_list_link_reg[v2]; + plm_instruction_timer[v2] = 1; + return; + } + QueueSfx2_Max6(0x57u); + } + plm_timers[v2] = 0; +} + +void PlmPreInstr_GoToLinkInstrIfShotWithAnyMissile(uint16 k) { // 0x84BD50 + int16 v3; + + uint16 v2 = plm_timers[k >> 1]; + if (v2) { + v3 = v2 & 0xF00; + if (v3 == 512) { + plm_variables[k >> 1] = 119; + goto LABEL_4; + } + if (v3 == 256) { +LABEL_4:; + int v4 = k >> 1; + plm_timers[v4] = 0; + plm_instr_list_ptrs[v4] = plm_instruction_list_link_reg[v4]; + plm_instruction_timer[v4] = 1; + return; + } + QueueSfx2_Max6(0x57u); + } + plm_timers[k >> 1] = 0; +} + +void PlmPreInstr_GoToLinkInstrIfShotWithSuperMissile(uint16 k) { // 0x84BD88 + int v2 = k >> 1; + uint16 v3 = plm_timers[v2]; + if (v3) { + if ((v3 & 0xF00) == 512) { + plm_timers[v2] = 0; + plm_instr_list_ptrs[v2] = plm_instruction_list_link_reg[v2]; + plm_instruction_timer[v2] = 1; + return; + } + QueueSfx2_Max6(0x57u); + } + plm_timers[v2] = 0; +} + +void PlmPreInstr_GoToLinkInstruction(uint16 k) { // 0x84BDB2 + int v2 = k >> 1; + plm_timers[v2] = 0; + plm_instr_list_ptrs[v2] = plm_instruction_list_link_reg[v2]; + plm_instruction_timer[v2] = 1; +} + +void PlmPreInstr_PlayDudSound(uint16 k) { // 0x84BE1C + int v2 = k >> 1; + if (plm_timers[v2]) + QueueSfx2_Max6(0x57u); + plm_timers[v2] = 0; +} + +void PlmPreInstr_GotoLinkIfBoss1Dead(uint16 k) { // 0x84BDD4 + if (CheckBossBitForCurArea(1u) & 1) + PlmPreInstr_GoToLinkInstruction(k); + else + PlmPreInstr_PlayDudSound(k); +} + +void PlmPreInstr_GotoLinkIfMiniBossDead(uint16 k) { // 0x84BDE3 + if (CheckBossBitForCurArea(2u) & 1) + PlmPreInstr_GoToLinkInstruction(k); + else + PlmPreInstr_PlayDudSound(k); +} + +void PlmPreInstr_GotoLinkIfTorizoDead(uint16 k) { // 0x84BDF2 + if (CheckBossBitForCurArea(4u) & 1) + PlmPreInstr_GoToLinkInstruction(k); + else + PlmPreInstr_PlayDudSound(k); +} + +void PlmPreInstr_GotoLinkIfEnemyDeathQuotaOk(uint16 k) { // 0x84BE01 + if (num_enemies_killed_in_room < num_enemy_deaths_left_to_clear) { + PlmPreInstr_PlayDudSound(k); + } else { + SetEventHappened(0); + PlmPreInstr_GoToLinkInstruction(k); + } +} + +void PlmPreInstr_GotoLinkIfTourianStatueFinishedProcessing(uint16 k) { // 0x84BE1F + if ((tourian_entrance_statue_finished & 0x8000u) == 0) + PlmPreInstr_PlayDudSound(k); + else + PlmPreInstr_GoToLinkInstruction(k); +} + +void PlmPreInstr_GotoLinkIfCrittersEscaped(uint16 k) { // 0x84BE30 + if (CheckEventHappened(0xFu) & 1) + PlmPreInstr_GoToLinkInstruction(k); + else + PlmPreInstr_PlayDudSound(k); +} + +uint16 PlmInstr_SetGreyDoorPreInstr(uint16 j, uint16 k) { // 0x84BE3F + plm_pre_instrs[k >> 1] = kGrayDoorPreInstrs[plm_variable[k >> 1] >> 1]; + return j; +} + +uint8 PlmSetup_C806_LeftGreenGateTrigger(uint16 j) { // 0x84C54D + if ((projectile_type[projectile_index >> 1] & 0xFFF) == 512) + return sub_84C63F(j); + QueueSfx2_Max6(0x57u); + plm_header_ptr[j >> 1] = 0; + return 0; +} + +uint8 PlmSetup_C80A_RightGreenGateTrigger(uint16 j) { // 0x84C56C + if ((projectile_type[projectile_index >> 1] & 0xFFF) == 512) + return sub_84C647(j); + QueueSfx2_Max6(0x57u); + plm_header_ptr[j >> 1] = 0; + return 0; +} + +uint8 PlmSetup_C80E_LeftRedGateTrigger(uint16 j) { // 0x84C58B + int16 v1; + + v1 = projectile_type[projectile_index >> 1] & 0xFFF; + if (v1 == 256 || v1 == 512) + return sub_84C63F(j); + QueueSfx2_Max6(0x57u); + plm_header_ptr[j >> 1] = 0; + return 0; +} + +uint8 PlmSetup_C812_RightRedGateTrigger(uint16 j) { // 0x84C5AF + int16 v1; + + v1 = projectile_type[projectile_index >> 1] & 0xFFF; + if (v1 == 256 || v1 == 512) + return sub_84C647(j); + QueueSfx2_Max6(0x57u); + plm_header_ptr[j >> 1] = 0; + return 0; +} + +uint8 PlmSetup_C81E_LeftYellowGateTrigger(uint16 j) { // 0x84C5D3 + if ((projectile_type[projectile_index >> 1] & 0xFFF) == 768) + return sub_84C63F(j); + QueueSfx2_Max6(0x57u); + int v1 = j >> 1; + plm_header_ptr[v1] = 0; + PlmSetup_C822_RightYellowGateTrigger(j); + return 0; +} + +uint8 PlmSetup_C822_RightYellowGateTrigger(uint16 j) { // 0x84C5F1 + if ((projectile_type[projectile_index >> 1] & 0xFFF) != 768) + return sub_84C647(j); + QueueSfx2_Max6(0x57u); + plm_header_ptr[j >> 1] = 0; + return 0; +} + +uint8 PlmSetup_C816_LeftBlueGateTrigger(uint16 j) { // 0x84C610 + if ((projectile_type[projectile_index >> 1] & 0xFFF) != 768) + return sub_84C63F(j); + plm_header_ptr[j >> 1] = 0; + PlmSetup_C81A_RightBlueGateTrigger(j); + return 0; +} + +uint8 PlmSetup_C81A_RightBlueGateTrigger(uint16 j) { // 0x84C627 + if ((projectile_type[projectile_index >> 1] & 0xFFF) != 768) + return sub_84C647(j); + plm_header_ptr[j >> 1] = 0; + return 0; +} + +uint8 sub_84C63F(uint16 j) { // 0x84C63F + return sub_84C64C(j, plm_block_indices[j >> 1] + 2); +} + +uint8 sub_84C647(uint16 j) { // 0x84C647 + return sub_84C64C(j, plm_block_indices[j >> 1] - 2); +} + +uint8 sub_84C64C(uint16 j, uint16 a) { // 0x84C64C + uint16 v2 = 78; + while (a != plm_block_indices[v2 >> 1]) { + v2 -= 2; + if ((v2 & 0x8000u) != 0) + goto LABEL_7; + } + int v3; + v3 = v2 >> 1; + if (!plm_timers[v3]) + ++plm_timers[v3]; +LABEL_7: + plm_header_ptr[j >> 1] = 0; + return 1; +} + +void SetBts0x10FiveStepsDown(uint16 j) { // 0x84C66A + uint16 v1 = SetBtsTo0x10AdvanceRow(plm_block_indices[j >> 1] >> 1); + uint16 v2 = SetBtsTo0x10AdvanceRow(v1); + uint16 v3 = SetBtsTo0x10AdvanceRow(v2); + uint16 v4 = SetBtsTo0x10AdvanceRow(v3); + SetBtsTo0x10AdvanceRow(v4); +} + +uint16 SetBtsTo0x10AdvanceRow(uint16 k) { // 0x84C67F + *(uint16 *)&BTS[k] = (BTS[k + 1] << 8) | 0x10; + return room_width_in_blocks + k; +} + +void SetBts0x10FiveStepsUp(uint16 j) { // 0x84C694 + uint16 v1 = SetBtsTo0x10AdvanceRowUp(plm_block_indices[j >> 1] >> 1); + uint16 v2 = SetBtsTo0x10AdvanceRowUp(v1); + uint16 v3 = SetBtsTo0x10AdvanceRowUp(v2); + uint16 v4 = SetBtsTo0x10AdvanceRowUp(v3); + SetBtsTo0x10AdvanceRowUp(v4); +} + +uint16 SetBtsTo0x10AdvanceRowUp(uint16 k) { // 0x84C6A9 + *(uint16 *)&BTS[k] = (BTS[k + 1] << 8) | 0x10; + return k - room_width_in_blocks; +} + +uint8 PlmSetup_C82A_DownwardsClosedGate(uint16 j) { // 0x84C6BE + SpawnEnemyProjectileWithRoomGfx(0xE659u, 0); + SetBts0x10FiveStepsDown(j); + return 0; +} + +uint8 PlmSetup_C832_UpwardsClosedGate(uint16 j) { // 0x84C6CB + SpawnEnemyProjectileWithRoomGfx(0xE675u, 0); + SetBts0x10FiveStepsUp(j); + return 0; +} + +uint8 PlmSetup_C826_DownwardsOpenGate(uint16 j) { // 0x84C6D8 + SetBts0x10FiveStepsDown(j); + return 0; +} + +uint8 PlmSetup_C82E_UpwardsOpenGate(uint16 j) { // 0x84C6DC + SetBts0x10FiveStepsUp(j); + return 0; +} + +uint8 PlmSetup_C836_DownwardsGateShootblock(uint16 j) { // 0x84C6E0 + int v1 = j >> 1; + plm_instr_list_ptrs[v1] = kDowardGatePlmListPtrs[plm_room_arguments[v1] >> 1]; + uint16 v2 = kDowardGateLeftBlockBts[plm_room_arguments[v1] >> 1]; + if (v2) + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] - 2, v2); + uint16 v3 = kDowardGateRightBlockBts[plm_room_arguments[v1] >> 1]; + if (v3) + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] + 2, v3); + return 0; +} + +uint8 PlmSetup_C73A_UpwardsGateShootblock(uint16 j) { // 0x84C73A + int v1 = j >> 1; + plm_instr_list_ptrs[v1] = kUpwardGatePlmListPtrs[plm_room_arguments[v1] >> 1]; + uint16 v2 = kUpwardGateLeftBlockBts[plm_room_arguments[v1] >> 1]; + if (v2) + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] - 2, v2); + uint16 v3 = kUpwardGateRightBlockBts[plm_room_arguments[v1] >> 1]; + if (v3) + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] + 2, v3); + return 0; +} + +uint8 PlmSetup_C794_GreyDoor(uint16 j) { // 0x84C794 + int v1 = j >> 1; + plm_variable[v1] = (uint16)(HIBYTE(plm_room_arguments[v1]) & 0x7C) >> 1; + plm_room_arguments[v1] &= ~0x7C00; + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1], 0xC044u); + return 0; +} + +uint8 PlmSetup_Door_Colored(uint16 j) { // 0x84C7B1 + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0xC044u); + return 0; +} + +uint8 PlmSetup_Door_Blue(uint16 j) { // 0x84C7BB + if (sign16(projectile_index)) + printf("BUG: projectile_index invalid\n"); + if (!sign16(projectile_index) && (projectile_type[projectile_index >> 1] & 0xF00) == 768) { + plm_header_ptr[j >> 1] = 0; + } else { + uint16 v1 = plm_block_indices[j >> 1]; + level_data[v1 >> 1] = level_data[v1 >> 1] & 0xFFF | 0x8000; + } + return 0; +} + +uint8 PlmSetup_Door_Strange(uint16 j) { // 0x84C7E2 + int v1 = j >> 1; + uint16 v2 = plm_block_indices[v1]; + plm_block_indices[v1] = 0; + uint16 v3 = 78; + while (v2 != plm_block_indices[v3 >> 1]) { + v3 -= 2; + if ((v3 & 0x8000u) != 0) + return 0; + } + plm_timers[v3 >> 1] = projectile_type[(int16)projectile_index >> 1] & 0x1FFF | 0x8000; + return 0; +} + +uint16 PlmInstr_SetBtsTo1(uint16 j, uint16 k) { // 0x84CD93 + *(uint16 *)&BTS[plm_block_indices[k >> 1] >> 1] = (BTS[(plm_block_indices[k >> 1] >> 1) + 1] << 8) | 1; + return j; +} + +uint8 PlmSetup_D028_D02C_Unused(uint16 j) { // 0x84CDC2 + if (samus_pose == kPose_81_FaceR_Screwattack || samus_pose == kPose_82_FaceL_Screwattack) { + int v1 = j >> 1; + int v2 = plm_block_indices[v1] >> 1; + uint16 v3 = level_data[v2]; + plm_variable[v1] = v3; + level_data[v2] = v3 & 0xFFF; + return 0; + } else { + plm_header_ptr[j >> 1] = 0; + return 1; + } +} + +uint8 PlmSetup_RespawningSpeedBoostBlock(uint16 j) { // 0x84CDEA + if ((speed_boost_counter & 0xF00) == 1024 + || samus_pose == kPose_C9_FaceR_Shinespark_Horiz + || samus_pose == kPose_CA_FaceL_Shinespark_Horiz + || samus_pose == kPose_CB_FaceR_Shinespark_Vert + || samus_pose == kPose_CC_FaceL_Shinespark_Vert + || samus_pose == kPose_CD_FaceR_Shinespark_Diag + || samus_pose == kPose_CE_FaceL_Shinespark_Diag) { + int v1 = j >> 1; + int v2 = plm_block_indices[v1] >> 1; + uint16 v3 = level_data[v2] & 0xF000 | 0xB6; + plm_variable[v1] = v3; + level_data[v2] = v3 & 0xFFF; + return 0; + } else { + plm_header_ptr[j >> 1] = 0; + return 1; + } +} + +uint8 PlmSetup_RespawningCrumbleBlock(uint16 j) { // 0x84CE37 + if ((samus_collision_direction & 0xF) == 3) { + int v1 = j >> 1; + int v2 = plm_block_indices[v1] >> 1; + uint16 v3 = level_data[v2] & 0xF000 | 0xBC; + plm_variable[v1] = v3; + level_data[v2] = v3 & 0x8FFF; + plm_instruction_timer[v1] = 4; + } else { + plm_header_ptr[j >> 1] = 0; + } + return 1; +} + +uint8 PlmSetup_RespawningShotBlock(uint16 j) { // 0x84CE6B + int v1 = j >> 1; + int v2 = plm_block_indices[v1] >> 1; + uint16 v3 = level_data[v2] & 0xF000 | 0x52; + plm_variable[v1] = v3; + level_data[v2] = v3 & 0x8FFF; + return 0; +} + +uint8 PlmSetup_RespawningBombBlock(uint16 j) { // 0x84CE83 + if ((speed_boost_counter & 0xF00) == 1024 + || samus_pose == kPose_81_FaceR_Screwattack + || samus_pose == kPose_82_FaceL_Screwattack + || samus_pose == kPose_C9_FaceR_Shinespark_Horiz + || samus_pose == kPose_CA_FaceL_Shinespark_Horiz + || samus_pose == kPose_CB_FaceR_Shinespark_Vert + || samus_pose == kPose_CC_FaceL_Shinespark_Vert + || samus_pose == kPose_CD_FaceR_Shinespark_Diag + || samus_pose == kPose_CE_FaceL_Shinespark_Diag) { + int v2 = j >> 1; + int v3 = plm_block_indices[v2] >> 1; + uint16 v4 = level_data[v3] & 0xF000 | 0x58; + plm_variable[v2] = v4; + level_data[v3] = v4 & 0xFFF; + return 0; + } else { + plm_header_ptr[j >> 1] = 0; + return 1; + } +} + +uint8 PlmSetup_RespawningBombBlock2(uint16 j) { // 0x84CEDA + int16 v1; + + v1 = projectile_type[projectile_index >> 1] & 0xF00; + if (v1 == 1280) { + int v5 = j >> 1; + plm_instr_list_ptrs[v5] += 3; + int v6 = plm_block_indices[v5] >> 1; + uint16 v7 = level_data[v6] & 0xF000 | 0x58; + plm_variable[v5] = v7; + level_data[v6] = v7 & 0x8FFF; + } else if (v1 == 768) { + int v2 = j >> 1; + int v3 = plm_block_indices[v2] >> 1; + uint16 v4 = level_data[v3] & 0xF000 | 0x58; + plm_variable[v2] = v4; + level_data[v3] = v4 & 0x8FFF; + } else { + plm_header_ptr[j >> 1] = 0; + } + return 0; +} + +uint8 PlmSetup_RespawningPowerBombBlock(uint16 j) { // 0x84CF2E + int16 v1; + + v1 = projectile_type[projectile_index >> 1] & 0xF00; + if (v1 == 1280) { + plm_instr_list_ptrs[j >> 1] = addr_kPlmInstrList_C91C; + } else if (v1 == 768) { + int v2 = j >> 1; + int v3 = plm_block_indices[v2] >> 1; + uint16 v4 = level_data[v3] & 0xF000 | 0x57; + plm_variable[v2] = v4; + level_data[v3] = v4 & 0x8FFF; + } else { + plm_header_ptr[j >> 1] = 0; + } + return 0; +} + +uint8 PlmSetup_D08C_SuperMissileBlockRespawning(uint16 j) { // 0x84CF67 + int16 v1; + + v1 = projectile_type[projectile_index >> 1] & 0xF00; + if (v1 == 1280) { + plm_instr_list_ptrs[j >> 1] = addr_kPlmInstrList_C922; + } else if (v1 == 512) { + int v2 = j >> 1; + int v3 = plm_block_indices[v2] >> 1; + uint16 v4 = level_data[v3] & 0xF000 | 0x9F; + plm_variable[v2] = v4; + level_data[v3] = v4 & 0x8FFF; + } else { + plm_header_ptr[j >> 1] = 0; + } + return 0; +} + +uint8 PlmSetup_D08C_CrumbleBlock(uint16 j) { // 0x84CFA0 + if ((projectile_type[projectile_index >> 1] & 0xF00) != 1280) + plm_header_ptr[j >> 1] = 0; + return 0; +} + +uint8 PlmSetup_D0DC_BreakableGrappleBlock(uint16 j) { // 0x84CFB5 + int v1 = j >> 1; + uint16 v2 = plm_block_indices[v1]; + plm_variable[v1] = level_data[v2 >> 1]; + *(uint16 *)&BTS[v2 >> 1] = BTS[(v2 >> 1) + 1] << 8; + return PlmSetup_D0D8_SetVFlag(j); +} + +uint8 PlmSetup_D0D8_SetVFlag(uint16 j) { // 0x84CFCD + return 0x41; +} + +uint8 PlmSetup_D0D8_ClearVflag(uint16 j) { // 0x84CFD1 + return 1; +} + +uint8 PlmSetup_D0E8_GiveSamusDamage(uint16 j) { // 0x84CFD5 + ++samus_periodic_damage; + return 0x41; +} + +uint8 PlmSetup_D113_LowerNorfairChozoRoomPlug(uint16 j) { // 0x84D108 + uint16 a = 0; // a undefined + level_data[plm_block_indices[j >> 1] >> 1] = a & 0xFFF; + return 0; +} + +uint8 PlmSetup_D127(uint16 j) { // 0x84D117 + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0xC000u); + return 0; +} + +uint8 PlmSetup_D138(uint16 j) { // 0x84D12B + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0xE000u); + return 0; +} + +uint16 PlmInstr_FxBaseYPos_0x2D2(uint16 j, uint16 k) { // 0x84D155 + fx_base_y_pos = 722; + return j; +} + +void PlmPreInstr_DeletePlmAndSpawnTriggerIfBlockDestroyed(uint16 k) { // 0x84D15C + uint16 prod = 8 * (uint8)room_width_in_blocks; + uint16 v1 = 2 * (prod + 4); + if (level_data[v1 >> 1] == 255) { + WriteLevelDataBlockTypeAndBts(v1, 0xB083u); + plm_header_ptr[plm_id >> 1] = 0; + } +} + +uint8 PlmSetup_D6DA_LowerNorfairChozoHandTrigger(uint16 j) { // 0x84D18F + static const SpawnHardcodedPlmArgs unk_84D1DA = { 0x0c, 0x1d, 0xd113 }; + + if ((collected_items & 0x200) != 0 + && (samus_collision_direction & 0xF) == 3 + && (samus_pose == kPose_1D_FaceR_Morphball_Ground + || samus_pose == kPose_79_FaceR_Springball_Ground + || samus_pose == kPose_7A_FaceL_Springball_Ground)) { + SetEventHappened(0xCu); + enemy_data[0].parameter_1 = 1; + int v2 = plm_block_indices[j >> 1] >> 1; + level_data[v2] &= 0xFFFu; + CallSomeSamusCode(0); + SpawnHardcodedPlm(&unk_84D1DA); + } + plm_header_ptr[j >> 1] = 0; + return 1; +} + +void PlmPreInstr_IncrementRoomArgIfShotBySuperMissile(uint16 k) { // 0x84D1E6 + int16 v3; + + int v1 = k >> 1; + uint16 v2 = plm_timers[v1]; + if (v2) { + v3 = v2 & 0xF00; + if (v3 == 512 || v3 == 256) { + plm_timers[v1] = 0; + ++plm_room_arguments[v1]; + } + } + plm_timers[v1] = 0; +} + +uint16 PlmInstr_GotoIfRoomArgLess(uint16 j, uint16 k) { // 0x84D2F9 + uint8 *v2 = RomPtr_84(j); + if (plm_room_arguments[k >> 1] >= *(uint16 *)v2) + return j + 4; + else + return *((uint16 *)v2 + 1); +} + +uint16 PlmInstr_SpawnFourMotherBrainGlass(uint16 j, uint16 k) { // 0x84D30B + QueueSfx3_Max15(0x2Eu); + uint16 *v2 = (uint16 *)RomPtr_84(j); + SpawnMotherBrainGlassShatteringShard(*v2); + SpawnMotherBrainGlassShatteringShard(v2[1]); + SpawnMotherBrainGlassShatteringShard(v2[2]); + SpawnMotherBrainGlassShatteringShard(v2[3]); + return j + 8; +} + +void SpawnMotherBrainGlassShatteringShard(uint16 a) { // 0x84D331 + SpawnEnemyProjectileWithRoomGfx(0xCEFCu, a); +} + +void PlmPreInstr_WakePlmIfSamusHasBombs(uint16 k) { // 0x84D33B + if ((collected_items & 0x1000) != 0) { + int v1 = k >> 1; + plm_instruction_timer[v1] = 1; + ++plm_instr_list_ptrs[v1]; + ++plm_instr_list_ptrs[v1]; + plm_pre_instrs[v1] = FUNC16(nullsub_351); + } +} + +uint16 PlmInstr_SpawnTorizoStatueBreaking(uint16 j, uint16 k) { // 0x84D357 + uint16 *v2 = (uint16 *)RomPtr_84(j); + SpawnEnemyProjectileWithRoomGfx(0xA993u, *v2); + return j + 2; +} + +uint16 PlmInstr_QueueSong1MusicTrack(uint16 j, uint16 k) { // 0x84D3C7 + QueueMusic_Delayed8(6u); + return j; +} + +uint16 PlmInstr_TransferWreckedShipChozoSpikesToSlopes(uint16 j, uint16 k) { // 0x84D3D7 + WriteLevelDataBlockTypeAndBts(0x1608u, 0x1012u); + WriteLevelDataBlockTypeAndBts(0x160Au, 0x1013u); + return j; +} + +uint16 PlmInstr_TransferWreckedShipSlopesToChozoSpikes(uint16 j, uint16 k) { // 0x84D3F4 + WriteLevelDataBlockTypeAndBts(0x1608u, 0xA000u); + WriteLevelDataBlockTypeAndBts(0x160Au, 0xA000u); + return j; +} + +void UNUSED_sub_84D409(uint16 k) { // 0x84D409 + int v1 = k >> 1; + if ((plm_timers[v1] & 0xF00) == 1280) { + plm_instr_list_ptrs[v1] = plm_instruction_list_link_reg[v1]; + plm_instruction_timer[v1] = 1; + } + plm_timers[v1] = 0; +} + +void UNUSED_sub_84D476(void) { // 0x84D476 + fx_target_y_pos = 722; + fx_y_vel = 112; + fx_timer = 32; +} + +void UNUSED_sub_84D489(void) { // 0x84D489 + fx_base_y_pos = 722; +} + +void PlmPreInstr_WakeOnKeyPress(uint16 k) { // 0x84D4BF + if ((joypad1_newkeys & (uint16)(kButton_B | kButton_Y | kButton_Left | kButton_Right | kButton_A | kButton_X)) != 0) { + int v2 = k >> 1; + plm_instruction_timer[v2] = 1; + ++plm_instr_list_ptrs[v2]; + ++plm_instr_list_ptrs[v2]; + } +} + +uint16 PlmInstr_EnableWaterPhysics(uint16 j, uint16 k) { // 0x84D525 + fx_liquid_options &= ~4u; + return j; +} + +uint16 PlmInstr_SpawnN00bTubeCrackEnemyProjectile(uint16 j, uint16 k) { // 0x84D52C + uint16 v2 = 0; // undefined + SpawnEnemyProjectileWithRoomGfx(0xD904u, v2); + return j; +} + +uint16 PlmInstr_DiagonalEarthquake(uint16 j, uint16 k) { // 0x84D536 + earthquake_type = 11; + earthquake_timer = 64; + return j; +} + +uint16 PlmInstr_Spawn10shardsAnd6n00bs(uint16 j, uint16 k) { // 0x84D543 + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeShards, 0); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeShards, 2u); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeShards, 4u); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeShards, 6u); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeShards, 8u); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeShards, 0xAu); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeShards, 0xCu); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeShards, 0xEu); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeShards, 0x10u); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeShards, 0x12u); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeReleasedAirBubbles, 0); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeReleasedAirBubbles, 2u); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeReleasedAirBubbles, 4u); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeReleasedAirBubbles, 6u); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeReleasedAirBubbles, 8u); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_N00bTubeReleasedAirBubbles, 0xAu); + return j; +} + +uint16 PlmInstr_DisableSamusControls(uint16 j, uint16 k) { // 0x84D5E6 + CallSomeSamusCode(0); + return j; +} + +uint16 PlmInstr_EnableSamusControls(uint16 j, uint16 k) { // 0x84D5EE + CallSomeSamusCode(1); + return j; +} + +uint8 PlmSetup_MotherBrainGlass(uint16 j) { // 0x84D5F6 + int v1 = j >> 1; + plm_room_arguments[v1] = 0; + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1], 0x8044u); + return 0; +} + +uint8 PlmSetup_DeletePlmIfAreaTorizoDead(uint16 j) { // 0x84D606 + if (CheckBossBitForCurArea(4u) & 1) + plm_header_ptr[j >> 1] = 0; + return 0; +} + +uint8 PlmSetup_MakeBllockChozoHandTrigger(uint16 j) { // 0x84D616 + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0xB080u); + return 0; +} + +uint8 PlmSetup_D6F2_WreckedShipChozoHandTrigger(uint16 j) { // 0x84D620 + if (CheckBossBitForCurArea(1u) & 1 + && (samus_collision_direction & 0xF) == 3 + && (samus_pose == kPose_1D_FaceR_Morphball_Ground + || samus_pose == kPose_79_FaceR_Springball_Ground + || samus_pose == kPose_7A_FaceL_Springball_Ground)) { + enemy_data[0].parameter_1 = 1; + *(uint16 *)&scrolls[7] = 514; + *(uint16 *)&scrolls[13] = 257; + int v1 = plm_block_indices[j >> 1] >> 1; + level_data[v1] &= 0xFFFu; + CallSomeSamusCode(0); + static const SpawnHardcodedPlmArgs unk_84D673 = { 0x17, 0x1d, 0xd6f8 }; + SpawnHardcodedPlm(&unk_84D673); + return 0; + } + plm_header_ptr[j >> 1] = 0; + return 1; +} + +uint8 PlmSetup_D700_MakePlmAirBlock_Unused(uint16 j) { // 0x84D67F + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0x44u); + return 0; +} + +uint8 PlmSetup_D704_AlteranateLowerNorfairChozoHand_Unused(uint16 j) { // 0x84D689 + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0x8044u); + return 0; +} + +uint8 PlmSetup_D708_LowerNorfairChozoBlockUnused(uint16 j) { // 0x84D693 + int v1 = j >> 1; + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1], 0x8044u); + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1] + 2, 0x50FFu); + WriteLevelDataBlockTypeAndBts( + room_width_in_blocks + + room_width_in_blocks + + plm_block_indices[v1], + 0xD0FFu); + WriteLevelDataBlockTypeAndBts( + room_width_in_blocks + + room_width_in_blocks + + plm_block_indices[v1] + + 2, + 0xD0FFu); + return 0; +} + +uint8 PlmSetup_D70C_NoobTube(uint16 j) { // 0x84D6CC + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0x8044u); + return 0; +} + +void PlmPreInstr_WakePlmIfRoomArgumentDoorIsSet(uint16 k) { // 0x84D753 + int v2 = k >> 1; + int idx = PrepareBitAccess(plm_room_arguments[v2]); + if ((bitmask & opened_door_bit_array[idx]) != 0) { + int v3 = k >> 1; + plm_pre_instrs[v3] = addr_locret_84D779; + plm_instr_list_ptrs[v3] = plm_instruction_list_link_reg[v3]; + plm_instruction_timer[v3] = 1; + } +} + +uint16 PlmInstr_ShootEyeDoorProjectileWithProjectileArg(uint16 j, uint16 k) { // 0x84D77A + uint16 *v2 = (uint16 *)RomPtr_84(j); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_EyeDoorProjectile, *v2); + QueueSfx2_Max6(0x4Cu); + return j + 2; +} + +uint16 PlmInstr_SpawnEyeDoorSweatEnemyProjectile(uint16 j, uint16 k) { // 0x84D790 + uint16 *v2 = (uint16 *)RomPtr_84(j); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_EyeDoorSweat, *v2); + return j + 2; +} + +uint16 PlmInstr_SpawnTwoEyeDoorSmoke(uint16 j, uint16 k) { // 0x84D79F + SpawnEnemyProjectileWithRoomGfx(0xE517u, 0x30Au); + SpawnEnemyProjectileWithRoomGfx(0xE517u, 0x30Au); + return j; +} + +uint16 PlmInstr_SpawnEyeDoorSmokeProjectile(uint16 j, uint16 k) { // 0x84D7B6 + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_EyeDoorSmoke, 0xBu); + return j; +} + +uint16 PlmInstr_MoveUpAndMakeBlueDoorFacingRight(uint16 j, uint16 k) { // 0x84D7C3 + int v2 = k >> 1; + uint16 v3 = (__PAIR32__(plm_block_indices[v2] - room_width_in_blocks, plm_block_indices[v2]) + - __PAIR32__(room_width_in_blocks, room_width_in_blocks)) >> 16; + plm_block_indices[v2] = v3; + uint16 v4 = v3; + WriteLevelDataBlockTypeAndBts(v3, 0xC041u); + sub_84D7EF(v4); + return j; +} + +uint16 PlmInstr_MoveUpAndMakeBlueDoorFacingLeft(uint16 j, uint16 k) { // 0x84D7DA + int v2 = k >> 1; + uint16 v3 = (__PAIR32__(plm_block_indices[v2] - room_width_in_blocks, plm_block_indices[v2]) + - __PAIR32__(room_width_in_blocks, room_width_in_blocks)) >> 16; + plm_block_indices[v2] = v3; + uint16 v4 = v3; + WriteLevelDataBlockTypeAndBts(v3, 0xC040u); + sub_84D7EF(v4); + return j; +} + +void sub_84D7EF(uint16 k) { // 0x84D7EF + uint16 v1 = room_width_in_blocks + room_width_in_blocks + k; + WriteLevelDataBlockTypeAndBts(v1, 0xD0FFu); + uint16 v2 = room_width_in_blocks + room_width_in_blocks + v1; + WriteLevelDataBlockTypeAndBts(v2, 0xD0FEu); + WriteLevelDataBlockTypeAndBts( + room_width_in_blocks + room_width_in_blocks + v2, + 0xD0FDu); +} + +uint8 PlmSetup_EyeDoorEye(uint16 j) { // 0x84DA8C + int idx = PrepareBitAccess(plm_room_arguments[j >> 1]); + if ((bitmask & opened_door_bit_array[idx]) == 0) { + int v1 = j >> 1; + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1], 0xC044u); + WriteLevelDataBlockTypeAndBts( + room_width_in_blocks + + room_width_in_blocks + + plm_block_indices[v1], + 0xD0FFu); + } + return 0; +} + +uint8 PlmSetup_EyeDoor(uint16 j) { // 0x84DAB9 + int idx = PrepareBitAccess(plm_room_arguments[j >> 1]); + if ((bitmask & opened_door_bit_array[idx]) == 0) + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0xA000u); + return 0; +} + +void PlmPreInstr_SetMetroidsClearState_Ev0x10(uint16 k) { // 0x84DADE + if (num_enemies_killed_in_room >= num_enemy_deaths_left_to_clear) + SetEventHappened(0x10u); +} + +void PlmPreInstr_SetMetroidsClearState_Ev0x11(uint16 k) { // 0x84DAEE + if (num_enemies_killed_in_room >= num_enemy_deaths_left_to_clear) + SetEventHappened(0x11u); +} + +void PlmPreInstr_SetMetroidsClearState_Ev0x12(uint16 k) { // 0x84DAFE + if (num_enemies_killed_in_room >= num_enemy_deaths_left_to_clear) + SetEventHappened(0x12u); +} + +void PlmPreInstr_SetMetroidsClearState_Ev0x13(uint16 k) { // 0x84DB0E + if (num_enemies_killed_in_room >= num_enemy_deaths_left_to_clear) + SetEventHappened(0x13u); +} + +uint8 PlmSetup_SetMetroidRequiredClearState(uint16 j) { // 0x84DB1E + plm_pre_instrs[j >> 1] = off_84DB28[plm_room_arguments[j >> 1] >> 1]; + return 0; +} + +void PlmPreInstr_GotoLinkIfShotWithSuperMissile(uint16 k) { // 0x84DB64 + int16 v1; + + v1 = plm_timers[k >> 1] & 0xF00; + if (v1 == 512) { + plm_room_arguments[k >> 1] = 119; + } else if (v1 != 256) { + return; + } + int v2 = k >> 1; + plm_timers[v2] = 0; + plm_instr_list_ptrs[v2] = plm_instruction_list_link_reg[v2]; + plm_instruction_timer[v2] = 1; +} + +uint16 PlmInstr_DamageDraygonTurret(uint16 j, uint16 k) { // 0x84DB8E + *(uint16 *)RomPtr_7E(plm_variable[k >> 1]) = 1; + uint16 v2 = plm_block_indices[k >> 1]; + WriteLevelDataBlockTypeAndBts(v2, 0xA003u); + WriteLevelDataBlockTypeAndBts( + room_width_in_blocks + room_width_in_blocks + v2, + 0xA003u); + return j; +} + +uint16 PlmInstr_DamageDraygonTurretFacingDownRight(uint16 j, uint16 k) { // 0x84DBB8 + *(uint16 *)RomPtr_7E(plm_variable[k >> 1]) = 1; + uint16 v2 = plm_block_indices[k >> 1]; + WriteLevelDataBlockTypeAndBts(v2, 0xA003u); + WriteLevelDataBlockTypeAndBts(v2 + 2, 0xA003u); + uint16 v3 = plm_block_indices[plm_id >> 1]; + uint16 v4 = room_width_in_blocks + room_width_in_blocks + v3; + WriteLevelDataBlockTypeAndBts(v4, 0xA003u); + WriteLevelDataBlockTypeAndBts(v4 + 2, 0); + return j; +} + +uint16 PlmInstr_DamageDraygonTurretFacingUpRight(uint16 j, uint16 k) { // 0x84DBF7 + *(uint16 *)RomPtr_7E(plm_variable[k >> 1]) = 1; + uint16 v2 = plm_block_indices[k >> 1]; + WriteLevelDataBlockTypeAndBts(v2, 0xA003u); + WriteLevelDataBlockTypeAndBts(v2 + 2, 0); + uint16 v3 = plm_block_indices[plm_id >> 1]; + uint16 v4 = room_width_in_blocks + room_width_in_blocks + v3; + WriteLevelDataBlockTypeAndBts(v4, 0xA003u); + WriteLevelDataBlockTypeAndBts(v4 + 2, 0xA003u); + return j; +} + +uint16 PlmInstr_DamageDraygonTurret2(uint16 j, uint16 k) { // 0x84DC36 + *(uint16 *)RomPtr_7E(plm_variable[k >> 1]) = 1; + uint16 v2 = plm_block_indices[k >> 1]; + WriteLevelDataBlockTypeAndBts(v2, 0xA003u); + WriteLevelDataBlockTypeAndBts( + room_width_in_blocks + room_width_in_blocks + v2, + 0xA003u); + return j; +} + +uint16 PlmInstr_DamageDraygonTurretFacingDownLeft(uint16 j, uint16 k) { // 0x84DC60 + *(uint16 *)RomPtr_7E(plm_variable[k >> 1]) = 1; + uint16 v2 = plm_block_indices[k >> 1]; + WriteLevelDataBlockTypeAndBts(v2, 0xA003u); + WriteLevelDataBlockTypeAndBts(v2 - 2, 0xA003u); + uint16 v3 = plm_block_indices[plm_id >> 1]; + uint16 v4 = room_width_in_blocks + room_width_in_blocks + v3; + WriteLevelDataBlockTypeAndBts(v4, 0xA003u); + WriteLevelDataBlockTypeAndBts(v4 - 2, 0); + return j; +} + +uint16 PlmInstr_DamageDraygonTurretFacingUpLeft(uint16 j, uint16 k) { // 0x84DC9F + *(uint16 *)RomPtr_7E(plm_variable[k >> 1]) = 1; + uint16 v2 = plm_block_indices[k >> 1]; + WriteLevelDataBlockTypeAndBts(v2, 0xA003u); + WriteLevelDataBlockTypeAndBts(v2 - 2, 0); + uint16 v3 = plm_block_indices[plm_id >> 1]; + uint16 v4 = room_width_in_blocks + room_width_in_blocks + v3; + WriteLevelDataBlockTypeAndBts(v4, 0xA003u); + WriteLevelDataBlockTypeAndBts(v4 - 2, 0xA003u); + return j; +} + +uint8 PlmSetup_DraygonCannonFacingRight(uint16 j) { // 0x84DE94 + int v1 = j >> 1; + plm_variable[v1] = plm_room_arguments[v1]; + plm_room_arguments[v1] = 0; + uint16 v2 = plm_block_indices[v1]; + WriteLevelDataBlockTypeAndBts(v2, 0xC044u); + WriteLevelDataBlockTypeAndBts( + room_width_in_blocks + room_width_in_blocks + v2, + 0xD0FFu); + return 0; +} + +uint8 PlmSetup_DraygonCannonFacingDiagonalRight(uint16 j) { // 0x84DEB9 + int v1 = j >> 1; + plm_variable[v1] = plm_room_arguments[v1]; + plm_room_arguments[v1] = 0; + uint16 v2 = plm_block_indices[v1]; + WriteLevelDataBlockTypeAndBts(v2, 0xC044u); + WriteLevelDataBlockTypeAndBts(v2 + 2, 0x50FFu); + uint16 v3 = room_width_in_blocks + + room_width_in_blocks + + plm_block_indices[v1]; + WriteLevelDataBlockTypeAndBts(v3, 0xD0FFu); + WriteLevelDataBlockTypeAndBts(v3 + 2, 0xD0FFu); + return 0; +} + +uint8 PlmSetup_DraygonCannonFacingLeft(uint16 j) { // 0x84DEF0 + int v1 = j >> 1; + plm_variable[v1] = plm_room_arguments[v1]; + plm_room_arguments[v1] = 0; + uint16 v2 = plm_block_indices[v1]; + WriteLevelDataBlockTypeAndBts(v2, 0xC044u); + WriteLevelDataBlockTypeAndBts( + room_width_in_blocks + room_width_in_blocks + v2, + 0xD0FFu); + return 0; +} + +uint8 PlmSetup_DraygonCannonFacingDiagonalLeft(uint16 j) { // 0x84DF15 + int v1 = j >> 1; + plm_variable[v1] = plm_room_arguments[v1]; + plm_room_arguments[v1] = 0; + uint16 v2 = plm_block_indices[v1]; + WriteLevelDataBlockTypeAndBts(v2, 0xC044u); + WriteLevelDataBlockTypeAndBts(v2 - 2, 0x5001u); + uint16 v3 = room_width_in_blocks + + room_width_in_blocks + + plm_block_indices[v1]; + WriteLevelDataBlockTypeAndBts(v3, 0xD0FFu); + WriteLevelDataBlockTypeAndBts(v3 - 2, 0xD0FFu); + return 0; +} + +uint8 PlmSetup_DraygonCannon(uint16 j) { // 0x84DF4C + int v1 = j >> 1; + plm_variable[v1] = plm_room_arguments[v1]; + plm_room_arguments[v1] = 3; + return 0; +} + +void PlmPreInstr_GotoLinkIfTriggered(uint16 k) { // 0x84DF89 + int v1 = k >> 1; + if (LOBYTE(plm_timers[v1]) == 255) { + plm_pre_instrs[v1] = FUNC16(PlmPreInstr_nullsub_301); + plm_instr_list_ptrs[v1] = plm_instruction_list_link_reg[v1]; + plm_instruction_timer[v1] = 1; + } +} + +void PlmPreInstr_WakeIfTriggered(uint16 k) { // 0x84DFE6 + int v1 = k >> 1; + uint16 v2 = plm_timers[v1]; + if (v2 != 768 && (uint8)v2 == 255) { + plm_timers[v1] = 0; + ++plm_instr_list_ptrs[v1]; + ++plm_instr_list_ptrs[v1]; + plm_instruction_timer[v1] = 1; + } +} + +uint16 PlmInstr_DrawItemFrame0(uint16 j, uint16 k) { // 0x84E04F + plm_instruction_draw_ptr[k >> 1] = off_84E05F[plm_variables[k >> 1] >> 1]; + return PlmInstr_DrawItemFrame_Common(j, k); +} + +uint16 PlmInstr_DrawItemFrame1(uint16 j, uint16 k) { // 0x84E067 + plm_instruction_draw_ptr[k >> 1] = off_84E077[plm_variables[k >> 1] >> 1]; + return PlmInstr_DrawItemFrame_Common(j, k); +} + +uint16 PlmInstr_DrawItemFrame_Common(uint16 j, uint16 k) { // 0x84E07F + int v2 = k >> 1; + plm_instruction_timer[v2] = 4; + plm_instr_list_ptrs[v2] = j; + ProcessPlmDrawInstruction(k); + uint16 v3 = plm_id; + CalculatePlmBlockCoords(plm_id); + DrawPlm(v3); + return 0; +} + +uint16 PlmInstr_ClearChargeBeamCounter(uint16 j, uint16 k) { // 0x84E29D + flare_counter = 0; + return j; +} + +uint16 PlmInstr_E63B(uint16 j, uint16 k) { // 0x84E63B + fx_y_vel = -32; + return j; +} + +uint8 sub_84EE4D(uint16 j) { // 0x84EE4D + return sub_84EE5F(j, 8u); +} + +uint8 sub_84EE52(uint16 j) { // 0x84EE52 + return sub_84EE5F(j, 0xAu); +} + +uint8 sub_84EE57(uint16 j) { // 0x84EE57 + return sub_84EE5F(j, 0xCu); +} + +uint8 sub_84EE5C(uint16 j) { // 0x84EE5C + return sub_84EE5F(j, 0xEu); +} + +uint8 sub_84EE5F(uint16 j, uint16 a) { // 0x84EE5F + plm_variables[j >> 1] = a; + return sub_84EE64(j); +} + +uint8 sub_84EE64(uint16 j) { // 0x84EE64 + WriteLevelDataBlockTypeAndBts(plm_block_indices[j >> 1], 0x45u); + ++global_number_of_items_loaded_ctr; + return 0; +} + +uint8 sub_84EE77(uint16 j) { // 0x84EE77 + return sub_84EE89(j, 8u); +} + +uint8 sub_84EE7C(uint16 j) { // 0x84EE7C + return sub_84EE89(j, 0xAu); +} + +uint8 sub_84EE81(uint16 j) { // 0x84EE81 + return sub_84EE89(j, 0xCu); +} + +uint8 sub_84EE86(uint16 j) { // 0x84EE86 + return sub_84EE89(j, 0xEu); +} + +uint8 sub_84EE89(uint16 j, uint16 a) { // 0x84EE89 + plm_variables[j >> 1] = a; + return sub_84EE8E(j); +} + +uint8 sub_84EE8E(uint16 j) { // 0x84EE8E + int v1 = j >> 1; + WriteLevelDataBlockTypeAndBts(plm_block_indices[v1], 0xC045u); + plm_variable[v1] = level_data[plm_block_indices[v1] >> 1]; + ++global_number_of_items_loaded_ctr; + return 0; +} + +uint8 sub_84EEAB(uint16 v0) { // 0x84EEAB + int i; + + if (time_is_frozen_flag) { + plm_header_ptr[v0 >> 1] = 0; + } else { + int v1 = v0 >> 1; + uint16 v2 = plm_block_indices[v1]; + plm_block_indices[v1] = 0; + for (i = 78; i >= 0; i -= 2) { + if (v2 == plm_block_indices[i >> 1]) + break; + } + plm_timers[i >> 1] = 255; + } + return 0; +} diff --git a/src/sm_85.c b/src/sm_85.c new file mode 100644 index 0000000..2665853 --- /dev/null +++ b/src/sm_85.c @@ -0,0 +1,435 @@ +// Message boxes +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" + +int DisplayMessageBox_Poll(uint16 a) { + if (a == message_box_index) { + message_box_index = 0; + return save_confirmation_selection; + } + queued_message_box_index = a; + return -1; +} + +void DisplayMessageBox(uint16 a) { // 0x858080 + queued_message_box_index = a; +} + +CoroutineRet DisplayMessageBox_Async(uint16 a) { // 0x858080 + COROUTINE_BEGIN(coroutine_state_3, 0) + message_box_index = a; + CancelSoundEffects(); + InitializePpuForMessageBoxes(); + ClearMessageBoxBg3Tilemap(); + InitializeMessageBox(); + COROUTINE_AWAIT(2, OpenMessageBox_Async()); + COROUTINE_AWAIT(3, HandleMessageBoxInteraction_Async()); + COROUTINE_AWAIT(4, CloseMessageBox_Async()); + + if (message_box_index == 28 && save_confirmation_selection != 2) { + message_box_index = 24; + ClearMessageBoxBg3Tilemap(); + QueueSfx1_Max6(0x2Eu); + + my_counter = 160; + do { + HandleMusicQueue(); + HandleSoundEffects(); + COROUTINE_AWAIT(8, WaitForNMI_NoUpdate_Async()); + } while (--my_counter); + + InitializeMessageBox(); + COROUTINE_AWAIT(5, OpenMessageBox_Async()); + COROUTINE_AWAIT(6, HandleMessageBoxInteraction_Async()); + COROUTINE_AWAIT(7, CloseMessageBox_Async()); + message_box_index = 28; + } + ClearMessageBoxBg3Tilemap(); + RestorePpuForMessageBox(); + QueueSamusMovementSfx(); + + if (message_box_index == 20) { + game_state = kGameState_12_Pausing; + } + COROUTINE_END(0); +// else if (message_box_index == 28 || message_box_index == 23) { +// return save_confirmation_selection; +// } +// return 0; +} + +void InitializePpuForMessageBoxes(void) { // 0x858143 + save_confirmation_selection = 0; + WriteReg(HDMAEN, 0); + WriteReg(CGADD, 0x19u); + WriteReg(CGDATA, 0xB1u); + WriteReg(CGDATA, 0xBu); + WriteReg(CGDATA, 0x1Fu); + WriteReg(CGDATA, 0); + ram3000.msgbox.backup_of_enabled_hdma_channels = reg_HDMAEN; + ram3000.misc.field_3E8[3] = gameplay_BG3SC; + gameplay_BG3SC = 88; + gameplay_TM = 23; + gameplay_CGWSEL = 0; + gameplay_CGADSUB = 0; + WriteReg(COLDATA, 0x20u); + WriteReg(COLDATA, 0x40u); + WriteReg(COLDATA, 0x80); + ReadReg(BG3HOFS); + WriteReg(BG3HOFS, 0); + WriteReg(BG3HOFS, 0); + ReadReg(BG3VOFS); + WriteReg(BG3VOFS, 0); + WriteReg(BG3VOFS, 0); + for (int i = 128; i >= 0; i -= 2) + *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + (uint16)i) = 0; + WriteRegWord(VMADDL, addr_unk_605880); + ReadRegWord(RDVRAML); + WriteRegWord(DMAP1, 0x3981u); + WriteRegWord(A1T1L, ADDR16_OF_RAM(ram4000) + 256); + WriteRegWord(A1B1, 0x7Eu); + WriteRegWord(DAS1L, 0x700u); + WriteRegWord(DAS10, 0); + WriteRegWord(A2A1H, 0); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 2u); +} + +void ClearMessageBoxBg3Tilemap(void) { // 0x8581F3 + int16 v0; + v0 = 1790; + do { + *(uint16 *)((char *)ram3800.cinematic_bg_tilemap + (uint16)v0) = 0xe; + v0 -= 2; + } while (v0 >= 0); + WriteRegWord(VMADDL, addr_unk_605880); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1T1L, ADDR16_OF_RAM(ram3800)); + WriteRegWord(A1B1, 0x7Eu); + WriteRegWord(DAS1L, 0x700u); + WriteRegWord(DAS10, 0); + WriteRegWord(A2A1H, 0); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 2u); +} + +void CallMsgBoxDraw(uint32 ea) { + switch (ea) { + case fnWriteLargeMessageBoxTilemap: WriteLargeMessageBoxTilemap(); return; + case fnWriteSmallMessageBoxTilemap: WriteSmallMessageBoxTilemap(); return; + default: Unreachable(); + } +} +void CallMsgBoxModify(uint32 ea) { + switch (ea) { + case fnDrawShootButtonAndSetupPpuForLargeMessageBox: DrawShootButtonAndSetupPpuForLargeMessageBox(); return; + case fnDrawRunButtonAndSetupPpuForLargeMessageBox: DrawRunButtonAndSetupPpuForLargeMessageBox(); return; + case fnSetupPpuForSmallMessageBox: SetupPpuForSmallMessageBox(); return; + case fnSetupPpuForLargeMessageBox: SetupPpuForLargeMessageBox(); return; + default: Unreachable(); + } +} +#define kMessageBoxDefs ((MsgBoxConfig*)RomPtr(0x85869b)) +void InitializeMessageBox(void) { // 0x858241 + bg3_tilemap_offset = 2 * (message_box_index - 1); + uint16 v0 = message_box_index - 1; + CallMsgBoxDraw(kMessageBoxDefs[v0].draw_initial_tilemap | 0x850000); + CallMsgBoxModify(kMessageBoxDefs[v0].modify_box_func | 0x850000); +} + +static const uint16 kLargeMsgBoxTopBottomBorderTilemap[32] = { // 0x85825A + 0xe, 0xe, 0xe, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x280f, 0x280f, 0x280f, 0x280f, 0x280f, 0x280f, 0x280f, + 0x280f, 0x280f, 0x280f, 0x280f, 0x280f, 0x280f, 0x280f, 0x280f, 0x280f, 0x280f, 0x280f, 0x284e, 0x284e, 0xe, 0xe, 0xe, +}; +static const uint16 kSmallMsgBoxTopBottomBorderTilemap[32] = { + 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, + 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0x284e, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, +}; +void WriteLargeMessageBoxTilemap(void) { + for (int i = 0; i != 32; ++i) + ram3000.pause_menu_map_tilemap[i + 256] = kLargeMsgBoxTopBottomBorderTilemap[i]; + uint16 i = WriteMessageTilemap(); + R22_ = 32; + uint16 v1 = 0; + do { + ram3000.pause_menu_map_tilemap[i + 256] = kLargeMsgBoxTopBottomBorderTilemap[v1 >> 1]; + v1 += 2; + ++i; + --R22_; + } while (R22_); +} + +void WriteSmallMessageBoxTilemap(void) { // 0x858289 + for (int i = 0; i != 32; ++i) + ram3000.pause_menu_map_tilemap[i + 256] = kSmallMsgBoxTopBottomBorderTilemap[i]; + uint16 i = WriteMessageTilemap(); + R22_ = 32; + uint16 v1 = 0; + do { + ram3000.pause_menu_map_tilemap[i + 256] = kSmallMsgBoxTopBottomBorderTilemap[v1 >> 1]; + v1 += 2; + ++i; + --R22_; + } while (R22_); +} + +uint16 WriteMessageTilemap(void) { // 0x8582B8 + message_box_animation_y1 = 112; + message_box_animation_y0 = 124; + message_box_animation_y_radius = 0; + for (int i = 0; i != 112; ++i) + ram3000.pause_menu_map_tilemap[i] = 0; + bg3_tilemap_offset = 2 * (message_box_index - 1); + R0_.addr = *(VoidP *)((char *)&kMessageBoxDefs[0].message_tilemap + (uint16)(6 * (message_box_index - 1))); + *(uint16 *)((char *)&R8_ + 1) = *(VoidP *)((char *)&kMessageBoxDefs[1].message_tilemap + + (uint16)(6 * (message_box_index - 1))) + - R0_.addr; + R22_ = *(uint16 *)((char *)&R8_ + 1) >> 1; + *(uint16 *)((char *)&R8_ + 1) += 128; + uint16 v1 = 32; + uint16 v2 = 0; + do { + ram3000.pause_menu_map_tilemap[v1 + 256] = *(uint16 *)&RomPtr_85(R0_.addr)[v2]; + ++v1; + v2 += 2; + --R22_; + } while (R22_); + return v1; +} + +void SetupMessageBoxBg3YscrollHdma(void) { // 0x858363 + *(uint32 *)&ram3000.menu.palette_backup_in_menu[64] = -516947713; + ram3000.pause_menu_map_tilemap[450] = 12542; + ram3000.msgbox.indirect_hdma[6] = 0; + WriteReg(DMAP6, 0x42u); + WriteReg(BBAD6, 0x12u); + WriteReg(A1T6L, 0x80); + WriteReg(DAS6L, 0x80); + WriteReg(A1T6H, 0x33u); + WriteReg(DAS6H, 0x33u); + WriteReg(A1B6, 0x7Eu); + WriteReg(DAS60, 0x7Eu); + WriteReg(A2A6L, 0); + WriteReg(A2A6H, 0); + WriteReg(NTRL6, 0); + MsgBoxMakeHdmaTable(); + WriteReg(HDMAEN, 0x40u); +} + +void SetupPpuForActiveMessageBox(void) { // 0x85831E + SetupMessageBoxBg3YscrollHdma(); + bg3_tilemap_offset += 22528; + WriteRegWord(VMADDL, bg3_tilemap_offset); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1T1L, ADDR16_OF_RAM(ram3000) + 512); + WriteRegWord(A1B1, 0x7Eu); + WriteRegWord(DAS1L, *(uint16 *)((char *)&R8_ + 1)); + WriteRegWord(DAS10, 0); + WriteRegWord(A2A1H, 0); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 2u); +} + +CoroutineRet OpenMessageBox_Async(void) { // 0x85844C + COROUTINE_BEGIN(coroutine_state_4, 0); + for (message_box_animation_y_radius = 0;; message_box_animation_y_radius += 512) { + COROUTINE_AWAIT(1, WaitForNMI_NoUpdate_Async()); + HandleMusicQueue(); + HandleSoundEffects(); + MsgBoxMakeHdmaTable(); + if (message_box_animation_y_radius == 0x1800) + break; + } + COROUTINE_END(0); +} + +CoroutineRet CloseMessageBox_Async(void) { // 0x858589 + COROUTINE_BEGIN(coroutine_state_4, 0); + do { + COROUTINE_AWAIT(1, WaitForNMI_NoUpdate_Async()); + HandleMusicQueue(); + HandleSoundEffects(); + MsgBoxMakeHdmaTable(); + message_box_animation_y_radius -= 512; + } while ((message_box_animation_y_radius & 0x8000u) == 0); + COROUTINE_END(0); +} + + +void DrawShootButtonAndSetupPpuForLargeMessageBox(void) { // 0x8583C5 + DrawSpecialButtonAndSetupPpuForLargeMessageBox(button_config_shoot_x); +} + +void DrawRunButtonAndSetupPpuForLargeMessageBox(void) { // 0x8583CC + DrawSpecialButtonAndSetupPpuForLargeMessageBox(button_config_run_b); +} +static const uint16 kMsgBoxSpecialButtonTilemapOffs[27] = { // 0x8583D1 + 0, 0x12a, 0x12a, 0x12c, 0x12c, 0x12c, 0, 0, 0, 0, 0, 0, 0x120, 0, 0, 0, + 0, 0, 0x12a, 0, 0, 0, 0, 0, 0, 0, 0, +}; +static const uint16 kTileNumbersForButtonLetters[8] = { 0x28e0, 0x3ce1, 0x2cf7, 0x38f8, 0x38d0, 0x38eb, 0x38f1, 0x284e }; + +void DrawSpecialButtonAndSetupPpuForLargeMessageBox(uint16 a) { + uint16 v1 = 0; + if ((a & kButton_A) == 0) { + v1 = 2; + if ((a & 0x8000u) == 0) { + v1 = 4; + if ((a & kButton_X) == 0) { + v1 = 6; + if ((a & kButton_Y) == 0) { + v1 = 8; + if ((a & kButton_Select) == 0) { + v1 = 10; + if ((a & kButton_L) == 0) { + v1 = 12; + if ((a & kButton_R) == 0) + v1 = 14; + } + } + } + } + } + } + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[256] + + kMsgBoxSpecialButtonTilemapOffs[message_box_index - 1]) = kTileNumbersForButtonLetters[v1 >> 1]; + bg3_tilemap_offset = 416; + SetupPpuForActiveMessageBox(); +} + +void SetupPpuForSmallMessageBox(void) { // 0x858436 + bg3_tilemap_offset = 448; + SetupPpuForActiveMessageBox(); +} + +void SetupPpuForLargeMessageBox(void) { // 0x858441 + bg3_tilemap_offset = 416; + SetupPpuForActiveMessageBox(); +} + + +CoroutineRet HandleMessageBoxInteraction_Async(void) { // 0x85846D + COROUTINE_BEGIN(coroutine_state_4, 0); + + if (message_box_index == 23 || message_box_index == 28) { + save_confirmation_selection = 0; + while (1) { + do { + COROUTINE_AWAIT(1, WaitForNMI_NoUpdate_Async()); + HandleMusicQueue(); + HandleSoundEffects(); + ReadJoypadInputs(); + } while (!joypad1_newkeys); + if ((joypad1_newkeys & kButton_A) != 0) + break; + if ((joypad1_newkeys & kButton_B) != 0) { + save_confirmation_selection = 2; + goto GETOUT; + } + if ((joypad1_newkeys & (kButton_Select | kButton_Left | kButton_Right)) != 0) { + ToggleSaveConfirmationSelection(); + QueueSfx1_Max6(0x37u); + } + } + } else { + my_counter = 10; + if (message_box_index != 20 && message_box_index != 21 && message_box_index != 22 && message_box_index != 24) + my_counter = 360; + do { + COROUTINE_AWAIT(2, WaitForNMI_NoUpdate_Async()); + HandleMusicQueue(); + HandleSoundEffects(); + } while (--my_counter); + do { + COROUTINE_AWAIT(3, WaitForNMI_NoUpdate_Async()); + ReadJoypadInputs(); + } while (!joypad1_newkeys); + } +GETOUT:; + COROUTINE_END(0); +} + +static const uint16 kSaveConfirmationSelectionTilemap[96] = { // 0x858507 + 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0x3c4e, 0x3c4e, 0x38cc, 0x38cd, 0x3cf8, 0x3ce4, 0x3cf2, 0x3c4e, 0x3c4e, 0x3c4e, + 0x3c4e, 0x3c4e, 0x3c4e, 0x2ced, 0x2cee, 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4e, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, + 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0x3c4e, 0x3c4e, 0x38cc, 0x38cd, 0x3cf8, 0x3ce4, 0x3cf2, 0x3c4e, 0x3c4e, 0x3c4e, + 0x3c4e, 0x3c4e, 0x3c4e, 0x2ced, 0x2cee, 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4e, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, + 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4e, 0x2cf8, 0x2ce4, 0x2cf2, 0x3c4e, 0x3c4e, 0x3c4e, + 0x3c4e, 0x38cc, 0x38cd, 0x3ced, 0x3cee, 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4e, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, +}; + +void ToggleSaveConfirmationSelection(void) { + save_confirmation_selection ^= 2u; + uint16 v0 = 64; + if (save_confirmation_selection == 2) + v0 = 128; + uint16 v1 = 128; + bg3_tilemap_offset = 32; + do { + ram3000.pause_menu_map_tilemap[v1 + 256] = kSaveConfirmationSelectionTilemap[v0 >> 1]; + ++v1; + v0 += 2; + --bg3_tilemap_offset; + } while (bg3_tilemap_offset); + bg3_tilemap_offset = addr_unk_6059A0; + WriteRegWord(VMADDL, addr_unk_6059A0); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1T1L, ADDR16_OF_RAM(ram3000) + 512); + WriteRegWord(A1B1, 0x7Eu); + WriteRegWord(DAS1L, 0x180u); + WriteRegWord(DAS10, 0); + WriteRegWord(A2A1H, 0); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 2u); +} + + +void MsgBoxMakeHdmaTable(void) { + message_box_animation_y2 = (uint16)(31488 - message_box_animation_y_radius) >> 8; + message_box_animation_y3 = 99; + message_box_animation_y0 = (uint16)(message_box_animation_y_radius + 31744) >> 8; + message_box_animation_y1 = 148; + uint16 v0 = 123; + uint16 v1 = 124; + R20_ = 30; + do { + ram3000.pause_menu_map_tilemap[v0] = message_box_animation_y3 - message_box_animation_y2; + --message_box_animation_y3; + --message_box_animation_y2; + ram3000.pause_menu_map_tilemap[v1] = message_box_animation_y1 - message_box_animation_y0; + --v0; + ++message_box_animation_y1; + ++message_box_animation_y0; + ++v1; + --R20_; + } while (R20_); + uint16 v2 = v1 * 2; + do { + *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + v2) = 0; + v2 += 2; + } while ((int16)(v2 - 480) < 0); +} + +void RestorePpuForMessageBox(void) { // 0x85861A + WriteRegWord(VMADDL, addr_unk_605880); + WriteRegWord(DMAP1, 0x1801u); + WriteRegWord(A1T1L, ADDR16_OF_RAM(ram4000) + 256); + WriteRegWord(A1B1, 0x7Eu); + WriteRegWord(DAS1L, 0x700u); + WriteRegWord(DAS10, 0); + WriteRegWord(A2A1H, 0); + WriteReg(VMAIN, 0x80); + WriteReg(MDMAEN, 2u); + reg_HDMAEN = ram3000.msgbox.backup_of_enabled_hdma_channels; + WriteReg(HDMAEN, ram3000.msgbox.backup_of_enabled_hdma_channels); + gameplay_BG3SC = ram3000.misc.field_3E8[3]; + gameplay_TM = reg_TM; + gameplay_CGWSEL = next_gameplay_CGWSEL; + gameplay_CGADSUB = next_gameplay_CGADSUB; + WriteReg(CGADD, 0x19u); + WriteReg(CGDATA, palette_buffer[25]); + WriteReg(CGDATA, HIBYTE(palette_buffer[25])); + WriteReg(CGDATA, palette_buffer[26]); + WriteReg(CGDATA, HIBYTE(palette_buffer[26])); +} diff --git a/src/sm_86.c b/src/sm_86.c new file mode 100644 index 0000000..9e7ea3e --- /dev/null +++ b/src/sm_86.c @@ -0,0 +1,5957 @@ +// Enemy projectiles +#include "ida_types.h" +#include "variables.h" +#include "sm_rtl.h" +#include "funcs.h" +#include "enemy_types.h" + +#define kScreenShakeOffsets ((uint16*)RomPtr(0x86846b)) +#define kAlignYPos_Tab0 ((uint8*)RomPtr(0x948b2b)) +#define kAlignPos_Tab1 ((uint8*)RomPtr(0x94892b)) +#define off_868A75 ((uint16*)RomPtr(0x868a75)) +#define word_869105 ((uint16*)RomPtr(0x869105)) +#define off_86A64D ((uint16*)RomPtr(0x86a64d)) +#define stru_86BB50 (*(EnemyProjectileDef*)RomPtr(0x86bb50)) +#define off_86BB1E ((uint16*)RomPtr(0x86bb1e)) +#define kCommonEnemySpeeds_Quadratic_Copy ((uint16*)RomPtr(0xa0cbc7)) +#define off_86C040 ((uint16*)RomPtr(0x86c040)) +#define off_86C929 ((uint16*)RomPtr(0x86c929)) + +void EnableEnemyProjectiles(void) { // 0x868000 + enemy_projectile_enable_flag |= 0x8000u; +} + +void DisableEnemyProjectiles(void) { // 0x86800B + enemy_projectile_enable_flag &= ~0x8000u; +} + +void ClearEnemyProjectiles(void) { // 0x868016 + for (int i = 34; i >= 0; i -= 2) + enemy_projectile_id[i >> 1] = 0; +} + +void CallEnemyProjectileInit(uint32 ea, uint16 j) { + switch (ea) { + case fnEnemyProj_Init_0x8aaf: EnemyProj_Init_0x8aaf(j); return; + case fnEnemyProj_Init_0x8bc2_SkreeDownRight: EnemyProj_Init_0x8bc2_SkreeDownRight(j); return; + case fnEnemyProj_Init_0x8bd0_SkreeUpRight: EnemyProj_Init_0x8bd0_SkreeUpRight(j); return; + case fnEnemyProj_Init_0x8bde_SkreeDownLeft: EnemyProj_Init_0x8bde_SkreeDownLeft(j); return; + case fnEnemyProj_Init_0x8bec_SkreeUpLeft: EnemyProj_Init_0x8bec_SkreeUpLeft(j); return; + case fnEprojInit_DraygonsGunk: EprojInit_DraygonsGunk(j); return; + case fnEprojInit_DraygonsWallTurretProjs: EprojInit_DraygonsWallTurretProjs(j); return; + case fnEprojInit_8E6C: EprojInit_8E6C(j); return; + case fnEprojInit_CrocomireProjectile: EprojInit_CrocomireProjectile(j); return; + case fnEprojInit_CrocomireSpikeWallPieces: EprojInit_CrocomireSpikeWallPieces(j); return; + case fnEprojInit_CrocomireBridgeCrumbling: EprojInit_CrocomireBridgeCrumbling(j); return; + case fnEprojInit_9634: EprojInit_9634(j); return; + case fnEprojInit_9642_RidleysFireball: EprojInit_9642_RidleysFireball(j); return; + case fnEprojInit_9660_FireballExplosion: EprojInit_9660_FireballExplosion(j); return; + case fnEprojInit_9688: EprojInit_9688(j); return; + case fnEprojInit_9696: EprojInit_9696(j); return; + case fnEprojInit_966C: EprojInit_966C(j); return; + case fnEprojInit_967A: EprojInit_967A(j); return; + case fnEprojInit_9734_CeresFallingDebris: EprojInit_9734_CeresFallingDebris(j); return; + case fnEprojInit_PhantoonDestroyableFireballs: EprojInit_PhantoonDestroyableFireballs(j); return; + case fnEprojInit_PhantoonStartingFireballs: EprojInit_PhantoonStartingFireballs(j); return; + case fnEprojInit_RocksKraidSpits: EprojInit_RocksKraidSpits(j); return; + case fnEprojInit_RocksFallingKraidCeiling: EprojInit_RocksFallingKraidCeiling(j); return; + case fnEprojInit_RocksWhenKraidRises: EprojInit_RocksWhenKraidRises(j); return; + case fnEprojInit_MiniKraidSpit: EprojInit_MiniKraidSpit(j); return; + case fnEprojInit_MiniKraidSpikesLeft: EprojInit_MiniKraidSpikesLeft(j); return; + case fnEprojInit_MiniKraidSpikesRight: EprojInit_MiniKraidSpikesRight(j); return; + case fnEprojInit_WalkingLavaSeahorseFireball: EprojInit_WalkingLavaSeahorseFireball(j); return; + case fnEprojInit_PirateMotherBrainLaser: EprojInit_PirateMotherBrainLaser(j); return; + case fnEprojInit_PirateClaw: EprojInit_PirateClaw(j); return; + case fnEprojInit_A379: EprojInit_A379(j); return; + case fnEprojInit_CeresElevatorPad: EprojInit_CeresElevatorPad(j); return; + case fnEprojInit_CeresElevatorPlatform: EprojInit_CeresElevatorPlatform(j); return; + case fnEprojPreInstr_PrePhantomRoom: EprojPreInstr_PrePhantomRoom(j); return; + case fnEprojInit_BombTorizoLowHealthDrool: EprojInit_BombTorizoLowHealthDrool(j); return; + case fnEprojInit_BombTorizoLowHealthInitialDrool: EprojInit_BombTorizoLowHealthInitialDrool(j); return; + case fnEprojInit_A977: EprojInit_A977(j); return; + case fnEprojInit_BombTorizoExplosiveSwipe: EprojInit_BombTorizoExplosiveSwipe(j); return; + case fnEprojInit_BombTorizoStatueBreaking: EprojInit_BombTorizoStatueBreaking(j); return; + case fnEprojInit_BombTorizoLowHealthExplode: EprojInit_BombTorizoLowHealthExplode(j); return; + case fnEprojInit_BombTorizoDeathExplosion: EprojInit_BombTorizoDeathExplosion(j); return; + case fnEprojInit_AB07: EprojInit_AB07(j); return; + case fnEprojInit_BombTorizosChozoOrbs: EprojInit_BombTorizosChozoOrbs(j); return; + case fnEprojInit_GoldenTorizosChozoOrbs: EprojInit_GoldenTorizosChozoOrbs(j); return; + case fnEprojInit_TorizoSonicBoom: EprojInit_TorizoSonicBoom(j); return; + case fnEprojInit_WreckedShipChozoSpikeFootsteps: EprojInit_WreckedShipChozoSpikeFootsteps(j); return; + case fnEprojInit_TourianStatueDustClouds: EprojInit_TourianStatueDustClouds(j); return; + case fnEprojInit_TourianLandingDustCloudsRightFoot: EprojInit_TourianLandingDustCloudsRightFoot(j); return; + case fnEprojInit_TorizoLandingDustCloudLeftFoot: EprojInit_TorizoLandingDustCloudLeftFoot(j); return; + case fnEprojInit_GoldenTorizoEgg: EprojInit_GoldenTorizoEgg(j); return; + case fnEprojInit_GoldenTorizoSuperMissile: EprojInit_GoldenTorizoSuperMissile(j); return; + case fnEprojInit_GoldenTorizoEyeBeam: EprojInit_GoldenTorizoEyeBeam(j); return; + case fnEprojInit_TourianEscapeShaftFakeWallExplode: EprojInit_TourianEscapeShaftFakeWallExplode(j); return; + case fnEprojInit_LavaSeahorseFireball: EprojInit_LavaSeahorseFireball(j); return; + case fnEprojInit_EyeDoorProjectile: EprojInit_EyeDoorProjectile(j); return; + case fnEprojInit_EyeDoorSweat: EprojInit_EyeDoorSweat(j); return; + case fnEprojInit_TourianStatueUnlockingParticleWaterSplash: EprojInit_TourianStatueUnlockingParticleWaterSplash(j); return; + case fnEprojInit_TourianStatueEyeGlow: EprojInit_TourianStatueEyeGlow(j); return; + case fnEprojInit_TourianStatueUnlockingParticle: EprojInit_TourianStatueUnlockingParticle(j); return; + case fnEprojIni_TourianStatueUnlockingParticleTail: EprojIni_TourianStatueUnlockingParticleTail(j); return; + case fnEprojInit_TourianStatueSoul: EprojInit_TourianStatueSoul(j); return; + case fnEprojInit_TourianStatueBaseDecoration: EprojInit_TourianStatueBaseDecoration(j); return; + case fnEprojInit_TourianStatueRidley: EprojInit_TourianStatueRidley(j); return; + case fnEprojInit_TourianStatuePhantoon: EprojInit_TourianStatuePhantoon(j); return; + case fnsub_86BB30: sub_86BB30(j); return; + case fnEprojInit_NuclearWaffleBody: EprojInit_NuclearWaffleBody(j); return; + case fnEprojInit_NorfairLavaquakeRocks: EprojInit_NorfairLavaquakeRocks(j); return; + case fnEprojInit_ShaktoolAttackMiddleBackCircle: EprojInit_ShaktoolAttackMiddleBackCircle(j); return; + case fnEprojInit_BDA2: EprojInit_BDA2(j); return; + case fnEprojInit_MotherBrainRoomTurrets: EprojInit_MotherBrainRoomTurrets(j); return; + case fnEprojInit_MotherBrainRoomTurretBullets: EprojInit_MotherBrainRoomTurretBullets(j); return; + case fnEproj_MotherBrainsBlueRingLasers: Eproj_MotherBrainsBlueRingLasers(j); return; + case fnEprojInit_MotherBrainBomb: EprojInit_MotherBrainBomb(j); return; + case fnsub_86C605: sub_86C605(j); return; + case fnEprojInit_MotherBrainDeathBeemFired: EprojInit_MotherBrainDeathBeemFired(j); return; + case fnEprojInit_MotherBrainRainbowBeam: EprojInit_MotherBrainRainbowBeam(j); return; + case fnEprojInit_MotherBrainsDrool: EprojInit_MotherBrainsDrool(j); return; + case fnEprojInit_MotherBrainsDeathExplosion: EprojInit_MotherBrainsDeathExplosion(j); return; + case fnEprojInit_MotherBrainsRainbowBeamExplosion: EprojInit_MotherBrainsRainbowBeamExplosion(j); return; + case fnEprojInit_MotherBrainEscapeDoorParticles: EprojInit_MotherBrainEscapeDoorParticles(j); return; + case fnEprojInit_MotherBrainPurpleBreathBig: EprojInit_MotherBrainPurpleBreathBig(j); return; + case fnEprojInit_MotherBrainPurpleBreathSmall: EprojInit_MotherBrainPurpleBreathSmall(j); return; + case fnEprojInit_TimeBombSetJapaneseText: EprojInit_TimeBombSetJapaneseText(j); return; + case fnEprojInit_MotherBrainTubeFalling: EprojInit_MotherBrainTubeFalling(j); return; + case fnEprojInit_MotherBrainGlassShatteringShard: EprojInit_MotherBrainGlassShatteringShard(j); return; + case fnEprojInit_MotherBrainGlassShatteringSparkle: EprojInit_MotherBrainGlassShatteringSparkle(j); return; + case fnEprojInit_KiHunterAcidSpitLeft: EprojInit_KiHunterAcidSpitLeft(j); return; + case fnEprojInit_KiHunterAcidSpitRight: EprojInit_KiHunterAcidSpitRight(j); return; + case fnEprojInit_KagosBugs: EprojInit_KagosBugs(j); return; + case fnEprojInit_MaridiaFloatersSpikes: EprojInit_MaridiaFloatersSpikes(j); return; + case fnEprojInit_WreckedShipRobotLaserDown: EprojInit_WreckedShipRobotLaserDown(j); return; + case fnEprojInit_WreckedShipRobotLaserHorizontal: EprojInit_WreckedShipRobotLaserHorizontal(j); return; + case fnEprojInit_WreckedShipRobotLaserUp: EprojInit_WreckedShipRobotLaserUp(j); return; + case fnEprojInit_N00bTubeCrack: EprojInit_N00bTubeCrack(j); return; + case fnEprojInit_N00bTubeShards: EprojInit_N00bTubeShards(j); return; + case fnEprojInit_N00bTubeReleasedAirBubbles: EprojInit_N00bTubeReleasedAirBubbles(j); return; + case fnsub_86D992: sub_86D992(j); return; + case fnEprojInit_DBF2: EprojInit_DBF2(j); return; + case fnEprojInit_Spores: EprojInit_Spores(j); return; + case fnEprojInit_SporeSpawnStalk: EprojInit_SporeSpawnStalk(j); return; + case fnEprojInit_SporeSpawners: EprojInit_SporeSpawners(j); return; + case fnEprojInit_NamiFuneFireball: EprojInit_NamiFuneFireball(j); return; + case fnEprojInit_LavaThrownByLavaman: EprojInit_LavaThrownByLavaman(j); return; + case fnEprojInst_DustCloudOrExplosion: EprojInst_DustCloudOrExplosion(j); return; + case fnEprojInit_EyeDoorSmoke: EprojInit_EyeDoorSmoke(j); return; + case fnEprojInit_SpawnedShotGate: EprojInit_SpawnedShotGate(j); return; + case fnEprojInit_ClosedDownwardsShotGate: EprojInit_ClosedDownwardsShotGate(j); return; + case fnEprojInit_ClosedUpwardsShotGate: EprojInit_ClosedUpwardsShotGate(j); return; + case fnEprojInit_SaveStationElectricity: EprojInit_SaveStationElectricity(j); return; + case fnEprojInit_BotwoonsBody: EprojInit_BotwoonsBody(j); return; + case fnEprojInit_BotwoonsSpit: EprojInit_BotwoonsSpit(j); return; + case fnEprojInit_YappingMawsBody: EprojInit_YappingMawsBody(j); return; + case fnEprojInit_F337: EprojInit_F337(j); return; + case fnEprojInit_EnemyDeathExplosion: EprojInit_EnemyDeathExplosion(j); return; + case fnEprojInit_Sparks: EprojInit_Sparks(j); return; + default: Unreachable(); + } +} +void SpawnEnemyProjectileWithGfx(uint16 a, uint16 k, uint16 j) { // 0x868027 + EnemyProjectileDef *EnemyProjectileDef; + + enemy_projectile_init_param = a; + EnemyData *v3 = gEnemyData(k); + uint16 v5 = 34; + while (enemy_projectile_id[v5 >> 1]) { + v5 -= 2; + if ((v5 & 0x8000u) != 0) + return; + } + int v6 = v5 >> 1; + enemy_projectile_gfx_idx[v6] = v3->vram_tiles_index | v3->palette_index; + enemy_projectile_id[v6] = j; + EnemyProjectileDef = get_EnemyProjectileDef(j); + enemy_projectile_pre_instr[v6] = EnemyProjectileDef->pre_instr_ptr; + enemy_projectile_instr_list_ptr[v6] = EnemyProjectileDef->instr_list; + enemy_projectile_radius[v6] = EnemyProjectileDef->radius; + enemy_projectile_properties[v6] = EnemyProjectileDef->properties; + enemy_projectile_instr_timers[v6] = 1; + enemy_projectile_spritemap_ptr[v6] = 0x8000; + enemy_projectile_E[v6] = 0; + enemy_projectile_F[v6] = 0; + enemy_projectile_timers[v6] = 0; + enemy_projectile_1A27[v6] = 0; + enemy_projectile_y_subpos[v6] = 0; + enemy_projectile_G[v6] = 0; + CallEnemyProjectileInit(EnemyProjectileDef->init_code_ptr | 0x860000, v5); +} + +void SpawnEnemyProjectileWithRoomGfx(uint16 j, uint16 a) { // 0x868097 + EnemyProjectileDef *EnemyProjectileDef; + + enemy_projectile_init_param = a; + uint16 v3 = 34; + while (enemy_projectile_id[v3 >> 1]) { + v3 -= 2; + if ((v3 & 0x8000u) != 0) + return; + } + int v4 = v3 >> 1; + enemy_projectile_gfx_idx[v4] = 0; + enemy_projectile_id[v4] = j; + EnemyProjectileDef = get_EnemyProjectileDef(j); + enemy_projectile_pre_instr[v4] = EnemyProjectileDef->pre_instr_ptr; + enemy_projectile_instr_list_ptr[v4] = EnemyProjectileDef->instr_list; + enemy_projectile_radius[v4] = EnemyProjectileDef->radius; + enemy_projectile_properties[v4] = EnemyProjectileDef->properties; + enemy_projectile_instr_timers[v4] = 1; + enemy_projectile_spritemap_ptr[v4] = 0x8000; + enemy_projectile_E[v4] = 0; + enemy_projectile_F[v4] = 0; + enemy_projectile_timers[v4] = 0; + enemy_projectile_timers[v4] = 0; + enemy_projectile_1A27[v4] = 0; + enemy_projectile_y_subpos[v4] = 0; + enemy_projectile_G[v4] = 0; + CallEnemyProjectileInit(EnemyProjectileDef->init_code_ptr | 0x860000, v3); +} + +void EprojRunAll(void) { // 0x868104 + if ((enemy_projectile_enable_flag & 0x8000u) != 0) { + for (int i = 34; i >= 0; i -= 2) { + enemy_projectile_index = i; + if (enemy_projectile_id[i >> 1]) { + EprojRunOne(i); + i = enemy_projectile_index; + } + } + } +} + +void CallEprojPreInstr(uint32 ea, uint16 k) { + switch (ea) { + case fnnullsub_352: return; + case fnEprojPreInstr_nullsub_297: return; + case fnEprojPreInstr_nullsub_83: return; + case fnEnemyProj_PreInit_0x8aaf: EnemyProj_PreInit_0x8aaf(k); return; + case fnEnemyProj_PreInstr_SkreeParticle: EnemyProj_PreInstr_SkreeParticle(k); return; + case fnnullsub_84: return; + case fnEprojPreInstr_8DCA: EprojPreInstr_8DCA(k); return; + case fnEprojPreInstr_DraygonsTurret_8DFF: EprojPreInstr_DraygonsTurret_8DFF(k); return; + case fnEprojPreInstr_DraygonsGunk_8E0F: EprojPreInstr_DraygonsGunk_8E0F(k); return; + case fnEprojPreInstr_8E6C: EprojPreInstr_8E6C(k); return; + case fnEprojPreInstr_CrocomireProjectile: EprojPreInstr_CrocomireProjectile(k); return; + case fnsub_8690B3: sub_8690B3(k); return; + case fnEprojPreInstr_CrocomireSpikeWallPieces: EprojPreInstr_CrocomireSpikeWallPieces(k); return; + case fnEprojPreInstr_CrocomireBridgeCrumbling: EprojPreInstr_CrocomireBridgeCrumbling(k); return; + case fnEprojPreInstr_9634: EprojPreInstr_9634(k); return; + case fnEprojPreInstr_9642_RidleysFireball: EprojPreInstr_9642_RidleysFireball(k); return; + case fnnullsub_85: return; + case fnEprojPreInstr_966C: EprojPreInstr_966C(k); return; + case fnEprojPreInstr_9688: EprojPreInstr_9688(k); return; + case fnEprojPreInstr_96A4: EprojPreInstr_96A4(k); return; + case fnEprojPreInstr_96C0: EprojPreInstr_96C0(k); return; + case fnEprojPreInstr_96CE: EprojPreInstr_96CE(k); return; + case fnEprojPreInstr_9734_CeresFallingDebris: EprojPreInstr_9734_CeresFallingDebris(k); return; + case fnEprojPreInstr_PhantoonStartingFireballs: EprojPreInstr_PhantoonStartingFireballs(k); return; + case fnEprojPreInstr_PhantoonStartingFireballs2: EprojPreInstr_PhantoonStartingFireballs2(k); return; + case fnEprojPreInstr_PhantoonStartingFireballs3: EprojPreInstr_PhantoonStartingFireballs3(k); return; + case fnnullsub_86: return; + case fnEprojPreInstr_PhantoonDestroyableFireballs: EprojPreInstr_PhantoonDestroyableFireballs(k); return; + case fnEprojPreInstr_PhantoonDestroyableFireballs_2: EprojPreInstr_PhantoonDestroyableFireballs_2(k); return; + case fnEprojPreInstr_PhantoonDestroyableFireballs_3: EprojPreInstr_PhantoonDestroyableFireballs_3(k); return; + case fnEprojPreInstr_PhantoonStartingFireballsB: EprojPreInstr_PhantoonStartingFireballsB(k); return; + case fnEprojPreInstr_PhantoonStartingFireballsB_2: EprojPreInstr_PhantoonStartingFireballsB_2(k); return; + case fnEprojPreInstr_KraidRocks: EprojPreInstr_KraidRocks(k); return; + case fnEprojPreInstr_RocksFallingKraidCeiling: EprojPreInstr_RocksFallingKraidCeiling(k); return; + case fnsub_869DA5: sub_869DA5(k); return; + case fnEprojPreInit_MiniKraidSpit: EprojPreInit_MiniKraidSpit(k); return; + case fnEprojPreInstr_MiniKraidSpikes: EprojPreInstr_MiniKraidSpikes(k); return; + case fnEprojPreInstr_WalkingLavaSeahorseFireball: EprojPreInstr_WalkingLavaSeahorseFireball(k); return; + case fnnullsub_87: return; + case fnEprojPreInstr_PirateMotherBrainLaser_MoveLeft: EprojPreInstr_PirateMotherBrainLaser_MoveLeft(k); return; + case fnEprojPreInstr_PirateMotherBrainLaser_MoveRight: EprojPreInstr_PirateMotherBrainLaser_MoveRight(k); return; + case fnEprojPreInstr_PirateClawThrownLeft: EprojPreInstr_PirateClawThrownLeft(k); return; + case fnEprojPreInstr_PirateClawThrownRight: EprojPreInstr_PirateClawThrownRight(k); return; + case fnnullsub_88: return; + case fnEprojPreInstr_CeresElevatorPad: EprojPreInstr_CeresElevatorPad(k); return; + case fnEprojPreInstr_CeresElevatorPlatform: EprojPreInstr_CeresElevatorPlatform(k); return; + case fnEprojPreInstr_PrePhantomRoom: EprojPreInstr_PrePhantomRoom(k); return; + case fnsub_86A887: sub_86A887(k); return; + case fnEprojPreInstr_A977: EprojPreInstr_A977(k); return; + case fnnullsub_89: return; + case fnEprojPreInstr_AB07: EprojPreInstr_AB07(k); return; + case fnEprojPreInstr_BombTorizosChozoOrbs: EprojPreInstr_BombTorizosChozoOrbs(k); return; + case fnEprojPreInstr_GoldenTorizosChozoOrbs: EprojPreInstr_GoldenTorizosChozoOrbs(k); return; + case fnEprojPreInstr_TorizoSonicBoom: EprojPreInstr_TorizoSonicBoom(k); return; + case fnEprojPreInstr_GoldenTorizoEgg: EprojPreInstr_GoldenTorizoEgg(k); return; + case fnsub_86B0B9: sub_86B0B9(k); return; + case fnsub_86B0DD: sub_86B0DD(k); return; + case fnEprojPreInstr_GoldenTorizoSuperMissile: EprojPreInstr_GoldenTorizoSuperMissile(k); return; + case fnEprojPreInstr_B237: EprojPreInstr_B237(k); return; + case fnEprojPreInstr_GoldenTorizoEyeBeam: EprojPreInstr_GoldenTorizoEyeBeam(k); return; + case fnnullsub_90: return; + case fnsub_86B535: sub_86B535(k); return; + case fnEprojPreInstr_EyeDoorProjectile: EprojPreInstr_EyeDoorProjectile(k); return; + case fnEprojPreInstr_EyeDoorSweat: EprojPreInstr_EyeDoorSweat(k); return; + case fnEprojPreInstr_TourianStatueUnlockingParticleWaterSplash: EprojPreInstr_TourianStatueUnlockingParticleWaterSplash(k); return; + case fnEprojPreInstr_TourianStatueUnlockingParticle: EprojPreInstr_TourianStatueUnlockingParticle(k); return; + case fnEprojPreInstr_TourianStatueSoul: EprojPreInstr_TourianStatueSoul(k); return; + case fnEprojPreInstr_TourianStatueStuff: EprojPreInstr_TourianStatueStuff(k); return; + case fnEprojPreInstr_BA42: EprojPreInstr_BA42(k); return; + case fnnullsub_91: return; + case fnnullsub_92: return; + case fnEprojPreInstr_NorfairLavaquakeRocks: EprojPreInstr_NorfairLavaquakeRocks(k); return; + case fnEprojPreInstr_NorfairLavaquakeRocks_Inner: EprojPreInstr_NorfairLavaquakeRocks_Inner(k); return; + case fnEprojPreInstr_NorfairLavaquakeRocks_Inner2: EprojPreInstr_NorfairLavaquakeRocks_Inner2(k); return; + case fnEprojInit_ShaktoolAttackFrontCircle: EprojInit_ShaktoolAttackFrontCircle(k); return; + case fnEprojPreInstr_BE12: EprojPreInstr_BE12(k); return; + case fnEprojPreInstr_MotherBrainRoomTurrets: EprojPreInstr_MotherBrainRoomTurrets(k); return; + case fnEprojPreInstr_MotherBrainRoomTurretBullets: EprojPreInstr_MotherBrainRoomTurretBullets(k); return; + case fnEproj_MoveToBlueRingSpawnPosition: Eproj_MoveToBlueRingSpawnPosition(k); return; + case fnEprojPreInstr_MotherBrainBomb: EprojPreInstr_MotherBrainBomb(k); return; + case fnEprojPreInstr_MotherBrainRainbowBeam: EprojPreInstr_MotherBrainRainbowBeam(k); return; + case fnEprojPreInstr_C84D: EprojPreInstr_C84D(k); return; + case fnEprojInit_MotherBrainsDrool_Falling: EprojInit_MotherBrainsDrool_Falling(k); return; + case fnEprojPreInit_MotherBrainsDeathExplosion_0: EprojPreInit_MotherBrainsDeathExplosion_0(k); return; + case fnEprojPreInstr_MotherBrainsRainbowBeamExplosion: EprojPreInstr_MotherBrainsRainbowBeamExplosion(k); return; + case fnEprojPreInstr_MotherBrainsExplodedDoorParticles: EprojPreInstr_MotherBrainsExplodedDoorParticles(k); return; + case fnnullsub_94: return; + case fnEprojPreInstr_TimeBombSetJapaneseText: EprojPreInstr_TimeBombSetJapaneseText(k); return; + case fnEprojPreInstr_MotherBrainTubeFalling: EprojPreInstr_MotherBrainTubeFalling(k); return; + case fnEprojPreInstr_MotherBrainGlassShatteringShard: EprojPreInstr_MotherBrainGlassShatteringShard(k); return; + case fnsub_86CFD5: sub_86CFD5(k); return; + case fnsub_86CFE6: sub_86CFE6(k); return; + case fnnullsub_95: return; + case fnsub_86CFF8: sub_86CFF8(k); return; + case fnEprojPreInstr_KagosBugs_Func1: EprojPreInstr_KagosBugs_Func1(k); return; + case fnEprojPreInstr_KagosBugs: EprojPreInstr_KagosBugs(k); return; + case fnnullsub_302: return; + case fnEprojPreInstr_D0EC: EprojPreInstr_D0EC(k); return; + case fnEprojPreInstr_D128: EprojPreInstr_D128(k); return; + case fnEprojPreInstr_KagosBugs_Func2: EprojPreInstr_KagosBugs_Func2(k); return; + case fnEprojPreInstr_MaridiaFloatersSpikes: EprojPreInstr_MaridiaFloatersSpikes(k); return; + case fnEprojPreInstr_WreckedShipRobotLaser: EprojPreInstr_WreckedShipRobotLaser(k); return; + case fnsub_86D7BF: sub_86D7BF(k); return; + case fnsub_86D7DE: sub_86D7DE(k); return; + case fnEprojPreInstr_N00bTubeShards: EprojPreInstr_N00bTubeShards(k); return; + case fnsub_86D83D: sub_86D83D(k); return; + case fnsub_86D89F: sub_86D89F(k); return; + case fnsub_86D8DF: sub_86D8DF(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes: EprojPreInstr_SpikeShootingPlantSpikes(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_MoveY1: EprojPreInstr_SpikeShootingPlantSpikes_MoveY1(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_MoveY2: EprojPreInstr_SpikeShootingPlantSpikes_MoveY2(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_MoveX1: EprojPreInstr_SpikeShootingPlantSpikes_MoveX1(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_MoveX2: EprojPreInstr_SpikeShootingPlantSpikes_MoveX2(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_0_MoveX1: EprojPreInstr_SpikeShootingPlantSpikes_0_MoveX1(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_2_MoveX2: EprojPreInstr_SpikeShootingPlantSpikes_2_MoveX2(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_1_MoveY1: EprojPreInstr_SpikeShootingPlantSpikes_1_MoveY1(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_4_MoveY2: EprojPreInstr_SpikeShootingPlantSpikes_4_MoveY2(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_6_MoveX1Y1: EprojPreInstr_SpikeShootingPlantSpikes_6_MoveX1Y1(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_8_MoveX1Y2: EprojPreInstr_SpikeShootingPlantSpikes_8_MoveX1Y2(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_7_MoveX2Y1: EprojPreInstr_SpikeShootingPlantSpikes_7_MoveX2Y1(k); return; + case fnEprojPreInstr_SpikeShootingPlantSpikes_9_MoveX2Y2: EprojPreInstr_SpikeShootingPlantSpikes_9_MoveX2Y2(k); return; + case fnEprojPreInstr_DBF2: EprojPreInstr_DBF2(k); return; + case fnEprojPreInstr_DBF2_MoveX1: EprojPreInstr_DBF2_MoveX1(k); return; + case fnEprojPreInstr_DBF2_MoveX2: EprojPreInstr_DBF2_MoveX2(k); return; + case fnEprojPreInstr_DBF2_Func1: EprojPreInstr_DBF2_Func1(k); return; + case fnEprojPreInstr_Spores: EprojPreInstr_Spores(k); return; + case fnnullsub_96: return; + case fnEprojPreInstr_SporeSpawners: EprojPreInstr_SporeSpawners(k); return; + case fnEprojPreInstr_NamiFuneFireball: EprojPreInstr_NamiFuneFireball(k); return; + case fnsub_86E049: sub_86E049(k); return; + case fnEprojPreInstr_DustCloudOrExplosion: EprojPreInstr_DustCloudOrExplosion(k); return; + case fnEprojPreInstr_nullsub_98: return; + case fnEprojPreInstr_nullsub_99: return; + case fnEprojPreInstr_E605: EprojPreInstr_E605(k); return; + case fnnullsub_100: return; + case fnEprojPreInstr_BotwoonsBody: EprojPreInstr_BotwoonsBody(k); return; + case fnEprojPreInstr_BotwoonsSpit: EprojPreInstr_BotwoonsSpit(k); return; + case fnEprojPreInstr_Empty2: return; + case fnEprojPreInstr_Empty: return; + case fnEprojPreInstr_Pickup: EprojPreInstr_Pickup(k); return; + case fnEprojPreInstr_Sparks: EprojPreInstr_Sparks(k); return; + case fnnullsub_366: return; + default: Unreachable(); + } +} +uint16 CallEprojInstr(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnEprojInstr_Delete: return EprojInstr_Delete(k, j); + case fnEprojInstr_Sleep: return EprojInstr_Sleep(k, j); + case fnEprojInstr_SetPreInstr_: return EprojInstr_SetPreInstr_(k, j); + case fnEprojInstr_ClearPreInstr: return EprojInstr_ClearPreInstr(k, j); + case fnEprojInstr_CallFunc: return EprojInstr_CallFunc(k, j); + case fnEprojInstr_Goto: return EprojInstr_Goto(k, j); + case fnEprojInstr_GotoRel: return EprojInstr_GotoRel(k, j); + case fnEprojInstr_DecTimerAndGotoIfNonZero: return EprojInstr_DecTimerAndGotoIfNonZero(k, j); + case fnEprojInstr_DecTimerAndGotoRelIfNonZero: return EprojInstr_DecTimerAndGotoRelIfNonZero(k, j); + case fnEprojInstr_SetTimer: return EprojInstr_SetTimer(k, j); + case fnEprojInstr_MoveRandomlyWithinRadius: return EprojInstr_MoveRandomlyWithinRadius(k, j); + case fnEprojInstr_SetProjectileProperties: return EprojInstr_SetProjectileProperties(k, j); + case fnEprojInstr_ClearProjectileProperties: return EprojInstr_ClearProjectileProperties(k, j); + case fnEprojInstr_EnableCollisionWithSamusProj: return EprojInstr_EnableCollisionWithSamusProj(k, j); + case fnEprojInstr_DisableCollisionWithSamusProj: return EprojInstr_DisableCollisionWithSamusProj(k, j); + case fnEprojInstr_DisableCollisionWithSamus: return EprojInstr_DisableCollisionWithSamus(k, j); + case fnEprojInstr_EnableCollisionWithSamus: return EprojInstr_EnableCollisionWithSamus(k, j); + case fnEprojInstr_SetToNotDieOnContact: return EprojInstr_SetToNotDieOnContact(k, j); + case fnEprojInstr_SetToDieOnContact: return EprojInstr_SetToDieOnContact(k, j); + case fnEprojInstr_SetLowPriority: return EprojInstr_SetLowPriority(k, j); + case fnEprojInstr_SetHighPriority: return EprojInstr_SetHighPriority(k, j); + case fnEprojInstr_SetXyRadius: return EprojInstr_SetXyRadius(k, j); + case fnEprojInstr_SetXyRadiusZero: return EprojInstr_SetXyRadiusZero(k, j); + case fnEprojInstr_CalculateDirectionTowardsSamus: return EprojInstr_CalculateDirectionTowardsSamus(k, j); + case fnEprojInstr_WriteColorsToPalette: return EprojInstr_WriteColorsToPalette(k, j); + case fnEprojInstr_QueueMusic: return EprojInstr_QueueMusic(k, j); + case fnEprojInstr_QueueSfx1_Max6: return EprojInstr_QueueSfx1_Max6(k, j); + case fnEprojInstr_QueueSfx2_Max6: return EprojInstr_QueueSfx2_Max6(k, j); + case fnEprojInstr_QueueSfx3_Max6: return EprojInstr_QueueSfx3_Max6(k, j); + case fnEprojInstr_QueueSfx1_Max15: return EprojInstr_QueueSfx1_Max15(k, j); + case fnEprojInstr_QueueSfx2_Max15: return EprojInstr_QueueSfx2_Max15(k, j); + case fnEprojInstr_QueueSfx3_Max15: return EprojInstr_QueueSfx3_Max15(k, j); + case fnEprojInstr_QueueSfx1_Max3: return EprojInstr_QueueSfx1_Max3(k, j); + case fnEprojInstr_QueueSfx2_Max3: return EprojInstr_QueueSfx2_Max3(k, j); + case fnEprojInstr_QueueSfx3_Max3: return EprojInstr_QueueSfx3_Max3(k, j); + case fnEprojInstr_QueueSfx1_Max9: return EprojInstr_QueueSfx1_Max9(k, j); + case fnEprojInstr_QueueSfx2_Max9: return EprojInstr_QueueSfx2_Max9(k, j); + case fnEprojInstr_QueueSfx3_Max9: return EprojInstr_QueueSfx3_Max9(k, j); + case fnEprojInstr_QueueSfx1_Max1: return EprojInstr_QueueSfx1_Max1(k, j); + case fnEprojInstr_QueueSfx2_Max1: return EprojInstr_QueueSfx2_Max1(k, j); + case fnEprojInstr_QueueSfx3_Max1: return EprojInstr_QueueSfx3_Max1(k, j); + case fnEprojInstr_868D55: return EprojInstr_868D55(k, j); + case fnEprojInstr_868D99: return EprojInstr_868D99(k, j); + case fnEprojInstr_DisableCollisionsWithSamus: return EprojInstr_DisableCollisionsWithSamus(k, j); + case fnEprojInstr_95BA: return EprojInstr_95BA(k, j); + case fnEprojInstr_95ED: return EprojInstr_95ED(k, j); + case fnEprojInstr_9620: return EprojInstr_9620(k, j); + case fnEprojInstr_980E: return EprojInstr_980E(k, j); + case fnEprojInstr_SetPreInstrAndRun: return EprojInstr_SetPreInstrAndRun(k, j); + case fnEprojInstr_GotoWithProbability25: return EprojInstr_GotoWithProbability25(k, j); + case fnEprojInstr_SpawnEnemyDrops: return EprojInstr_SpawnEnemyDrops(k, j); + case fnEprojInstr_GotoDependingOnXDirection: return EprojInstr_GotoDependingOnXDirection(k, j); + case fnEprojInstr_ResetXYpos1: return EprojInstr_ResetXYpos1(k, j); + case fnEprojInstr_MoveY_Minus4: return EprojInstr_MoveY_Minus4(k, j); + case fnEprojInstr_GotoIfFunc1: return EprojInstr_GotoIfFunc1(k, j); + case fnEprojInstr_ResetXYpos2: return EprojInstr_ResetXYpos2(k, j); + case fnEprojInstr_SpawnTourianStatueUnlockingParticle: return EprojInstr_SpawnTourianStatueUnlockingParticle(k, j); + case fnEprojInstr_Earthquake: return EprojInstr_Earthquake(k, j); + case fnEprojInstr_SpawnTourianStatueUnlockingParticleTail: return EprojInstr_SpawnTourianStatueUnlockingParticleTail(k, j); + case fnEprojInstr_AddToYpos: return EprojInstr_AddToYpos(k, j); + case fnEprojInstr_BB24: return EprojInstr_BB24(k, j); + case fnEprojInstr_SwitchJump: return EprojInstr_SwitchJump(k, j); + case fnEprojInstr_UserPalette0: return EprojInstr_UserPalette0(k, j); + case fnEprojInstr_Add12ToY: return EprojInstr_Add12ToY(k, j); + case fnEprojInstr_MotherBrainPurpleBreathIsActive: return EprojInstr_MotherBrainPurpleBreathIsActive(k, j); + case fnEprojInstr_D15C: return EprojInstr_D15C(k, j); + case fnEprojInstr_D1B6: return EprojInstr_D1B6(k, j); + case fnEprojInstr_D1C7: return EprojInstr_D1C7(k, j); + case fnEprojInstr_D1CE: return EprojInstr_D1CE(k, j); + case fnEprojInstr_AssignNewN00bTubeShardVelocity: return EprojInstr_AssignNewN00bTubeShardVelocity(k, j); + case fnEprojInstr_SetN00bTubeShardX: return EprojInstr_SetN00bTubeShardX(k, j); + case fnEprojInstr_D62A: return EprojInstr_D62A(k, j); + case fnEprojInstr_SetXvelRandom: return EprojInstr_SetXvelRandom(k, j); + case fnEprojInstr_DC5A: return EprojInstr_DC5A(k, j); + case fnEprojInstr_SpawnEnemyDrops_0: return EprojInstr_SpawnEnemyDrops_0(k, j); + case fnEprojInstr_SpawnSporesEproj: return EprojInstr_SpawnSporesEproj(k, j); + case fnEprojInstr_DFEA: return EprojInstr_DFEA(k, j); + case fnEprojInstr_SetYVel: return EprojInstr_SetYVel(k, j); + case fnEprojInstr_ECE3: return EprojInstr_ECE3(k, j); + case fnEprojInstr_ED17: return EprojInstr_ED17(k, j); + case fnEprojInstr_QueueSfx2_9: return EprojInstr_QueueSfx2_9(k, j); + case fnEprojInstr_QueueSfx2_24: return EprojInstr_QueueSfx2_24(k, j); + case fnEprojInstr_QueueSfx2_B: return EprojInstr_QueueSfx2_B(k, j); + case fnEprojInstr_EEAF: return EprojInstr_EEAF(k, j); + case fnEprojInstr_HandleRespawningEnemy: return EprojInstr_HandleRespawningEnemy(k, j); + case fnEnemyProjInstr_SetPreInstrA: return EnemyProjInstr_SetPreInstrA(k, j); + // EXTRA!!! + case fnEprojPreInstr_PirateMotherBrainLaser_MoveRight: + EprojPreInstr_PirateMotherBrainLaser_MoveRight(k); + return j; + case fnEprojPreInstr_PirateMotherBrainLaser_MoveLeft: + EprojPreInstr_PirateMotherBrainLaser_MoveLeft(k); + return j; + + case fnEprojInstr_A3BE: return EprojInstr_A3BE(k, j); + case fnEprojInstr_9270: return EprojInstr_9270(k, j); + case fnnullsub_82: return j; // really j + case fnsub_86B13E: return sub_86B13E(k, j); + default: return Unreachable(); + } +} + +void EprojRunOne(uint16 k) { // 0x868125 + CallEprojPreInstr(enemy_projectile_pre_instr[k >> 1] | 0x860000, k); + uint16 v1 = enemy_projectile_index; + int v2 = enemy_projectile_index >> 1; + if (enemy_projectile_instr_timers[v2]-- == 1) { + uint16 v4 = enemy_projectile_instr_list_ptr[v2], v6; + while (1) { + uint16 *v5 = (uint16 *)RomPtr_86(v4); + v6 = *v5; + if ((*v5 & 0x8000u) == 0) + break; + R18_ = *v5; + v4 = CallEprojInstr(v6 | 0x860000, v1, v4 + 2); + if (!v4) + return; + } + if (v4 == 0) { + + v4 = 0; + } + int v7 = v1 >> 1; + enemy_projectile_instr_timers[v7] = v6; + enemy_projectile_spritemap_ptr[v7] = *((uint16 *)RomPtr_86(v4) + 1); + enemy_projectile_instr_list_ptr[v7] = v4 + 4; + } +} + +uint16 EprojInstr_Delete(uint16 k, uint16 j) { // 0x868154 + enemy_projectile_id[k >> 1] = 0; + return 0; +} + +uint16 EprojInstr_Sleep(uint16 k, uint16 j) { // 0x868159 + enemy_projectile_instr_list_ptr[k >> 1] = j - 2; + return 0; +} + +uint16 EprojInstr_SetPreInstr_(uint16 k, uint16 j) { // 0x868161 + enemy_projectile_pre_instr[k >> 1] = *(uint16 *)RomPtr_86(j); + return j + 2; +} + +uint16 EprojInstr_ClearPreInstr(uint16 k, uint16 j) { // 0x86816A + enemy_projectile_pre_instr[k >> 1] = 0x8170; + return j; +} + +void CallEprojFunc(uint32 ea, uint32 k) { + switch (ea) { + case fnSpawnMotherBrainDeathBeam: SpawnMotherBrainDeathBeam(k); return; + default: Unreachable(); + } +} + +uint16 EprojInstr_CallFunc(uint16 k, uint16 j) { // 0x868171 + uint8 *v2 = RomPtr_86(j); + copy24((LongPtr *)&R18_, (LongPtr *)v2); + + uint32 ea = Load24((LongPtr *)&R18_); + CallEprojFunc(ea, k); + + //CallFar((LongPtr *)&R18_); + return j + 3; +} + +uint16 EprojInstr_Goto(uint16 k, uint16 j) { // 0x8681AB + return *(uint16 *)RomPtr_86(j); +} + +uint16 EprojInstr_GotoRel(uint16 k, uint16 j) { // 0x8681B0 + int16 v2; + + R18_ = j; + LOBYTE(v2) = HIBYTE(*(uint16 *)RomPtr_86(j - 1)); + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + else + v2 = (uint8)v2; + return R18_ + v2; +} + +uint16 EprojInstr_DecTimerAndGotoIfNonZero(uint16 k, uint16 j) { // 0x8681C6 + int v2 = k >> 1; + if (enemy_projectile_timers[v2]-- == 1) + return j + 2; + else + return EprojInstr_Goto(k, j); +} + +uint16 EprojInstr_DecTimerAndGotoRelIfNonZero(uint16 k, uint16 j) { // 0x8681CE + int v2 = k >> 1; + if (enemy_projectile_timers[v2]-- == 1) + return j + 1; + else + return EprojInstr_GotoRel(k, j); +} + +uint16 EprojInstr_SetTimer(uint16 k, uint16 j) { // 0x8681D5 + enemy_projectile_timers[k >> 1] = *(uint16 *)RomPtr_86(j); + return j + 2; +} + +uint16 EprojInstr_MoveRandomlyWithinRadius(uint16 k, uint16 j) { // 0x8681DF + char Random; + char v4; + int16 v6; + + R18_ = NextRandom(); + do { + Random = NextRandom(); + uint8 *v3 = RomPtr_86(j); + v4 = (*v3 & Random) - v3[1]; + } while (v4 < 0); + enemy_projectile_x_pos[k >> 1] += sign16(R18_) ? -(uint8)v4 : (uint8)v4; + do { + LOBYTE(v6) = NextRandom(); + uint8 *v5 = RomPtr_86(j); + LOBYTE(v6) = (v5[2] & v6) - v5[3]; + } while ((v6 & 0x80) != 0); + v6 = (uint8)v6; + if ((R18_ & 0x4000) != 0) + v6 = -(uint8)v6; + enemy_projectile_y_pos[k >> 1] += v6; + return j + 4; +} + +uint16 EprojInstr_SetProjectileProperties(uint16 k, uint16 j) { // 0x868230 + enemy_projectile_properties[k >> 1] |= *(uint16 *)RomPtr_86(j); + return j + 2; +} + +uint16 EprojInstr_ClearProjectileProperties(uint16 k, uint16 j) { // 0x86823C + enemy_projectile_properties[k >> 1] &= *(uint16 *)RomPtr_86(j); + return j + 2; +} + +uint16 EprojInstr_EnableCollisionWithSamusProj(uint16 k, uint16 j) { // 0x868248 + enemy_projectile_properties[k >> 1] |= 0x8000u; + return j; +} + +uint16 EprojInstr_DisableCollisionWithSamusProj(uint16 k, uint16 j) { // 0x868252 + enemy_projectile_properties[k >> 1] &= ~0x8000u; + return j; +} + +uint16 EprojInstr_DisableCollisionWithSamus(uint16 k, uint16 j) { // 0x86825C + enemy_projectile_properties[k >> 1] |= 0x2000u; + return j; +} + +uint16 EprojInstr_EnableCollisionWithSamus(uint16 k, uint16 j) { // 0x868266 + enemy_projectile_properties[k >> 1] &= ~0x2000u; + return j; +} + +uint16 EprojInstr_SetToNotDieOnContact(uint16 k, uint16 j) { // 0x868270 + enemy_projectile_properties[k >> 1] |= 0x4000u; + return j; +} + +uint16 EprojInstr_SetToDieOnContact(uint16 k, uint16 j) { // 0x86827A + enemy_projectile_properties[k >> 1] &= ~0x4000u; + return j; +} + +uint16 EprojInstr_SetLowPriority(uint16 k, uint16 j) { // 0x868284 + enemy_projectile_properties[k >> 1] |= 0x1000u; + return j; +} + +uint16 EprojInstr_SetHighPriority(uint16 k, uint16 j) { // 0x86828E + enemy_projectile_properties[k >> 1] &= ~0x1000u; + return j; +} + +uint16 EprojInstr_SetXyRadius(uint16 k, uint16 j) { // 0x868298 + enemy_projectile_radius[k >> 1] = *(uint16 *)RomPtr_86(j); + return j + 2; +} + +uint16 EprojInstr_SetXyRadiusZero(uint16 k, uint16 j) { // 0x8682A1 + enemy_projectile_radius[k >> 1] = 0; + return j; +} + +uint16 EprojInstr_CalculateDirectionTowardsSamus(uint16 k, uint16 j) { // 0x8682A5 + int v2 = k >> 1; + R18_ = samus_x_pos - enemy_projectile_x_pos[v2]; + R20_ = samus_y_pos - enemy_projectile_y_pos[v2]; + uint16 v3 = 2 * CalculateAngleFromXY(); + int v4 = enemy_projectile_index >> 1; + enemy_projectile_E[v4] = v3; + int v5 = v3 >> 1; + enemy_projectile_x_vel[v4] = kSinCosTable8bit_Sext[v5 + 64]; + enemy_projectile_y_vel[v4] = kSinCosTable8bit_Sext[v5]; + return j; +} + +uint16 EprojInstr_WriteColorsToPalette(uint16 k, uint16 j) { // 0x8682D5 + uint8 *v2 = RomPtr_86(j); + uint16 v3 = *((uint16 *)v2 + 1); + R18_ = v2[4]; + uint16 v4 = *(uint16 *)v2; + do { + palette_buffer[v3 >> 1] = *(uint16 *)RomPtr_86(v4); + v4 += 2; + v3 += 2; + --R18_; + } while ((R18_ & 0x8000u) == 0); + return j + 5; +} + +uint16 EprojInstr_QueueMusic(uint16 k, uint16 j) { // 0x8682FD + uint8 *v2 = RomPtr_86(j); + QueueMusic_Delayed8(*v2); + return j + 1; +} + +uint16 EprojInstr_QueueSfx1_Max6(uint16 k, uint16 j) { // 0x868309 + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx1_Max6(*v2); + return j + 1; +} +uint16 EprojInstr_QueueSfx2_Max6(uint16 k, uint16 j) { // 0x868312 + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx2_Max6(*v2); + return j + 1; +} +uint16 EprojInstr_QueueSfx3_Max6(uint16 k, uint16 j) { // 0x86831B + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx3_Max6(*v2); + return j + 1; +} +uint16 EprojInstr_QueueSfx1_Max15(uint16 k, uint16 j) { // 0x868324 + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx1_Max15(*v2); + return j + 1; +} + +uint16 EprojInstr_QueueSfx2_Max15(uint16 k, uint16 j) { // 0x86832D + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx2_Max15(*v2); + return j + 1; +} + +uint16 EprojInstr_QueueSfx3_Max15(uint16 k, uint16 j) { // 0x868336 + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx3_Max15(*v2); + return j + 1; +} + +uint16 EprojInstr_QueueSfx1_Max3(uint16 k, uint16 j) { // 0x86833F + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx1_Max3(*v2); + return j + 1; +} + +uint16 EprojInstr_QueueSfx2_Max3(uint16 k, uint16 j) { // 0x868348 + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx2_Max3(*v2); + return j + 1; +} + +uint16 EprojInstr_QueueSfx3_Max3(uint16 k, uint16 j) { // 0x868351 + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx3_Max3(*v2); + return j + 1; +} + +uint16 EprojInstr_QueueSfx1_Max9(uint16 k, uint16 j) { // 0x86835A + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx1_Max9(*v2); + return j + 1; +} + +uint16 EprojInstr_QueueSfx2_Max9(uint16 k, uint16 j) { // 0x868363 + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx2_Max9(*v2); + return j + 1; +} + +uint16 EprojInstr_QueueSfx3_Max9(uint16 k, uint16 j) { // 0x86836C + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx3_Max9(*v2); + return j + 1; +} +uint16 EprojInstr_QueueSfx1_Max1(uint16 k, uint16 j) { // 0x868375 + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx1_Max1(*v2); + return j + 1; +} +uint16 EprojInstr_QueueSfx2_Max1(uint16 k, uint16 j) { // 0x86837E + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx2_Max1(*v2); + return j + 1; +} +uint16 EprojInstr_QueueSfx3_Max1(uint16 k, uint16 j) { // 0x868387 + uint16 *v2 = (uint16 *)RomPtr_86(j); + QueueSfx3_Max1(*v2); + return j + 1; +} + +void DrawLowPriorityEnemyProjectiles(void) { // 0x868390 + GetValuesForScreenShaking(); + for (int i = 34; i >= 0; i -= 2) { + int v1 = i >> 1; + if (enemy_projectile_id[v1]) { + if ((enemy_projectile_properties[v1] & 0x1000) != 0) + DrawEnemyProjectiles(i); + } + } +} + +void DrawHighPriorityEnemyProjectiles(void) { // 0x8683B2 + GetValuesForScreenShaking(); + for (int i = 34; i >= 0; i -= 2) { + int v1 = i >> 1; + if (enemy_projectile_id[v1]) { + if ((enemy_projectile_properties[v1] & 0x1000) == 0) + DrawEnemyProjectiles(i); + } + } +} + +void DrawEnemyProjectiles(uint16 k) { // 0x8683D6 + int v1 = k >> 1; + uint16 v2 = enemy_projectile_spritemap_ptr[v1]; + R26_ = LOBYTE(enemy_projectile_gfx_idx[v1]); + R28_ = enemy_projectile_gfx_idx[v1] & 0xFF00; + R20_ = R36 + enemy_projectile_x_pos[v1] - layer1_x_pos; + if (((R20_ + 128) & 0xFE00) == 0) { + uint16 v3 = R34 + enemy_projectile_y_pos[v1] - layer1_y_pos; + R18_ = v3; + if ((v3 & 0xFF00) != 0) { + if (((v3 + 128) & 0xFE00) == 0) + DrawEnemyProjectileSpritemapWithBaseTileOffscreen(0x8D, v2); + } else { + DrawEnemyProjectileSpritemapWithBaseTile(0x8D, v2); + } + } +} + +void GetValuesForScreenShaking(void) { // 0x868427 + if (earthquake_timer && !time_is_frozen_flag && sign16(earthquake_type - 36)) { + int v0 = (uint16)(4 * earthquake_type) >> 1; + if ((earthquake_timer & 2) != 0) { + R36 = -kScreenShakeOffsets[v0]; + R34 = -kScreenShakeOffsets[v0 + 1]; + } else { + R36 = kScreenShakeOffsets[v0]; + R34 = kScreenShakeOffsets[v0 + 1]; + } + } else { + R34 = 0; + R36 = 0; + } +} + +uint8 EprojColl_8506(void) { // 0x868506 + int16 v1; + + LOBYTE(v1) = BTS[cur_block_index]; + if ((uint8)v1) { + if ((BTS[cur_block_index] & 0x80) != 0) + v1 |= 0xFF00u; + else + v1 = (uint8)v1; + cur_block_index += v1; + return 0xff; + } + return 0; +} + +uint8 EprojColl_Unknown8536(void) { // 0x86853C + if (BTS[cur_block_index]) { + uint16 v1; + if ((BTS[cur_block_index] & 0x80) != 0) { + temp_collision_DD4 = BTS[cur_block_index] | 0xFF00; + v1 = cur_block_index; + do { + v1 -= room_width_in_blocks; + ++temp_collision_DD4; + } while (temp_collision_DD4); + } else { + temp_collision_DD4 = BTS[cur_block_index]; + v1 = cur_block_index; + do { + v1 += room_width_in_blocks; + --temp_collision_DD4; + } while (temp_collision_DD4); + } + cur_block_index = v1; + return 0xff; + } + return 0; +} + +uint8 EprojColl_ClearCarry(void) { // 0x86858A + return 0; +} + +uint8 EprojColl_SetCarry(void) { // 0x86858C + return 1; +} + +uint8 EprojColl_858E(void) { // 0x86858E + uint16 v0 = BTS[cur_block_index] & 0x1F; + if (v0 < 5u) + return EprojColl_85C2(v0, cur_block_index); + current_slope_bts = BTS[cur_block_index]; + return EprojColl_873D(); +} + +uint8 EprojColl_85AD(void) { // 0x8685AD + uint16 v0 = BTS[cur_block_index] & 0x1F; + if (v0 >= 5u) + return EprojColl_874E(); + else + return EprojColl_8676(v0, cur_block_index, 0); +} + +static const uint8 unk_868729[20] = { // 0x8685C2 + 0, 1, 0x82, 0x83, 0, 0x81, 2, 0x83, 0, 1, 2, 0x83, 0, 0x81, 0x82, 0x83, + 0x80, 0x81, 0x82, 0x83, +}; + + +#define CHECK_locret_868728(i) (unk_868729[i] & 0x80 ? -1 : 0) + +uint8 EprojColl_85C2(uint16 a, uint16 k) { + + temp_collision_DD4 = 4 * a; + temp_collision_DD6 = BTS[k] >> 6; + uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R34 & 8) >> 3)); + if (!R32) { + int v3 = enemy_projectile_index >> 1; + if ((((uint8)enemy_projectile_y_pos[v3] - (uint8)g_word_7E001E) & 8) != 0 + || CHECK_locret_868728(v2) >= 0) { + uint16 v4 = v2 ^ 2; + if ((((uint8)g_word_7E001E + (uint8)enemy_projectile_y_pos[v3] - 1) & 8) == 0 + || CHECK_locret_868728(v4) >= 0) { + return 0; + } + } + goto LABEL_17; + } + if (!R26_) { + if ((((uint8)g_word_7E001E + (uint8)enemy_projectile_y_pos[enemy_projectile_index >> 1] - 1) & 8) == 0) { + if (CHECK_locret_868728(v2) >= 0) + return 0; + goto LABEL_17; + } + goto LABEL_14; + } + if (R26_ != R32 + || (((uint8)enemy_projectile_y_pos[enemy_projectile_index >> 1] - (uint8)g_word_7E001E) & 8) == 0) { +LABEL_14: + if (CHECK_locret_868728(v2) < 0) + goto LABEL_17; + } + if (CHECK_locret_868728(v2 ^ 2) >= 0) + return 0; +LABEL_17:; + int v6 = enemy_projectile_index >> 1; + uint16 v7; + enemy_projectile_1A27[v6] = 0; + if ((R20_ & 0x8000u) != 0) + v7 = R28_ + (R34 | 7) + 1; + else + v7 = (R34 & 0xFFF8) - R28_; + enemy_projectile_x_pos[v6] = v7; + return 1; +} + +uint8 EprojColl_8676(uint16 a, uint16 k, uint16 j) { // 0x868676 + uint16 v2 = enemy_projectile_index; + + temp_collision_DD4 = 4 * a; + temp_collision_DD6 = BTS[k] >> 6; + uint16 v3 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R34 & 8) >> 2)); + if (!R32) { + printf("Y unknown!\n"); + int v4 = v2 >> 1; + if ((((uint8)enemy_projectile_x_pos[v4] - (uint8)R28_) & 8) != 0 + || CHECK_locret_868728(v3) >= 0) { + uint16 v5 = v3 ^ 1; + if ((((uint8)R28_ + (uint8)enemy_projectile_x_pos[v4] - 1) & 8) == 0 + || CHECK_locret_868728(v5) >= 0) { + return 0; + } + } + goto LABEL_17; + } + if (!R26_) { + if ((((uint8)R28_ + (uint8)enemy_projectile_x_pos[enemy_projectile_index >> 1] - 1) & 8) == 0) { + if (CHECK_locret_868728(v3) >= 0) + return 0; + goto LABEL_17; + } + goto LABEL_14; + } + if (R26_ != R32 || (((uint8)enemy_projectile_x_pos[enemy_projectile_index >> 1] - (uint8)R28_) & 8) == 0) { +LABEL_14: + if (CHECK_locret_868728(v3) < 0) + goto LABEL_17; + } + if (CHECK_locret_868728(v3 ^ 1) >= 0) + return 0; +LABEL_17:; + int v7 = enemy_projectile_index >> 1; + uint16 v8; + enemy_projectile_y_subpos[v7] = 0; + if ((R20_ & 0x8000u) != 0) + v8 = g_word_7E001E + (R34 | 7) + 1; + else + v8 = (R34 & 0xFFF8) - g_word_7E001E; + enemy_projectile_y_pos[v7] = v8; + return 1; +} + +uint8 EprojColl_873D(void) { // 0x86873D + return 0; +} + +uint8 EprojColl_874E(void) { // 0x86874E + int16 v3; + int16 v5; + uint16 v6; + uint16 v7; + int16 v8; + int16 v11; + int16 v12; + uint16 v13; + uint16 v14; + int16 v15; + + uint16 v0 = enemy_projectile_index; + if ((R20_ & 0x8000u) != 0) { + uint16 v9 = cur_block_index; + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + int v10 = v0 >> 1; + v11 = enemy_projectile_x_pos[v10] >> 4; + if (v11 == mod) { + temp_collision_DD4 = ((uint8)R24_ - (uint8)g_word_7E001E) & 0xF ^ 0xF; + temp_collision_DD6 = 16 * (BTS[v9] & 0x1F); + v12 = BTS[v9] << 8; + if (v12 < 0 + && ((v12 & 0x4000) != 0 ? (v13 = enemy_projectile_x_pos[v10] ^ 0xF) : (v13 = enemy_projectile_x_pos[v10]), + (v14 = temp_collision_DD6 + (v13 & 0xF), + v15 = (kAlignYPos_Tab0[v14] & 0x1F) - temp_collision_DD4 - 1, + (kAlignYPos_Tab0[v14] & 0x1F) - temp_collision_DD4 == 1) + || v15 < 0)) { + enemy_projectile_y_pos[v10] = R24_ - v15; + enemy_projectile_y_subpos[v10] = 0; + return 1; + } else { + return 0; + } + } else { + return 0; + } + } else { + uint16 v1 = cur_block_index; + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + int v2 = v0 >> 1; + v3 = enemy_projectile_x_pos[v2] >> 4; + if (v3 == mod) { + temp_collision_DD4 = ((uint8)g_word_7E001E + (uint8)R24_ - 1) & 0xF; + temp_collision_DD6 = 16 * (BTS[v1] & 0x1F); + v5 = BTS[v1] << 8; + if (v5 >= 0 + && ((v5 & 0x4000) != 0 ? (v6 = enemy_projectile_x_pos[v2] ^ 0xF) : (v6 = enemy_projectile_x_pos[v2]), + (v7 = temp_collision_DD6 + (v6 & 0xF), + v8 = (kAlignYPos_Tab0[v7] & 0x1F) - temp_collision_DD4 - 1, + (kAlignYPos_Tab0[v7] & 0x1F) - temp_collision_DD4 == 1) + || v8 < 0)) { + enemy_projectile_y_pos[v2] = R24_ + v8; + enemy_projectile_y_subpos[v2] = -1; + return 1; + } else { + return 0; + } + } else { + return 0; + } + } +} + +static Func_U8 *const kEnemyProjectileBlockCollisition_FuncA[16] = { // 0x868886 + EprojColl_ClearCarry, + EprojColl_858E, + EprojColl_ClearCarry, + EprojColl_ClearCarry, + EprojColl_ClearCarry, + EprojColl_8506, + EprojColl_ClearCarry, + EprojColl_ClearCarry, + EprojColl_SetCarry, + EprojColl_SetCarry, + EprojColl_SetCarry, + EprojColl_SetCarry, + EprojColl_SetCarry, + EprojColl_Unknown8536, + EprojColl_ClearCarry, + EprojColl_SetCarry, +}; +static Func_U8 *const kEnemyProjectileBlockCollisition_FuncB[16] = { + EprojColl_ClearCarry, + EprojColl_85AD, + EprojColl_ClearCarry, + EprojColl_ClearCarry, + EprojColl_ClearCarry, + EprojColl_8506, + EprojColl_ClearCarry, + EprojColl_ClearCarry, + EprojColl_SetCarry, + EprojColl_SetCarry, + EprojColl_SetCarry, + EprojColl_SetCarry, + EprojColl_SetCarry, + EprojColl_Unknown8536, + EprojColl_ClearCarry, + EprojColl_SetCarry, +}; + +uint8 EnemyProjectileBlockCollisition_CheckHorizontal(uint16 k) { + uint8 rv; + cur_block_index = k >> 1; + do { + rv = kEnemyProjectileBlockCollisition_FuncA[(level_data[cur_block_index] & 0xF000) >> 12](); + } while (rv & 0x80); + return rv; +} + +uint8 EnemyProjectileBlockCollisition_CheckVertical(uint16 k) { // 0x86889E + uint8 rv; + cur_block_index = k >> 1; + do { + rv = kEnemyProjectileBlockCollisition_FuncB[(level_data[cur_block_index] & 0xF000) >> 12](); + } while (rv & 0x80); + return rv; +} + +uint8 EnemyProjectileBlockCollisition_Horiz(uint16 k) { // 0x8688B6 + int16 v2; + + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = enemy_projectile_x_vel[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + g_word_7E001E = HIBYTE(enemy_projectile_radius[v1]); + R28_ = LOBYTE(enemy_projectile_radius[v1]); + R26_ = (enemy_projectile_y_pos[v1] - g_word_7E001E) & 0xFFF0; + R26_ = (uint16)(g_word_7E001E + enemy_projectile_y_pos[v1] - 1 - R26_) >> 4; + R32 = R26_; + uint16 prod = Mult8x8((uint16)(enemy_projectile_y_pos[v1] - g_word_7E001E) >> 4, room_width_in_blocks); + uint16 v3 = (__PAIR32__(R20_, R18_) + __PAIR32__(enemy_projectile_x_pos[v1], enemy_projectile_1A27[v1])) >> 16; + R22_ = R18_ + enemy_projectile_1A27[v1]; + R24_ = v3; + uint16 v4; + if ((R20_ & 0x8000u) != 0) + v4 = v3 - R28_; + else + v4 = R28_ + v3 - 1; + R34 = v4; + uint16 v5 = 2 * (prod + (v4 >> 4)); + while (!(EnemyProjectileBlockCollisition_CheckHorizontal(v5) & 1)) { + v5 += room_width_in_blocks + room_width_in_blocks; + if ((--R26_ & 0x8000u) != 0) { + int v6 = k >> 1; + enemy_projectile_1A27[v6] = R22_; + enemy_projectile_x_pos[v6] = R24_; + return 0; + } + } + int v8 = k >> 1; + enemy_projectile_1A27[v8] = 0; + if ((R20_ & 0x8000u) != 0) { + uint16 v10 = R28_ + (R34 | 0xF) + 1; + if (v10 < enemy_projectile_x_pos[v8] || v10 == enemy_projectile_x_pos[v8]) + enemy_projectile_x_pos[v8] = v10; + return 1; + } else { + uint16 v9 = (R34 & 0xFFF0) - R28_; + if (v9 >= enemy_projectile_x_pos[v8]) + enemy_projectile_x_pos[v8] = v9; + return 1; + } +} + +uint8 EnemyProjectileBlockCollisition_Vertical(uint16 k) { // 0x86897B + int16 v2; + int16 v5; + + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = enemy_projectile_y_vel[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + g_word_7E001E = HIBYTE(enemy_projectile_radius[v1]); + R28_ = LOBYTE(enemy_projectile_radius[v1]); + R26_ = (enemy_projectile_x_pos[v1] - R28_) & 0xFFF0; + R26_ = (uint16)(R28_ + enemy_projectile_x_pos[v1] - 1 - R26_) >> 4; + R32 = R26_; + uint16 v3 = (__PAIR32__(R20_, R18_) + __PAIR32__(enemy_projectile_y_pos[v1], enemy_projectile_y_subpos[v1])) >> 16; + R22_ = R18_ + enemy_projectile_y_subpos[v1]; + R24_ = v3; + uint16 v4; + if ((R20_ & 0x8000u) != 0) + v4 = v3 - g_word_7E001E; + else + v4 = g_word_7E001E + v3 - 1; + R34 = v4; + uint prod = (v4 >> 4) * (uint8)room_width_in_blocks; + v5 = (uint16)(enemy_projectile_x_pos[v1] - R28_) >> 4; + for (int i = 2 * (prod + v5); !(EnemyProjectileBlockCollisition_CheckVertical(i) & 1); i += 2) { + if ((--R26_ & 0x8000u) != 0) { + int v7 = k >> 1; + enemy_projectile_y_subpos[v7] = R22_; + enemy_projectile_y_pos[v7] = R24_; + return 0; + } + } + int v9 = k >> 1; + enemy_projectile_y_subpos[v9] = 0; + if ((R20_ & 0x8000u) != 0) { + uint16 v11 = g_word_7E001E + (R34 | 0xF) + 1; + if (v11 < enemy_projectile_y_pos[v9] || v11 == enemy_projectile_y_pos[v9]) + enemy_projectile_y_pos[v9] = v11; + return 1; + } else { + uint16 v10 = (R34 & 0xFFF0) - g_word_7E001E; + if (v10 >= enemy_projectile_y_pos[v9]) + enemy_projectile_y_pos[v9] = v10; + return 1; + } +} + +void EnemyProj_Init_0x8aaf(uint16 j) { // 0x868A39 + NextRandom(); + EnemyData *v1 = gEnemyData(cur_enemy_index); + uint16 v2 = v1->y_pos + 12; + int v3 = j >> 1; + enemy_projectile_y_pos[v3] = v2; + enemy_projectile_timers[v3] = v2 + 72; + enemy_projectile_y_vel[v3] = v1->ai_var_D; + enemy_projectile_x_pos[v3] = v1->x_pos + (random_number & 0x1F) - 16; + enemy_projectile_instr_list_ptr[v3] = off_868A75[(uint16)(HIBYTE(enemy_projectile_y_vel[v3]) & 6) >> 1]; +} + +void EnemyProj_PreInit_0x8aaf(uint16 k) { // 0x868A7D + int v1 = k >> 1; + R20_ = LOBYTE(enemy_projectile_y_vel[v1]) << 8; + R18_ = (int8)HIBYTE(enemy_projectile_y_vel[v1]); + uint16 v3 = enemy_projectile_y_subpos[v1]; + bool v4 = __CFADD__uint16(R20_, v3); + enemy_projectile_y_subpos[v1] = R20_ + v3; + uint16 v5 = R18_ + v4 + enemy_projectile_y_pos[v1]; + enemy_projectile_y_pos[v1] = v5; + if (v5 >= enemy_projectile_timers[v1]) + enemy_projectile_id[v1] = 0; +} + +void EnemyProj_Init_0x8bc2_SkreeDownRight(uint16 j) { // 0x868ACD + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_y_pos[v2] = v1->y_pos; + enemy_projectile_y_vel[v2] = -769; + enemy_projectile_x_pos[v2] = v1->x_pos + 6; + enemy_projectile_x_vel[v2] = 320; +} + +void EnemyProj_Init_0x8bd0_SkreeUpRight(uint16 j) { // 0x868AF1 + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_y_pos[v2] = v1->y_pos; + enemy_projectile_y_vel[v2] = -1025; + enemy_projectile_x_pos[v2] = v1->x_pos + 6; + enemy_projectile_x_vel[v2] = 96; +} + +void EnemyProj_Init_0x8bde_SkreeDownLeft(uint16 j) { // 0x868B15 + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_y_pos[v2] = v1->y_pos; + enemy_projectile_y_vel[v2] = -769; + enemy_projectile_x_pos[v2] = v1->x_pos - 6; + enemy_projectile_x_vel[v2] = -320; +} + +void EnemyProj_Init_0x8bec_SkreeUpLeft(uint16 j) { // 0x868B39 + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_y_pos[v2] = v1->y_pos; + enemy_projectile_y_vel[v2] = -1025; + enemy_projectile_x_pos[v2] = v1->x_pos - 6; + enemy_projectile_x_vel[v2] = -96; +} + +void EnemyProj_PreInstr_SkreeParticle(uint16 k) { // 0x868B5D + int v1 = k >> 1; + R20_ = LOBYTE(enemy_projectile_x_vel[v1]) << 8; + R18_ = (int8)HIBYTE(enemy_projectile_x_vel[v1]); + uint16 v4 = enemy_projectile_1A27[v1]; + bool v3 = __CFADD__uint16(R20_, v4); + enemy_projectile_1A27[v1] = R20_ + v4; + enemy_projectile_x_pos[v1] += R18_ + v3; + R20_ = LOBYTE(enemy_projectile_y_vel[v1]) << 8; + R18_ = (int8)HIBYTE(enemy_projectile_y_vel[v1]); + uint16 v5 = enemy_projectile_y_subpos[v1]; + v3 = __CFADD__uint16(R20_, v5); + enemy_projectile_y_subpos[v1] = R20_ + v5; + enemy_projectile_y_pos[v1] += R18_ + v3; + enemy_projectile_y_vel[v1] += 80; + if (CheckIfEnemyProjectileIsOffScreen(k)) + enemy_projectile_id[v1] = 0; +} + +void EnemyProjInstr_SpawnEnemyDropsWithDraygonsEyeDrops(uint16 k) { // 0x868C68 + int v1 = k >> 1; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + SpawnEnemyDrops(addr_kEnemyDef_DE7F, k); +} + +uint16 EnemyProjInstr_SetPreInstrA(uint16 k, uint16 j) { // 0x868CF6 + enemy_projectile_pre_instr[k >> 1] = FUNC16(EprojPreInstr_DraygonsTurret_8DFF); + return j; +} + +void EnemyProjInstr_SetPreInstrB(uint16 k) { // 0x868CFD + enemy_projectile_pre_instr[k >> 1] = FUNC16(EprojPreInstr_8DCA); +} + +void EprojInit_DraygonsGunk(uint16 j) { // 0x868D04 + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = R18_; + enemy_projectile_y_pos[v1] = R20_; + uint16 v2 = enemy_projectile_unk1995; + g_word_7E97DC[v1] = enemy_projectile_unk1995; + R18_ = v2; + R20_ = enemy_projectile_init_param; + ConvertAngleToXy(); + enemy_projectile_x_vel[v1] = R22_; + enemy_projectile_E[v1] = R24_; + enemy_projectile_y_vel[v1] = R26_; + enemy_projectile_F[v1] = R28_; + enemy_projectile_gfx_idx[v1] = 1024; +} + +void EprojInit_DraygonsWallTurretProjs(uint16 j) { // 0x868D40 + Eproj_AngleToSamus(j); + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 2560; + enemy_projectile_pre_instr[v1] = FUNC16(nullsub_84); +} + +uint16 EprojInstr_868D55(uint16 k, uint16 j) { // 0x868D55 + enemy_projectile_id[j >> 1] = 0; + return j; +} + +void EprojPowerBombCollision(uint16 k) { // 0x868D5C + R18_ = HIBYTE(power_bomb_explosion_radius); + if (HIBYTE(power_bomb_explosion_radius)) { + R20_ = (uint16)(R18_ + (HIBYTE(power_bomb_explosion_radius) & 1) + (power_bomb_explosion_radius >> 9)) >> 1; + int v1 = k >> 1; + if (abs16(power_bomb_explosion_x_pos - enemy_projectile_x_pos[v1]) < R18_ + && abs16(power_bomb_explosion_y_pos - enemy_projectile_y_pos[v1]) < R20_) { + enemy_projectile_id[v1] = 0; + samus_x_speed_divisor = 0; + } + } +} + +uint16 EprojInstr_868D99(uint16 k, uint16 j) { // 0x868D99 + EprojPowerBombCollision(k); + uint16 v2 = samus_x_speed_divisor + 1; + if (sign16(samus_x_speed_divisor - 5)) { + ++samus_x_speed_divisor; + int v3 = k >> 1; + enemy_projectile_F[v3] = v2; + enemy_projectile_E[v3] = 256; + enemy_projectile_pre_instr[v3] = FUNC16(EprojPreInstr_8DCA); + enemy_projectile_properties[v3] = enemy_projectile_properties[v3] & 0x5FFF | 0x2000; + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + } + return j; +} + +void EprojPreInstr_8DCA(uint16 k) { // 0x868DCA + int v1; + + EprojPowerBombCollision(k); + if (samus_contact_damage_index + || (v1 = k >> 1, + enemy_projectile_x_pos[v1] = samus_x_pos, + enemy_projectile_y_pos[v1] = samus_y_pos + 4 * enemy_projectile_F[v1] - 12, + --enemy_projectile_E[v1], + !enemy_projectile_E[v1])) { + enemy_projectile_id[k >> 1] = 0; + if ((--samus_x_speed_divisor & 0x8000u) != 0) + samus_x_speed_divisor = 0; + } +} + +void EprojPreInstr_DraygonsTurret_8DFF(uint16 k) { // 0x868DFF + int16 v1; + + EprojPowerBombCollision(k); + Eproj_FuncE73E_MoveXY(k); + v1 = Eproj_FuncE722(k); + if (v1) + enemy_projectile_id[k >> 1] = 0; +} + +void EprojPreInstr_DraygonsGunk_8E0F(uint16 k) { // 0x868E0F + uint16 v3; + + EprojPowerBombCollision(k); + Eproj_FuncE73E_MoveXY(k); + int v1 = k >> 1; + uint16 v2 = abs16(samus_x_pos - enemy_projectile_x_pos[v1]); + if (sign16(v2 - 16) && (v3 = abs16(samus_y_pos - enemy_projectile_y_pos[v1]), sign16(v3 - 20))) { + enemy_projectile_instr_list_ptr[v1] = 0x8C38; + enemy_projectile_instr_timers[v1] = 1; + } else { + if (Eproj_FuncE722(k)) + enemy_projectile_id[v1] = 0; + } +} + +void EprojInit_8E6C(uint16 j) { // 0x868E7A + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 1008; + enemy_projectile_x_pos[v1] = R18_; + enemy_projectile_y_pos[v1] = R20_; + enemy_projectile_instr_list_ptr[v1] = addr_word_868EDF; + enemy_projectile_instr_timers[v1] = 1; +} + +void EprojPreInstr_8E6C(uint16 k) { // 0x868E99 + R18_ = enemy_data[0].x_pos - R18_; + R20_ = enemy_data[0].y_pos - R20_; + uint16 v1 = (uint8)(64 - CalculateAngleFromXY()); + int v2 = k >> 1; + g_word_7E97DC[v2] = v1; + R18_ = v1; + R20_ = 1; + ConvertAngleToXy(); + enemy_projectile_x_vel[v2] = R22_; + enemy_projectile_E[v2] = R24_; + enemy_projectile_y_vel[v2] = R26_; + enemy_projectile_F[v2] = R28_; + Eproj_FuncE73E_MoveXY(k); +} + +void EprojInit_CrocomireProjectile(uint16 j) { // 0x869023 + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = -512; + enemy_projectile_y_vel[v2] = 1; + EnemyData *v3 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v2] = v3->x_pos - 32; + enemy_projectile_y_pos[v2] = v3->y_pos - 16; + enemy_projectile_timers[v2] = 0; + enemy_projectile_1A27[v2] = 0; + enemy_projectile_y_subpos[v2] = 0; + enemy_projectile_gfx_idx[v2] = 2560; +} + +static const int16 word_869059[9] = { -16, 0, 32, -16, 0, 32, -16, 0, 32 }; // bug: oob read +#define g_word_869059 ((uint16*)RomPtr(0x869059)) +void EprojPreInstr_CrocomireProjectile(uint16 k) { // 0x86906B + EnemyProjectileBlockCollisition_Horiz(k); + enemy_projectile_gfx_idx[0] = 2560; + enemy_projectile_timers[k >> 1] += enemy_projectile_x_vel[k >> 1]; + R18_ = -64; + R20_ = g_word_869059[enemy_data[0].ai_preinstr >> 1]; // bug: out of bounds read... + int v1 = (uint16)(2 * CalculateAngleFromXY()) >> 1; + R18_ = kSinCosTable8bit_Sext[v1 + 64]; + int v2 = k >> 1; + enemy_projectile_x_vel[v2] = 4 * R18_; + R18_ = kSinCosTable8bit_Sext[v1]; + enemy_projectile_y_vel[v2] = 4 * R18_; + enemy_projectile_pre_instr[v2] = FUNC16(sub_8690B3); +} + +void sub_8690B3(uint16 k) { // 0x8690B3 + if (EnemyProjectileBlockCollisition_Horiz(k) & 1 || EnemyProjectileBlockCollisition_Vertical(k) & 1) + enemy_projectile_id[k >> 1] = 0; +} + +void EprojInit_CrocomireSpikeWallPieces(uint16 j) { // 0x8690CF + int v1 = j >> 1; + enemy_projectile_y_pos[v1] = word_869105[(uint16)(j - 20) >> 1]; + enemy_projectile_x_pos[v1] = 528; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + enemy_projectile_E[v1] = 0; + enemy_projectile_F[v1] = 0; + enemy_projectile_1A27[v1] = 0; + enemy_projectile_y_subpos[v1] = 0; + enemy_projectile_y_vel[v1] = -5; + enemy_projectile_F[v1] = -30720; +} + +static const uint16 CrocomireSpikeWallPieces_Tab2[18] = { // 0x869115 + 0, 0, 0xff0, 0xee0, 0xcc0, 0xaa0, 0x880, 0x660, 0x440, 0x220, 0xff0, 0xee0, + 0xcc0, 0xaa0, 0x880, 0x660, 0x440, 0x220, +}; +static const uint16 CrocomireSpikeWallPieces_Tab1[18] = { + 0, 0, 0xff00, 0xee00, 0xcc00, 0xaa00, 0x8800, 0x6600, 0x4400, 0x2200, 0xff00, 0xee00, + 0xcc00, 0xaa00, 0x8800, 0x6600, 0x4400, 0x2200, +}; +static const int8 CrocomireSpikeWallPieces_Tab3[36] = { + 0, 0, 0, 0, 4, 0, 4, 0, 3, 0, 3, 0, + 2, 0, 2, 0, 1, 0, 1, 0, 6, 0, 5, 0, + 4, 0, 3, 0, 2, 0, 2, 0, 1, 0, 1, 0, +}; + +void EprojPreInstr_CrocomireSpikeWallPieces(uint16 k) { + char v3; + char v6; + char v7; + char v8; + + int v1 = k >> 1; + uint16 v2 = enemy_projectile_E[v1]; + if (v2 != CrocomireSpikeWallPieces_Tab1[v1]) { + v2 += CrocomireSpikeWallPieces_Tab2[v1]; + if (v2 >= CrocomireSpikeWallPieces_Tab1[v1]) + v2 = CrocomireSpikeWallPieces_Tab1[v1]; + } + enemy_projectile_E[v1] = v2; + v3 = *((uint8 *)enemy_projectile_E + k + 1); + bool v4 = __CFADD__uint8(*((uint8 *)enemy_projectile_x_vel + k), v3); + *((uint8 *)enemy_projectile_x_vel + k) += v3; + uint8 v5 = v4 + *((uint8 *)enemy_projectile_x_vel + k + 1); + if ((int8)(v5 - CrocomireSpikeWallPieces_Tab3[k]) >= 0) + v5 = CrocomireSpikeWallPieces_Tab3[k]; + *((uint8 *)enemy_projectile_x_vel + k + 1) = v5; + v6 = *((uint8 *)enemy_projectile_x_vel + k); + v4 = __CFADD__uint8(*((uint8 *)enemy_projectile_1A27 + k + 1), v6); + *((uint8 *)enemy_projectile_1A27 + k + 1) += v6; + v7 = *((uint8 *)enemy_projectile_x_vel + k + 1); + bool v9 = v4; + v4 = __CFADD__uint8(v4, v7); + v8 = v9 + v7; + v4 |= __CFADD__uint8(*((uint8 *)enemy_projectile_x_pos + k), v8); + *((uint8 *)enemy_projectile_x_pos + k) += v8; + *((uint8 *)enemy_projectile_x_pos + k + 1) += v4; + uint16 v10 = enemy_projectile_F[v1]; + enemy_projectile_F[v1] = v10 + 12288; + enemy_projectile_y_vel[v1] += __CFADD__uint16(v10, 12288); + uint16 v11 = enemy_projectile_y_subpos[v1]; + v4 = __CFADD__uint16(enemy_projectile_F[v1], v11); + enemy_projectile_y_subpos[v1] = enemy_projectile_F[v1] + v11; + enemy_projectile_y_pos[v1] += enemy_projectile_y_vel[v1] + v4; + if (enemy_projectile_y_pos[v1] >= 0xA8u) { + enemy_projectile_id[v1] = 0; + if ((k & 2) == 0) + QueueSfx2_Max6(0x29u); + int v12 = k >> 1; + R18_ = enemy_projectile_x_pos[v12]; + R20_ = enemy_projectile_y_pos[v12]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + QueueSfx2_Max6(0x25u); + } +} + +uint16 EprojInstr_9270(uint16 v0, uint16 j) { // 0x869270 + int v1 = v0 >> 1; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + SpawnEnemyDrops(addr_kEnemyDef_DDBF, v0); + return j; +} + +void EprojInit_CrocomireBridgeCrumbling(uint16 j) { // 0x869286 + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = enemy_projectile_init_param; + enemy_projectile_y_pos[v1] = 187; + enemy_projectile_y_subpos[v1] = 0; + enemy_projectile_1A27[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = (random_number & 0x3F) + 64; + enemy_projectile_gfx_idx[v1] = 1024; +} + +void EprojPreInstr_CrocomireBridgeCrumbling(uint16 k) { // 0x8692BA + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) + enemy_projectile_id[k >> 1] = 0; + else + enemy_projectile_y_vel[k >> 1] = (enemy_projectile_y_vel[k >> 1] + 24) & 0x3FFF; +} + +uint16 MoveEprojWithVelocity(uint16 k) { // 0x8692D6 + int16 v3; + char v4; // t0 + + int v1 = k >> 1; + uint16 v2 = enemy_projectile_x_vel[v1]; + int carry = *((uint8 *)enemy_projectile_1A27 + k + 1) + LOBYTE(v2); + LOBYTE(v2) = carry; + *((uint8 *)enemy_projectile_1A27 + k + 1) = v2; + v2 &= 0xFF00u; + v4 = v2; + LOBYTE(v3) = HIBYTE(v2); + HIBYTE(v3) = v4; + if ((v3 & 0x80) != 0) + v3 |= 0xFF00u; + enemy_projectile_x_pos[v1] += v3 + (carry >> 8); + return MoveEprojWithVelocityY(k); +} + +uint16 MoveEprojWithVelocityY(uint16 k) { // 0x8692F3 + int16 v3; + char v4; // t0 + + int v1 = k >> 1; + uint16 v2 = enemy_projectile_y_vel[v1]; + int carry = *((uint8 *)enemy_projectile_y_subpos + k + 1) + LOBYTE(v2); + LOBYTE(v2) = carry; + *((uint8 *)enemy_projectile_y_subpos + k + 1) = v2; + v2 &= 0xFF00u; + v4 = v2; + LOBYTE(v3) = HIBYTE(v2); + HIBYTE(v3) = v4; + if ((v3 & 0x80) != 0) + v3 |= 0xFF00u; + uint16 result = enemy_projectile_y_pos[v1] + v3 + (carry >> 8); + enemy_projectile_y_pos[v1] = result; + return result; +} + +uint16 MoveEprojWithVelocityX(uint16 k) { // 0x869311 + int16 v3; + char v4; // t0 + + int v1 = k >> 1; + uint16 v2 = enemy_projectile_x_vel[v1]; + int carry = *((uint8 *)enemy_projectile_1A27 + k + 1) + LOBYTE(v2); + LOBYTE(v2) = carry; + *((uint8 *)enemy_projectile_1A27 + k + 1) = v2; + v2 &= 0xFF00u; + v4 = v2; + LOBYTE(v3) = HIBYTE(v2); + HIBYTE(v3) = v4; + if ((v3 & 0x80) != 0) + v3 |= 0xFF00u; + uint16 result = enemy_projectile_x_pos[v1] + v3 + (carry >> 8); + enemy_projectile_x_pos[v1] = result; + return result; +} + +void SetAreaDependentEprojPropertiesEx(uint16 k, uint16 j) { // 0x86932F + uint16 v2; + if (area_index == 2) { + v2 = *((uint16 *)RomPtr_86(k) + 1); + } else if (area_index == 5) { + v2 = *((uint16 *)RomPtr_86(k) + 2); + } else { + v2 = *(uint16 *)RomPtr_86(k); + } + enemy_projectile_properties[j >> 1] = v2; +} + +static const int16 kEprojInit_9634_Xvel[4] = { -0x200, -0x1f0, -0x1bc, -0x16a }; +static const int16 kEprojInit_9634_Yvel[4] = { 0, 0x88, 0xfc, 0x16a }; + +void EprojInit_9634(uint16 j) { // 0x86934D + int v1 = j >> 1; + enemy_projectile_E[v1] = 0; + enemy_projectile_F[v1] = 0; + enemy_projectile_x_pos[v1] = enemy_data[0].x_pos - 29; + enemy_projectile_y_pos[v1] = enemy_data[0].y_pos - 35; + enemy_projectile_gfx_idx[v1] = 2560; + int v2 = (uint16)(2 * enemy_data[0].parameter_1) >> 1; + enemy_projectile_x_vel[v1] = kEprojInit_9634_Xvel[v2]; + enemy_projectile_y_vel[v1] = kEprojInit_9634_Yvel[v2]; +} + +void EprojPreInstr_9634(uint16 k) { // 0x869392 + int v1 = k >> 1; + if (enemy_projectile_E[v1] >= 8u) { + MoveEprojWithVelocity(k); + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) { + enemy_projectile_instr_list_ptr[v1] = addr_off_869574; + ++enemy_projectile_E[v1]; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + enemy_projectile_gfx_idx[v1] = 2560; + QueueSfx2_Max6(0x2Bu); + } + } else { + ++enemy_projectile_E[v1]; + } +} + +void EprojInit_9642_RidleysFireball(uint16 j) { // 0x8693CA + int16 v2; + + int v1 = j >> 1; + enemy_projectile_F[v1] = enemy_projectile_unk1995; + if (enemy_projectile_init_param) + v2 = 25; + else + v2 = -25; + enemy_projectile_x_pos[v1] = enemy_data[0].x_pos + v2; + enemy_projectile_y_pos[v1] = enemy_data[0].y_pos - 43; + enemy_projectile_gfx_idx[v1] = 2560; + + Ram7800_Default *v4 = gRam7800_Default(0); + enemy_projectile_x_vel[v1] = v4->var_19; + enemy_projectile_y_vel[v1] = v4->var_1A; + SetAreaDependentEprojPropertiesEx(addr_kRidleysFireball_Tab0, j); +} + +void SetAreaDependentEprojProperties(uint16 j) { // 0x869402 + SetAreaDependentEprojPropertiesEx(addr_kRidleysFireball_Tab0, j); +} + +void EprojPreInstr_9642_RidleysFireball(uint16 k) { // 0x86940E + uint16 v1; + if (EnemyProjectileBlockCollisition_Horiz(k) & 1) { + v1 = -27042; + } else { + if (!(EnemyProjectileBlockCollisition_Vertical(k) & 1)) + return; + v1 = -27056; + } + int v2 = k >> 1; + enemy_projectile_id[v2] = 0; + if (!enemy_projectile_F[v2]) { + R18_ = enemy_projectile_x_pos[v2]; + R20_ = enemy_projectile_y_pos[v2]; + SpawnEnemyProjectileWithRoomGfx(v1, 3u); + QueueSfx2_Max6(0x2Bu); + } +} + +uint16 EprojInstr_DisableCollisionsWithSamus(uint16 k, uint16 j) { // 0x869475 + enemy_projectile_properties[k >> 1] |= 0x2000u; + return j; +} + +void EprojInit_9660_FireballExplosion(uint16 j) { // 0x86947F + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 2560; + enemy_projectile_x_pos[v1] = R18_; + enemy_projectile_y_pos[v1] = R20_; + enemy_projectile_E[v1] = enemy_projectile_init_param; + enemy_projectile_F[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; +} + +void EprojInit_9688(uint16 j) { // 0x8694A0 + uint16 v1 = enemy_projectile_init_param; + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = 0; + enemy_projectile_y_vel[v2] = -3584; + EprojInit_Common(j, v1, 0x9688u); +} + +void EprojInit_9696(uint16 j) { // 0x8694B4 + uint16 v1 = enemy_projectile_init_param; + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = 0; + enemy_projectile_y_vel[v2] = 3584; + EprojInit_Common(j, v1, 0x9696); +} + +void EprojInit_966C(uint16 j) { // 0x8694C8 + uint16 v1 = enemy_projectile_init_param; + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = 3584; + enemy_projectile_y_vel[v2] = 0; + EprojInit_Common(j, v1, 0x966C); +} + +void EprojInit_967A(uint16 j) { // 0x8694DC + uint16 v1 = enemy_projectile_init_param; + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = -3584; + enemy_projectile_y_vel[v2] = 0; + EprojInit_Common(j, v1, 0x967Au); +} + +void EprojInit_Common(uint16 j, uint16 k, uint16 a) { // 0x8694EE + int v3 = j >> 1; + enemy_projectile_F[v3] = a; + int v4 = k >> 1; + enemy_projectile_x_pos[v3] = enemy_projectile_x_pos[v4]; + enemy_projectile_y_pos[v3] = enemy_projectile_y_pos[v4]; + enemy_projectile_E[v3] = enemy_projectile_E[v4]; + enemy_projectile_gfx_idx[v3] = 2560; + SetAreaDependentEprojProperties(j); +} + +void EprojPreInstr_966C(uint16 k) { // 0x86950D + MoveEprojWithVelocityX(k); + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) { + int v1 = k >> 1; + enemy_projectile_instr_list_ptr[v1] = addr_off_869574; + enemy_projectile_instr_timers[v1] = 1; + } +} + +void EprojPreInstr_9688(uint16 k) { // 0x869522 + MoveEprojWithVelocityY(k); + if (EnemyProjectileBlockCollisition_Horiz(k) & 1) { + int v1 = k >> 1; + enemy_projectile_instr_list_ptr[v1] = addr_off_869574; + enemy_projectile_instr_timers[v1] = 1; + } +} + +void EprojPreInstr_96A4(uint16 k) { // 0x869537 + if (EnemyProjectileBlockCollisition_Horiz(k) & 1) + enemy_projectile_id[k >> 1] = 0; +} + +void EprojPreInstr_96C0(uint16 k) { // 0x869540 + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) + enemy_projectile_id[k >> 1] = 0; +} + +void EprojPreInstr_96CE(uint16 k) { // 0x869549 + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) + enemy_projectile_id[k >> 1] = 0; +} + +uint16 EprojInstr_95BA(uint16 k, uint16 j) { // 0x8695BA + enemy_projectile_unk1995 = 0; + SpawnEnemyProjectileWithRoomGfx(addr_stru_86966C, k); + enemy_projectile_unk1995 = 0; + SpawnEnemyProjectileWithRoomGfx(addr_stru_86967A, k); + return j; +} + +uint16 EprojInstr_95ED(uint16 k, uint16 j) { // 0x8695ED + enemy_projectile_unk1995 = 0; + SpawnEnemyProjectileWithRoomGfx(addr_stru_869688, k); + enemy_projectile_unk1995 = 0; + SpawnEnemyProjectileWithRoomGfx(addr_stru_869696, k); + return j; +} + +uint16 EprojInstr_9620(uint16 k, uint16 j) { // 0x869620 + if ((int8)-- * ((uint8 *)enemy_projectile_E + k) >= 0) + SpawnEnemyProjectileWithRoomGfx(enemy_projectile_F[k >> 1], k); + return j; +} + +void EprojInit_9734_CeresFallingDebris(uint16 j) { // 0x8696DC + int v1 = j >> 1; + enemy_projectile_E[v1] = 0; + enemy_projectile_F[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_gfx_idx[v1] = 3584; + enemy_projectile_x_pos[v1] = enemy_projectile_init_param; + enemy_projectile_y_pos[v1] = 42; + enemy_projectile_y_vel[v1] = 16; +} + +void EprojPreInstr_9734_CeresFallingDebris(uint16 k) { // 0x869701 + int v1 = k >> 1; + enemy_projectile_y_vel[v1] += 16; + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) { + enemy_projectile_id[v1] = 0; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 9u); + QueueSfx2_Max6(0x6Du); + } +} + +uint16 EprojInstr_980E(uint16 k, uint16 j) { // 0x86980E + int v2 = k >> 1; + R18_ = enemy_projectile_x_pos[v2]; + R20_ = enemy_projectile_y_pos[v2]; + SpawnEnemyDrops(addr_kEnemyDef_E4FF, k); + return j; +} + +static const uint8 byte_8698B4[16] = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80 }; +static const uint8 byte_8698F7[9] = { 0x30, 0x44, 0x58, 0x6c, 0x80, 0x94, 0xa8, 0xbc, 0xd0 }; +static const uint8 byte_869979[8] = { 0, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0 }; + + +void EprojInit_PhantoonDestroyableFireballs(uint16 j) { // 0x869824 + char v1; + + v1 = (uint16)(enemy_projectile_init_param & 0xFF00) >> 8; + if (v1) { + switch (v1) { + case 2: { + int v3 = j >> 1; + enemy_projectile_1A27[v3] = 0; + enemy_projectile_y_subpos[v3] = 0; + enemy_projectile_y_vel[v3] = 0; + uint16 v4 = (uint8)enemy_projectile_init_param; + if ((int16)((uint8)enemy_projectile_init_param - 8) >= 0) + enemy_projectile_x_vel[v3] = -2; + else + enemy_projectile_x_vel[v3] = 2; + enemy_projectile_E[v3] = byte_8698B4[v4]; + enemy_projectile_x_pos[v3] = enemy_data[0].x_pos; + enemy_projectile_y_pos[v3] = enemy_data[0].y_pos + 32; + enemy_projectile_pre_instr[v3] = FUNC16(EprojPreInstr_PhantoonDestroyableFireballs); + break; + } + case 4: { + int v5 = j >> 1; + enemy_projectile_1A27[v5] = 0; + enemy_projectile_y_subpos[v5] = 0; + enemy_projectile_y_vel[v5] = 0; + uint16 v6 = enemy_projectile_init_param & 0xF; + enemy_projectile_x_vel[v5] = (uint8)(enemy_projectile_init_param & 0xF0) >> 1; + enemy_projectile_x_pos[v5] = byte_8698F7[v6]; + enemy_projectile_y_pos[v5] = 40; + enemy_projectile_pre_instr[v5] = FUNC16(EprojPreInstr_PhantoonDestroyableFireballs_2); + break; + } + case 6: { + int v7 = j >> 1; + enemy_projectile_1A27[v7] = 0; + enemy_projectile_y_subpos[v7] = 0; + enemy_projectile_y_vel[v7] = 0; + enemy_projectile_x_vel[v7] = 128; + enemy_projectile_E[v7] = byte_869979[(uint8)enemy_projectile_init_param]; + enemy_projectile_x_pos[v7] = enemy_data[0].x_pos; + enemy_projectile_y_pos[v7] = enemy_data[0].y_pos + 16; + enemy_projectile_pre_instr[v7] = FUNC16(EprojPreInstr_PhantoonDestroyableFireballs_3); + break; + } + default: + Unreachable(); + while (1) + ; + } + } else { + int v2 = j >> 1; + enemy_projectile_1A27[v2] = 0; + enemy_projectile_y_subpos[v2] = 0; + enemy_projectile_x_vel[v2] = 0; + enemy_projectile_y_vel[v2] = 0; + enemy_projectile_x_pos[v2] = enemy_data[0].x_pos; + enemy_projectile_y_pos[v2] = enemy_data[0].y_pos + 32; + enemy_projectile_instr_list_ptr[v2] = addr_off_8697B4; + enemy_projectile_properties[v2] = enemy_projectile_properties[v2] & 0xFFF | 0x2000; + } +} + +void EprojInit_PhantoonStartingFireballs(uint16 j) { // 0x86993A + int v1 = j >> 1; + enemy_projectile_1A27[v1] = 0; + enemy_projectile_y_subpos[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + uint16 v2 = byte_869979[enemy_projectile_init_param]; + enemy_projectile_E[v1] = v2; + Eproj_PhantomFireballs_Func1(v2, 0x30u); + enemy_projectile_x_pos[v1] = R20_ + enemy_data[0].x_pos; + enemy_projectile_y_pos[v1] = R22_ + enemy_data[0].y_pos + 16; +} + +void EprojPreInstr_PhantoonStartingFireballs(uint16 k) { // 0x869981 + int v1 = k >> 1; + enemy_projectile_y_vel[v1] += 16; + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) { + enemy_projectile_properties[v1] = enemy_projectile_properties[v1] & 0xFFF | 0x8000; + enemy_projectile_pre_instr[v1] = FUNC16(EprojPreInstr_PhantoonStartingFireballs2); + enemy_projectile_instr_list_ptr[v1] = addr_word_86976C; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_E[v1] = 8; + enemy_projectile_y_pos[v1] += 8; + } +} + +void EprojPreInstr_PhantoonStartingFireballs2(uint16 k) { // 0x8699BF + int v1 = k >> 1; + bool v2 = enemy_projectile_E[v1] == 1; + bool v3 = (--enemy_projectile_E[v1] & 0x8000u) != 0; + if (v2 || v3) { + enemy_projectile_pre_instr[v1] = FUNC16(EprojPreInstr_PhantoonStartingFireballs3); + enemy_projectile_instr_list_ptr[v1] = addr_word_869772; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_y_pos[v1] -= 8; + enemy_projectile_y_vel[v1] = -768; + enemy_projectile_E[v1] = 0; + if ((nmi_frame_counter_word & 1) != 0) + enemy_projectile_x_vel[v1] = -128; + else + enemy_projectile_x_vel[v1] = 128; + } +} + +static const uint16 word_869A3E[3] = { 0xfd00, 0xfe00, 0xff00 }; + +void EprojPreInstr_PhantoonStartingFireballs3(uint16 k) { // 0x869A01 + int v1 = k >> 1; + enemy_projectile_y_vel[v1] += 16; + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) { + uint16 v2 = enemy_projectile_E[v1] + 1; + enemy_projectile_E[v1] = v2; + if (sign16(v2 - 3)) { + enemy_projectile_y_vel[v1] = word_869A3E[v2]; + return; + } + goto LABEL_6; + } + if (EnemyProjectileBlockCollisition_Horiz(k) & 1) { +LABEL_6: + enemy_projectile_instr_list_ptr[v1] = addr_word_869782; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_pre_instr[v1] = FUNC16(nullsub_86); + } +} + +void EprojPreInstr_PhantoonDestroyableFireballs(uint16 k) { // 0x869A45 + int16 v4; + uint16 v5; + int v1 = k >> 1; + enemy_projectile_y_vel[v1] += 4; + uint16 v2 = (uint8)(LOBYTE(enemy_projectile_x_vel[v1]) + enemy_projectile_E[v1]); + enemy_projectile_E[v1] = v2; + Eproj_PhantomFireballs_Func1(v2, enemy_projectile_y_vel[v1]); + bool v3 = (int16)(R20_ + enemy_data[0].x_pos) < 0; + v4 = R20_ + enemy_data[0].x_pos; + enemy_projectile_x_pos[v1] = R20_ + enemy_data[0].x_pos; + if (v3 + || !sign16(v4 - 256) + || (v3 = (int16)(R22_ + enemy_data[0].y_pos + 16) < 0, + v5 = R22_ + enemy_data[0].y_pos + 16, + enemy_projectile_y_pos[v1] = v5, + v3) + || !sign16(v5 - 256)) { + enemy_projectile_instr_list_ptr[v1] = addr_off_8697F8; + enemy_projectile_instr_timers[v1] = 1; + } +} + +void EprojPreInstr_PhantoonDestroyableFireballs_2(uint16 k) { // 0x869A94 + int v1 = k >> 1; + if (!enemy_projectile_x_vel[v1]) + goto LABEL_5; + bool v2, v3; + v2 = enemy_projectile_x_vel[v1] == 1; + v3 = (--enemy_projectile_x_vel[v1] & 0x8000u) != 0; + if (v2 || v3) { + QueueSfx3_Max6(0x1Du); +LABEL_5: + enemy_projectile_y_vel[v1] += 16; + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) { + enemy_projectile_instr_list_ptr[v1] = addr_word_8697AC; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_y_pos[v1] += 8; + enemy_projectile_pre_instr[v1] = FUNC16(nullsub_86); + QueueSfx3_Max6(0x1Du); + } + } +} + +void EprojPreInstr_PhantoonDestroyableFireballs_3(uint16 k) { // 0x869ADA + int16 v4; + uint16 v5; + int v1 = k >> 1; + enemy_projectile_y_vel[v1] += 2; + uint16 v2 = (uint8)(enemy_projectile_E[v1] + 2); + enemy_projectile_E[v1] = v2; + Eproj_PhantomFireballs_Func1(v2, enemy_projectile_y_vel[v1]); + bool v3 = (int16)(R20_ + enemy_data[0].x_pos) < 0; + v4 = R20_ + enemy_data[0].x_pos; + enemy_projectile_x_pos[v1] = R20_ + enemy_data[0].x_pos; + if (v3 + || !sign16(v4 - 256) + || (v3 = (int16)(R22_ + enemy_data[0].y_pos + 16) < 0, + v5 = R22_ + enemy_data[0].y_pos + 16, + enemy_projectile_y_pos[v1] = v5, + v3) + || !sign16(v5 - 256)) { + enemy_projectile_instr_list_ptr[v1] = addr_off_8697F8; + enemy_projectile_instr_timers[v1] = 1; + } +} + +void EprojPreInstr_PhantoonStartingFireballsB(uint16 k) { // 0x869B29 + if (enemy_data[0].ai_var_B) { + int v1 = k >> 1; + enemy_projectile_pre_instr[v1] = FUNC16(EprojPreInstr_PhantoonStartingFireballsB_2); + enemy_projectile_x_vel[v1] = 180; + enemy_projectile_y_vel[v1] = 48; + } +} + +void EprojPreInstr_PhantoonStartingFireballsB_2(uint16 k) { // 0x869B41 + int v1 = k >> 1; + uint16 v2 = enemy_projectile_x_vel[v1]; + if (v2) { + enemy_projectile_x_vel[v1] = v2 - 1; +LABEL_5:; + uint8 v4 = enemy_projectile_E[v1] + 1; + enemy_projectile_E[v1] = v4; + Eproj_PhantomFireballs_Func1(v4, enemy_projectile_y_vel[v1]); + enemy_projectile_x_pos[v1] = R20_ + enemy_data[0].x_pos; + enemy_projectile_y_pos[v1] = R22_ + enemy_data[0].y_pos + 16; + return; + } + if ((nmi_frame_counter_word & 1) == 0) + goto LABEL_5; + uint16 v3 = enemy_projectile_y_vel[v1] - 1; + enemy_projectile_y_vel[v1] = v3; + if (v3) + goto LABEL_5; + enemy_projectile_x_pos[v1] = enemy_data[0].x_pos; + enemy_projectile_y_pos[v1] = enemy_data[0].y_pos + 16; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_instr_list_ptr[v1] = addr_off_8697F8; +} + +void Eproj_PhantomFireballs_Func1(uint16 j, uint16 a) { // 0x869BA2 + int16 v3; + uint16 v2, v4; + + R24_ = a; + R26_ = j; + if (sign16(j - 128)) + v2 = Eproj_PhantomFireballs_Func2(2 * j); + else + v2 = -Eproj_PhantomFireballs_Func2(2 * (uint8)(j + 0x80)); + R20_ = v2; + v3 = (uint8)(R26_ - 64); + if (sign16(v3 - 128)) + v4 = Eproj_PhantomFireballs_Func2(2 * v3); + else + v4 = -Eproj_PhantomFireballs_Func2(2 * (uint8)(v3 + 0x80)); + R22_ = v4; +} + + +uint16 Eproj_PhantomFireballs_Func2(uint16 k) { // 0x869BF3 + R18_ = Mult8x8(*((uint8 *)&kSinCosTable8bit_Sext[64] + k), R24_) >> 8; + return R18_ + Mult8x8(*((uint8 *)&kSinCosTable8bit_Sext[64] + k + 1), R24_); +} + +void EprojInit_RocksKraidSpits(uint16 j) { // 0x869CA3 + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = v1->x_pos + 16; + enemy_projectile_y_pos[v2] = v1->y_pos - 96; + enemy_projectile_y_subpos[v2] = 0; + enemy_projectile_1A27[v2] = 0; + enemy_projectile_x_vel[v2] = enemy_projectile_init_param; + enemy_projectile_y_vel[v2] = -1024; + enemy_projectile_gfx_idx[v2] = 1536; +} + +void EprojInit_RocksFallingKraidCeiling(uint16 j) { // 0x869CD8 + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = enemy_projectile_init_param; + enemy_projectile_y_pos[v1] = 312; + enemy_projectile_y_subpos[v1] = 0; + enemy_projectile_1A27[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = (random_number & 0x3F) + 64; + enemy_projectile_gfx_idx[v1] = 1536; +} + +void EprojInit_RocksWhenKraidRises(uint16 j) { // 0x869D0C + int16 v1; + + v1 = random_number & 0x3F; + if ((random_number & 1) == 0) + v1 = ~v1; + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = gEnemyData(cur_enemy_index)->x_pos + v1; + enemy_projectile_y_pos[v2] = 432; + enemy_projectile_y_subpos[v2] = 0; + enemy_projectile_1A27[v2] = 0; + enemy_projectile_x_vel[v2] = enemy_projectile_init_param; + enemy_projectile_y_vel[v2] = -1280; + enemy_projectile_gfx_idx[v2] = 1536; + QueueSfx3_Max6(0x1Eu); +} + +void EprojPreInstr_KraidRocks(uint16 k) { // 0x869D56 + if (EnemyProjectileBlockCollisition_Horiz(k) & 1 || EnemyProjectileBlockCollisition_Vertical(k) & 1) { + enemy_projectile_id[k >> 1] = 0; + } else { + int v1 = k >> 1; + uint16 v2 = enemy_projectile_x_vel[v1] + 8; + enemy_projectile_x_vel[v1] = v2; + if (!sign16(v2 - 256)) + v2 = -256; + enemy_projectile_x_vel[v1] = v2; + enemy_projectile_y_vel[v1] += 64; + } +} + +void EprojPreInstr_RocksFallingKraidCeiling(uint16 k) { // 0x869D89 + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) + enemy_projectile_id[k >> 1] = 0; + else + enemy_projectile_y_vel[k >> 1] = (enemy_projectile_y_vel[k >> 1] + 24) & 0x3FFF; +} + +void sub_869DA5(uint16 k) { // 0x869DA5 + enemy_projectile_gfx_idx[k >> 1] = 0; +} + +void EprojInit_MiniKraidSpit(uint16 j) { // 0x869DEC + ExtraEnemyRam7800 *v2; + + EnemyData *v1 = gEnemyData(cur_enemy_index); + v2 = gExtraEnemyRam7800(cur_enemy_index); + int v3 = j >> 1; + enemy_projectile_x_pos[v3] = v2->kraid.field_4 + v1->x_pos; + enemy_projectile_y_pos[v3] = v1->y_pos - 16; + enemy_projectile_y_subpos[v3] = 0; + enemy_projectile_1A27[v3] = 0; + enemy_projectile_x_vel[v3] = v2->kraid.kraid_next; + enemy_projectile_y_vel[v3] = v2->kraid.field_2; +} + +void EprojPreInit_MiniKraidSpit(uint16 k) { // 0x869E1E + int16 v2; + + if (EnemyProjectileBlockCollisition_Horiz(k) & 1 || EnemyProjectileBlockCollisition_Vertical(k) & 1) { + enemy_projectile_id[k >> 1] = 0; + } else { + int v1 = k >> 1; + v2 = enemy_projectile_y_vel[v1] + 64; + if (v2 >= 0 && !sign16(enemy_projectile_y_vel[v1] - 960)) + v2 = 1024; + enemy_projectile_y_vel[v1] = v2; + } +} + +void EprojInit_MiniKraidSpikesLeft(uint16 j) { // 0x869E46 + EprojInit_MiniKraidSpikes(j, -0x200); +} + +void EprojInit_MiniKraidSpikesRight(uint16 j) { // 0x869E4B + EprojInit_MiniKraidSpikes(j, 0x200); +} +static const int16 kEprojInit_MiniKraidSpikes_Tab0[3] = { -2, 12, 24 }; +void EprojInit_MiniKraidSpikes(uint16 j, uint16 a) { // 0x869E4E + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = a; + R18_ = kEprojInit_MiniKraidSpikes_Tab0[gExtraEnemyRam7800(cur_enemy_index)->kraid.kraid_healths_8ths[0] >> 1]; + EnemyData *v3 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v2] = v3->x_pos; + enemy_projectile_y_pos[v2] = R18_ + v3->y_pos; + enemy_projectile_y_subpos[v2] = 0; + enemy_projectile_1A27[v2] = 0; + enemy_projectile_y_vel[v2] = 0; +} + +void EprojPreInstr_MiniKraidSpikes(uint16 k) { // 0x869E83 + if (EnemyProjectileBlockCollisition_Horiz(k) & 1) + enemy_projectile_id[k >> 1] = 0; +} + +void EprojInit_WalkingLavaSeahorseFireball(uint16 j) { // 0x869EB2 + static const int16 word_869EF9[3] = { -0x100, 0, 0x100 }; + + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_y_pos[v2] = v1->y_pos - 12; + enemy_projectile_x_vel[v2] = -1024; + enemy_projectile_x_pos[v2] = v1->x_pos - 16; + if ((v1->ai_var_D & 0x8000u) == 0) { + enemy_projectile_x_vel[v2] = 1024; + enemy_projectile_x_pos[v2] = v1->x_pos + 16; + } + enemy_projectile_y_vel[v2] = word_869EF9[enemy_projectile_init_param >> 1]; + enemy_projectile_y_subpos[v2] = 0; + enemy_projectile_1A27[v2] = 0; +} + +void EprojPreInstr_WalkingLavaSeahorseFireball(uint16 k) { // 0x869EFF + uint16 v2; + if (EnemyProjectileBlockCollisition_Vertical(k) & 1 || EnemyProjectileBlockCollisition_Horiz(k) & 1) { + enemy_projectile_id[k >> 1] = 0; + } else { + int v1 = k >> 1; + if ((enemy_projectile_x_vel[v1] & 0x8000u) == 0) { + v2 = enemy_projectile_x_vel[v1] - 64; + enemy_projectile_x_vel[v1] = v2; + if (sign16(v2 - 512)) + v2 = 512; + } else { + v2 = enemy_projectile_x_vel[v1] + 64; + enemy_projectile_x_vel[v1] = v2; + if (!sign16(v2 + 512)) + v2 = -512; + } + enemy_projectile_x_vel[v1] = v2; + } +} + +void EprojInit_PirateMotherBrainLaser(uint16 j) { // 0x86A009 + uint16 v1 = addr_word_869F41; + if (R22_) + v1 = addr_word_869F7D; + int v2 = j >> 1; + enemy_projectile_instr_list_ptr[v2] = v1; + enemy_projectile_pre_instr[v2] = FUNC16(nullsub_87); + enemy_projectile_x_pos[v2] = R18_; + enemy_projectile_y_pos[v2] = R20_; + EnemyData *v3 = gEnemyData(cur_enemy_index); + enemy_projectile_properties[v2] = *((uint16 *)RomPtr_A0(v3->enemy_ptr) + 3) | 0x1000; + enemy_projectile_E[v2] = gEnemyData(cur_enemy_index)->parameter_1; + QueueSfx2_Max6(0x67u); +} + +uint16 EprojInstr_SetPreInstrAndRun(uint16 k, uint16 j) { // 0x86A050 + enemy_projectile_pre_instr[k >> 1] = *(uint16 *)RomPtr_86(j); + return j; +} + +void EprojPreInstr_PirateMotherBrainLaser_MoveLeft(uint16 k) { // 0x86A05C + int v1 = k >> 1; + --enemy_projectile_x_pos[v1]; + --enemy_projectile_x_pos[v1]; + if ((enemy_projectile_E[v1] & 0x8000u) == 0) { + --enemy_projectile_x_pos[v1]; + --enemy_projectile_x_pos[v1]; + } + if (CheckIfEnemyProjectileIsOffScreen(k)) + enemy_projectile_id[v1] = 0; +} + +void EprojPreInstr_PirateMotherBrainLaser_MoveRight(uint16 k) { // 0x86A07A + int v1 = k >> 1; + ++enemy_projectile_x_pos[v1]; + ++enemy_projectile_x_pos[v1]; + if ((enemy_projectile_E[v1] & 0x8000u) == 0) { + ++enemy_projectile_x_pos[v1]; + ++enemy_projectile_x_pos[v1]; + } + if (CheckIfEnemyProjectileIsOffScreen(k)) + enemy_projectile_id[v1] = 0; +} + +void EprojInit_PirateClaw(uint16 j) { // 0x86A098 + int v1 = j >> 1; + enemy_projectile_y_pos[v1] = R24_ + R20_; + enemy_projectile_x_pos[v1] = R22_ + R18_; + uint16 v2 = addr_off_869FB9; + if (enemy_projectile_init_param) + v2 = addr_off_869FE1; + enemy_projectile_instr_list_ptr[v1] = v2; + enemy_projectile_pre_instr[v1] = FUNC16(nullsub_87); + enemy_projectile_E[v1] = 2048; + enemy_projectile_F[v1] = 1; +} + +void EprojPreInstr_PirateClawThrownLeft(uint16 k) { // 0x86A0D1 + int v1 = k >> 1; + if (enemy_projectile_F[v1]) { + R18_ = HIBYTE(enemy_projectile_E[v1]); + enemy_projectile_x_pos[v1] -= R18_; + uint16 v2 = enemy_projectile_E[v1] - 32; + enemy_projectile_E[v1] = v2; + if (!v2) + enemy_projectile_F[v1] = 0; + } else { + enemy_projectile_x_pos[v1] += HIBYTE(enemy_projectile_E[v1]); + enemy_projectile_E[v1] += 32; + } + ++enemy_projectile_y_pos[v1]; + if (CheckIfEnemyProjectileIsOffScreen(k)) + enemy_projectile_id[v1] = 0; +} + +void EprojPreInstr_PirateClawThrownRight(uint16 k) { // 0x86A124 + int v1 = k >> 1; + if (enemy_projectile_F[v1]) { + R18_ = HIBYTE(enemy_projectile_E[v1]); + enemy_projectile_x_pos[v1] += R18_; + uint16 v2 = enemy_projectile_E[v1] - 32; + enemy_projectile_E[v1] = v2; + if (!v2) + enemy_projectile_F[v1] = 0; + } else { + R18_ = HIBYTE(enemy_projectile_E[v1]); + enemy_projectile_x_pos[v1] -= R18_; + enemy_projectile_E[v1] += 32; + } + ++enemy_projectile_y_pos[v1]; + if (CheckIfEnemyProjectileIsOffScreen(k)) + enemy_projectile_id[v1] = 0; +} + +static const int16 word_86A2D6[6] = { 64, 72, 80, -64, -72, -80 }; +#define off_86A2E2 ((uint16*)RomPtr(0x86a2e2)) + +void EprojInit_A379(uint16 j) { // 0x86A2A1 + int v1 = j >> 1; + enemy_projectile_1A27[v1] = 0; + enemy_projectile_y_subpos[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + uint16 v2 = enemy_projectile_init_param; + int v3 = enemy_projectile_init_param >> 1; + enemy_projectile_x_pos[v1] = word_86A2D6[v3] + samus_x_pos; + enemy_projectile_y_pos[v1] = samus_y_pos + 80; + enemy_projectile_instr_list_ptr[v1] = off_86A2E2[v3]; + enemy_projectile_E[v1] = v2; +} + +void EprojInit_CeresElevatorPad(uint16 j) { // 0x86A2EE + int v1 = j >> 1; + enemy_projectile_y_pos[v1] = samus_y_pos + 28; + enemy_projectile_E[v1] = 60; + sub_86A301(j); +} + +void sub_86A301(uint16 j) { // 0x86A301 + int v1 = j >> 1; + enemy_projectile_1A27[v1] = 0; + enemy_projectile_y_subpos[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + enemy_projectile_gfx_idx[v1] = 0; + enemy_projectile_x_pos[v1] = samus_x_pos; +} + + +void EprojInit_CeresElevatorPlatform(uint16 j) { // 0x86A31B + enemy_projectile_y_pos[j >> 1] = 97; + sub_86A301(j); +} + + +void EprojPreInstr_CeresElevatorPad(uint16 k) { // 0x86A328 + bool v2; // zf + bool v3; // sf + + int v1 = k >> 1; + if (!enemy_projectile_E[v1] + || (v2 = enemy_projectile_E[v1] == 1, v3 = (int16)(enemy_projectile_E[v1] - 1) < 0, --enemy_projectile_E[v1], v2) + || v3) { + enemy_projectile_y_pos[v1] = samus_y_pos + 28; + if (!sign16(++samus_y_pos - 73)) { + samus_y_pos = 72; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_instr_list_ptr[v1] = addr_off_86A28B; + CallSomeSamusCode(0xEu); + } + } +} + +void EprojPreInstr_CeresElevatorPlatform(uint16 k) { // 0x86A364 + if (samus_y_pos == 72) { + int v1 = k >> 1; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_instr_list_ptr[v1] = addr_off_86A28B; + } +} + +void EprojPreInstr_PrePhantomRoom(uint16 j) { // 0x86A3A3 + bg2_y_scroll = 0; +} + +uint16 EprojInstr_A3BE(uint16 k, uint16 j) { // 0x86A3BE + int v1 = k >> 1; + enemy_projectile_x_pos[v1] = enemy_projectile_E[v1]; + enemy_projectile_y_pos[v1] = enemy_projectile_F[v1]; + return j; +} + +uint16 EprojInstr_GotoWithProbability25(uint16 k, uint16 j) { // 0x86A456 + if ((NextRandom() & 0xC000) == 0xC000) + return *(uint16 *)RomPtr_86(j); + else + return j + 2; +} + +void EprojInit_BombTorizoLowHealthDrool(uint16 j) { // 0x86A5D3 + int16 parameter_1; // dx + uint16 v4, v5, v8; + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 0; + enemy_projectile_instr_list_ptr[v1] = off_86A64D[(uint16)((NextRandom() >> 1) & 0xE) >> 1]; + NextRandom(); + EnemyData *v2 = gEnemyData(cur_enemy_index); + enemy_projectile_y_pos[v1] = v2->y_pos - 5; + parameter_1 = v2->parameter_1; + if ((parameter_1 & 0x4000) != 0) { + v4 = random_number & 0x1FE; + } else { + if (parameter_1 < 0) + v5 = 32; + else + v5 = 224; + R18_ = v5; + v4 = 2 * (v5 + (random_number & 0xF) - 8); + } + int v6 = v4 >> 1; + enemy_projectile_x_vel[v1] = kSinCosTable8bit_Sext[v6 + 64]; + enemy_projectile_y_vel[v1] = kSinCosTable8bit_Sext[v6]; + EnemyData *v7 = gEnemyData(cur_enemy_index); + if ((v7->parameter_1 & 0x8000u) != 0) + v8 = v7->x_pos + 8; + else + v8 = v7->x_pos - 8; + enemy_projectile_x_pos[v1] = v8; +} + +void EprojInit_BombTorizoLowHealthInitialDrool(uint16 j) { // 0x86A65D + int16 v3; + int16 parameter_1; // dx + + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 0; + NextRandom(); + EnemyData *v2 = gEnemyData(cur_enemy_index); + enemy_projectile_y_pos[v1] = v2->y_pos + (random_number & 3) - 5; + enemy_projectile_y_vel[v1] = (random_number & 0x1F) + 48; + NextRandom(); + v3 = random_number & 3; + parameter_1 = v2->parameter_1; + if ((parameter_1 & 0x4000) != 0) { + enemy_projectile_x_pos[v1] = v2->x_pos + v3; + enemy_projectile_x_vel[v1] = 0; + } else { + if (parameter_1 < 0) + enemy_projectile_x_pos[v1] = v2->x_pos + v3 + 8; + else + enemy_projectile_x_pos[v1] = v2->x_pos + v3 - 8; + enemy_projectile_x_vel[v1] = 0; + } +} + +void EprojInit_A977(uint16 j) { // 0x86A6C7 + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 0; + CalculatePlmBlockCoords(plm_id); + enemy_projectile_x_pos[v1] = 16 * plm_x_block; + enemy_projectile_y_pos[v1] = 16 * plm_y_block - 4; + enemy_projectile_1A27[v1] = 0; + enemy_projectile_y_subpos[v1] = 0; +} + +static const int16 kEprojInit_BombTorizoExplosiveSwipe_Tab0[11] = { -30, -40, -47, -31, -21, -1, -28, -43, -48, -31, -21 }; +static const int16 kEprojInit_BombTorizoExplosiveSwipe_Tab1[11] = { -52, -28, -11, 9, 21, 20, -52, -27, -10, 9, 20 }; +#define kEprojInit_BombTorizoStatueBreaking_InstrList ((uint16*)RomPtr(0x86a7ab)) +static const int16 kEprojInit_BombTorizoStatueBreaking_Xpos[16] = { 8, 0x18, -8, 8, 0x18, -8, 8, 0x18, 8, -8, 0x18, 8, -8, 0x18, 8, -8 }; +static const int16 kEprojInit_BombTorizoStatueBreaking_Ypos[8] = { -8, -8, 8, 8, 8, 0x18, 0x18, 0x18 }; +static const int16 kEprojInit_BombTorizoStatueBreaking_Yvel[8] = { 256, 256, 256, 256, 256, 256, 256, 256 }; +static const int16 kEprojInit_BombTorizoStatueBreaking_F[8] = { 16, 16, 16, 16, 16, 16, 16, 16 }; +static const int16 kEprojInit_BombTorizoLowHealthExplode_X[6] = { 0, 12, -12, 0, 16, -16 }; +static const int16 kEprojInit_BombTorizoLowHealthExplode_Y[6] = { -8, -8, -8, -20, -20, -20 }; + +void EprojInit_BombTorizoExplosiveSwipe(uint16 j) { // 0x86A6F6 + EnemyData *v1 = gEnemyData(cur_enemy_index); + R18_ = v1->x_pos; + R20_ = v1->y_pos; + if ((v1->parameter_1 & 0x8000u) != 0) { + int v4 = enemy_projectile_init_param >> 1; + int v5 = j >> 1; + enemy_projectile_x_pos[v5] = R18_ - kEprojInit_BombTorizoExplosiveSwipe_Tab0[v4]; + enemy_projectile_y_pos[v5] = R20_ + kEprojInit_BombTorizoExplosiveSwipe_Tab1[v4]; + } else { + int v2 = enemy_projectile_init_param >> 1; + int v3 = j >> 1; + enemy_projectile_x_pos[v3] = R18_ + kEprojInit_BombTorizoExplosiveSwipe_Tab0[v2]; + enemy_projectile_y_pos[v3] = R20_ + kEprojInit_BombTorizoExplosiveSwipe_Tab1[v2]; + } +} + +void EprojInit_BombTorizoStatueBreaking(uint16 j) { // 0x86A764 + char v1; + + CalculatePlmBlockCoords(plm_id); + v1 = enemy_projectile_init_param; + int v2 = enemy_projectile_init_param >> 1; + int v3 = j >> 1; + enemy_projectile_instr_list_ptr[v3] = kEprojInit_BombTorizoStatueBreaking_InstrList[v2]; + enemy_projectile_x_pos[v3] = kEprojInit_BombTorizoStatueBreaking_Xpos[v2] + 16 * plm_x_block; + int v4 = (uint8)(v1 & 0xF) >> 1; + enemy_projectile_y_pos[v3] = kEprojInit_BombTorizoStatueBreaking_Ypos[v4] + 16 * plm_y_block; + enemy_projectile_y_vel[v3] = kEprojInit_BombTorizoStatueBreaking_Yvel[v4]; + enemy_projectile_F[v3] = kEprojInit_BombTorizoStatueBreaking_F[v4]; + enemy_projectile_properties[v3] |= 0x1000u; +} + +void EprojInit_BombTorizoLowHealthExplode(uint16 j) { // 0x86A81B + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = v1->x_pos; + enemy_projectile_y_pos[v2] = v1->y_pos; + if ((v1->parameter_1 & 0x8000u) == 0) { + ++enemy_projectile_init_param; + ++enemy_projectile_init_param; + } + ++enemy_projectile_init_param; + int v3 = ++enemy_projectile_init_param >> 1; + uint16 v4 = kEprojInit_BombTorizoLowHealthExplode_X[v3] + enemy_projectile_x_pos[v2]; + enemy_projectile_x_pos[v2] = v4; + enemy_projectile_E[v2] = v4; + uint16 v5 = kEprojInit_BombTorizoLowHealthExplode_Y[v3] + enemy_projectile_y_pos[v2]; + enemy_projectile_y_pos[v2] = v5; + enemy_projectile_F[v2] = v5; +} + +void EprojInit_BombTorizoDeathExplosion(uint16 j) { // 0x86A871 + EnemyData *v1 = gEnemyData(cur_enemy_index); + uint16 x_pos = v1->x_pos; + int v3 = j >> 1; + enemy_projectile_x_pos[v3] = x_pos; + enemy_projectile_E[v3] = x_pos; + uint16 y_pos = v1->y_pos; + enemy_projectile_y_pos[v3] = y_pos; + enemy_projectile_F[v3] = y_pos; +} + +void sub_86A887(uint16 v0) { // 0x86A887 + int16 v2; + int16 v3; + int16 v4; + + if (EnemyProjectileBlockCollisition_Horiz(v0) & 1) { + int v6 = v0 >> 1; + enemy_projectile_instr_list_ptr[v6] = 0xA48A; + enemy_projectile_instr_timers[v6] = 1; + } else { + int v1 = v0 >> 1; + v2 = enemy_projectile_x_vel[v1]; + if (v2 >= 0) { + v4 = v2 - 4; + if (v4 < 0) + v4 = 3; + enemy_projectile_x_vel[v1] = v4; + } else { + v3 = v2 + 4; + if (v3 >= 0) + v3 = 3; + enemy_projectile_x_vel[v1] = v3; + } + uint8 carry = EnemyProjectileBlockCollisition_Vertical(v0); + if ((enemy_projectile_y_vel[v1] & 0x8000u) != 0 || !carry) { + uint16 v5 = enemy_projectile_y_vel[v1] + 16; + enemy_projectile_y_vel[v1] = v5; + if ((v5 & 0xF000) == 4096) + enemy_projectile_id[v1] = 0; + } else { + int v7 = v0 >> 1; + enemy_projectile_y_pos[v7] -= 3; + enemy_projectile_instr_list_ptr[v7] = 0xA48E; + enemy_projectile_instr_timers[v7] = 1; + } + } +} + +void EprojPreInstr_A977(uint16 k) { // 0x86A8EF + uint8 carry = EnemyProjectileBlockCollisition_Vertical(k); + int v1 = k >> 1; + if ((enemy_projectile_y_vel[v1] & 0x8000u) != 0 || !carry) { + uint16 v2 = enemy_projectile_F[0] + enemy_projectile_y_vel[v1]; + enemy_projectile_y_vel[v1] = v2; + if ((v2 & 0xF000) == 4096) + enemy_projectile_y_vel[v1] = 4096; + } else { + enemy_projectile_pre_instr[v1] = 0xA918; + } +} + +void sub_86A91A(uint16 v0) { // 0x86A91A + int v1 = v0 >> 1; + enemy_projectile_x_vel[v1] = 0; + if ((joypad2_last & 0x100) != 0) + enemy_projectile_x_vel[v1] = 256; + if ((joypad2_last & 0x200) != 0) + enemy_projectile_x_vel[v1] = -256; + EnemyProjectileBlockCollisition_Horiz(v0); + enemy_projectile_y_vel[v1] = 0; + if ((joypad2_last & 0x400) != 0) + enemy_projectile_y_vel[v1] = 256; + if ((joypad2_last & 0x800) != 0) + enemy_projectile_y_vel[v1] = -256; + EnemyProjectileBlockCollisition_Vertical(v0); +} + +void EprojInit_AB07(uint16 j) { // 0x86AA3D + VramWriteEntry *v2; + VramWriteEntry *v3; + + uint16 v1 = vram_write_queue_tail; + v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 64; + v2->src.addr = addr_kEprojInit_AB07_Tile0; + *(uint16 *)&v2->src.bank = 134; + v2->vram_dst = 28160; + v1 += 7; + v3 = gVramWriteEntry(v1); + v3->size = 64; + v3->src.addr = addr_kEprojInit_AB07_Tile1; + *(uint16 *)&v3->src.bank = 134; + v3->vram_dst = 28416; + vram_write_queue_tail = v1 + 7; + int v4 = j >> 1; + enemy_projectile_x_pos[v4] = samus_x_pos; + enemy_projectile_y_pos[v4] = samus_y_pos - 36; +} + +void EprojPreInstr_AB07(uint16 k) { // 0x86AA8C + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + uint16 v2 = 8 * (samus_x_pos - enemy_projectile_x_pos[v1]); + if (((samus_x_pos - enemy_projectile_x_pos[v1]) & 0x1000) != 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + bool v3 = __CFADD__uint16(enemy_projectile_1A27[v1], R18_); + enemy_projectile_1A27[v1] += R18_; + enemy_projectile_x_pos[v1] += v3 + R20_; + R18_ = 0; + R20_ = 0; + uint16 v4 = 8 * (samus_y_pos - 36 - enemy_projectile_y_pos[v1]); + if (((samus_y_pos - 36 - enemy_projectile_y_pos[v1]) & 0x1000) != 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v4; + v3 = __CFADD__uint16(enemy_projectile_y_subpos[v1], R18_); + enemy_projectile_y_subpos[v1] += R18_; + enemy_projectile_y_pos[v1] += v3 + R20_; +} + +uint16 EprojInstr_SpawnEnemyDrops(uint16 k, uint16 j) { // 0x86AB8A + int v2 = k >> 1; + uint16 v3; + R18_ = enemy_projectile_x_pos[v2]; + R20_ = enemy_projectile_y_pos[v2]; + if (area_index) + v3 = *((uint16 *)RomPtr_86(j) + 1); + else + v3 = *(uint16 *)RomPtr_86(j); + SpawnEnemyDrops(v3, k); + return j + 4; +} + +void Eproj_InitXYVelRandom(uint16 j, uint16 k) { // 0x86ABAE + uint16 *v2 = (uint16 *)RomPtr_86(k); + int v3 = j >> 1; + enemy_projectile_instr_list_ptr[v3] = *v2; + enemy_projectile_x_pos[v3] = v2[1] + R18_; + enemy_projectile_x_vel[v3] = v2[2] + (uint8)NextRandom() - 128; + enemy_projectile_y_pos[v3] = v2[3] + R20_; + enemy_projectile_y_vel[v3] = v2[4] + (uint8)NextRandom() - 128; +} + +void EprojInit_BombTorizosChozoOrbs(uint16 j) { // 0x86ABEB + EnemyData *v1 = gEnemyData(cur_enemy_index); + uint16 v2; + R18_ = v1->x_pos; + R20_ = v1->y_pos; + if ((v1->parameter_1 & 0x8000u) != 0) + v2 = addr_kEprojInit_BombTorizosChozoOrbs_init0; + else + v2 = addr_kEprojInit_BombTorizosChozoOrbs_init1; + Eproj_InitXYVelRandom(j, v2); +} + +void EprojInit_GoldenTorizosChozoOrbs(uint16 j) { // 0x86AC7C + EnemyData *v1 = gEnemyData(cur_enemy_index); + uint16 v2; + R18_ = v1->x_pos; + R20_ = v1->y_pos; + if ((v1->parameter_1 & 0x8000u) != 0) + v2 = addr_kEprojInit_GoldenTorizosChozoOrbs_init0; + else + v2 = addr_kEprojInit_GoldenTorizosChozoOrbs_init1; + Eproj_InitXYVelRandom(j, v2); +} + +void EprojPreInstr_BombTorizosChozoOrbs(uint16 k) { // 0x86ACAD + if (EnemyProjectileBlockCollisition_Horiz(k)) { + int v3 = k >> 1; + enemy_projectile_instr_list_ptr[v3] = addr_off_86AB25; + enemy_projectile_instr_timers[v3] = 1; + } else { + uint8 carry = EnemyProjectileBlockCollisition_Vertical(k); + int v1 = k >> 1; + if ((enemy_projectile_y_vel[v1] & 0x8000u) != 0 || !carry) { + uint16 v2 = enemy_projectile_y_vel[v1] + 18; + enemy_projectile_y_vel[v1] = v2; + if ((v2 & 0xF000) == 4096) + enemy_projectile_id[v1] = 0; + } else { + int v4 = k >> 1; + enemy_projectile_y_pos[v4] = (enemy_projectile_y_pos[v4] & 0xFFF0 | 8) - 2; + enemy_projectile_instr_list_ptr[v4] = addr_off_86AB41; + enemy_projectile_instr_timers[v4] = 1; + } + } +} + +void EprojPreInstr_GoldenTorizosChozoOrbs(uint16 k) { // 0x86ACFA + int v1; + int16 v2; + uint16 v3; + uint16 v4; + + if (EnemyProjectileBlockCollisition_Horiz(k) & 1) + enemy_projectile_x_vel[k >> 1] = -enemy_projectile_x_vel[k >> 1]; + if (EnemyProjectileBlockCollisition_Vertical(k) & 1 + && (v1 = k >> 1, (enemy_projectile_y_vel[v1] & 0x8000u) == 0) + && ((v2 = enemy_projectile_x_vel[v1], v2 >= 0) ? (v3 = v2 - 64) : (v3 = v2 + 64), + enemy_projectile_x_vel[v1] = v3, + v4 = -(enemy_projectile_y_vel[v1] >> 1), + enemy_projectile_y_vel[v1] = v4, + (v4 & 0xFF80) == 0xFF80)) { + int v5 = k >> 1; + enemy_projectile_y_pos[v5] = (enemy_projectile_y_pos[v5] & 0xFFF0 | 8) - 2; + enemy_projectile_instr_list_ptr[v5] = addr_off_86AB41; + enemy_projectile_instr_timers[v5] = 1; + } else { + enemy_projectile_y_vel[k >> 1] += 24; + } +} + +uint16 EprojInstr_GotoDependingOnXDirection(uint16 k, uint16 j) { // 0x86AD92 + int16 v3; + + R18_ = 0; + R20_ = 0; + int v2 = k >> 1; + v3 = enemy_projectile_x_vel[v2]; + if (v3 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v3; + uint16 v4 = enemy_projectile_1A27[v2]; + bool v5 = __CFADD__uint16(R18_, v4); + enemy_projectile_1A27[v2] = R18_ + v4; + enemy_projectile_x_pos[v2] += R20_ + v5; + if ((enemy_projectile_x_vel[v2] & 0x8000u) == 0) + return *((uint16 *)RomPtr_86(j) + 1); + else + return *(uint16 *)RomPtr_86(j); +} + +void EprojInit_TorizoSonicBoom(uint16 j) { // 0x86AE15 + int16 v1; + + NextRandom(); + if ((random_number & 1) != 0) + v1 = -12; + else + v1 = 20; + EnemyData *v2 = gEnemyData(cur_enemy_index); + int v3 = j >> 1; + enemy_projectile_y_pos[v3] = v2->y_pos + v1; + enemy_projectile_y_vel[v3] = 0; + if ((v2->parameter_1 & 0x8000u) != 0) { + enemy_projectile_x_pos[v3] = v2->x_pos + 32; + enemy_projectile_x_vel[v3] = 624; + enemy_projectile_instr_list_ptr[v3] = addr_off_86ADD2; + } else { + enemy_projectile_x_pos[v3] = v2->x_pos - 32; + enemy_projectile_x_vel[v3] = -624; + enemy_projectile_instr_list_ptr[v3] = addr_off_86ADBF; + } +} + +void EprojPreInstr_TorizoSonicBoom(uint16 k) { // 0x86AE6C + int16 v2; + uint16 v3; + + if (EnemyProjectileBlockCollisition_Horiz(k) & 1) { + int v4 = k >> 1; + enemy_projectile_instr_list_ptr[v4] = addr_off_86ADE5; + enemy_projectile_instr_timers[v4] = 1; + enemy_projectile_E[v4] = enemy_projectile_x_pos[v4]; + enemy_projectile_F[v4] = enemy_projectile_y_pos[v4]; + } else { + int v1 = k >> 1; + v2 = enemy_projectile_x_vel[v1]; + if (v2 < 0) + v3 = v2 - 16; + else + v3 = v2 + 16; + enemy_projectile_x_vel[v1] = v3; + if ((v3 & 0xF000) == 4096) + enemy_projectile_id[v1] = 0; + } +} + +void EprojInit_WreckedShipChozoSpikeFootsteps(uint16 j) { // 0x86AEFC + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = enemy_projectile_init_param + v1->x_pos; + enemy_projectile_y_pos[v2] = v1->y_pos + 28; +} + +uint16 EprojInstr_ResetXYpos1(uint16 k, uint16 j) { // 0x86AF36 + int v2 = k >> 1; + enemy_projectile_x_pos[v2] = enemy_projectile_E[v2]; + enemy_projectile_y_pos[v2] = enemy_projectile_F[v2]; + return j; +} + +void EprojInit_TourianStatueDustClouds(uint16 j) { // 0x86AF43 + int v1 = j >> 1; + enemy_projectile_E[v1] = 128; + enemy_projectile_F[v1] = 188; +} + +void EprojInit_TourianLandingDustCloudsRightFoot(uint16 j) { // 0x86AF50 + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_y_pos[v2] = v1->y_pos + 48; + enemy_projectile_x_pos[v2] = v1->x_pos + 24; +} + +uint16 EprojInstr_MoveY_Minus4(uint16 k, uint16 j) { // 0x86AF92 + enemy_projectile_y_pos[k >> 1] -= 4; + return j; +} + +void EprojInit_TorizoLandingDustCloudLeftFoot(uint16 j) { // 0x86AFCD + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_y_pos[v2] = v1->y_pos + 48; + enemy_projectile_x_pos[v2] = v1->x_pos - 24; +} + +void EprojInit_GoldenTorizoEgg(uint16 j) { // 0x86B001 + int16 parameter_1; + uint16 v4; + EnemyData *v1 = gEnemyData(cur_enemy_index); + R18_ = v1->x_pos; + R20_ = v1->y_pos; + int v2 = j >> 1; + enemy_projectile_F[v2] = (0xe2 & 0x1F) + 64; + parameter_1 = v1->parameter_1; + enemy_projectile_E[v2] = parameter_1; + if (parameter_1 < 0) + v4 = addr_kEprojInit_GoldenTorizoEgg0; + else + v4 = addr_kEprojInit_GoldenTorizoEgg1; + Eproj_InitXYVelRandom(j, v4); +} + +void EprojPreInstr_GoldenTorizoEgg(uint16 k) { // 0x86B043 + int16 v3; + uint16 v4, v6; + int v1 = k >> 1; + if ((--enemy_projectile_F[v1] & 0x8000u) != 0) { + ++enemy_projectile_instr_list_ptr[v1]; + ++enemy_projectile_instr_list_ptr[v1]; + enemy_projectile_instr_timers[v1] = 1; + if ((enemy_projectile_E[v1] & 0x8000u) != 0) + v6 = 256; + else + v6 = -256; + enemy_projectile_x_vel[v1] = v6; + } else { + if (EnemyProjectileBlockCollisition_Horiz(k) & 1) { + enemy_projectile_x_vel[v1] = -enemy_projectile_x_vel[v1]; + enemy_projectile_E[v1] ^= 0x8000u; + } + if (EnemyProjectileBlockCollisition_Vertical(k) & 1 && (enemy_projectile_y_vel[v1] & 0x8000u) == 0) { + v3 = enemy_projectile_x_vel[v1]; + if (v3 >= 0) + v4 = v3 - 32; + else + v4 = v3 + 32; + enemy_projectile_x_vel[v1] = v4; + enemy_projectile_y_vel[v1] = -enemy_projectile_y_vel[v1]; + } + uint16 v5 = enemy_projectile_y_vel[v1] + 48; + enemy_projectile_y_vel[v1] = v5; + if ((v5 & 0xF000) == 4096) + enemy_projectile_id[v1] = 0; + } +} + +void sub_86B0B9(uint16 k) { // 0x86B0B9 + int16 v2; + + if (EnemyProjectileBlockCollisition_Horiz(k) & 1) { + int v3 = k >> 1; + enemy_projectile_pre_instr[v3] = 0xB0DD; + enemy_projectile_y_vel[v3] = 0; + } else { + int v1 = k >> 1; + if ((enemy_projectile_E[v1] & 0x8000u) != 0) + v2 = 48; + else + v2 = -48; + enemy_projectile_x_vel[v1] += v2; + } +} + +void sub_86B0DD(uint16 k) { // 0x86B0DD + uint16 v2; + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) { + int v1 = k >> 1; + if ((enemy_projectile_E[v1] & 0x8000u) != 0) + v2 = addr_off_86B1A8; + else + v2 = addr_off_86B190; + enemy_projectile_instr_list_ptr[v1] = v2; + enemy_projectile_instr_timers[v1] = 1; + } else { + enemy_projectile_y_vel[k >> 1] += 48; + } +} + +uint16 sub_86B13E(uint16 k, uint16 j) { // 0x86B13E + if ((enemy_projectile_E[k >> 1] & 0x8000u) != 0) + return addr_off_86B166; + else + return addr_off_86B14B; +} + +uint16 sub_86B183(uint16 k, uint16 j) { // 0x86B183 + if ((enemy_projectile_E[k >> 1] & 0x8000u) != 0) + return addr_off_86B1A8; + else + return addr_off_86B190; +} + +static const int16 word_86B205[2] = { -0x1e, 0x1e }; +#define off_86B209 ((uint16*)RomPtr(0x86b209)) + +void EprojInit_GoldenTorizoSuperMissile(uint16 j) { // 0x86B1CE + uint16 v4; + + int v2 = j >> 1; + enemy_projectile_E[v2] = cur_enemy_index; + EnemyData *v3 = gEnemyData(cur_enemy_index); + R18_ = v3->x_pos; + R20_ = v3->y_pos; + if ((v3->parameter_1 & 0x8000u) != 0) + v4 = 2; + else + v4 = 0; + int v5 = v4 >> 1; + enemy_projectile_x_pos[v2] = R18_ + word_86B205[v5]; + enemy_projectile_y_pos[v2] = R20_ - 52; + enemy_projectile_instr_list_ptr[v2] = off_86B209[v5]; +} + +void EprojPreInstr_GoldenTorizoSuperMissile(uint16 k) { // 0x86B20D + int16 v3; + + int v1 = k >> 1; + EnemyData *v2 = gEnemyData(enemy_projectile_E[v1]); + R18_ = v2->x_pos; + R20_ = v2->y_pos; + if ((v2->parameter_1 & 0x8000u) != 0) + v3 = 32; + else + v3 = -32; + enemy_projectile_x_pos[v1] = R18_ + v3; + enemy_projectile_y_pos[v1] = R20_ - 52; +} + +void EprojPreInstr_B237(uint16 k) { // 0x86B237 + int v1; + uint8 carry; + + if (EnemyProjectileBlockCollisition_Horiz(k) + || (carry = EnemyProjectileBlockCollisition_Vertical(k), v1 = k >> 1, (enemy_projectile_y_vel[v1] & 0x8000u) == 0) + && carry) { + int v3 = k >> 1; + enemy_projectile_instr_list_ptr[v3] = addr_off_86B2EF; + enemy_projectile_instr_timers[v3] = 1; + } else { + uint16 v2 = enemy_projectile_y_vel[v1] + 16; + enemy_projectile_y_vel[v1] = v2; + if ((v2 & 0xF000) == 4096) + enemy_projectile_id[v1] = 0; + } +} + +void Eproj_SetVelTowardsSamus1(uint16 k) { // 0x86B269 + char v1; + + v1 = CalculateAngleOfSamusFromEproj(k); + sub_86B279(k, v1 & 0x7F); +} + +void Eproj_SetVelTowardsSamus2(uint16 k) { // 0x86B272 + uint16 v1 = CalculateAngleOfSamusFromEproj(k); + sub_86B279(k, v1 | 0x80); +} + +void sub_86B279(uint16 k, uint16 a) { // 0x86B279 + int v2 = a; + int v3 = k >> 1; + enemy_projectile_x_vel[v3] = 4 * kSinCosTable8bit_Sext[v2 + 64]; + enemy_projectile_y_vel[v3] = 4 * kSinCosTable8bit_Sext[v2]; +} +void EprojInit_GoldenTorizoEyeBeam(uint16 j) { // 0x86B328 + EnemyData *v1 = gEnemyData(cur_enemy_index); + uint16 v2; + R18_ = v1->x_pos; + R20_ = v1->y_pos; + if ((v1->parameter_1 & 0x8000u) != 0) + v2 = addr_stru_86B376; + else + v2 = addr_stru_86B380; + Eproj_InitXYVelRandom(j, v2); + uint16 v3 = (NextRandom() & 0x1E) - 16 + 192; + if ((gEnemyData(cur_enemy_index)->parameter_1 & 0x8000u) == 0) + v3 += 128; + int v4 = v3 >> 1; + int v5 = j >> 1; + enemy_projectile_x_vel[v5] = 8 * kSinCosTable8bit_Sext[v4 + 64]; + enemy_projectile_y_vel[v5] = 8 * kSinCosTable8bit_Sext[v4]; +} + +void EprojPreInstr_GoldenTorizoEyeBeam(uint16 k) { // 0x86B38A + if (EnemyProjectileBlockCollisition_Horiz(k) & 1) { + enemy_projectile_instr_list_ptr[k >> 1] = addr_off_86B3CD; +LABEL_6: + enemy_projectile_instr_timers[k >> 1] = 1; + return; + } + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) { + int v1 = k >> 1; + enemy_projectile_y_pos[v1] = (enemy_projectile_y_pos[v1] & 0xFFF0 | 8) - 2; + enemy_projectile_instr_list_ptr[v1] = addr_off_86B3E5; + goto LABEL_6; + } +} + +uint16 EprojInstr_GotoIfFunc1(uint16 k, uint16 j) { // 0x86B3B8 + if ((gExtraEnemyRam7800(enemy_projectile_F[k >> 1])->kraid.kraid_healths_8ths[0] & 0x8000u) == 0) + return *(uint16 *)RomPtr_86(j); + else + return j + 2; +} + +uint16 EprojInstr_ResetXYpos2(uint16 k, uint16 j) { // 0x86B436 + int v2 = k >> 1; + enemy_projectile_x_pos[v2] = enemy_projectile_E[v2]; + enemy_projectile_y_pos[v2] = enemy_projectile_F[v2]; + return j; +} + +void EprojInit_TourianEscapeShaftFakeWallExplode(uint16 j) { // 0x86B49D + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = 272; + enemy_projectile_E[v1] = 272; + enemy_projectile_y_pos[v1] = 2184; + enemy_projectile_F[v1] = 2184; +} + +void EprojInit_LavaSeahorseFireball(uint16 j) { // 0x86B4EF + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_y_pos[v2] = v1->y_pos - 28; + enemy_projectile_y_vel[v2] = -961; + if ((v1->ai_var_A & 0x8000u) == 0) { + enemy_projectile_x_pos[v2] = v1->x_pos + 12; + enemy_projectile_x_vel[v2] = 704; + enemy_projectile_instr_list_ptr[v2] = addr_word_86B4CB; + } else { + enemy_projectile_x_pos[v2] = v1->x_pos - 12; + enemy_projectile_x_vel[v2] = -704; + enemy_projectile_instr_list_ptr[v2] = addr_word_86B4BF; + } +} + +void sub_86B535(uint16 k) { // 0x86B535 + int16 v6; + uint16 v7; + + int v1 = k >> 1; + R20_ = LOBYTE(enemy_projectile_x_vel[v1]) << 8; + R18_ = (int8)HIBYTE(enemy_projectile_x_vel[v1]); + uint16 v4 = enemy_projectile_1A27[v1]; + bool v3 = __CFADD__uint16(R20_, v4); + enemy_projectile_1A27[v1] = R20_ + v4; + enemy_projectile_x_pos[v1] += R18_ + v3; + R20_ = LOBYTE(enemy_projectile_y_vel[v1]) << 8; + R18_ = (int8)HIBYTE(enemy_projectile_y_vel[v1]); + uint16 v5 = enemy_projectile_y_subpos[v1]; + v3 = __CFADD__uint16(R20_, v5); + enemy_projectile_y_subpos[v1] = R20_ + v5; + enemy_projectile_y_pos[v1] += R18_ + v3; + v6 = enemy_projectile_y_vel[v1]; + if (v6 >= 0) { + enemy_projectile_y_vel[v1] = v6 + 32; + Eproj_DeleteIfYposOutside(k); + } else { + enemy_projectile_y_vel[v1] = v6 + 32; + if ((int16)(v6 + 32) >= 0) { + if ((enemy_projectile_x_vel[v1] & 0x8000u) == 0) + v7 = addr_word_86B4E3; + else + v7 = addr_word_86B4D7; + enemy_projectile_instr_list_ptr[v1] = v7; + enemy_projectile_instr_timers[v1] = 1; + } + } +} + +void Eproj_DeleteIfYposOutside(uint16 k) { // 0x86B5B9 + int v1 = k >> 1; + if ((int16)(enemy_projectile_y_pos[v1] - layer1_y_pos) >= 288) + enemy_projectile_id[v1] = 0; +} + +static const int16 word_86B65B[20] = { // 0x86B62D + -16, 16, -96, -64, -128, -32, -96, 64, -128, 32, 16, 16, 96, -64, 112, -64, + 128, -64, 144, -64, +}; + +void EprojInit_EyeDoorProjectile(uint16 j) { + + uint16 v1 = plm_id; + int v2 = j >> 1; + enemy_projectile_F[v2] = plm_room_arguments[plm_id >> 1]; + CalculatePlmBlockCoords(v1); + int v3 = enemy_projectile_init_param >> 1; + enemy_projectile_x_pos[v2] = word_86B65B[v3] + 8 * (2 * plm_x_block + 1); + enemy_projectile_y_pos[v2] = word_86B65B[v3 + 1] + 16 * plm_y_block; +} + +static const int16 word_86B6B1[4] = { -64, 512, 64, 512 }; + +void EprojInit_EyeDoorSweat(uint16 j) { // 0x86B683 + CalculatePlmBlockCoords(plm_id); + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = 8 * (2 * (plm_x_block - 1) + 1); + enemy_projectile_y_pos[v1] = 16 * (plm_y_block + 1); + int v2 = enemy_projectile_init_param >> 1; + enemy_projectile_x_vel[v1] = word_86B6B1[v2]; + enemy_projectile_y_vel[v1] = word_86B6B1[v2 + 1]; +} + +void EprojPreInstr_EyeDoorProjectile(uint16 k) { // 0x86B6B9 + int16 v2; + int16 v4; + + if (EnemyProjectileBlockCollisition_Horiz(k) & 1 || EnemyProjectileBlockCollisition_Vertical(k) & 1) { +LABEL_8:; + int v5 = k >> 1; // bug fixed + enemy_projectile_instr_list_ptr[v5] = addr_off_86B5F3; + enemy_projectile_instr_timers[v5] = 1; + return; + } + int v1 = enemy_projectile_E[k >> 1] >> 1; + v2 = kSinCosTable8bit_Sext[v1 + 64] >> 4; + if ((v2 & 0x800) != 0) + v2 |= 0xF000u; + int v3 = k >> 1; + enemy_projectile_x_vel[v3] += v2; + v4 = kSinCosTable8bit_Sext[v1] >> 4; + if ((v4 & 0x800) != 0) + v4 |= 0xF000u; + enemy_projectile_y_vel[v3] += v4; + int t = PrepareBitAccess(enemy_projectile_F[v3]); + if ((bitmask & opened_door_bit_array[t]) != 0) { + goto LABEL_8; + } +} + +void EprojPreInstr_EyeDoorSweat(uint16 k) { // 0x86B714 + EnemyProjectileBlockCollisition_Horiz(k); + uint8 carry = EnemyProjectileBlockCollisition_Vertical(k); + int v1 = k >> 1; + if ((enemy_projectile_y_vel[v1] & 0x8000u) != 0 || !carry) { + enemy_projectile_y_vel[v1] += 12; + } else { + enemy_projectile_y_pos[v1] -= 4; + enemy_projectile_instr_list_ptr[v1] = addr_off_86B61D; + enemy_projectile_instr_timers[v1] = 1; + } +} + +uint16 EprojInstr_SpawnTourianStatueUnlockingParticle(uint16 k, uint16 j) { // 0x86B7EA + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatueUnlockingParticle, k); + return j; +} + +uint16 EprojInstr_Earthquake(uint16 k, uint16 j) { // 0x86B7F5 + earthquake_type = 1; + earthquake_timer |= 0x20u; + return j; +} + +uint16 EprojInstr_SpawnTourianStatueUnlockingParticleTail(uint16 k, uint16 j) { // 0x86B818 + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatueUnlockingParticleTail, k); + return j; +} + +uint16 EprojInstr_AddToYpos(uint16 k, uint16 j) { // 0x86B841 + enemy_projectile_y_pos[k >> 1] += *(uint16 *)RomPtr_86(j); + return j + 2; +} + +void EprojInit_TourianStatueUnlockingParticleWaterSplash(uint16 j) { // 0x86B87A + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = enemy_projectile_x_pos[enemy_projectile_init_param >> 1]; + enemy_projectile_y_pos[v1] = fx_y_pos - 4; +} + +static const uint16 kEprojInit_TourianStatueEyeGlow_X[4] = { 0x84, 0x7a, 0x9e, 0x68 }; +static const uint16 kEprojInit_TourianStatueEyeGlow_Y[4] = { 0x90, 0x51, 0x80, 0x72 }; +static const uint16 kEprojInit_TourianStatueEyeGlow_Colors[16] = { 0x6bff, 0x33b, 0x216, 0x173, 0x7f5f, 0x7c1f, 0x5816, 0x300c, 0x7f5a, 0x7ec0, 0x6de0, 0x54e0, 0x6bfa, 0x3be0, 0x2680, 0x1580 }; + +void EprojInit_TourianStatueEyeGlow(uint16 j) { // 0x86B88E + uint16 v1 = enemy_projectile_init_param; + int v2 = enemy_projectile_init_param >> 1; + int v3 = j >> 1; + enemy_projectile_x_pos[v3] = kEprojInit_TourianStatueEyeGlow_X[v2]; + enemy_projectile_y_pos[v3] = kEprojInit_TourianStatueEyeGlow_Y[v2]; + uint16 v4 = 4 * v1; + for (int i = 498; i != 506; i += 2) { + palette_buffer[i >> 1] = kEprojInit_TourianStatueEyeGlow_Colors[v4 >> 1]; + v4 += 2; + } +} + +void EprojInit_TourianStatueUnlockingParticle(uint16 j) { // 0x86B8B5 + int v1 = enemy_projectile_init_param >> 1; + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = enemy_projectile_x_pos[v1]; + enemy_projectile_y_pos[v2] = enemy_projectile_y_pos[v1]; + uint16 v3 = 2 * (uint8)((NextRandom() & 0x3F) - 32); + enemy_projectile_E[v2] = v3; + int v4 = v3 >> 1; + enemy_projectile_x_vel[v2] = kSinCosTable8bit_Sext[v4 + 64]; + enemy_projectile_y_vel[v2] = 4 * kSinCosTable8bit_Sext[v4]; +} + +void EprojIni_TourianStatueUnlockingParticleTail(uint16 v0) { // 0x86B8E8 + int v1 = enemy_projectile_init_param >> 1; + int v2 = v0 >> 1; + enemy_projectile_x_pos[v2] = enemy_projectile_x_pos[v1]; + enemy_projectile_y_pos[v2] = enemy_projectile_y_pos[v1]; +} + +void EprojInit_TourianStatueSoul(uint16 j) { // 0x86B8F8 + int v1 = enemy_projectile_init_param >> 1; + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = kEprojInit_TourianStatueEyeGlow_X[v1]; + enemy_projectile_y_pos[v2] = kEprojInit_TourianStatueEyeGlow_Y[v1]; + enemy_projectile_y_vel[v2] = -1024; +} + +void EprojInit_TourianStatueBaseDecoration(uint16 j) { // 0x86B93E + int v1 = j >> 1; + enemy_projectile_E[v1] = 120; + enemy_projectile_x_pos[v1] = 120; + enemy_projectile_F[v1] = 184; + enemy_projectile_y_pos[v1] = 184; +} + +void EprojInit_TourianStatueRidley(uint16 j) { // 0x86B951 + int v1 = j >> 1; + enemy_projectile_E[v1] = 142; + enemy_projectile_x_pos[v1] = 142; + enemy_projectile_F[v1] = 85; + enemy_projectile_y_pos[v1] = 85; +} + +void EprojInit_TourianStatuePhantoon(uint16 j) { // 0x86B964 + int v1 = j >> 1; + enemy_projectile_E[v1] = 132; + enemy_projectile_x_pos[v1] = 132; + enemy_projectile_F[v1] = 136; + enemy_projectile_y_pos[v1] = 136; +} + +void EprojPreInstr_TourianStatueUnlockingParticleWaterSplash(uint16 k) { // 0x86B977 + enemy_projectile_y_pos[k >> 1] = fx_y_pos - 4; +} + +void EprojPreInstr_TourianStatueUnlockingParticle(uint16 k) { // 0x86B982 + int16 v2; + int16 v5; + int16 v7; + + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = enemy_projectile_x_vel[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + uint16 v3 = enemy_projectile_1A27[v1]; + bool v4 = __CFADD__uint16(R18_, v3); + enemy_projectile_1A27[v1] = R18_ + v3; + enemy_projectile_x_pos[v1] += R20_ + v4; + v7 = fx_y_pos - enemy_projectile_y_pos[v1]; + R18_ = 0; + R20_ = 0; + v5 = enemy_projectile_y_vel[v1]; + if (v5 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v5; + uint16 v6 = enemy_projectile_y_subpos[v1]; + v4 = __CFADD__uint16(R18_, v6); + enemy_projectile_y_subpos[v1] = R18_ + v6; + enemy_projectile_y_pos[v1] += R20_ + v4; + if (((v7 ^ (fx_y_pos - enemy_projectile_y_pos[v1])) & 0x8000u) != 0) + SpawnEnemyProjectileWithRoomGfx(addr_stru_86BA5C, k); + if ((enemy_projectile_y_pos[v1] & 0xFF00) == 256) { + enemy_projectile_instr_list_ptr[v1] = addr_off_86B79F; + enemy_projectile_instr_timers[v1] = 1; + } else { + enemy_projectile_y_vel[v1] += 16; + } +} + +void EprojPreInstr_TourianStatueSoul(uint16 k) { // 0x86B9FD + int16 v2; + + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = enemy_projectile_y_vel[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + uint16 v3 = enemy_projectile_y_subpos[v1]; + bool v4 = __CFADD__uint16(R18_, v3); + enemy_projectile_y_subpos[v1] = R18_ + v3; + uint16 v5 = R20_ + v4 + enemy_projectile_y_pos[v1]; + enemy_projectile_y_pos[v1] = v5; + if ((v5 & 0x100) != 0) { + enemy_projectile_instr_list_ptr[v1] = addr_off_86B79F; + enemy_projectile_instr_timers[v1] = 1; + } + enemy_projectile_y_vel[v1] -= 128; +} + +void EprojPreInstr_TourianStatueStuff(uint16 k) { // 0x86BA37 + if (!tourian_entrance_statue_animstate) + tourian_entrance_statue_finished |= 0x8000; + EprojPreInstr_BA42(k); +} + +void EprojPreInstr_BA42(uint16 k) { // 0x86BA42 + int v1 = k >> 1; + enemy_projectile_x_pos[v1] = enemy_projectile_E[v1]; + enemy_projectile_y_pos[v1] = enemy_projectile_F[v1] + layer1_y_pos - *(uint16 *)&hdma_window_1_left_pos[0].field_0; +} + +uint16 EprojInstr_BB24(uint16 k, uint16 j) { // 0x86BB24 + enemy_projectile_instr_list_ptr[stru_86BB50.init_code_ptr >> 1] = 0; + return j; +} + +void sub_86BB30(uint16 j) { // 0x86BB30 + ExtraEnemyRam8000 *v1; + + v1 = gExtraEnemyRam8000(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = *(uint16 *)&v1->pad[34]; + enemy_projectile_y_pos[v2] = *(uint16 *)&v1->pad[36]; + enemy_projectile_instr_list_ptr[v2] = off_86BB1E[enemy_projectile_init_param]; +} + +void EprojInit_NuclearWaffleBody(uint16 j) { // 0x86BB92 + ExtraEnemyRam8000 *v4; + + EnemyData *v2 = gEnemyData(cur_enemy_index); + int v3 = j >> 1; + enemy_projectile_x_pos[v3] = v2->x_pos; + enemy_projectile_1A27[v3] = v2->x_subpos; + enemy_projectile_y_pos[v3] = v2->y_pos; + enemy_projectile_y_subpos[v3] = v2->y_subpos; + v4 = gExtraEnemyRam8000(cur_enemy_index); + gExtraEnemyRam7800(cur_enemy_index + *(uint16 *)&v4->pad[20])->kraid.kraid_next = j; + enemy_projectile_flags[v3] = 1; +} + +void EprojInit_NorfairLavaquakeRocks(uint16 j) { // 0x86BBDB + int v1 = j >> 1; + enemy_projectile_instr_list_ptr[v1] = addr_word_86BBD5; + enemy_projectile_E[v1] = FUNC16(Eproj_NorfairLavaquakeRocks_Func1); + enemy_projectile_y_vel[v1] = enemy_projectile_init_param; + enemy_projectile_x_vel[v1] = enemy_projectile_unk1995; + EnemyData *v2 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v1] = v2->x_pos; + enemy_projectile_1A27[v1] = v2->x_subpos; + enemy_projectile_y_pos[v1] = v2->y_pos; + enemy_projectile_y_subpos[v1] = v2->y_subpos; +} + +void CallNorfairLavaquakeRocksFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnEproj_NorfairLavaquakeRocks_Func1: Eproj_NorfairLavaquakeRocks_Func1(k); return; + case fnEproj_NorfairLavaquakeRocks_Func2: Eproj_NorfairLavaquakeRocks_Func2(k); return; + default: Unreachable(); + } +} + +void EprojPreInstr_NorfairLavaquakeRocks(uint16 k) { // 0x86BC0F + CallNorfairLavaquakeRocksFunc(enemy_projectile_E[k >> 1] | 0x860000, k); + EprojPreInstr_NorfairLavaquakeRocks_Inner(k); +} + +void Eproj_NorfairLavaquakeRocks_Func1(uint16 k) { // 0x86BC16 + int16 v2; + int16 v3; + int16 v8; + + int v1 = k >> 1; + v2 = enemy_projectile_y_vel[v1] - 2; + enemy_projectile_y_vel[v1] = v2; + if (v2 >= 0) { + R18_ = 2; + do { + v3 = R18_ + enemy_projectile_y_vel[k >> 1] - 1; + if (v3 < 0) + v3 = 0; + int v4 = k >> 1; + enemy_projectile_F[v4] = kCommonEnemySpeeds_Quadratic_Copy[(uint16)(8 * v3 + 4) >> 1]; + uint16 v5 = enemy_projectile_y_subpos[v4]; + bool v6 = __CFADD__uint16(enemy_projectile_F[v4], v5); + uint16 v7 = enemy_projectile_F[v4] + v5; + if (v6) + ++enemy_projectile_y_pos[v4]; + enemy_projectile_y_subpos[v4] = v7; + v8 = R18_ + enemy_projectile_y_vel[v4] - 1; + if (v8 < 0) + v8 = 0; + int v9 = k >> 1; + enemy_projectile_F[v9] = kCommonEnemySpeeds_Quadratic_Copy[(uint16)(8 * v8 + 6) >> 1]; + enemy_projectile_y_pos[v9] += enemy_projectile_F[v9]; + --R18_; + } while (R18_); + Eproj_NorfairLavaquakeRocks_Func3(k); + } else { + enemy_projectile_y_vel[v1] = 0; + enemy_projectile_E[v1] = FUNC16(Eproj_NorfairLavaquakeRocks_Func2); + } +} + +void Eproj_NorfairLavaquakeRocks_Func2(uint16 k) { // 0x86BC8F + int v1 = k >> 1; + uint16 v2 = enemy_projectile_y_vel[v1] + 2; + enemy_projectile_y_vel[v1] = v2; + if (!sign16(v2 - 64)) + enemy_projectile_y_vel[v1] = 64; + R18_ = 2; + do { + int v3 = k >> 1; + enemy_projectile_F[v3] = kCommonEnemySpeeds_Quadratic_Copy[(uint16)(8 + * (enemy_projectile_y_vel[v3] - R18_ + 1)) >> 1]; + uint16 v4 = enemy_projectile_y_subpos[v3]; + bool v5 = __CFADD__uint16(enemy_projectile_F[v3], v4); + uint16 v6 = enemy_projectile_F[v3] + v4; + if (v5) + ++enemy_projectile_y_pos[v3]; + enemy_projectile_y_subpos[v3] = v6; + int v7 = k >> 1; + enemy_projectile_F[v7] = kCommonEnemySpeeds_Quadratic_Copy[(uint16)(8 + * (enemy_projectile_y_vel[v3] - R18_ + 1) + + 2) >> 1]; + enemy_projectile_y_pos[v7] += enemy_projectile_F[v7]; + --R18_; + } while (R18_); + Eproj_NorfairLavaquakeRocks_Func3(k); +} + +void Eproj_NorfairLavaquakeRocks_Func3(uint16 k) { // 0x86BCF4 + int v1 = k >> 1; + enemy_projectile_x_pos[v1] += SignExtend8((uint8)((uint16)(enemy_projectile_x_vel[v1] & 0xFF00) >> 8)); + uint16 v2 = SignExtend8(LOBYTE(enemy_projectile_x_vel[v1]) << 8); + bool v3 = __CFADD__uint16(enemy_projectile_1A27[v1], v2); + uint16 v4 = enemy_projectile_1A27[v1] + v2; + if (v3) + ++enemy_projectile_x_pos[v1]; + enemy_projectile_1A27[v1] = v4; +} + +void EprojPreInstr_NorfairLavaquakeRocks_Inner(uint16 k) { // 0x86BD1E + if (EprojPreInstr_NorfairLavaquakeRocks_Inner2(k)) + enemy_projectile_id[k >> 1] = 0; +} + +uint16 EprojPreInstr_NorfairLavaquakeRocks_Inner2(uint16 k) { // 0x86BD2A + int v1 = k >> 1; + return (int16)(enemy_projectile_x_pos[v1] - layer1_x_pos) < 0 + || (int16)(layer1_x_pos + 256 - enemy_projectile_x_pos[v1]) < 0 + || (int16)(enemy_projectile_y_pos[v1] - layer1_y_pos) < 0 + || (int16)(layer1_y_pos + 256 - enemy_projectile_y_pos[v1]) < 0; +} + +static const int16 kEprojInit_ShaktoolAttackMiddleBackCircle_X[8] = { 0, 12, 16, 12, 0, -12, -16, -12 }; +static const int16 kEprojInit_ShaktoolAttackMiddleBackCircle_Y[8] = { -16, -12, 0, 12, 16, 12, 0, -12 }; + +void EprojInit_ShaktoolAttackMiddleBackCircle(uint16 j) { // 0x86BD9C + enemy_projectile_E[j >> 1] = enemy_projectile_init_param; + EprojInit_BDA2(j); +} + +void EprojInit_BDA2(uint16 j) { // 0x86BDA2 + int v1 = j >> 1; + EnemyData *v2 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v1] = v2->x_pos; + enemy_projectile_y_pos[v1] = v2->y_pos; + uint16 v3 = 2 * LOBYTE(v2->ai_var_D); + int v4 = v3 >> 1; + enemy_projectile_x_vel[v1] = kSinCosTable8bit_Sext[v4 + 64]; + enemy_projectile_y_vel[v1] = kSinCosTable8bit_Sext[v4]; + int v5 = (uint16)(v3 >> 5) >> 1; + enemy_projectile_x_pos[v1] += kEprojInit_ShaktoolAttackMiddleBackCircle_X[v5]; + enemy_projectile_y_pos[v1] += kEprojInit_ShaktoolAttackMiddleBackCircle_Y[v5]; +} + +void EprojInit_ShaktoolAttackFrontCircle(uint16 v1) { // 0x86BE03 + if (EnemyProjectileBlockCollisition_Horiz(v1) & 1 || EnemyProjectileBlockCollisition_Vertical(v1) & 1) + enemy_projectile_id[v1 >> 1] = 0; +} + +void EprojPreInstr_BE12(uint16 k) { // 0x86BE12 + int v1 = k >> 1; + if (enemy_projectile_id[enemy_projectile_E[v1] >> 1]) { + EnemyProjectileBlockCollisition_Horiz(k); + EnemyProjectileBlockCollisition_Vertical(k); + } else { + enemy_projectile_id[v1] = 0; + } +} + +#define kEproj_MotherBrainRoomTurrets_DirectionIndexes ((uint16*)RomPtr(0x86bee1)) +#define kEproj_MotherBrainRoomTurrets_AllowedRotations ((uint16*)RomPtr(0x86bec9)) +#define kEproj_MotherBrainRoomTurrets_InstrLists ((uint16*)RomPtr(0x86beb9)) +static const int16 kEprojInit_MotherBrainRoomTurrets_X[12] = { 0x398, 0x348, 0x328, 0x2d8, 0x288, 0x268, 0x218, 0x1c8, 0x1a8, 0x158, 0x108, 0xe8 }; +static const int16 EprojInit_MotherBrainRoomTurrets_Y[12] = { 0x30, 0x40, 0x40, 0x30, 0x40, 0x40, 0x30, 0x40, 0x40, 0x30, 0x40, 0x40 }; + +void EprojInit_MotherBrainRoomTurrets(uint16 j) { // 0x86BE4F + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 1024; + uint16 v2 = 2 * enemy_projectile_init_param; + uint16 v3 = kEproj_MotherBrainRoomTurrets_DirectionIndexes[enemy_projectile_init_param] | 0x100; + enemy_projectile_y_subpos[v1] = v3; + enemy_projectile_instr_list_ptr[v1] = kEproj_MotherBrainRoomTurrets_InstrLists[(uint16)(2 + * (uint8)v3) >> 1]; + int v4 = v2 >> 1; + enemy_projectile_x_pos[v1] = kEprojInit_MotherBrainRoomTurrets_X[v4]; + enemy_projectile_y_pos[v1] = EprojInit_MotherBrainRoomTurrets_Y[v4]; + enemy_projectile_1A27[v1] = kEproj_MotherBrainRoomTurrets_AllowedRotations[v4]; + Eproj_SetXvelRandom(j); + Eproj_SetYvelRandom(j); +} + +static const int16 kEproj_MotherBrainRoomTurretBullets_X[8] = { -17, -12, 0, 12, 17, 12, 0, -12 }; +static const int16 kEproj_MotherBrainRoomTurretBullets_Y[8] = { -9, 3, 7, 3, -9, -19, -21, -19 }; +static const int16 kEproj_MotherBrainRoomTurretBullets_Xvel[8] = { -704, -498, 0, 498, 704, 498, 0, -498 }; +static const int16 kEproj_MotherBrainRoomTurretBullets_Yvel[8] = { 0, 498, 704, 498, 0, -498, -704, -498 }; + +void EprojInit_MotherBrainRoomTurretBullets(uint16 j) { // 0x86BF59 + int v1 = j >> 1; + enemy_projectile_F[v1] = 0; + enemy_projectile_gfx_idx[v1] = 1024; + uint16 v2 = 2 * LOBYTE(enemy_projectile_y_subpos[enemy_projectile_init_param >> 1]); + enemy_projectile_E[v1] = v2; + int v3 = v2 >> 1; + R18_ = kEproj_MotherBrainRoomTurretBullets_X[v3]; + R20_ = kEproj_MotherBrainRoomTurretBullets_Y[v3]; + enemy_projectile_x_vel[v1] = kEproj_MotherBrainRoomTurretBullets_Xvel[v3]; + enemy_projectile_y_vel[v1] = kEproj_MotherBrainRoomTurretBullets_Yvel[v3]; + int v4 = enemy_projectile_init_param >> 1; + enemy_projectile_x_pos[v1] = R18_ + enemy_projectile_x_pos[v4]; + enemy_projectile_y_pos[v1] = R20_ + enemy_projectile_y_pos[v4]; +} + +#define g_off_86C040 ((uint16*)RomPtr(0x86c040)) + +void EprojPreInstr_MotherBrainRoomTurrets(uint16 k) { // 0x86BFDF + if (Eproj_MotherBrainRoomTurretBullets_CheckIfTurretOnScreen(k) & 1) { + if (gRam7800_Default(0)->var_1D) + *(uint16 *)((char *)enemy_projectile_id + k) = 0; + } else if (gRam7800_Default(0)->var_1D) { + *(uint16 *)((char *)enemy_projectile_id + k) = 0; + int v5 = k >> 1; + R18_ = enemy_projectile_x_pos[v5]; + R20_ = enemy_projectile_y_pos[v5]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0xCu); + } else { + int v1 = k >> 1; + bool v2 = enemy_projectile_x_vel[v1]-- == 1; + if (v2) { + Eproj_SetXvelRandom(k); + Eproj_MotherBrainRoomTurretBullets_Func2(k); + int v3 = k >> 1; + enemy_projectile_instr_list_ptr[v3] = g_off_86C040[(uint16)(2 * LOBYTE(enemy_projectile_y_subpos[v3])) >> 1]; + enemy_projectile_instr_timers[v3] = 1; + } + int v4 = k >> 1; + v2 = enemy_projectile_y_vel[v4]-- == 1; + if (v2) { + Eproj_SetYvelRandom(k); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainRoomTurretBullets, k); + } + } +} + +void Eproj_MotherBrainRoomTurretBullets_Func2(uint16 v0) { // 0x86C050 + char v1; + + LOBYTE(R20_) = (*((uint8 *)enemy_projectile_y_subpos + v0 + 1) + *((uint8 *)enemy_projectile_y_subpos + v0)) & 7; + R18_ = enemy_projectile_1A27[v0 >> 1]; + if (RomPtr_86(R18_)[R20_ & 7]) { + *((uint8 *)enemy_projectile_y_subpos + v0) = R20_; + } else { + v1 = -*((uint8 *)enemy_projectile_y_subpos + v0 + 1); + *((uint8 *)enemy_projectile_y_subpos + v0 + 1) = v1; + *((uint8 *)enemy_projectile_y_subpos + v0) += v1; + } +} + +void Eproj_SetXvelRandom(uint16 v0) { // 0x86C08E + uint16 Random = (uint8)NextRandom(); + if (sign16((uint8)Random - 32)) + Random = 32; + enemy_projectile_x_vel[v0 >> 1] = Random; +} + +void Eproj_SetYvelRandom(uint16 v0) { // 0x86C0A1 + uint16 Random = (uint8)NextRandom(); + if (sign16((uint8)Random - 128)) + Random = 128; + enemy_projectile_y_vel[v0 >> 1] = Random; +} + +uint8 Eproj_MotherBrainRoomTurretBullets_CheckIfTurretOnScreen(uint16 k) { // 0x86C0B4 + int16 v2; + int16 v3; + int16 v4; + int16 v5; + + int v1 = k >> 1; + v2 = enemy_projectile_y_pos[v1]; + uint8 result = 1; + if (v2 >= 0) { + v3 = v2 + 16 - layer1_y_pos; + if (v3 >= 0) { + if (sign16(v3 - 256)) { + v4 = enemy_projectile_x_pos[v1]; + if (v4 >= 0) { + v5 = v4 + 4 - layer1_x_pos; + if (v5 >= 0) { + if (sign16(v5 - 264)) + return 0; + } + } + } + } + } + return result; +} + +void EprojPreInstr_MotherBrainRoomTurretBullets(uint16 k) { // 0x86C0E0 + int v1 = k >> 1; + enemy_projectile_properties[v1] ^= 0x8000u; + MoveEprojWithVelocity(k); + if (Ridley_Func_103(enemy_projectile_x_pos[v1], enemy_projectile_y_pos[v1]) & 1) + enemy_projectile_id[enemy_projectile_index >> 1] = 0; +} + +static const int16 kMotherBrainsBomb_Yaccel[10] = { 7, 0x10, 0x20, 0x40, 0x70, 0xb0, 0xf0, 0x130, 0x170, 0 }; + +void EprojPreInstr_MotherBrainBomb(uint16 k) { // 0x86C4C8 + int16 v2; + + if (MotherBrainBomb_Bomb_CollDetect_DoubleRet(k)) + return; + int v1 = k >> 1; + if (enemy_projectile_F[v1]) { + int v4 = k >> 1; + uint16 v5 = kMotherBrainsBomb_Yaccel[enemy_projectile_F[v4] >> 1]; + if (!v5) { + enemy_projectile_x_vel[v4] = 0; + enemy_projectile_y_vel[v4] = 0; + --enemy_ram7800[1].kraid.kraid_mouth_flags; + enemy_projectile_id[v4] = 0; + R18_ = enemy_projectile_x_pos[v4]; + R20_ = enemy_projectile_y_pos[v4]; + SpawnEnemyProjectileWithRoomGfx(addr_stru_869650, LOBYTE(enemy_projectile_1A27[v4])); + R18_ = enemy_projectile_x_pos[v4]; + R20_ = enemy_projectile_y_pos[v4]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 3u); + QueueSfx3_Max6(0x13u); + return; + } + if (MoveMotherBrainBomb(k, v5) & 1) + goto LABEL_5; + } else { + v2 = abs16(enemy_projectile_x_vel[v1]) - 2; + if (v2 < 0) + v2 = 0; + enemy_projectile_x_vel[v1] = sign16(enemy_projectile_x_vel[v1]) ? -v2 : v2; + if (MoveMotherBrainBomb(k, 7u) & 1) { +LABEL_5:; + int v3 = k >> 1; + ++enemy_projectile_F[v3]; + ++enemy_projectile_F[v3]; + } + } +} + +uint16 EprojInstr_SwitchJump(uint16 k, uint16 j) { // 0x86C173 + return *(uint16 *)RomPtr_86(enemy_projectile_E[k >> 1] + j); +} + +uint16 EprojInstr_UserPalette0(uint16 k, uint16 j) { // 0x86C1B4 + enemy_projectile_gfx_idx[k >> 1] = 0; + return j; +} + +uint8 Eproj_CheckForBombCollisionWithRect(void) { // 0x86C1B8 + if (!bomb_counter) + return 0; + uint16 v1 = 10; + while (1) { + int v2 = v1 >> 1; + if ((projectile_type[v2] & 0xF00) == 1280 && !projectile_variables[v2]) { + uint16 v3 = abs16(projectile_x_pos[v2] - R18_); + bool v4 = v3 < projectile_x_radius[v2]; + uint16 v5 = v3 - projectile_x_radius[v2]; + if (v4 || v5 < R22_) { + uint16 v6 = abs16(projectile_y_pos[v2] - R20_); + v4 = v6 < projectile_y_radius[v2]; + uint16 v7 = v6 - projectile_y_radius[v2]; + if (v4 || v7 < R24_) + break; + } + } + v1 += 2; + if ((int16)(v1 - 20) >= 0) + return 0; + } + return 1; +} + +uint8 Eproj_CheckForEnemyCollisionWithRect(uint16 k) { // 0x86C209 + EnemyData *v1 = gEnemyData(k); + uint16 v2 = abs16(v1->x_pos - R18_); + bool v3 = v2 < v1->x_width; + uint16 v4 = v2 - v1->x_width; + uint8 result = 0; + if (v3 || v4 < R22_) { + uint16 v5 = abs16(v1->y_pos - R20_); + v3 = v5 < v1->y_height; + uint16 v6 = v5 - v1->y_height; + if (v3 || v6 < R24_) + return 1; + } + return result; +} + +uint8 Eproj_CheckForCollisionWithSamus(uint16 v0) { // 0x86C239 + Eproj_InitForCollDetect(v0); + uint16 v1 = abs16(samus_x_pos - R18_); + bool v2 = v1 < samus_x_radius; + uint16 v3 = v1 - samus_x_radius; + uint8 result = 0; + if (v2 || v3 < R22_) { + uint16 v4 = abs16(samus_y_pos - R20_); + v2 = v4 < samus_y_radius; + uint16 v5 = v4 - samus_y_radius; + if (v2 || v5 < R24_) + return 1; + } + return result; +} + +uint16 Math_MultBySin(uint16 a) { // 0x86C26C + R38 = a; + return Math_MultBySinCos(R18_); +} + +uint16 Math_MultByCos(uint16 a) { // 0x86C272 + R38 = a; + return Math_MultBySinCos(R18_ + 64); +} + +uint16 Math_MultBySinCos(uint16 a) { // 0x86C27A + R46 = kSinCosTable8bit_Sext[((uint16)((2 * a) & 0x1FE) >> 1) + 64]; + R40 = abs16(R46); + Math_Mult16U(); + uint16 r = *(uint16 *)((char *)&R42 + 1); + return sign16(R46) ? -r : r; +} + + +void Math_Mult16U(void) { // 0x86C29B + uint32 t = (uint32)R38 * (uint32)R40; + R42 = t; + R44 = (t >> 16); +} + +void Eproj_MotherBrainsBlueRingLasers(uint16 j) { // 0x86C2F3 + int v1 = j >> 1; + enemy_projectile_E[v1] = 8; + enemy_projectile_F[v1] = 0; + enemy_projectile_gfx_idx[v1] = 1024; + R18_ = enemy_projectile_init_param; + enemy_projectile_x_vel[v1] = Math_MultBySin(0x450u); + enemy_projectile_y_vel[v1] = Math_MultByCos(0x450u); + enemy_projectile_x_pos[v1] = enemy_data[1].x_pos + 10; + enemy_projectile_y_pos[v1] = enemy_data[1].y_pos + 16; + sub_86C320(j); +} + +void sub_86C320(uint16 k) { // 0x86C320 + int v1 = k >> 1; + enemy_projectile_x_pos[v1] = enemy_data[1].x_pos + 10; + enemy_projectile_y_pos[v1] = enemy_data[1].y_pos + 16; +} + +void Eproj_MoveToBlueRingSpawnPosition(uint16 k) { // 0x86C335 + int16 v5; + + int v1 = k >> 1; + if (enemy_projectile_E[v1]) { + --enemy_projectile_E[v1]; + sub_86C320(k); + } else { + MoveEprojWithVelocity(k); + uint8 t = CheckForCollisionWithShitroid_DoubleRet(k); + if (t & 0x80) + return; + if (t) { + ++enemy_ram7800[0].kraid.field_28; + BlueRingContactExplosion(k); + uint16 v3 = enemy_ram7800[1].kraid.kraid_healths_8ths[4]; + gExtraEnemyRam7800(enemy_ram7800[1].kraid.kraid_healths_8ths[4])->kraid.kraid_healths_8ths[0] = 16; + EnemyData *v4 = gEnemyData(v3); + v5 = v4->health - 80; + if (v5 < 0) + v5 = 0; + v4->health = v5; + } else if (Eproj_CheckForCollisionWithSamus(k) & 1) { + BlueRingContactExplosion(k); + uint16 v2 = SuitDamageDivision(0x50u); + Samus_DealDamage(v2); + samus_invincibility_timer = 96; + samus_knockback_timer = 5; + knockback_x_dir = (int16)(samus_x_pos - enemy_projectile_x_pos[k >> 1]) >= 0; + } else if (CheckForBlueRingCollisionWithRoom(k) & 1) { + Eproj_Earthqhake5(k); + } + } +} + +uint8 CheckForCollisionWithShitroid_DoubleRet(uint16 v0) { // 0x86C3A9 + if (!enemy_ram7800[1].kraid.kraid_healths_8ths[4]) + return 0; + if (gEnemyData(enemy_ram7800[1].kraid.kraid_healths_8ths[4])->health) { + Eproj_InitForCollDetect(v0); + return Eproj_CheckForEnemyCollisionWithRect(enemy_ram7800[1].kraid.kraid_healths_8ths[4]); + } + enemy_projectile_id[v0 >> 1] = 0; + return 0xff; +} + +uint8 CheckForBlueRingCollisionWithRoom(uint16 k) { // 0x86C3C9 + int16 v2; + int16 v3; + + int v1 = k >> 1; + uint8 result = 1; + if (!sign16(enemy_projectile_y_pos[v1] - 32) && enemy_projectile_y_pos[v1] < 0xD8u) { + v2 = enemy_projectile_x_pos[v1]; + if (v2 >= 0) { + v3 = v2 - layer1_x_pos; + if (v3 >= 0) { + if (sign16(v3 - 248)) + return 0; + } + } + } + return result; +} + +void Eproj_InitForCollDetect(uint16 k) { // 0x86C3E9 + int v1 = k >> 1; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + R22_ = LOBYTE(enemy_projectile_radius[v1]); + R24_ = HIBYTE(enemy_projectile_radius[v1]); +} + +void Eproj_Earthqhake5(uint16 k) { // 0x86C404 + earthquake_timer = 10; + earthquake_type = 5; + BlueRingContactExplosion(k); +} + +void BlueRingContactExplosion(uint16 k) { // 0x86C410 + int v1 = k >> 1; + enemy_projectile_id[v1] = 0; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 3u); + QueueSfx3_Max6(0x13u); + sub_86C42E(k); +} + +void sub_86C42E(uint16 k) { // 0x86C42E + enemy_projectile_gfx_idx[k >> 1] = 0; +} + +void EprojInit_MotherBrainBomb(uint16 j) { // 0x86C482 + *((uint8 *)enemy_projectile_1A27 + j) = enemy_projectile_init_param; + int v1 = j >> 1; + enemy_projectile_y_vel[v1] = 256; + enemy_projectile_x_vel[v1] = 224; + enemy_projectile_x_pos[v1] = enemy_data[1].x_pos + 12; + enemy_projectile_y_pos[v1] = enemy_data[1].y_pos + 16; + enemy_projectile_gfx_idx[v1] = 1024; + enemy_projectile_E[v1] = 112; + enemy_projectile_F[v1] = 0; + ++enemy_ram7800[1].kraid.kraid_mouth_flags; +} + +uint8 MotherBrainBomb_Bomb_CollDetect_DoubleRet(uint16 k) { // 0x86C564 + int v1 = k >> 1; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + R22_ = LOBYTE(enemy_projectile_radius[v1]); + R24_ = HIBYTE(enemy_projectile_radius[v1]); + if (!Eproj_CheckForBombCollisionWithRect()) + return 0; + + --enemy_ram7800[1].kraid.kraid_mouth_flags; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + enemy_projectile_id[v1] = 0; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 9u); + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + SpawnEnemyDrops(addr_kEnemyDef_EC3F, k); + return 1; // double return +} + +uint8 MoveMotherBrainBomb(uint16 k, uint16 a) { // 0x86C5C2 + int v2 = k >> 1; + enemy_projectile_y_vel[v2] += a; + MoveEprojWithVelocity(k); + if (!sign16(enemy_projectile_x_pos[v2] - 240)) + enemy_projectile_x_vel[v2] = -enemy_projectile_x_vel[v2]; + if (sign16(enemy_projectile_y_pos[v2] - 208)) + return 0; + enemy_projectile_y_pos[v2] = 208; + enemy_projectile_x_vel[v2] = sign16(enemy_projectile_x_vel[v2]) ? -enemy_projectile_E[v2] : enemy_projectile_E[v2]; + enemy_projectile_y_vel[v2] = -512; + return 1; +} + +void sub_86C605(uint16 j) { // 0x86C605 + int16 v2; + int16 v3; + + int v1 = j >> 1; + enemy_projectile_E[v1] = 0; + enemy_projectile_F[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + enemy_projectile_1A27[v1] = 0; + enemy_projectile_y_subpos[v1] = 0; + *(uint16 *)&extra_enemy_ram8000[0].pad[6] = 0; + *(uint16 *)&extra_enemy_ram8000[0].pad[10] = 0; + enemy_projectile_gfx_idx[v1] = 1024; + v2 = enemy_data[0].x_pos + 64; + enemy_projectile_x_pos[v1] = enemy_data[0].x_pos + 64; + *(uint16 *)&extra_enemy_ram8000[0].pad[8] = v2; + R18_ = samus_x_pos - v2; + v3 = enemy_data[0].y_pos - 48; + enemy_projectile_y_pos[v1] = enemy_data[0].y_pos - 48; + *(uint16 *)&extra_enemy_ram8000[0].pad[12] = v3; + R20_ = samus_y_pos - v3; + R18_ = (uint8)-(int8)(CalculateAngleFromXY() + 0x80); + *(uint16 *)&extra_enemy_ram8000[0].pad[18] = R18_; + *(uint16 *)&extra_enemy_ram8000[0].pad[14] = Math_MultBySin(0xC00u); + *(uint16 *)&extra_enemy_ram8000[0].pad[16] = Math_MultByCos(0xC00u); +} + +void EprojInit_MotherBrainDeathBeemFired(uint16 j) { // 0x86C684 + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = *(uint16 *)&extra_enemy_ram8000[0].pad[8]; + enemy_projectile_1A27[v1] = *(uint16 *)&extra_enemy_ram8000[0].pad[6]; + enemy_projectile_y_pos[v1] = *(uint16 *)&extra_enemy_ram8000[0].pad[12]; + enemy_projectile_y_subpos[v1] = *(uint16 *)&extra_enemy_ram8000[0].pad[10]; + enemy_projectile_x_vel[v1] = *(uint16 *)&extra_enemy_ram8000[0].pad[14]; + enemy_projectile_y_vel[v1] = *(uint16 *)&extra_enemy_ram8000[0].pad[16]; + MoveEprojWithVelocity(j); + *(uint16 *)&extra_enemy_ram8000[0].pad[8] = enemy_projectile_x_pos[v1]; + *(uint16 *)&extra_enemy_ram8000[0].pad[6] = enemy_projectile_1A27[v1]; + *(uint16 *)&extra_enemy_ram8000[0].pad[12] = enemy_projectile_y_pos[v1]; + *(uint16 *)&extra_enemy_ram8000[0].pad[10] = enemy_projectile_y_subpos[v1]; + R18_ = (uint8)(extra_enemy_ram8000[0].pad[18] + NextRandom()); + uint16 rv = NextRandom(); + enemy_projectile_x_vel[v1] = Math_MultBySin(rv & 0x700); + enemy_projectile_y_vel[v1] = Math_MultByCos(random_number & 0x700); + MoveEprojWithVelocity(j); + if (sign16(enemy_projectile_y_pos[v1] - 34) + || !sign16(enemy_projectile_y_pos[v1] - 206) + || sign16(enemy_projectile_x_pos[v1] - 2) + || !sign16(enemy_projectile_x_pos[v1] - 238)) { + enemy_projectile_id[v1] = 0; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x1Du); + QueueSfx3_Max6(0x13u); + earthquake_timer = 10; + earthquake_type = 5; + } else { + enemy_projectile_E[v1] = ((uint8)enemy_projectile_E[v1] + 1) & 3; + enemy_projectile_F[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + } +} + +void SpawnMotherBrainDeathBeam(uint16 x) { // 0x86C7FB + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainDeathBeamFired, enemy_projectile_E[x >> 1]); +} + +void EprojInit_MotherBrainRainbowBeam(uint16 j) { // 0x86C80A + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + EprojPreInstr_MotherBrainRainbowBeam(j); +} + +void EprojPreInstr_MotherBrainRainbowBeam(uint16 k) { // 0x86C814 + int v2 = k >> 1; + enemy_projectile_x_pos[v2] = enemy_data[1].x_pos; + enemy_projectile_y_pos[v2] = enemy_data[1].y_pos; +} + +static const int16 kEprojInit_MotherBrainsDrool[12] = { 6, 0x14, 0xe, 0x12, 8, 0x17, 0xa, 0x13, 0xb, 0x19, 0xc, 0x12 }; + +void EprojInit_MotherBrainsDrool(uint16 j) { // 0x86C843 + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 0; + enemy_projectile_E[v1] = enemy_projectile_init_param; + EprojPreInstr_C84D(j); +} + +void EprojPreInstr_C84D(uint16 k) { // 0x86C84D + int v1 = k >> 1; + int v2 = (uint16)(4 * enemy_projectile_E[v1]) >> 1; + enemy_projectile_x_pos[v1] = enemy_data[1].x_pos + kEprojInit_MotherBrainsDrool[v2]; + enemy_projectile_y_pos[v1] = enemy_data[1].y_pos + kEprojInit_MotherBrainsDrool[v2 + 1]; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + +} + +void EprojInit_MotherBrainsDrool_Falling(uint16 k) { // 0x86C886 + int v1 = k >> 1; + enemy_projectile_y_vel[v1] += 12; + if (MoveEprojWithVelocityY(k) >= 0xD7u) { + enemy_projectile_y_pos[v1] -= 4; + enemy_projectile_instr_list_ptr[v1] = addr_off_86C8E1; + enemy_projectile_instr_timers[v1] = 1; + } +} + +uint16 EprojInstr_Add12ToY(uint16 k, uint16 j) { // 0x86C8D0 + enemy_projectile_y_pos[k >> 1] += 12; + return j; +} + +void EprojInit_MotherBrainsDeathExplosion(uint16 j) { // 0x86C8F5 + int v1 = j >> 1; + enemy_projectile_instr_list_ptr[v1] = off_86C929[enemy_projectile_init_param]; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_gfx_idx[v1] = 0; + enemy_projectile_x_vel[v1] = R18_; + enemy_projectile_y_vel[v1] = R20_; + EprojPreInit_MotherBrainsDeathExplosion_0(j); +} + +void EprojPreInit_MotherBrainsDeathExplosion_0(uint16 k) { // 0x86C914 + int v2 = k >> 1; + enemy_projectile_x_pos[v2] = enemy_data[0].x_pos + enemy_projectile_x_vel[v2]; + enemy_projectile_y_pos[v2] = enemy_data[0].y_pos + enemy_projectile_y_vel[v2]; +} + +void EprojInit_MotherBrainsRainbowBeamExplosion(uint16 j) { // 0x86C92F + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 0; + uint16 v2 = R18_; + enemy_projectile_x_vel[v1] = R18_; + enemy_projectile_x_pos[v1] = samus_x_pos + v2; + uint16 v3 = R20_; + enemy_projectile_y_vel[v1] = R20_; + enemy_projectile_y_pos[v1] = samus_y_pos + v3; +} + +void EprojPreInstr_MotherBrainsRainbowBeamExplosion(uint16 k) { // 0x86C94C + int v1 = k >> 1; + enemy_projectile_x_pos[v1] = samus_x_pos + enemy_projectile_x_vel[v1]; + enemy_projectile_y_pos[v1] = samus_y_pos + enemy_projectile_y_vel[v1]; +} + +void EprojInit_MotherBrainEscapeDoorParticles(uint16 j) { // 0x86C961 + static const int16 kEprojInit_MotherBrainEscapeDoorParticles_X[16] = { + 0, -0x20, 0, -0x18, 0, -0x10, 0, -8, 0, 0, 0, 8, + 0, 0x10, 0, 0x18, + }; + static const int16 kEprojInit_MotherBrainEscapeDoorParticles_Xvel[16] = { + 0x500, -0x200, 0x500, -0x100, 0x500, -0x100, 0x500, -0x80, 0x500, -0x80, 0x500, 0x80, + 0x500, -0x100, 0x500, 0x200, + }; + + + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 0; + int v2 = (uint16)(4 * enemy_projectile_init_param) >> 1; + enemy_projectile_x_pos[v1] = kEprojInit_MotherBrainEscapeDoorParticles_X[v2] + 16; + enemy_projectile_y_pos[v1] = kEprojInit_MotherBrainEscapeDoorParticles_X[v2 + 1] + 128; + enemy_projectile_x_vel[v1] = kEprojInit_MotherBrainEscapeDoorParticles_Xvel[v2]; + enemy_projectile_y_vel[v1] = kEprojInit_MotherBrainEscapeDoorParticles_Xvel[v2 + 1]; + enemy_projectile_E[v1] = 32; +} + +void EprojPreInstr_MotherBrainsExplodedDoorParticles(uint16 k) { // 0x86C9D2 + int16 v2; + + int v1 = k >> 1; + v2 = abs16(enemy_projectile_x_vel[v1]) - 16; + if (v2 < 0) + v2 = 0; + enemy_projectile_x_vel[v1] = sign16(enemy_projectile_x_vel[v1]) ? -v2 : v2; + enemy_projectile_y_vel[v1] += 32; + MoveEprojWithVelocity(k); + if ((--enemy_projectile_E[v1] & 0x8000u) != 0) { + enemy_projectile_id[v1] = 0; + uint16 v4 = enemy_projectile_y_pos[v1] - 4; + enemy_projectile_y_pos[v1] = v4; + R20_ = v4; + R18_ = enemy_projectile_x_pos[v1]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 9u); + } +} + +void EprojInit_MotherBrainPurpleBreathBig(uint16 j) { // 0x86CA6A + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 0; + enemy_projectile_x_pos[v1] = enemy_data[1].x_pos + 6; + enemy_projectile_y_pos[v1] = enemy_data[1].y_pos + 16; +} + +void EprojInit_MotherBrainPurpleBreathSmall(uint16 j) { // 0x86CA83 + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 0; + enemy_projectile_x_pos[v1] = enemy_data[1].x_pos + 6; + enemy_projectile_y_pos[v1] = enemy_data[1].y_pos + 16; + enemy_ram7800[1].kraid.kraid_hurt_frame = 1; +} + +uint16 EprojInstr_MotherBrainPurpleBreathIsActive(uint16 k, uint16 j) { // 0x86CAEE + enemy_ram7800[1].kraid.kraid_hurt_frame = 0; + return j; +} + +void EprojInit_TimeBombSetJapaneseText(uint16 j) { // 0x86CAF6 + enemy_projectile_gfx_idx[j >> 1] = 0; + EprojPreInstr_TimeBombSetJapaneseText(j); +} + +void EprojPreInstr_TimeBombSetJapaneseText(uint16 k) { // 0x86CAFA + int v1 = k >> 1; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + enemy_projectile_x_pos[v1] = 128; + enemy_projectile_y_pos[v1] = 192; +} +void EprojInit_MotherBrainTubeFalling(uint16 j) { // 0x86CBC9 + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] = 3584; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + enemy_projectile_x_pos[v1] = R18_; + enemy_projectile_y_pos[v1] = R20_; + enemy_projectile_E[v1] = FUNC16(MotherBrainTubeFallingFunc_GenerateExplosion); +} + +void CallMotherBrainTubeFallingFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnMotherBrainTubeFallingFunc_GenerateExplosion: MotherBrainTubeFallingFunc_GenerateExplosion(k); return; + case fnMotherBrainTubeFallingFunc_Falling: MotherBrainTubeFallingFunc_Falling(k); return; + default: Unreachable(); + } +} + +void EprojPreInstr_MotherBrainTubeFalling(uint16 k) { // 0x86CBE7 + CallMotherBrainTubeFallingFunc(enemy_projectile_E[k >> 1] | 0x860000, k); +} + +void MotherBrainTubeFallingFunc_GenerateExplosion(uint16 k) { // 0x86CBEA + int v1 = k >> 1; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1] + 8; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 9u); + enemy_projectile_E[v1] = FUNC16(MotherBrainTubeFallingFunc_Falling); + MotherBrainTubeFallingFunc_Falling(k); +} + +void MotherBrainTubeFallingFunc_Falling(uint16 k) { // 0x86CC08 + int16 v2; + + int v1 = k >> 1; + enemy_projectile_y_vel[v1] += 6; + v2 = MoveEprojWithVelocityY(k); + if (!sign16(v2 - 208)) { + enemy_projectile_id[v1] = 0; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0xCu); + } +} + +#define kEprojInit_MotherBrainGlassShatteringShard_InstrPtrs ((uint16*)RomPtr(0x86ce41)) +static const int16 kEprojInit_MotherBrainGlassShatteringShard_X[3] = { 8, -40, -16 }; +static const int16 kEprojInit_MotherBrainGlassShatteringShard_Y[3] = { 32, 32, 32 }; + +void EprojInit_MotherBrainGlassShatteringShard(uint16 j) { // 0x86CDC5 + uint16 v1 = (2 * NextRandom()) & 0x1FE; + int v2 = j >> 1; + enemy_projectile_E[v2] = v1; + int v3 = v1 >> 1; + enemy_projectile_x_vel[v2] = kSinCosTable8bit_Sext[v3 + 64]; + enemy_projectile_y_vel[v2] = 4 * kSinCosTable8bit_Sext[v3]; + enemy_projectile_instr_list_ptr[v2] = kEprojInit_MotherBrainGlassShatteringShard_InstrPtrs[(uint16)((v1 >> 4) & 0x1E) >> 1]; + enemy_projectile_gfx_idx[v2] = 1600; + CalculatePlmBlockCoords(plm_id); + int v4 = enemy_projectile_init_param >> 1; + enemy_projectile_x_pos[v2] = kEprojInit_MotherBrainGlassShatteringShard_X[v4] + 16 * plm_x_block; + enemy_projectile_y_pos[v2] = kEprojInit_MotherBrainGlassShatteringShard_Y[v4] + 16 * plm_y_block; + enemy_projectile_x_pos[v2] += (NextRandom() & 0xF) - 8; + enemy_projectile_y_pos[v2] += (NextRandom() & 0xF) - 8; +} + +void EprojInit_MotherBrainGlassShatteringSparkle(uint16 j) { // 0x86CE6D + int v1 = enemy_projectile_init_param >> 1; + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = enemy_projectile_x_pos[v1] + (NextRandom() & 0x1F) - 16; + enemy_projectile_y_pos[v2] = enemy_projectile_y_pos[v1] + (NextRandom() & 0x1F) - 16; + enemy_projectile_gfx_idx[v2] = 1600; +} + +void EprojPreInstr_MotherBrainGlassShatteringShard(uint16 k) { // 0x86CE9B + int16 v2; + int16 v5; + + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = enemy_projectile_x_vel[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + uint16 v3 = enemy_projectile_1A27[v1]; + bool v4 = __CFADD__uint16(R18_, v3); + enemy_projectile_1A27[v1] = R18_ + v3; + enemy_projectile_x_pos[v1] += R20_ + v4; + R18_ = 0; + R20_ = 0; + v5 = enemy_projectile_y_vel[v1]; + if (v5 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v5; + uint16 v6 = enemy_projectile_y_subpos[v1]; + v4 = __CFADD__uint16(R18_, v6); + enemy_projectile_y_subpos[v1] = R18_ + v6; + uint16 v7 = R20_ + v4 + enemy_projectile_y_pos[v1]; + enemy_projectile_y_pos[v1] = v7; + if ((v7 & 0xFF00) != 0) { + enemy_projectile_id[v1] = 0; + } else { + enemy_projectile_y_vel[v1] += 32; + if ((NextRandom() & 0x420) == 0) + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainGlassShatteringSparkle, k); + } +} + +void EprojInit_KiHunterAcidSpitLeft(uint16 j) { // 0x86CF90 + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = -768; + enemy_projectile_x_pos[v2] = gEnemyData(cur_enemy_index)->x_pos - 22; + EprojInit_KiHunterAcidSpitCommon(cur_enemy_index, j); +} + +void EprojInit_KiHunterAcidSpitRight(uint16 j) { // 0x86CFA6 + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = 768; + enemy_projectile_x_pos[v2] = gEnemyData(cur_enemy_index)->x_pos + 22; + EprojInit_KiHunterAcidSpitCommon(cur_enemy_index, j); +} + +void EprojInit_KiHunterAcidSpitCommon(uint16 k, uint16 j) { // 0x86CFBA + int v2 = j >> 1; + enemy_projectile_y_vel[v2] = 0; + enemy_projectile_y_pos[v2] = gEnemyData(k)->y_pos - 16; + enemy_projectile_y_subpos[v2] = 0; + enemy_projectile_1A27[v2] = 0; +} + +void sub_86CFD5(uint16 k) { // 0x86CFD5 + int v1 = k >> 1; + enemy_projectile_pre_instr[v1] = FUNC16(sub_86CFF8); + enemy_projectile_x_pos[v1] -= 19; +} + +void sub_86CFE6(uint16 k) { // 0x86CFE6 + int v1 = k >> 1; + enemy_projectile_pre_instr[v1] = FUNC16(sub_86CFF8); + enemy_projectile_x_pos[v1] += 19; +} + +void sub_86CFF8(uint16 k) { // 0x86CFF8 + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) { + int v3 = k >> 1; + enemy_projectile_instr_list_ptr[v3] = addr_off_86CF56; + enemy_projectile_instr_timers[v3] = 1; + } else if (EnemyProjectileBlockCollisition_Horiz(k) & 1) { + enemy_projectile_x_vel[k >> 1] = 0; + } else { + int v1 = k >> 1; + uint16 v2 = enemy_projectile_y_vel[v1] + 16; + enemy_projectile_y_vel[v1] = v2; + if (!sign16(v2 - 512)) + v2 = 512; + enemy_projectile_y_vel[v1] = v2; + } +} + +void EprojInit_KagosBugs(uint16 j) { // 0x86D088 + int v2 = j >> 1; + enemy_projectile_F[v2] = cur_enemy_index; + EnemyData *v3 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v2] = v3->x_pos; + enemy_projectile_y_pos[v2] = v3->y_pos; + uint16 v4 = (random_number & 7) + 1; + enemy_projectile_G[v2] = v4; + enemy_projectile_E[v2] = v4 + 4; + enemy_projectile_pre_instr[v2] = FUNC16(EprojPreInstr_KagosBugs); +} + +void EprojPreInstr_KagosBugs_Func1(uint16 k) { // 0x86D0B3 + int v1 = k >> 1; + uint16 v2 = enemy_projectile_E[v1]; + if (v2) { + uint16 v3 = v2 - 1; + enemy_projectile_E[v1] = v3; + if (!v3) + QueueSfx2_Max6(0x6Cu); + } +} + +void EprojPreInstr_KagosBugs(uint16 k) { // 0x86D0CA + EprojPreInstr_KagosBugs_Func1(k); + EprojPreInstr_KagosBugs_Func2(k); + int v1 = k >> 1; + if (enemy_projectile_G[v1]) { + --enemy_projectile_G[v1]; + } else { + enemy_projectile_instr_list_ptr[v1] = addr_word_86D052; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_pre_instr[v1] = FUNC16(nullsub_302); + } +} + +static const uint16 word_86D082 = 0xe0; + +void EprojPreInstr_D0EC(uint16 v0) { // 0x86D0EC + EprojPreInstr_KagosBugs_Func1(v0); + EprojPreInstr_KagosBugs_Func2(v0); + if (EnemyProjectileBlockCollisition_Horiz(v0) & 1) { + enemy_projectile_x_vel[v0 >> 1] = 0; + goto LABEL_6; + } + if (EnemyProjectileBlockCollisition_Vertical(v0) & 1) { +LABEL_6: + enemy_projectile_y_vel[v0 >> 1] = 256; +LABEL_7:; + int v4 = v0 >> 1; + enemy_projectile_pre_instr[v4] = FUNC16(EprojPreInstr_D128); + enemy_projectile_instr_list_ptr[v4] = addr_word_86D04A; + enemy_projectile_instr_timers[v4] = 1; + return; + } + int v1 = v0 >> 1; + uint16 v2 = enemy_projectile_y_vel[v1]; + bool v3 = (int16)(word_86D082 + v2) < 0; + enemy_projectile_y_vel[v1] = word_86D082 + v2; + if (!v3) { + goto LABEL_7; + } +} + +void EprojPreInstr_D128(uint16 v0) { // 0x86D128 + EprojPreInstr_KagosBugs_Func1(v0); + EprojPreInstr_KagosBugs_Func2(v0); + if (EnemyProjectileBlockCollisition_Horiz(v0) & 1) { + enemy_projectile_x_vel[v0 >> 1] = 0; + } else if (EnemyProjectileBlockCollisition_Vertical(v0) & 1) { + int v1 = v0 >> 1; + enemy_projectile_pre_instr[v1] = FUNC16(nullsub_302); + enemy_projectile_instr_list_ptr[v1] = addr_word_86D03C; + enemy_projectile_instr_timers[v1] = 1; + } else { + enemy_projectile_y_vel[v0 >> 1] += word_86D082; + } +} + +static const uint16 g_word_86D086 = 0x200; +static const uint16 g_word_86D084 = 0x30; + +uint16 EprojInstr_D15C(uint16 k, uint16 j) { // 0x86D15C + EprojPreInstr_KagosBugs_Func1(k); + EprojPreInstr_KagosBugs_Func2(k); + int v2 = k >> 1; + + uint16 t = (random_number & 0x300) + 2048; + enemy_projectile_y_vel[v2] = -t; + EnemyData *v3 = gEnemyData(enemy_projectile_F[v2]); + uint16 t2 = v3->x_pos - enemy_projectile_x_pos[v2]; + + if ((int16)(abs16(t2) - g_word_86D084) >= 0) + t = sign16(t2) ? -1 : 0; + + uint16 v4 = g_word_86D086; + if (t & 0x100) + v4 = -v4; + enemy_projectile_x_vel[v2] = v4; + enemy_projectile_pre_instr[v2] = FUNC16(EprojPreInstr_D0EC); + + return j; +} + +uint16 EprojInstr_D1B6(uint16 k, uint16 j) { // 0x86D1B6 + int v1 = k >> 1; + enemy_projectile_G[v1] = (random_number & 0x1F) + 1; + enemy_projectile_pre_instr[v1] = FUNC16(EprojPreInstr_KagosBugs); + + return j; +} + + +uint16 EprojInstr_D1C7(uint16 v0, uint16 j) { // 0x86D1C7 + enemy_projectile_gfx_idx[v0 >> 1] = 0; + return j; +} + +uint16 EprojInstr_D1CE(uint16 v0, uint16 j) { // 0x86D1CE + int v1 = v0 >> 1; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + SpawnEnemyDrops(addr_kEnemyDef_E7FF, v0); + return j; +} + +void EprojPreInstr_KagosBugs_Func2(uint16 k) { // 0x86D1E4 + int v1 = k >> 1; + EnemyData *v2 = gEnemyData(enemy_projectile_F[v1]); + uint16 v3 = abs16(v2->x_pos - enemy_projectile_x_pos[v1]); + if (!sign16(v3 - 23)) + enemy_projectile_properties[v1] |= 0x8000u; +} + +void EprojInit_MaridiaFloatersSpikes(uint16 j) { // 0x86D23A + int v1 = j >> 1; + enemy_projectile_1A27[v1] = 0; + enemy_projectile_y_subpos[v1] = 0; + enemy_projectile_x_vel[v1] = 0; + enemy_projectile_y_vel[v1] = 0; + EnemyData *v2 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v1] = v2->x_pos; + enemy_projectile_y_pos[v1] = v2->y_pos; + enemy_projectile_E[v1] = enemy_projectile_init_param; +} + +static const int16 word_86D21A[8] = { 0, 32, 32, 32, 0, -32, -32, -32 }; +static const int16 word_86D22A[8] = { -32, -32, 0, 32, 32, 32, 0, -32 }; + +void EprojPreInstr_MaridiaFloatersSpikes(uint16 k) { // 0x86D263 + int v1 = k >> 1; + enemy_projectile_x_vel[v1] += word_86D21A[enemy_projectile_E[v1]]; + if (EnemyProjectileBlockCollisition_Horiz(k) & 1 + || (enemy_projectile_y_vel[v1] += word_86D22A[enemy_projectile_E[v1]], + EnemyProjectileBlockCollisition_Vertical(k) & 1)) { + enemy_projectile_instr_list_ptr[v1] = addr_off_86D218; + enemy_projectile_instr_timers[v1] = 1; + } +} + +void EprojInit_WreckedShipRobotLaserDown(uint16 j) { // 0x86D30C + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = gEnemyData(cur_enemy_index)->ai_var_A; + enemy_projectile_y_vel[v2] = 128; + enemy_projectile_gfx_idx[v2] = 0; + EprojInit_WreckedShipRobotLaserCommon(cur_enemy_index, j); +} + +void EprojInit_WreckedShipRobotLaserHorizontal(uint16 j) { // 0x86D32E + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = gEnemyData(cur_enemy_index)->ai_var_A; + enemy_projectile_y_vel[v2] = 0; + EprojInit_WreckedShipRobotLaserCommon(cur_enemy_index, j); +} + +void EprojInit_WreckedShipRobotLaserUp(uint16 j) { // 0x86D341 + int v2 = j >> 1; + enemy_projectile_x_vel[v2] = gEnemyData(cur_enemy_index)->ai_var_A; + enemy_projectile_y_vel[v2] = -128; + EprojInit_WreckedShipRobotLaserCommon(cur_enemy_index, j); +} + +void EprojInit_WreckedShipRobotLaserCommon(uint16 k, uint16 j) { // 0x86D35B + int16 x_pos; + uint16 v5; + + EnemyData *v2 = gEnemyData(k); + int v3 = j >> 1; + enemy_projectile_y_pos[v3] = v2->y_pos - 16; + x_pos = v2->x_pos; + if (sign16(enemy_projectile_x_vel[v3])) + v5 = x_pos - 4; + else + v5 = x_pos + 4; + enemy_projectile_x_pos[v3] = v5; + enemy_projectile_y_subpos[v3] = 0; + enemy_projectile_1A27[v3] = 0; + if ((int16)(v2->x_width + v2->x_pos - layer1_x_pos) >= 0 + && (int16)(v2->x_pos - v2->x_width - 257 - layer1_x_pos) < 0 + && (int16)(v2->y_height + v2->y_pos - layer1_y_pos) >= 0 + && (int16)(v2->y_pos - v2->y_height - 224) < 0) { + QueueSfx2_Max6(0x67u); + } +} + +void EprojPreInstr_WreckedShipRobotLaser(uint16 k) { // 0x86D3BF + int v1 = k >> 1; + enemy_projectile_gfx_idx[v1] = 0; + if (EnemyProjectileBlockCollisition_Horiz(k) & 1 || EnemyProjectileBlockCollisition_Vertical(k) & 1) + enemy_projectile_id[v1] = 0; +} + +uint16 EprojInstr_AssignNewN00bTubeShardVelocity(uint16 k, uint16 j) { // 0x86D5E1 + NextRandom(); + int v2 = k >> 1; + enemy_projectile_x_vel[v2] = *(uint16 *)((char *)&random_number + 1); + enemy_projectile_y_vel[v2] = 192; + return j; +} + +uint16 EprojInstr_SetN00bTubeShardX(uint16 k, uint16 j) { // 0x86D5F2 + int v2 = k >> 1; + if (nmi_frame_counter_word & 1) { + enemy_projectile_x_pos[v2] = enemy_projectile_F[v2]; + enemy_projectile_spritemap_ptr[v2] = *(uint16 *)RomPtr_86(j); + } else { + enemy_projectile_x_pos[v2] = 128 - enemy_projectile_F[v2] + 128; + enemy_projectile_spritemap_ptr[v2] = *((uint16 *)RomPtr_86(j) + 1); + } + int v3 = k >> 1; + enemy_projectile_instr_list_ptr[v3] = j + 4; + enemy_projectile_instr_timers[v3] = 1; + return 0; +} + +uint16 EprojInstr_D62A(uint16 k, uint16 j) { // 0x86D62A + if (nmi_frame_counter_word & 1) + enemy_projectile_x_pos[k >> 1] = enemy_projectile_F[k >> 1]; + else + enemy_projectile_x_pos[k >> 1] = -4608; + int v2 = k >> 1; + enemy_projectile_spritemap_ptr[v2] = *(uint16 *)RomPtr_86(j); + enemy_projectile_instr_list_ptr[v2] = j + 2; + enemy_projectile_instr_timers[v2] = 1; + return 0; +} + +uint16 EprojInstr_SetXvelRandom(uint16 k, uint16 j) { // 0x86D69A + NextRandom(); + enemy_projectile_x_vel[k >> 1] = *(uint16 *)((char *)&random_number + 1); + return j; +} + +void EprojInit_N00bTubeCrack(uint16 j) { // 0x86D6A5 + CalculatePlmBlockCoords(plm_id); + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = 16 * plm_x_block + 96; + enemy_projectile_y_pos[v1] = 16 * plm_y_block + 48; +} + +static const int16 kEprojInit_N00bTubeShards_X[10] = { -56, -64, -20, -40, -64, -48, -24, -40, 0, -8 }; +static const int16 kEprojInit_N00bTubeShards_Y[10] = { 8, -12, -26, -24, -32, 28, 16, -8, -24, 16 }; +static const int16 kEprojInit_N00bTubeShards_Xvel[10] = { -384, -384, -160, -288, -288, -320, -96, -352, 0, -64 }; +static const int16 kEprojInit_N00bTubeShards_Yvel[10] = { 320, -256, -416, -288, -288, 448, 576, -96, -288, 384 }; +#define kEprojInit_N00bTubeShards_InstrPtrs ((uint16*)RomPtr(0x86d760)) + +void EprojInit_N00bTubeShards(uint16 j) { // 0x86D6C9 + CalculatePlmBlockCoords(plm_id); + int v1 = enemy_projectile_init_param >> 1; + int v2 = j >> 1; + enemy_projectile_F[v2] = kEprojInit_N00bTubeShards_X[v1] + 16 * plm_x_block + 96; + enemy_projectile_E[v2] = 0; + enemy_projectile_y_pos[v2] = kEprojInit_N00bTubeShards_Y[v1] + 16 * plm_y_block + 48; + enemy_projectile_instr_list_ptr[v2] = kEprojInit_N00bTubeShards_InstrPtrs[v1]; + enemy_projectile_x_vel[v2] = kEprojInit_N00bTubeShards_Xvel[v1]; + enemy_projectile_y_vel[v2] = kEprojInit_N00bTubeShards_Yvel[v1]; +} + +static const uint16 kEprojInit_N00bTubeReleasedAirBubbles_X[6] = { 40, 80, 104, 120, 152, 184 }; +static const uint16 kEprojInit_N00bTubeReleasedAirBubbles_Y[6] = { 80, 72, 84, 32, 64, 84 }; + +void EprojInit_N00bTubeReleasedAirBubbles(uint16 j) { // 0x86D774 + CalculatePlmBlockCoords(plm_id); + int v1 = enemy_projectile_init_param >> 1; + int v2 = j >> 1; + enemy_projectile_F[v2] = kEprojInit_N00bTubeReleasedAirBubbles_X[v1] + 16 * plm_x_block; + enemy_projectile_E[v2] = 0; + enemy_projectile_y_pos[v2] = kEprojInit_N00bTubeReleasedAirBubbles_Y[v1] + 16 * plm_y_block; + enemy_projectile_y_vel[v2] = -1280; +} + +void sub_86D7BF(uint16 k) { // 0x86D7BF + int v1 = k >> 1; + if (enemy_projectile_x_pos[v1] != 0xEE00) + enemy_projectile_E[v1] = enemy_projectile_x_pos[v1]; + if (nmi_frame_counter_word & 1) + enemy_projectile_x_pos[v1] = -4608; + else + enemy_projectile_x_pos[v1] = enemy_projectile_E[v1]; +} + +void sub_86D7DE(uint16 k) { // 0x86D7DE + R18_ = 0; + R20_ = 0; + *(uint16 *)((char *)&R18_ + 1) = 192; + int v1 = k >> 1; + uint16 v2 = enemy_projectile_y_subpos[v1]; + bool v3 = __CFADD__uint16(R18_, v2); + enemy_projectile_y_subpos[v1] = R18_ + v2; + enemy_projectile_y_pos[v1] += R20_ + v3; +} + +void EprojPreInstr_N00bTubeShards(uint16 k) { // 0x86D7FD + int16 v2; + int16 v5; + + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = enemy_projectile_x_vel[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + uint16 v3 = enemy_projectile_E[v1]; + bool v4 = __CFADD__uint16(R18_, v3); + enemy_projectile_E[v1] = R18_ + v3; + enemy_projectile_F[v1] += R20_ + v4; + R18_ = 0; + R20_ = 0; + v5 = enemy_projectile_y_vel[v1]; + if (v5 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v5; + uint16 v6 = enemy_projectile_y_subpos[v1]; + v4 = __CFADD__uint16(R18_, v6); + enemy_projectile_y_subpos[v1] = R18_ + v6; + enemy_projectile_y_pos[v1] += R20_ + v4; + Eproj_DeleteIfYposOutside(k); +} + +void sub_86D83D(uint16 k) { // 0x86D83D + int16 v8; + + uint16 v1 = enemy_projectile_x_vel[k >> 1] & 0x17E | 0x80; + R18_ = 0; + R20_ = 0; + int v2 = v1 >> 1; + uint16 v3 = kSinCosTable8bit_Sext[v2 + 64]; + if ((kSinCosTable8bit_Sext[v2 + 64] & 0x8000u) != 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = (int16)v3 >> 2; + uint16 v5 = enemy_projectile_index; + int v6 = enemy_projectile_index >> 1; + uint16 v7 = enemy_projectile_E[v6]; + bool v4 = __CFADD__uint16(R18_, v7); + enemy_projectile_E[v6] = R18_ + v7; + enemy_projectile_F[v6] += R20_ + v4; + enemy_projectile_x_vel[v6] += 2; + R18_ = 0; + R20_ = 0; + v8 = enemy_projectile_y_vel[v6]; + if (v8 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v8; + uint16 v9 = enemy_projectile_y_subpos[v6]; + v4 = __CFADD__uint16(R18_, v9); + enemy_projectile_y_subpos[v6] = R18_ + v9; + enemy_projectile_y_pos[v6] += R20_ + v4; + Eproj_DeleteIfYposOutside(v5); +} + +void sub_86D89F(uint16 k) { // 0x86D89F + uint16 v1 = enemy_projectile_x_vel[k >> 1] & 0x17E | 0x80; + R18_ = 0; + R20_ = 0; + int v2 = v1 >> 1; + uint16 v3 = kSinCosTable8bit_Sext[v2 + 64]; + if ((kSinCosTable8bit_Sext[v2 + 64] & 0x8000u) != 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = (int16)v3 >> 2; + int v5 = enemy_projectile_index >> 1; + uint16 v6 = enemy_projectile_E[v5]; + bool v4 = __CFADD__uint16(R18_, v6); + enemy_projectile_E[v5] = R18_ + v6; + enemy_projectile_F[v5] += R20_ + v4; + enemy_projectile_x_vel[v5] += 4; + sub_86D8DF(enemy_projectile_index); +} + +void sub_86D8DF(uint16 k) { // 0x86D8DF + int v5 = k >> 1; + int16 v7; + R18_ = 0; + R20_ = 0; + v7 = enemy_projectile_y_vel[v5]; + if (v7 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v7; + uint16 v8 = enemy_projectile_y_subpos[v5]; + bool v4 = __CFADD__uint16(R18_, v8); + enemy_projectile_y_subpos[v5] = R18_ + v8; + enemy_projectile_y_pos[v5] += R20_ + v4; + enemy_projectile_x_pos[v5] = enemy_projectile_F[v5]; +} + +#define off_86D96A ((uint16*)RomPtr(0x86d96a)) + +void sub_86D992(uint16 v0) { // 0x86D992 + uint16 v1 = enemy_projectile_init_param; + int v2 = v0 >> 1; + enemy_projectile_E[v2] = enemy_projectile_init_param; + enemy_projectile_instr_list_ptr[v2] = off_86D96A[v1 >> 1]; + EnemyData *v3 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v2] = v3->x_pos; + enemy_projectile_1A27[v2] = v3->x_subpos; + enemy_projectile_y_pos[v2] = v3->y_pos; + enemy_projectile_y_subpos[v2] = v3->y_subpos; + enemy_projectile_y_vel[v2] = -512; + enemy_projectile_x_vel[v2] = 512; + if (!sign16(enemy_projectile_init_param - 12)) { + enemy_projectile_y_vel[v2] = -384; + enemy_projectile_x_vel[v2] = 384; + } +} + +static Func_X_V *const kEprojPreInstr_SpikeShootingPlantSpikes[10] = { // 0x86D9DB + EprojPreInstr_SpikeShootingPlantSpikes_0_MoveX1, + EprojPreInstr_SpikeShootingPlantSpikes_1_MoveY1, + EprojPreInstr_SpikeShootingPlantSpikes_2_MoveX2, + EprojPreInstr_SpikeShootingPlantSpikes_0_MoveX1, + EprojPreInstr_SpikeShootingPlantSpikes_4_MoveY2, + EprojPreInstr_SpikeShootingPlantSpikes_2_MoveX2, + EprojPreInstr_SpikeShootingPlantSpikes_6_MoveX1Y1, + EprojPreInstr_SpikeShootingPlantSpikes_7_MoveX2Y1, + EprojPreInstr_SpikeShootingPlantSpikes_8_MoveX1Y2, + EprojPreInstr_SpikeShootingPlantSpikes_9_MoveX2Y2, +}; + +void EprojPreInstr_SpikeShootingPlantSpikes(uint16 k) { + kEprojPreInstr_SpikeShootingPlantSpikes[enemy_projectile_E[k >> 1] >> 1](k); + EprojPreInstrHelper_SpikeShootingPlantSpikes_Func1(k); +} + +void EprojPreInstr_SpikeShootingPlantSpikes_MoveY1(uint16 k) { // 0x86D9E6 + int16 v2; + + int v1 = k >> 1; + enemy_projectile_y_pos[v1] += SignExtend8((uint8)((uint16)(enemy_projectile_y_vel[v1] & 0xFF00) >> 8)); + v2 = LOBYTE(enemy_projectile_y_vel[v1]) << 8; + bool v3 = __CFADD__uint16(enemy_projectile_y_subpos[v1], v2); + enemy_projectile_y_subpos[v1] += v2; + if (v3) + ++enemy_projectile_y_pos[v1]; +} + +void EprojPreInstr_SpikeShootingPlantSpikes_MoveY2(uint16 k) { // 0x86DA10 + int16 v2; + + int v1 = k >> 1; + enemy_projectile_y_pos[v1] += SignExtend8((uint8)((uint16)(enemy_projectile_x_vel[v1] & 0xFF00) >> 8)); + v2 = LOBYTE(enemy_projectile_x_vel[v1]) << 8; + bool v3 = __CFADD__uint16(enemy_projectile_y_subpos[v1], v2); + enemy_projectile_y_subpos[v1] += v2; + if (v3) + ++enemy_projectile_y_pos[v1]; +} + +void EprojPreInstr_SpikeShootingPlantSpikes_MoveX1(uint16 k) { // 0x86DA3A + int16 v2; + + int v1 = k >> 1; + enemy_projectile_x_pos[v1] += SignExtend8((uint8)((uint16)(enemy_projectile_y_vel[v1] & 0xFF00) >> 8)); + v2 = LOBYTE(enemy_projectile_y_vel[v1]) << 8; + bool v3 = __CFADD__uint16(enemy_projectile_1A27[v1], v2); + enemy_projectile_1A27[v1] += v2; + if (v3) + ++enemy_projectile_x_pos[v1]; +} + +void EprojPreInstr_SpikeShootingPlantSpikes_MoveX2(uint16 k) { // 0x86DA64 + int16 v2; + + int v1 = k >> 1; + enemy_projectile_x_pos[v1] += SignExtend8((uint8)((uint16)(enemy_projectile_x_vel[v1] & 0xFF00) >> 8)); + v2 = LOBYTE(enemy_projectile_x_vel[v1]) << 8; + bool v3 = __CFADD__uint16(enemy_projectile_1A27[v1], v2); + enemy_projectile_1A27[v1] += v2; + if (v3) + ++enemy_projectile_x_pos[v1]; +} + +void EprojPreInstr_SpikeShootingPlantSpikes_0_MoveX1(uint16 k) { // 0x86DA8E + EprojPreInstr_SpikeShootingPlantSpikes_MoveX1(k); +} + +void EprojPreInstr_SpikeShootingPlantSpikes_2_MoveX2(uint16 k) { // 0x86DA93 + EprojPreInstr_SpikeShootingPlantSpikes_MoveX2(k); +} + +void EprojPreInstr_SpikeShootingPlantSpikes_1_MoveY1(uint16 k) { // 0x86DA98 + EprojPreInstr_SpikeShootingPlantSpikes_MoveY1(k); +} + +void EprojPreInstr_SpikeShootingPlantSpikes_4_MoveY2(uint16 k) { // 0x86DA9D + EprojPreInstr_SpikeShootingPlantSpikes_MoveY2(k); +} + +void EprojPreInstr_SpikeShootingPlantSpikes_6_MoveX1Y1(uint16 k) { // 0x86DAA2 + EprojPreInstr_SpikeShootingPlantSpikes_MoveX1(k); + EprojPreInstr_SpikeShootingPlantSpikes_MoveY1(k); +} + +void EprojPreInstr_SpikeShootingPlantSpikes_8_MoveX1Y2(uint16 k) { // 0x86DAAA + EprojPreInstr_SpikeShootingPlantSpikes_MoveX1(k); + EprojPreInstr_SpikeShootingPlantSpikes_MoveY2(k); +} + +void EprojPreInstr_SpikeShootingPlantSpikes_7_MoveX2Y1(uint16 k) { // 0x86DAB2 + EprojPreInstr_SpikeShootingPlantSpikes_MoveX2(k); + EprojPreInstr_SpikeShootingPlantSpikes_MoveY1(k); +} + +void EprojPreInstr_SpikeShootingPlantSpikes_9_MoveX2Y2(uint16 k) { // 0x86DABA + EprojPreInstr_SpikeShootingPlantSpikes_MoveX2(k); + EprojPreInstr_SpikeShootingPlantSpikes_MoveY2(k); +} + +void EprojPreInstrHelper_SpikeShootingPlantSpikes_Func1(uint16 k) { // 0x86DAC2 + if (EprojPreInstrHelper_SpikeShootingPlantSpikes_Func2(k)) + enemy_projectile_id[k >> 1] = 0; +} + +uint16 EprojPreInstrHelper_SpikeShootingPlantSpikes_Func2(uint16 k) { // 0x86DACE + int v1 = k >> 1; + return (int16)(enemy_projectile_x_pos[v1] - layer1_x_pos) < 0 + || (int16)(layer1_x_pos + 256 - enemy_projectile_x_pos[v1]) < 0 + || (int16)(enemy_projectile_y_pos[v1] - layer1_y_pos) < 0 + || (int16)(layer1_y_pos + 256 - enemy_projectile_y_pos[v1]) < 0; +} + +void EprojInit_DBF2(uint16 j) { // 0x86DB18 + int v2 = j >> 1; + enemy_projectile_instr_list_ptr[v2] = addr_word_86DB0C; + enemy_projectile_E[v2] = FUNC16(EprojPreInstr_DBF2_MoveX1); + if (enemy_projectile_init_param) + enemy_projectile_E[v2] = FUNC16(EprojPreInstr_DBF2_MoveX2); + EnemyData *v3 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v2] = v3->x_pos; + enemy_projectile_1A27[v2] = v3->x_subpos; + enemy_projectile_y_pos[v2] = v3->y_pos + 2; + enemy_projectile_y_subpos[v2] = v3->y_subpos; + enemy_projectile_y_vel[v2] = -256; + enemy_projectile_x_vel[v2] = 256; +} + +void EprojPreInstr_DBF2(uint16 k) { // 0x86DB5B + CallEprojPreInstr(enemy_projectile_E[k >> 1] | 0x860000, k); + EprojPreInstr_DBF2_Func1(k); +} + +void EprojPreInstr_DBF2_MoveX1(uint16 k) { // 0x86DB62 + int16 v2; + + int v1 = k >> 1; + enemy_projectile_x_pos[v1] += SignExtend8((uint8)((uint16)(enemy_projectile_y_vel[v1] & 0xFF00) >> 8)); + v2 = LOBYTE(enemy_projectile_y_vel[v1]) << 8; + bool v3 = __CFADD__uint16(enemy_projectile_1A27[v1], v2); + enemy_projectile_1A27[v1] += v2; + if (v3) + ++enemy_projectile_x_pos[v1]; +} + +void EprojPreInstr_DBF2_MoveX2(uint16 k) { // 0x86DB8C + int16 v2; + + int v1 = k >> 1; + enemy_projectile_x_pos[v1] += SignExtend8((uint8)((uint16)(enemy_projectile_x_vel[v1] & 0xFF00) >> 8)); + v2 = LOBYTE(enemy_projectile_x_vel[v1]) << 8; + bool v3 = __CFADD__uint16(enemy_projectile_1A27[v1], v2); + enemy_projectile_1A27[v1] += v2; + if (v3) + ++enemy_projectile_x_pos[v1]; +} + +void EprojPreInstr_DBF2_Func1(uint16 k) { // 0x86DBB6 + if (EprojPreInstrHelper_DBF2_Func2(k)) + enemy_projectile_id[k >> 1] = 0; +} + +uint16 EprojPreInstrHelper_DBF2_Func2(uint16 k) { // 0x86DBC2 + int v1 = k >> 1; + return (int16)(enemy_projectile_x_pos[v1] - layer1_x_pos) < 0 + || (int16)(layer1_x_pos + 256 - enemy_projectile_x_pos[v1]) < 0 + || (int16)(enemy_projectile_y_pos[v1] - layer1_y_pos) < 0 + || (int16)(layer1_y_pos + 256 - enemy_projectile_y_pos[v1]) < 0; +} + +uint16 EprojInstr_DC5A(uint16 k, uint16 j) { // 0x86DC5A + enemy_projectile_properties[k >> 1] = 12288; + return j; +} + +uint16 EprojInstr_SpawnEnemyDrops_0(uint16 k, uint16 j) { // 0x86DC61 + int v2 = k >> 1; + R18_ = enemy_projectile_x_pos[v2]; + R20_ = enemy_projectile_y_pos[v2]; + SpawnEnemyDrops(addr_kEnemyDef_DF7F, k); + return j; +} + +uint16 EprojInstr_SpawnSporesEproj(uint16 k, uint16 j) { // 0x86DC77 + int v2 = k >> 1; + R18_ = enemy_projectile_x_pos[v2]; + R20_ = enemy_projectile_y_pos[v2]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_Spores, R20_); + return j; +} + +void EprojInit_Spores(uint16 j) { // 0x86DC8D + uint16 v1 = R18_; + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = R18_; + enemy_projectile_F[v2] = v1; + enemy_projectile_y_pos[v2] = R20_; + enemy_projectile_gfx_idx[v2] = 512; +} + +static const int16 word_86DCB9[5] = { -64, -56, -48, -40, -32 }; + +void EprojInit_SporeSpawnStalk(uint16 j) { // 0x86DCA3 + int v1 = j >> 1; + enemy_projectile_y_pos[v1] = enemy_data[0].y_pos + + word_86DCB9[enemy_projectile_init_param]; + enemy_projectile_x_pos[v1] = enemy_data[0].x_pos; +} + +void sub_86DCC3(uint16 v0) { // 0x86DCC3 + int v1 = v0 >> 1; + enemy_projectile_y_pos[v1] = enemy_data[0].y_pos - 96; + enemy_projectile_x_pos[v1] = enemy_data[0].x_pos; +} + +static const int16 kEprojInit_SporeSpawners_X[4] = { 0x20, 0x60, 0xa0, 0xe0 }; + +void EprojInit_SporeSpawners(uint16 j) { // 0x86DCD4 + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = kEprojInit_SporeSpawners_X[enemy_projectile_init_param]; + enemy_projectile_y_pos[v1] = 520; +} + +#define kSporeMovementData ((uint8*)RomPtr(0x86dd6c)) + +void EprojPreInstr_Spores(uint16 k) { // 0x86DCEE + int v1 = k >> 1; + uint16 v2 = LOBYTE(enemy_projectile_E[v1]); + R18_ = SignExtend8(kSporeMovementData[LOBYTE(enemy_projectile_E[v1])]); + if ((enemy_projectile_F[v1] & 0x80) != 0) + R18_ = -R18_; + enemy_projectile_x_pos[v1] += R18_; + R18_ = SignExtend8(kSporeMovementData[v2 + 1]); + uint16 v3 = R18_ + enemy_projectile_y_pos[v1] + R18_; + enemy_projectile_y_pos[v1] = v3; + if (!sign16(v3 - 768)) + enemy_projectile_id[v1] = 0; + enemy_projectile_E[v1] = (uint8)(LOBYTE(enemy_projectile_E[v1]) + 2); +} + +void EprojPreInstr_SporeSpawners(uint16 k) { // 0x86DD46 + if (!kraid_unk9000) { + int v1 = k >> 1; + if (!enemy_projectile_F[v1]) { + enemy_projectile_instr_list_ptr[v1] = addr_word_86DC06; + enemy_projectile_instr_timers[v1] = 1; + enemy_projectile_F[v1] = NextRandom() & 0x1FF; + } + --enemy_projectile_F[v1]; + } +} + +#define word_86DEB6 ((uint16*)RomPtr(0x86deb6)) + +void EprojInit_NamiFuneFireball(uint16 j) { // 0x86DED6 + int v2 = j >> 1; + enemy_projectile_instr_list_ptr[v2] = addr_word_86DE96; + enemy_projectile_E[v2] = FUNC16(EprojInit_NamiFuneFireball_MoveX1); + if (enemy_projectile_init_param) { + enemy_projectile_instr_list_ptr[v2] = addr_word_86DEA6; + enemy_projectile_E[v2] = FUNC16(EprojInit_NamiFuneFireball_MoveX2); + } + EnemyData *v3 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v2] = v3->x_pos; + enemy_projectile_1A27[v2] = v3->x_subpos; + enemy_projectile_y_pos[v2] = v3->y_pos; + enemy_projectile_y_subpos[v2] = v3->y_subpos; + if ((v3->parameter_1 & 0xF) != 0) + enemy_projectile_y_pos[v2] += 4; + int v4 = (uint16)(4 * LOBYTE(v3->parameter_2)) >> 1; + enemy_projectile_y_vel[v2] = word_86DEB6[v4]; + enemy_projectile_x_vel[v2] = word_86DEB6[v4 + 1]; +} + +void CallNamiFuneFireballFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnEprojInit_NamiFuneFireball_MoveX1: EprojInit_NamiFuneFireball_MoveX1(k); return; + case fnEprojInit_NamiFuneFireball_MoveX2: EprojInit_NamiFuneFireball_MoveX2(k); return; + default: Unreachable(); + } +} +void EprojPreInstr_NamiFuneFireball(uint16 v0) { // 0x86DF39 + CallNamiFuneFireballFunc(enemy_projectile_E[v0 >> 1] | 0x860000, v0); + Eproj_NamiFuneFireball_After(v0); +} + +void EprojInit_NamiFuneFireball_MoveX1(uint16 v1) { // 0x86DF40 + int16 v3; + + int v2 = v1 >> 1; + enemy_projectile_x_pos[v2] += SignExtend8((uint8)((uint16)(enemy_projectile_y_vel[v2] & 0xFF00) >> 8)); + v3 = LOBYTE(enemy_projectile_y_vel[v2]) << 8; + bool v4 = __CFADD__uint16(enemy_projectile_1A27[v2], v3); + enemy_projectile_1A27[v2] += v3; + if (v4) + ++enemy_projectile_x_pos[v2]; +} + +void EprojInit_NamiFuneFireball_MoveX2(uint16 v1) { // 0x86DF6A + int16 v3; + + int v2 = v1 >> 1; + enemy_projectile_x_pos[v2] += SignExtend8((uint8)((uint16)(enemy_projectile_x_vel[v2] & 0xFF00) >> 8)); + v3 = LOBYTE(enemy_projectile_x_vel[v2]) << 8; + bool v4 = __CFADD__uint16(enemy_projectile_1A27[v2], v3); + enemy_projectile_1A27[v2] += v3; + if (v4) + ++enemy_projectile_x_pos[v2]; +} + +void Eproj_NamiFuneFireball_After(uint16 v0) { // 0x86DF94 + if (EprojPreInstrHelper_DBF2_Func2(v0)) + enemy_projectile_id[v0 >> 1] = 0; +} + +uint16 sub_86DFA0(uint16 k) { // 0x86DFA0 + int v1 = k >> 1; + return (int16)(enemy_projectile_x_pos[v1] - layer1_x_pos) < 0 + || (int16)(layer1_x_pos + 256 - enemy_projectile_x_pos[v1]) < 0; +} + +uint16 EprojInstr_DFEA(uint16 k, uint16 j) { // 0x86DFEA + int v1 = k >> 1; + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + SpawnEnemyDrops(addr_kEnemyDef_E83F, k); + return j; +} + +void EprojInit_LavaThrownByLavaman(uint16 j) { // 0x86E000 + int v2 = j >> 1; + enemy_projectile_instr_list_ptr[v2] = addr_word_86DFD8; + enemy_projectile_E[v2] = FUNC16(Eproj_LavaThrownByLavaman_MoveX1); + if (enemy_projectile_init_param) { + enemy_projectile_instr_list_ptr[v2] = addr_word_86DFDE; + enemy_projectile_E[v2] = FUNC16(Eproj_LavaThrownByLavaman_MoveX2); + } + EnemyData *v3 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v2] = v3->x_pos; + enemy_projectile_1A27[v2] = v3->x_subpos; + enemy_projectile_y_pos[v2] = v3->y_pos + 2; + enemy_projectile_y_subpos[v2] = v3->y_subpos; + enemy_projectile_y_vel[v2] = -768; + enemy_projectile_x_vel[v2] = 768; +} + +void CallLavamanFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnEproj_LavaThrownByLavaman_MoveX1: Eproj_LavaThrownByLavaman_MoveX1(k); return; + case fnEproj_LavaThrownByLavaman_MoveX2: Eproj_LavaThrownByLavaman_MoveX2(k); return; + default: Unreachable(); + } +} + +void sub_86E049(uint16 v0) { // 0x86E049 + CallLavamanFunc(enemy_projectile_E[v0 >> 1] | 0x860000, v0); + sub_86E0A4(v0); +} + +void Eproj_LavaThrownByLavaman_MoveX1(uint16 k) { // 0x86E050 + int16 v2; + + int v1 = k >> 1; + enemy_projectile_x_pos[v1] += SignExtend8((enemy_projectile_y_vel[v1] & 0xFF00) >> 8); + v2 = LOBYTE(enemy_projectile_y_vel[v1]) << 8; + bool v3 = __CFADD__uint16(enemy_projectile_1A27[v1], v2); + enemy_projectile_1A27[v1] += v2; + if (v3) + ++enemy_projectile_x_pos[v1]; +} + +void Eproj_LavaThrownByLavaman_MoveX2(uint16 k) { // 0x86E07A + int16 v2; + + int v1 = k >> 1; + enemy_projectile_x_pos[v1] += SignExtend8((enemy_projectile_x_vel[v1] & 0xFF00) >> 8); + v2 = LOBYTE(enemy_projectile_x_vel[v1]) << 8; + bool v3 = __CFADD__uint16(enemy_projectile_1A27[v1], v2); + enemy_projectile_1A27[v1] += v2; + if (v3) + ++enemy_projectile_x_pos[v1]; +} + +void sub_86E0A4(uint16 v0) { // 0x86E0A4 + int16 v1; + + v1 = sub_86E0B0(v0); + if (v1) + enemy_projectile_id[v0 >> 1] = 0; +} + +uint16 sub_86E0B0(uint16 k) { // 0x86E0B0 + int v1 = k >> 1; + return (int16)(enemy_projectile_x_pos[v1] - layer1_x_pos) < 0 + || (int16)(layer1_x_pos + 256 - enemy_projectile_x_pos[v1]) < 0 + || (int16)(enemy_projectile_y_pos[v1] - layer1_y_pos) < 0 + || (int16)(layer1_y_pos + 256 - enemy_projectile_y_pos[v1]) < 0; +} + +#define off_86E42C ((uint16*)RomPtr(0x86e42c)) +#define word_86E47E ((uint16*)RomPtr(0x86e47e)) + +void EprojInst_DustCloudOrExplosion(uint16 v0) { // 0x86E468 + int v1 = v0 >> 1; + enemy_projectile_instr_list_ptr[v1] = off_86E42C[enemy_projectile_init_param]; + enemy_projectile_x_pos[v1] = R18_; + enemy_projectile_y_pos[v1] = R20_; +} + +void EprojInit_EyeDoorSmoke(uint16 j) { // 0x86E4A6 + int v1 = j >> 1; + enemy_projectile_instr_list_ptr[v1] = off_86E42C[(uint16)(2 * (uint8)enemy_projectile_init_param) >> 1]; + int v2 = (uint16)(8 * HIBYTE(enemy_projectile_init_param)) >> 1; + R18_ = word_86E47E[v2 + 2] + (word_86E47E[v2] & random_number); + R20_ = word_86E47E[v2 + 3] + (word_86E47E[v2 + 1] & *(uint16 *)((char *)&random_number + 1)); + CalculatePlmBlockCoords(plm_id); + enemy_projectile_x_pos[v1] = R18_ + 8 * (2 * plm_x_block + 1); + enemy_projectile_y_pos[v1] = R20_ + 8 * (2 * plm_y_block + 1); + NextRandom(); +} + +void EprojPreInstr_DustCloudOrExplosion(uint16 k) { // 0x86E4FE + if (CheckIfEnemyProjectileIsOffScreen(k)) + enemy_projectile_id[k >> 1] = 0; +} + +uint16 EprojInstr_SetYVel(uint16 k, uint16 j) { // 0x86E533 + enemy_projectile_y_vel[k >> 1] = *(uint16 *)RomPtr_86(j); + return j + 2; +} + +void EprojInit_SpawnedShotGate(uint16 j) { // 0x86E5D0 + EprojInit_SpawnedGate_Common(j, 0); +} + +void EprojInit_ClosedDownwardsShotGate(uint16 j) { // 0x86E5D5 + EprojInit_SpawnedGate_Common(j, 0x40); +} + +void EprojInit_ClosedUpwardsShotGate(uint16 j) { // 0x86E5DA + EprojInit_SpawnedGate_Common(j, -0x40); +} + +void EprojInit_SpawnedGate_Common(uint16 j, uint16 v1) { // 0x86E5DD + R18_ = v1; + uint16 v2 = plm_id; + CalculatePlmBlockCoords(plm_id); + int v3 = j >> 1; + enemy_projectile_E[v3] = plm_block_indices[v2 >> 1]; + enemy_projectile_x_pos[v3] = 16 * plm_x_block; + enemy_projectile_y_pos[v3] = R18_ + 16 * plm_y_block; +} + +void EprojPreInstr_E605(uint16 k) { // 0x86E605 + int v1 = k >> 1; + uint16 v2 = enemy_projectile_timers[v1] + abs16(enemy_projectile_y_vel[v1]); + if (v2 >= 0x1000u) { + enemy_projectile_instr_timers[v1] = 1; + ++enemy_projectile_instr_list_ptr[v1]; + ++enemy_projectile_instr_list_ptr[v1]; + v2 = 0; + } + enemy_projectile_timers[v1] = v2; + enemy_projectile_y_subpos[v1] += LOBYTE(enemy_projectile_y_vel[v1]) << 8; + enemy_projectile_y_pos[v1] += (int8)HIBYTE(enemy_projectile_y_vel[v1]); +} + +void EprojInit_SaveStationElectricity(uint16 j) { // 0x86E6AD + CalculatePlmBlockCoords(plm_id); + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = 16 * (plm_x_block + 1); + enemy_projectile_y_pos[v1] = 16 * (plm_y_block - 2); +} + +uint16 CheckIfEnemyProjectileIsOffScreen(uint16 k) { // 0x86E6E0 + int v1 = k >> 1; + uint16 result = 1; + if ((int16)(enemy_projectile_x_pos[v1] - layer1_x_pos) >= 0) { + enemy_population_ptr = layer1_x_pos + 256; + if ((int16)(enemy_projectile_x_pos[v1] - (layer1_x_pos + 256)) < 0 + && (int16)(enemy_projectile_y_pos[v1] - layer1_y_pos) >= 0) { + enemy_population_ptr = layer1_y_pos + 256; + if ((int16)(enemy_projectile_y_pos[v1] - (layer1_y_pos + 256)) < 0) + return 0; + } + } + return result; +} + +uint16 Eproj_FuncE722(uint16 k) { // 0x86E722 + int16 v2; + int16 v3; + + int v1 = k >> 1; + v2 = enemy_projectile_x_pos[v1]; + uint16 result = 1; + if (v2 >= 0) { + if (sign16(v2 - 512)) { + v3 = enemy_projectile_y_pos[v1]; + if (v3 >= 0) { + if (sign16(v3 - 512)) + return 0; + } + } + } + return result; +} + +void Eproj_FuncE73E_MoveXY(uint16 k) { // 0x86E73E + int v1 = k >> 1; + uint16 v2 = enemy_projectile_1A27[v1]; + uint16 v4; + if (((g_word_7E97DC[v1] + 64) & 0x80) != 0) { + bool v3 = v2 < enemy_projectile_E[v1]; + enemy_projectile_1A27[v1] = v2 - enemy_projectile_E[v1]; + v4 = enemy_projectile_x_pos[v1] - (v3 + enemy_projectile_x_vel[v1]); + } else { + bool v3 = __CFADD__uint16(enemy_projectile_E[v1], v2); + enemy_projectile_1A27[v1] = enemy_projectile_E[v1] + v2; + v4 = enemy_projectile_x_vel[v1] + v3 + enemy_projectile_x_pos[v1]; + } + enemy_projectile_x_pos[v1] = v4; + uint16 v5 = enemy_projectile_y_subpos[v1], v6; + if (((g_word_7E97DC[v1] + 128) & 0x80) != 0) { + bool v3 = v5 < enemy_projectile_F[v1]; + enemy_projectile_y_subpos[v1] = v5 - enemy_projectile_F[v1]; + v6 = enemy_projectile_y_pos[v1] - (v3 + enemy_projectile_y_vel[v1]); + } else { + bool v3 = __CFADD__uint16(enemy_projectile_F[v1], v5); + enemy_projectile_y_subpos[v1] = enemy_projectile_F[v1] + v5; + v6 = enemy_projectile_y_vel[v1] + v3 + enemy_projectile_y_pos[v1]; + } + enemy_projectile_y_pos[v1] = v6; +} + +void Eproj_AngleToSamus(uint16 j) { // 0x86E7AB + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = R18_; + enemy_projectile_y_pos[v1] = R20_; + R18_ = samus_x_pos - enemy_projectile_x_pos[v1]; + R20_ = samus_y_pos - enemy_projectile_y_pos[v1]; + uint16 v2 = (uint8)(64 - CalculateAngleFromXY()); + g_word_7E97DC[v1] = v2; + R18_ = v2; + R20_ = enemy_projectile_init_param; + ConvertAngleToXy(); + enemy_projectile_x_vel[v1] = R22_; + enemy_projectile_E[v1] = R24_; + enemy_projectile_y_vel[v1] = R26_; + enemy_projectile_F[v1] = R28_; +} + +#define kEprojInit_BotwoonsBody_InstrLists ((uint16*)RomPtr(0x86e9f1)) + +void EprojInit_BotwoonsBody(uint16 j) { // 0x86EA31 + int v1 = j >> 1; + enemy_projectile_x_pos[v1] = enemy_data[0].x_pos; + enemy_projectile_y_pos[v1] = enemy_data[0].y_pos; + enemy_projectile_y_vel[v1] = 0; + uint16 v2 = 16; + if (!enemy_data[0].ai_var_A) + v2 = 48; + R18_ = v2; + uint16 v3 = kEprojInit_BotwoonsBody_InstrLists[v2 >> 1]; + int v4 = j >> 1; + enemy_projectile_instr_list_ptr[v4] = v3; + enemy_projectile_F[v4] = v3; + enemy_projectile_E[v4] = R18_; + enemy_projectile_x_vel[v4] = FUNC16(Eproj_BotwoonsBody_Main); + uint16 ai_var_A = enemy_data[0].ai_var_A; + gExtraEnemyRam7800(enemy_data[0].ai_var_A)->kraid.kraid_next = j; + enemy_projectile_flags[v4] = 2; + gExtraEnemyRam7800(ai_var_A)->kraid.kraid_healths_4ths[0] = 1; +} + +void CallBotwoonEprojFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnEproj_BotwoonsBody_Main: Eproj_BotwoonsBody_Main(k); return; + case fnEproj_BotwonsBodyFunction_Dying: Eproj_BotwonsBodyFunction_Dying(k); return; + case fnEproj_BotwonsBodyFunction_Dying2: Eproj_BotwonsBodyFunction_Dying2(k); return; + case fnEproj_BotwonsBodyFunction_DyingFalling: Eproj_BotwonsBodyFunction_DyingFalling(k); return; + case fnnullsub_101: return; + default: Unreachable(); + } +} + +void EprojPreInstr_BotwoonsBody(uint16 k) { // 0x86EA80 + if (*(uint16 *)&extra_enemy_ram8000[0].pad[32]) { + int v1 = k >> 1; + if (enemy_projectile_x_vel[v1] == (uint16)FUNC16(Eproj_BotwoonsBody_Main)) + enemy_projectile_x_vel[v1] = FUNC16(Eproj_BotwonsBodyFunction_Dying); + } + CallBotwoonEprojFunc(enemy_projectile_x_vel[k >> 1] | 0x860000, k); +} + +void Eproj_BotwoonsBody_Main(uint16 k) { // 0x86EA98 + int v1 = k >> 1; + uint16 v2 = kEprojInit_BotwoonsBody_InstrLists[enemy_projectile_E[v1] >> 1]; + if (v2 != enemy_projectile_F[v1]) { + enemy_projectile_instr_list_ptr[v1] = v2; + enemy_projectile_F[v1] = v2; + enemy_projectile_instr_timers[v1] = 1; + } + Eproj_BotwoonsBodyHurtFlashHandling1(k); +} + +void Eproj_BotwoonsBodyHurtFlashHandling1(uint16 k) { // 0x86EAB4 + int v1 = k >> 1; + enemy_projectile_gfx_idx[v1] |= 0xE00u; + if (enemy_data[0].flash_timer) { + if ((enemy_damage_routine_exec_count & 2) != 0) + enemy_projectile_gfx_idx[v1] &= 0xF1FFu; + } +} + +void Eproj_BotwoonsBodyHurtFlashHandling2(uint16 j) { // 0x86EAD4 + int v1 = j >> 1; + enemy_projectile_gfx_idx[v1] |= 0xE00u; + if (enemy_data[0].flash_timer) { + if ((enemy_damage_routine_exec_count & 2) != 0) + enemy_projectile_gfx_idx[v1] &= 0xF1FFu; + } +} + +void Eproj_BotwonsBodyFunction_Dying(uint16 v0) { // 0x86EAF4 + int v1 = v0 >> 1; + enemy_projectile_E[v1] = 4 * v0 + 96; + enemy_projectile_x_vel[v1] = 0xEB04; + Eproj_BotwonsBodyFunction_Dying2(v0); +} + +void Eproj_BotwonsBodyFunction_Dying2(uint16 v0) { // 0x86EB04 + int v1 = v0 >> 1; + if (!sign16(++enemy_projectile_E[v1] - 256)) + enemy_projectile_x_vel[v1] = FUNC16(Eproj_BotwonsBodyFunction_DyingFalling); + enemy_projectile_instr_timers[v1] = 0; + Eproj_BotwoonsBodyHurtFlashHandling1(v0); +} + +void Eproj_BotwonsBodyFunction_DyingFalling(uint16 v0) { // 0x86EB1F + int v1 = v0 >> 1; + uint16 v2 = enemy_projectile_y_subpos[v1]; + int v3 = (uint16)(8 * (uint8)((uint16)(enemy_projectile_y_vel[v1] & 0xFF00) >> 8)) >> 1; + bool v4 = __CFADD__uint16(kCommonEnemySpeeds_Quadratic_Copy[v3], v2); + uint16 v5 = kCommonEnemySpeeds_Quadratic_Copy[v3] + v2; + if (v4) + ++enemy_projectile_y_pos[v1]; + enemy_projectile_y_subpos[v1] = v5; + uint16 v6 = kCommonEnemySpeeds_Quadratic_Copy[v3 + 1] + enemy_projectile_y_pos[v1]; + enemy_projectile_y_pos[v1] = v6; + if (sign16(v6 - 200)) { + int v7 = v0 >> 1; + enemy_projectile_y_vel[v7] += 192; + enemy_projectile_instr_timers[v7] = 0; + Eproj_BotwoonsBodyHurtFlashHandling2(v0); + } else { + enemy_projectile_y_pos[v1] = 200; + enemy_projectile_x_vel[v1] = FUNC16(nullsub_101); + enemy_projectile_instr_list_ptr[v1] = addr_word_86E208; + enemy_projectile_gfx_idx[v1] = 2560; + enemy_projectile_instr_timers[v1] = 1; + QueueSmallExplosionSfx(); + if (v0 == 10) + *(uint16 *)&extra_enemy_ram8800[0].pad[62] = 1; + } +} + +void QueueSmallExplosionSfx(void) { // 0x86EB94 + QueueSfx2_Max6(0x24u); +} + +void EprojInit_BotwoonsSpit(uint16 j) { // 0x86EBC6 + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = v1->x_pos; + enemy_projectile_y_pos[v2] = v1->y_pos; + enemy_projectile_instr_list_ptr[v2] = addr_word_86EBAE; + uint16 v3 = remaining_enemy_spritemap_entries; + g_word_7E97DC[v2] = remaining_enemy_spritemap_entries; + R18_ = v3; + R20_ = enemy_projectile_init_param; + ConvertAngleToXy(); + enemy_projectile_x_vel[v2] = R22_; + enemy_projectile_E[v2] = R24_; + enemy_projectile_y_vel[v2] = R26_; + enemy_projectile_F[v2] = R28_; +} + +void EprojPreInstr_BotwoonsSpit(uint16 k) { // 0x86EC05 + Eproj_FuncE73E_MoveXY(k); + sub_86EC0C(k); +} + +void sub_86EC0C(uint16 k) { // 0x86EC0C + int16 v1; + + v1 = sub_86EC18(k); + if (v1) + enemy_projectile_id[k >> 1] = 0; +} + +uint16 sub_86EC18(uint16 k) { // 0x86EC18 + int v1 = k >> 1; + return (int16)(enemy_projectile_x_pos[v1] - layer1_x_pos) < 0 + || (int16)(layer1_x_pos + 256 - enemy_projectile_x_pos[v1]) < 0 + || (int16)(enemy_projectile_y_pos[v1] - layer1_y_pos) < 0 + || (int16)(layer1_y_pos + 256 - enemy_projectile_y_pos[v1]) < 0; +} + +void EprojInit_YappingMawsBody(uint16 j) { // 0x86EC62 + EnemyData *v2 = gEnemyData(cur_enemy_index); + int v3 = j >> 1; + enemy_projectile_x_pos[v3] = v2->x_pos; + enemy_projectile_y_pos[v3] = v2->y_pos; + enemy_projectile_instr_list_ptr[v3] = addr_word_86EC5C; + if (!v2->parameter_2) + enemy_projectile_instr_list_ptr[v3] = addr_word_86EC56; + *(uint16 *)&extra_enemy_ram8800[0].pad[(uint16)(cur_enemy_index + + 2 * *(uint16 *)&extra_enemy_ram8800[0].pad[cur_enemy_index + 8])] = j; +} + +uint16 EprojInstr_ECE3(uint16 k, uint16 j) { // 0x86ECE3 + int v2 = k >> 1; + R18_ = enemy_projectile_x_pos[v2] + (NextRandom() & 0x3F) - 32; + R20_ = enemy_projectile_y_pos[v2] + ((uint16)(random_number & 0x3F00) >> 8) - 32; + R22_ = *(uint16 *)RomPtr_86(j); + R24_ = 0; + CreateSpriteAtPos(); + return j + 2; +} + +uint16 EprojInstr_ED17(uint16 k, uint16 j) { // 0x86ED17 + int v2 = k >> 1; + R18_ = enemy_projectile_x_pos[v2] + (NextRandom() & 0x1F) - 16; + R20_ = enemy_projectile_y_pos[v2] + ((uint16)(random_number & 0x1F00) >> 8) - 16; + R22_ = *(uint16 *)RomPtr_86(j); + R24_ = 0; + CreateSpriteAtPos(); + return j + 2; +} + +uint16 EprojInstr_QueueSfx2_9(uint16 k, uint16 j) { // 0x86EE8B + QueueSfx2_Max1(9u); + return j; +} + +uint16 EprojInstr_QueueSfx2_24(uint16 k, uint16 j) { // 0x86EE97 + QueueSfx2_Max1(0x24u); + return j; +} + +uint16 EprojInstr_QueueSfx2_B(uint16 k, uint16 j) { // 0x86EEA3 + QueueSfx2_Max1(0xBu); + return j; +} + +#define off_86EF04 ((uint16*)RomPtr(0x86ef04)) + +uint16 EprojInstr_EEAF(uint16 k, uint16 j) { // 0x86EEAF + uint16 v2 = RandomDropRoutine(k); + if (sign16(v2 - 6)) { + uint16 v3 = 2 * v2; + int v4 = k >> 1; + enemy_projectile_E[v4] = v3; + enemy_projectile_instr_list_ptr[v4] = off_86EF04[v3 >> 1]; + enemy_projectile_instr_timers[v4] = 1; + enemy_projectile_F[v4] = 400; + enemy_projectile_pre_instr[v4] = FUNC16(EprojPreInstr_Pickup); + enemy_projectile_properties[v4] &= ~0x4000u; + return enemy_projectile_instr_list_ptr[v4]; + } else { + int v6 = k >> 1; + enemy_projectile_instr_timers[v6] = 1; + enemy_projectile_properties[v6] = 12288; + enemy_projectile_pre_instr[v6] = FUNC16(EprojPreInstr_Empty); + enemy_projectile_instr_list_ptr[v6] = 0xECA3; + return 0xECA3; + } +} + +uint16 EprojInstr_HandleRespawningEnemy(uint16 k, uint16 j) { // 0x86EF10 + if ((int16)enemy_projectile_killed_enemy_index[k >> 1] <= -2) + RespawnEnemy(enemy_projectile_killed_enemy_index[k >> 1] & 0x7fff); + return j; +} + +void EprojInit_F337(uint16 j) { // 0x86EF29 + printf("X is undefined\n"); + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = R18_; + enemy_projectile_y_pos[v2] = R20_; + enemy_projectile_gfx_idx[v2] = 0; + enemy_projectile_enemy_header_ptr[v2] = varE24; // this is X?! + uint16 v3 = RandomDropRoutine(j); + if (v3 != 0 && sign16(v3 - 6)) { // bug, why does it compare x here. + uint16 v4 = 2 * v3; + enemy_projectile_E[v2] = v4; + enemy_projectile_instr_list_ptr[v2] = off_86EF04[v4 >> 1]; + enemy_projectile_instr_timers[v2] = 1; + enemy_projectile_F[v2] = 400; + enemy_projectile_killed_enemy_index[j >> 1] = -1; + } else { + int v5 = j >> 1; + enemy_projectile_instr_list_ptr[v5] = addr_word_86ECA3; + enemy_projectile_instr_timers[v5] = 1; + enemy_projectile_properties[v5] = 12288; + enemy_projectile_pre_instr[v5] = FUNC16(EprojPreInstr_Empty); + } +} + +#define off_86EFD5 ((uint16*)RomPtr(0x86efd5)) + +void EprojInit_EnemyDeathExplosion(uint16 j) { // 0x86EF89 + EnemyData *v1 = gEnemyData(cur_enemy_index); + int v2 = j >> 1; + enemy_projectile_x_pos[v2] = v1->x_pos; + enemy_projectile_y_pos[v2] = v1->y_pos; + enemy_projectile_killed_enemy_index[v2] = cur_enemy_index; + if ((v1->properties & 0x4000) != 0) + enemy_projectile_killed_enemy_index[v2] = cur_enemy_index | 0x8000; + enemy_projectile_enemy_header_ptr[v2] = v1->enemy_ptr; + enemy_projectile_gfx_idx[v2] = 0; + enemy_projectile_instr_list_ptr[v2] = off_86EFD5[enemy_projectile_init_param]; + enemy_projectile_instr_timers[v2] = 1; +} + +static Func_V *const off_86F0AD[7] = { // 0x86EFE0 + 0, + Eproj_Pickup_SmallHealth, + Eproj_Pickup_BigHealth, + Eproj_Pickup_PowerBombs, + Eproj_Pickup_Missiles, + Eproj_Pickup_SuperMissiles, + 0, +}; + +void EprojPreInstr_Pickup(uint16 k) { + + int v1 = k >> 1; + if (!--enemy_projectile_F[v1]) + goto LABEL_7; + if (CallSomeSamusCode(0xDu)) { + if (sign16(enemy_projectile_F[v1] - 384)) { + uint16 v2, v3; + v2 = abs16(enemy_projectile_x_pos[v1] - grapple_beam_end_x_pos); + if (sign16(v2 - 16)) { + v3 = abs16(enemy_projectile_y_pos[v1] - grapple_beam_end_y_pos); + if (sign16(v3 - 16)) { + off_86F0AD[enemy_projectile_E[v1] >> 1](); +LABEL_7:; + int v4 = k >> 1; + enemy_projectile_instr_list_ptr[v4] = addr_word_86ECA3; + enemy_projectile_instr_timers[v4] = 1; + enemy_projectile_properties[v4] = 12288; + enemy_projectile_pre_instr[v4] = FUNC16(EprojPreInstr_Empty); + return; + } + } + } + } + int v5 = k >> 1; + enemy_population_ptr = LOBYTE(enemy_projectile_radius[v5]); + draw_oam_x_offset = HIBYTE(enemy_projectile_radius[v5]); + uint16 v6 = abs16(samus_x_pos - enemy_projectile_x_pos[v5]); + bool v7 = v6 < samus_x_radius; + uint16 v8 = v6 - samus_x_radius; + if (v7 || v8 < enemy_population_ptr) { + uint16 v9 = abs16(samus_y_pos - enemy_projectile_y_pos[v5]); + v7 = v9 < samus_y_radius; + uint16 v10 = v9 - samus_y_radius; + if (v7 || v10 < draw_oam_x_offset) { + off_86F0AD[enemy_projectile_E[v5] >> 1](); + int v11 = k >> 1; + enemy_projectile_instr_list_ptr[v11] = addr_word_86ECA3; + enemy_projectile_instr_timers[v11] = 1; + enemy_projectile_properties[v11] = 12288; + enemy_projectile_pre_instr[v11] = FUNC16(EprojPreInstr_Empty); + } + } +} + +void Eproj_Pickup_SmallHealth(void) { // 0x86F0BB + Samus_RestoreHealth(5u); + QueueSfx2_Max1(1u); +} + +void Eproj_Pickup_BigHealth(void) { // 0x86F0CA + Samus_RestoreHealth(0x14u); + QueueSfx2_Max1(2u); +} + +void Eproj_Pickup_PowerBombs(void) { // 0x86F0D9 + Samus_RestorePowerBombs(1u); + QueueSfx2_Max1(5u); +} + +void Eproj_Pickup_Missiles(void) { // 0x86F0E8 + Samus_RestoreMissiles(2u); + QueueSfx2_Max1(3u); +} + +void Eproj_Pickup_SuperMissiles(void) { // 0x86F0F7 + Samus_RestoreSuperMissiles(1u); + QueueSfx2_Max1(4u); +} + +static const uint8 byte_86F25E[6] = { 1, 2, 4, 6, 5, 3 }; + +uint16 RandomDropRoutine(uint16 k) { // 0x86F106 + char v9; // cf + + int v1 = k >> 1; + varE2A = enemy_projectile_killed_enemy_index[v1] & 0x7FFF; + varE28 = enemy_projectile_enemy_header_ptr[v1]; + if (varE28 == 0) + goto LABEL_30; + uint16 v2; + v2 = *((uint16 *)RomPtr_A0(varE28) + 29); + if (!v2) + goto LABEL_30; + uint8 Random; + do + Random = NextRandom(); + while (!Random); + R26_ = Random; + R20_ = 255; + R24_ = 0; + uint16 v5; + v5 = 1; + if ((uint16)(samus_reserve_health + samus_health) >= 0x1Eu) { + if ((uint16)(samus_reserve_health + samus_health) < 0x32u) + goto LABEL_7; + v5 = 0; + } + health_drop_bias_flag = v5; +LABEL_7: + if ((uint8)health_drop_bias_flag) { + uint8 *v6 = RomPtr_B4(v2); + LOBYTE(R18_) = v6[1] + *v6; + LOBYTE(R22_) = 3; + } else { + uint8 *v7 = RomPtr_B4(v2); + LOBYTE(R18_) = v7[3]; + LOBYTE(R22_) = 8; + if (samus_health != samus_max_health || samus_reserve_health != samus_max_reserve_health) { + LOBYTE(R18_) = v7[1] + *v7 + R18_; + LOBYTE(R22_) = R22_ | 3; + } + if (samus_missiles != samus_max_missiles) { + LOBYTE(R18_) = v7[2] + R18_; + LOBYTE(R22_) = R22_ | 4; + } + if (samus_super_missiles != samus_max_super_missiles) { + LOBYTE(R20_) = R20_ - v7[4]; + LOBYTE(R22_) = R22_ | 0x10; + } + if (samus_power_bombs != samus_max_power_bombs) { + LOBYTE(R20_) = R20_ - v7[5]; + LOBYTE(R22_) = R22_ | 0x20; + } + } + int i; + for (i = 0; i != 4; ++i) { + if (!(uint8)R18_) { + LOBYTE(R22_) = (uint8)R22_ >> 4; + v2 += 4; + i = 4; + goto LABEL_26; + } + v9 = R22_ & 1; + LOBYTE(R22_) = (uint8)R22_ >> 1; + if (v9) { + uint8 *v10 = RomPtr_B4(v2); + uint16 RegWord = Mult8x8(R20_, *v10); + int divved = SnesDivide(RegWord, R18_); + uint16 v12 = R24_; + uint16 v13 = divved + v12; + if (v13 >= R26_) + return byte_86F25E[i]; + R24_ = v13; + } + ++v2; + } + do { +LABEL_26: + v9 = R22_ & 1; + LOBYTE(R22_) = (uint8)R22_ >> 1; + if (v9) { + uint8 *v14 = RomPtr_B4(v2); + if ((uint16)(R24_ + *v14) >= R26_) + return byte_86F25E[i]; + R24_ += *v14; + } + ++v2; + ++i; + } while (i != 6); +LABEL_30: + i = 3; + return byte_86F25E[i]; +} + +void RespawnEnemy(uint16 v0) { // 0x86F264 + EnemySpawnData *v3; // r10 + EnemyDef_A2 *EnemyDef_A2; // r10 + int16 v7; + + cur_enemy_index = v0; + uint8 *v1 = RomPtr_A1(room_enemy_population_ptr + (v0 >> 2)); + EnemyData *v2 = gEnemyData(v0); + v2->enemy_ptr = *(uint16 *)v1; + v2->x_pos = *((uint16 *)v1 + 1); + v2->y_pos = *((uint16 *)v1 + 2); + v2->current_instruction = *((uint16 *)v1 + 3); + v2->properties = *((uint16 *)v1 + 4); + v2->extra_properties = *((uint16 *)v1 + 5); + v2->parameter_1 = *((uint16 *)v1 + 6); + v2->parameter_2 = *((uint16 *)v1 + 7); + v3 = gEnemySpawnData(v0); + EnemyData *v4 = gEnemyData(v0); + v4->palette_index = v3->palette_index; + v4->vram_tiles_index = v3->vram_tiles_index; + v2->frozen_timer = 0; + v2->flash_timer = 0; + v2->invincibility_timer = 0; + v2->timer = 0; + v2->frame_counter = 0; + v2->ai_var_A = 0; + v2->ai_var_B = 0; + v2->ai_var_C = 0; + v2->ai_var_D = 0; + v2->ai_var_E = 0; + v2->ai_preinstr = 0; + v2->instruction_timer = 1; + uint16 enemy_ptr = gEnemyData(cur_enemy_index)->enemy_ptr; + EnemyDef_A2 = get_EnemyDef_A2(enemy_ptr); + enemy_ai_pointer.addr = EnemyDef_A2->ai_init; + v2->x_width = EnemyDef_A2->x_radius; + v2->y_height = EnemyDef_A2->y_radius; + v2->health = EnemyDef_A2->health; + v2->layer = RomPtr_A0(enemy_ptr)[57]; + v7 = *(uint16 *)&EnemyDef_A2->bank; + *(uint16 *)&v2->bank = v7; + enemy_ai_pointer.bank = v7; + CallEnemyAi(Load24(&enemy_ai_pointer)); +} + +#define kEnemyDef_F3D3 (*(EnemyDef_B2*)RomPtr(0xa0f3d3)) + +void EprojInit_Sparks(uint16 j) { // 0x86F391 + static const uint16 word_86F3D4[14] = { 0xffff, 0xb800, 0xffff, 0xc000, 0xffff, 0xe000, 0xffff, 0xff00, 0, 0x100, 0, 0x2000, 0, 0x4000 }; +#define g_word_86F3D4 ((uint16*)RomPtr(0x86f3d4)) // bug:: oob read + int v2 = j >> 1; + enemy_projectile_instr_list_ptr[v2] = addr_kEnemyDef_F353; + EnemyData *v3 = gEnemyData(cur_enemy_index); + enemy_projectile_x_pos[v2] = v3->x_pos; + enemy_projectile_1A27[v2] = v3->x_subpos; + enemy_projectile_y_pos[v2] = v3->y_pos + 8; + enemy_projectile_y_subpos[v2] = v3->y_subpos; + enemy_projectile_x_vel[v2] = 0; + enemy_projectile_y_vel[v2] = 0; + uint16 v4 = (NextRandom() & 0x1C) >> 1; + enemy_projectile_F[v2] = g_word_86F3D4[v4 + 0]; + enemy_projectile_E[v2] = g_word_86F3D4[v4 + 1]; +} + +void EprojPreInstr_Sparks(uint16 k) { // 0x86F3F0 + int v1 = k >> 1; + if ((enemy_projectile_y_vel[v1] & 0x8000u) == 0) { + if (EnemyProjectileBlockCollisition_Vertical(k) & 1) { + enemy_projectile_instr_list_ptr[v1] = 0xF363; + enemy_projectile_instr_timers[v1] = 1; + + enemy_projectile_F[v1] = enemy_projectile_F[v1] * 2 + (enemy_projectile_E[v1] >> 15); + enemy_projectile_E[v1] *= 2; + + enemy_projectile_F[v1] = enemy_projectile_F[v1] * 2 + (enemy_projectile_E[v1] >> 15); + enemy_projectile_E[v1] *= 2; + + enemy_projectile_x_vel[v1] = 0x8000; + enemy_projectile_y_vel[v1] = -1; + enemy_projectile_y_pos[v1] -= 2; + return; + } + uint16 v2 = enemy_projectile_x_vel[v1]; + enemy_projectile_x_vel[v1] = v2 + 0x4000; + uint16 v3 = __CFADD__uint16(v2, 0x4000) + enemy_projectile_y_vel[v1]; + if (v3 < 4u) + enemy_projectile_y_vel[v1] = v3; + } + uint16 v4 = enemy_projectile_y_subpos[v1]; + bool v5 = __CFADD__uint16(enemy_projectile_x_vel[v1], v4); + enemy_projectile_y_subpos[v1] = enemy_projectile_x_vel[v1] + v4; + enemy_projectile_y_pos[v1] += enemy_projectile_y_vel[v1] + v5; + uint16 v6 = enemy_projectile_1A27[v1]; + v5 = __CFADD__uint16(enemy_projectile_E[v1], v6); + enemy_projectile_1A27[v1] = enemy_projectile_E[v1] + v6; + enemy_projectile_x_pos[v1] += enemy_projectile_F[v1] + v5; + if ((nmi_frame_counter_byte & 3) == 0) { + R18_ = enemy_projectile_x_pos[v1]; + R20_ = enemy_projectile_y_pos[v1]; + R22_ = 48; + R24_ = enemy_projectile_gfx_idx[v1]; + CreateSpriteAtPos(); + } +} diff --git a/src/sm_87.c b/src/sm_87.c new file mode 100644 index 0000000..a750346 --- /dev/null +++ b/src/sm_87.c @@ -0,0 +1,276 @@ +// Animated tiles +#include "ida_types.h" +#include "funcs.h" +#include "variables.h" + +void EnableAnimtiles(void) { // 0x878000 + animtiles_enable_flag |= 0x8000; +} + +void DisableAnimtiles(void) { // 0x87800B + animtiles_enable_flag &= ~0x8000u; +} + +void ClearAnimtiles(void) { // 0x878016 + for (int i = 10; i >= 0; i -= 2) + animtiles_ids[i >> 1] = 0; +} + +void SpawnAnimtiles(uint16 j) { // 0x878027 + uint16 v0 = j; + + uint16 v1 = 10; + while (animtiles_ids[v1 >> 1]) { + v1 -= 2; + if ((v1 & 0x8000u) != 0) + return; + } + int v2 = v1 >> 1; + animtiles_ids[v2] = v0; + animtiles_timers[v2] = 0; + uint16 *v3 = (uint16 *)RomPtr_87(v0); + animtiles_instr_list_ptrs[v2] = *v3; + animtiles_src_ptr[v2] = 0; + animtiles_sizes[v2] = v3[1]; + animtiles_vram_ptr[v2] = v3[2]; + animtiles_instr_timers[v2] = 1; +} + +void AnimtilesHandler(void) { // 0x878064 + if ((animtiles_enable_flag & 0x8000u) != 0) { + for (int i = 10; i >= 0; i -= 2) { + animtiles_object_index = i; + if (animtiles_ids[i >> 1]) { + ProcessAnimtilesObject(); + i = animtiles_object_index; + } + } + } +} + +uint16 CallAnimtilesInstr(uint32 ea, uint16 j, uint16 k) { + switch (ea) { + case fnAnimtilesInstr_Delete: return AnimtilesInstr_Delete(j, k); + case fnAnimtilesInstr_Goto: return AnimtilesInstr_Goto(j, k); + case fnAnimtilesInstr_GotoRel: return AnimtilesInstr_GotoRel(j, k); + case fnAnimtilesInstr_DecrementTimerAndGoto: return AnimtilesInstr_DecrementTimerAndGoto(j, k); + case fnAnimtilesInstr_DecrementTimerAndGotoRel: return AnimtilesInstr_DecrementTimerAndGotoRel(j, k); + case fnAnimtilesInstr_SetTimer: return AnimtilesInstr_SetTimer(j, k); + case fnAnimtilesInstr_QueueMusic: return AnimtilesInstr_QueueMusic(j, k); + case fnAnimtilesInstr_QueueSfx1: return AnimtilesInstr_QueueSfx1(j, k); + case fnAnimtilesInstr_QueueSfx2: return AnimtilesInstr_QueueSfx2(j, k); + case fnAnimtilesInstr_QueueSfx3: return AnimtilesInstr_QueueSfx3(j, k); + case fnAnimtilesInstr_GotoIfBossBitSet: return AnimtilesInstr_GotoIfBossBitSet(j, k); + case fnAnimtilesInstr_SetBossBit: return AnimtilesInstr_SetBossBit(j, k); + case fnAnimtilesInstr_GotoIfEventHappened: return AnimtilesInstr_GotoIfEventHappened(j, k); + case fnAnimtilesInstr_SetEventHappened: return AnimtilesInstr_SetEventHappened(j, k); + case fnAnimtilesInstr_WaitUntilAreaBossDead_DoubleRet: return AnimtilesInstr_WaitUntilAreaBossDead_DoubleRet(j, k); + case fnAnimtilesInstr_GotoIfBossBitSetInArea: return AnimtilesInstr_GotoIfBossBitSetInArea(j, k); + case fnAnimtilesInstr_SpawnTourianStatueEyeGlow: return AnimtilesInstr_SpawnTourianStatueEyeGlow(j, k); + case fnAnimtilesInstr_SpawnTourianStatueSoul: return AnimtilesInstr_SpawnTourianStatueSoul(j, k); + case fnAnimtilesInstr_GotoIfTourianStatueBusy: return AnimtilesInstr_GotoIfTourianStatueBusy(j, k); + case fnAnimtilesInstr_TourianStatueSetState: return AnimtilesInstr_TourianStatueSetState(j, k); + case fnAnimtilesInstr_TourianStatueClearState: return AnimtilesInstr_TourianStatueClearState(j, k); + case fnAnimtilesInstr_Clear3PaletteColors: return AnimtilesInstr_Clear3PaletteColors(j, k); + case fnAnimtilesInstr_SpawnPalfxObj: return AnimtilesInstr_SpawnPalfxObj(j, k); + case fnAnimtilesInstr_Write8PaletteColors: return AnimtilesInstr_Write8PaletteColors(j, k); + default: return Unreachable(); + } +} + +void ProcessAnimtilesObject(void) { // 0x878085 + uint16 v0 = animtiles_object_index; + int v1 = animtiles_object_index >> 1; + if (animtiles_instr_timers[v1]-- == 1) { + uint16 v3 = animtiles_instr_list_ptrs[v1], v5; + while (1) { + uint16 *v4 = (uint16 *)RomPtr_87(v3); + v5 = *v4; + if ((*v4 & 0x8000u) == 0) + break; + animtiles_instruction = *v4; + v3 = CallAnimtilesInstr(v5 | 0x870000, v0, v3 + 2); + if (!v3) + return; + } + int v6 = v0 >> 1; + animtiles_instr_timers[v6] = v5; + animtiles_src_ptr[v6] = *((uint16 *)RomPtr_87(v3) + 1); + animtiles_instr_list_ptrs[v6] = v3 + 4; + } +} + +uint16 AnimtilesInstr_Delete(uint16 k, uint16 j) { // 0x8780B2 + animtiles_ids[k >> 1] = 0; + return 0; +} + +uint16 AnimtilesInstr_Goto(uint16 k, uint16 j) { // 0x8780B7 + return *(uint16 *)RomPtr_87(j); +} + +uint16 AnimtilesInstr_GotoRel(uint16 k, uint16 j) { // 0x8780BC + int16 v2; + + animtiles_instruction = j; + LOBYTE(v2) = HIBYTE(*(uint16 *)RomPtr_87(j - 1)); + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + else + v2 = (uint8)v2; + return animtiles_instruction + v2; +} + +uint16 AnimtilesInstr_DecrementTimerAndGoto(uint16 k, uint16 j) { // 0x8780D4 + int v2 = k >> 1; + if (animtiles_timers[v2]-- == 1) + return j + 2; + else + return AnimtilesInstr_Goto(k, j); +} + +uint16 AnimtilesInstr_DecrementTimerAndGotoRel(uint16 k, uint16 j) { // 0x8780DC + int v2 = k >> 1; + if (animtiles_timers[v2]-- == 1) + return j + 1; + else + return AnimtilesInstr_GotoRel(k, j); +} + +uint16 AnimtilesInstr_SetTimer(uint16 k, uint16 j) { // 0x8780E3 + *((uint8 *)animtiles_timers + k) = *RomPtr_87(j); + return j + 1; +} + +uint16 AnimtilesInstr_QueueMusic(uint16 k, uint16 j) { // 0x8780F0 + uint8 *v2 = RomPtr_87(j); + QueueMusic_Delayed8(*v2); + return j + 1; +} + +uint16 AnimtilesInstr_QueueSfx1(uint16 k, uint16 j) { // 0x8780FC + uint8 *v2 = RomPtr_87(j); + QueueSfx1_Max6(*v2); + return j + 1; +} + +uint16 AnimtilesInstr_QueueSfx2(uint16 k, uint16 j) { // 0x878108 + uint8 *v2 = RomPtr_87(j); + QueueSfx2_Max6(*v2); + return j + 1; +} + +uint16 AnimtilesInstr_QueueSfx3(uint16 k, uint16 j) { // 0x878114 + uint8 *v2 = RomPtr_87(j); + QueueSfx3_Max6(*v2); + return j + 1; +} + +uint16 AnimtilesInstr_GotoIfBossBitSet(uint16 k, uint16 j) { // 0x878120 + uint8 *v2 = RomPtr_87(j); + uint16 v3 = j + 1; + if (CheckBossBitForCurArea((uint8) * (uint16 *)v2) & 1) + return AnimtilesInstr_Goto(k, v3); + else + return v3 + 2; +} + +uint16 AnimtilesInstr_SetBossBit(uint16 k, uint16 j) { // 0x878133 + uint8 *v2 = RomPtr_87(j); + SetBossBitForCurArea(*v2); + return j + 1; +} + +uint16 AnimtilesInstr_GotoIfEventHappened(uint16 k, uint16 j) { // 0x87813F + uint16 *v2 = (uint16 *)RomPtr_87(j); + uint16 v3 = j + 2; + if (CheckEventHappened(*v2) & 1) + return AnimtilesInstr_Goto(k, v3); + else + return v3 + 2; +} + +uint16 AnimtilesInstr_SetEventHappened(uint16 k, uint16 j) { // 0x878150 + uint16 *v2 = (uint16 *)RomPtr_87(j); + SetEventHappened(*v2); + return j + 2; +} + +void UNUSED_sub_87815A(void) { // 0x87815A + CallSomeSamusCode(0); +} + +void UNUSED_sub_878162(void) { // 0x878162 + CallSomeSamusCode(1u); +} + +uint16 AnimtilesInstr_WaitUntilAreaBossDead_DoubleRet(uint16 k, uint16 j) { // 0x8781BA + if (!(CheckBossBitForCurArea(1u) & 1)) { + animtiles_instr_timers[k >> 1] = 1; + return 0; + } + return j; +} + +uint16 AnimtilesInstr_GotoIfBossBitSetInArea(uint16 k, uint16 j) { // 0x878303 + uint8 *v2 = RomPtr_87(j); + uint16 v3 = j + 2; + if ((*v2 & boss_bits_for_area[v2[1]]) != 0) + return AnimtilesInstr_Goto(k, v3); + else + return v3 + 2; +} + +uint16 AnimtilesInstr_SpawnTourianStatueEyeGlow(uint16 k, uint16 j) { // 0x878320 + uint16 *v2 = (uint16 *)RomPtr_87(j); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatueEyeGlow, *v2); + return j + 2; +} + +uint16 AnimtilesInstr_SpawnTourianStatueSoul(uint16 k, uint16 j) { // 0x87832F + uint16 *v2 = (uint16 *)RomPtr_87(j); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatueSoul, *v2); + return j + 2; +} + +uint16 AnimtilesInstr_GotoIfTourianStatueBusy(uint16 k, uint16 j) { // 0x87833E + if ((tourian_entrance_statue_animstate & 0x8000u) == 0) + return j + 2; + else + return AnimtilesInstr_Goto(k, j); +} + +uint16 AnimtilesInstr_TourianStatueSetState(uint16 k, uint16 j) { // 0x878349 + tourian_entrance_statue_animstate |= *(uint16 *)RomPtr_87(j); + return j + 2; +} + +uint16 AnimtilesInstr_TourianStatueClearState(uint16 k, uint16 j) { // 0x878352 + tourian_entrance_statue_animstate &= ~*(uint16 *)RomPtr_87(j); + return j + 2; +} + +uint16 AnimtilesInstr_Clear3PaletteColors(uint16 k, uint16 j) { // 0x87835B + int v2 = *(uint16 *)RomPtr_87(j) >> 1; + palette_buffer[v2] = 0; + palette_buffer[v2 + 1] = 0; + palette_buffer[v2 + 2] = 0; + return j + 2; +} + +uint16 AnimtilesInstr_SpawnPalfxObj(uint16 k, uint16 j) { // 0x878372 + uint16 *v2 = (uint16 *)RomPtr_87(j); + SpawnPalfxObject(*v2); + return j + 2; +} + +uint16 AnimtilesInstr_Write8PaletteColors(uint16 k, uint16 j) { // 0x87837F + static const uint16 kAnimtilesInstr_Write8PaletteColors[8] = { 0x3800, 0x7f58, 0x6ed5, 0x5a71, 0x49ee, 0x356a, 0x24e7, 0x1083 }; + + uint16 v2 = *(uint16 *)RomPtr_87(j); + for (int i = 0; i != 16; i += 2) { + target_palettes[v2 >> 1] = kAnimtilesInstr_Write8PaletteColors[i >> 1]; + v2 += 2; + } + return j + 2; +} diff --git a/src/sm_88.c b/src/sm_88.c new file mode 100644 index 0000000..924a26d --- /dev/null +++ b/src/sm_88.c @@ -0,0 +1,3534 @@ +// HDMA +#include "ida_types.h" +#include "variables.h" +#include "sm_rtl.h" +#include "funcs.h" + +static Func_Y_Y *const kLayerBlendFuncTable[27] = { + nullsub_9, + nullsub_9, + LayerBlendFunc_4_PhantoonIntro, + LayerBlendFunc_6, + LayerBlendFunc_8, + LayerBlendFunc_A, + LayerBlendFunc_C, + nullsub_10, + LayerBlendFunc_10, + LayerBlendFunc_10, + LayerBlendFunc_14, + LayerBlendFunc_16, + LayerBlendFunc_18, + LayerBlendFunc_1A, + LayerBlendFunc_1C, + LayerBlendFunc_18, + nullsub_11, + LayerBlendFunc_14, + LayerBlendFunc_24, + LayerBlendFunc_26, + LayerBlendFunc_28, + LayerBlendFunc_2A, + LayerBlendFunc_2C, + LayerBlendFunc_2E, + LayerBlendFunc_18, + LayerBlendFunc_32, + LayerBlendFunc_34, +}; + +void LayerBlendingHandler(void) { // 0x888000 + uint16 v0 = 0; + uint8 v1 = fx_layer_blending_config_c; + if ((uint8)fx_layer_blending_config_c) { + InitializeLayerBlending(); + v0 = kLayerBlendFuncTable[v1 >> 1](v0); + } + if ((fx_layer_blending_config_c & 0x8000u) == 0) { + if ((fx_layer_blending_config_c & 0x4000) != 0) { + HandleLayerBlendingXrayCanShowBlocks(); + } else if ((fx_layer_blending_config_c & 0x2000) != 0) { + HandleLayerBlendingXrayCantShowBlocks(); + } else if ((fx_layer_blending_config_c & 0x1000) != 0) { + HandleLayerBlendingXrayFirefleaRoom(); + } + } else { + HandleLayerBlendingPowerBomb(v0); + } +} + +uint16 nullsub_9(uint16 j) { // 0x888074 + return j; +} + +void InitializeLayerBlending(void) { // 0x888075 + reg_W12SEL = 0; + reg_W34SEL = 0; + reg_WOBJSEL = 0; + reg_TM = 19; + reg_TS = 4; + reg_TMW = 0; + reg_TSW = 0; + next_gameplay_CGWSEL = 2; + next_gameplay_CGADSUB = 51; +} + +uint16 LayerBlendFunc_4_PhantoonIntro(uint16 j) { // 0x888090 + reg_TM = 17; + reg_TS = 4; + return j; +} + +uint16 LayerBlendFunc_6(uint16 j) { // 0x888099 + reg_TS = 20; + next_gameplay_CGADSUB = 39; + return j; +} + +uint16 LayerBlendFunc_8(uint16 j) { // 0x8880A2 + reg_TS = 20; + next_gameplay_CGADSUB = 34; + return j; +} + +uint16 LayerBlendFunc_A(uint16 j) { // 0x8880AB + next_gameplay_CGADSUB = 50; + return j; +} + +uint16 LayerBlendFunc_C(uint16 j) { // 0x8880B0 + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = -94; + return j; +} + +uint16 nullsub_10(uint16 j) { // 0x8880B7 + return j; +} + +uint16 LayerBlendFunc_10(uint16 j) { // 0x8880B8 + reg_W34SEL = 2; + reg_WOBJSEL = 32; + reg_TSW = 4; + return j; +} + +uint16 LayerBlendFunc_14(uint16 j) { // 0x8880C5 + next_gameplay_CGADSUB = -77; + return j; +} + +uint16 LayerBlendFunc_16(uint16 j) { // 0x8880CA + LOBYTE(j) = 4; + reg_TM = 17; + reg_TS = 6; + next_gameplay_CGADSUB = -79; + return j; +} + +uint16 LayerBlendFunc_1A(uint16 j) { // 0x8880D9 + LOBYTE(j) = 4; + reg_TM = 21; + reg_TS = 2; + next_gameplay_CGADSUB = 53; + return j; +} + +uint16 LayerBlendFunc_1C(uint16 j) { // 0x8880E8 + reg_TM = 21; + reg_TS = 2; + next_gameplay_CGADSUB = 85; + return j; +} + +uint16 LayerBlendFunc_18(uint16 j) { // 0x8880F5 + j = 2; + if ((reg_NMITIMEN & 0x30) == 0x30) { + next_gameplay_CGADSUB = 36; + reg_TS = 19; + reg_TM = 4; + } + return j; +} + +uint16 nullsub_11(uint16 j) { // 0x88810C + return j; +} + +uint16 LayerBlendFunc_26(uint16 j) { // 0x88810D + next_gameplay_CGADSUB = 119; + return j; +} + +uint16 LayerBlendFunc_28(uint16 j) { // 0x888112 + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = -77; + if ((fx_layer_blending_config_c & 0x8000u) == 0) { + reg_COLDATA[0] = 37; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + } + return j; +} + +uint16 LayerBlendFunc_2A(uint16 j) { // 0x88812A + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = -77; + if ((fx_layer_blending_config_c & 0x8000u) == 0) { + reg_COLDATA[0] = 38; + reg_COLDATA[1] = 66; + reg_COLDATA[2] = 0x80; + } + return j; +} + +uint16 LayerBlendFunc_2C(uint16 j) { // 0x888142 + next_gameplay_CGWSEL = 0; + return j; +} + +uint16 LayerBlendFunc_2E(uint16 j) { // 0x888145 + next_gameplay_CGADSUB = -77; + return j; +} + +uint16 LayerBlendFunc_32(uint16 j) { // 0x88814A + reg_TS = 68; + next_gameplay_CGADSUB = -78; + return j; +} + +uint16 LayerBlendFunc_34(uint16 j) { // 0x888153 + j = 6; + return j; +} + +uint16 LayerBlendFunc_24(uint16 j) { // 0x888156 + reg_W12SEL = 0; + reg_W34SEL = 2; + reg_WOBJSEL = 32; + reg_TM = 19; + reg_TS = 4; + reg_TMW = 19; + reg_TSW = 4; + next_gameplay_CGWSEL = 16; + next_gameplay_CGADSUB = 51; + return j; +} + +void HandleLayerBlendingXrayCanShowBlocks(void) { // 0x88817B + reg_W12SEL = -56; + reg_W34SEL = 8; + reg_WOBJSEL = 0x80; + reg_TM = 19; + reg_TS = 4; + reg_TMW = 3; + reg_TSW = 4; + next_gameplay_CGWSEL = 34; + next_gameplay_CGADSUB = next_gameplay_CGADSUB & 0x80 | 0x73; +} + +void HandleLayerBlendingXrayCantShowBlocks(void) { // 0x8881A4 + reg_W12SEL = 0; + reg_W34SEL = 8; + reg_WOBJSEL = 0x80; + reg_TM = 19; + reg_TS = 4; + reg_TMW = 3; + reg_TSW = 4; + next_gameplay_CGWSEL = 34; + next_gameplay_CGADSUB = next_gameplay_CGADSUB & 0x80 | 0x61; + if (room_ptr == (uint16)addr_kRoom_cefb) + reg_TM = 17; +} + +void HandleLayerBlendingXrayFirefleaRoom(void) { // 0x8881DB + reg_W12SEL = 0; + reg_W34SEL = 8; + reg_WOBJSEL = 0x80; + reg_TM = 19; + reg_TS = 0; + reg_TMW = 3; + reg_TSW = 4; + next_gameplay_CGWSEL = 32; + next_gameplay_CGADSUB = -77; +} +static Func_V *const kLayerBlendPowerBombFuncs[4] = { // 0x8881FE + LayerBlendPowerBombFunc_0, + LayerBlendPowerBombFunc_0, + LayerBlendPowerBombFunc_4, + LayerBlendPowerBombFunc_6, +}; +void HandleLayerBlendingPowerBomb(uint16 j) { + if (room_ptr == (uint16)addr_kRoom_a66a) + j = 6; + kLayerBlendPowerBombFuncs[j >> 1](); +} + +void LayerBlendPowerBombFunc_0(void) { // 0x888219 + reg_W12SEL = 0; + reg_W34SEL = 8; + reg_WOBJSEL = 0x80; + next_gameplay_CGWSEL = 2; + next_gameplay_CGADSUB = 55; + reg_TMW = 0; + reg_TSW = 4; + reg_TM = 19; + reg_TS = 4; +} + +void LayerBlendPowerBombFunc_4(void) { // 0x88823E + reg_W12SEL = 0x80; + reg_W34SEL = 8; + reg_WOBJSEL = 0x80; + next_gameplay_CGWSEL = 2; + next_gameplay_CGADSUB = 55; + reg_TMW = 0; + reg_TSW = 6; + reg_TM = 17; + reg_TS = 6; +} + +void LayerBlendPowerBombFunc_6(void) { // 0x888263 + reg_W12SEL = 0; + reg_W34SEL = 8; + reg_WOBJSEL = 0x80; + next_gameplay_CGWSEL = 2; + next_gameplay_CGADSUB = 49; + reg_TMW = 0; + reg_TSW = 4; + reg_TM = 19; + reg_TS = 4; +} + +void EnableHdmaObjects(void) { // 0x888288 + hdma_objects_enable_flag |= 0x8000u; +} + +void DisableHdmaObjects(void) { // 0x888293 + hdma_objects_enable_flag &= ~0x8000u; +} + +void WaitUntilEndOfVblankAndClearHdma(void) { // 0x88829E +// Patched away wait, it will wait until the very start of the next frame until it disabled hdma +// but we run the frames instantly so no need. + WriteReg(MDMAEN, 0); + WriteReg(HDMAEN, 0); + sub_8882AC(); +} + +void sub_8882AC(void) { // 0x8882AC + reg_HDMAEN = 0; + for (int i = 10; i >= 0; i -= 2) + hdma_object_channels_bitmask[i >> 1] = 0; +} + +void InitializeSpecialEffectsForNewRoom(void) { // 0x8882C1 + earthquake_sfx_index = 0; + earthquake_sfx_timer = 0; + if (room_ptr == (uint16)addr_kRoom_9804 + || room_ptr == (uint16)addr_kRoom_96ba + || room_ptr == (uint16)addr_kRoom_b32e + || room_ptr == (uint16)addr_kRoom_b457 + || room_ptr == (uint16)addr_kRoom_dd58 + || room_ptr == (uint16)addr_kRoom_dede) { + earthquake_sfx_timer = -1; + } + debug_disable_minimap = 0; + for (int i = 32; i != 0x80; i += 16) { + WriteReg((SnesRegs)(i + 17152), 0); + WriteReg((SnesRegs)(i + 17153), 0x13u); + WriteReg((SnesRegs)(i + 17154), 0); + WriteReg((SnesRegs)(i + 17155), 0); + WriteReg((SnesRegs)(i + 17156), 0); + WriteReg((SnesRegs)(i + 17157), 0); + WriteReg((SnesRegs)(i + 17158), 0); + WriteReg((SnesRegs)(i + 17160), 0); + WriteReg((SnesRegs)(i + 17161), 0); + } + fx_y_subpos = 0; + fx_y_pos = -1; + lava_acid_y_subpos = 0; + lava_acid_y_pos = -1; + hud_bg3_xpos = 0; + hud_bg3_ypos = 0; + bg3_xpos = 0; + bg3_ypos = 0; + irq_enable_mode7 = 0; + camera_distance_index = 0; + tourian_entrance_statue_animstate = 0; + tourian_entrance_statue_finished = 0; + earthquake_timer = 0; + phantom_related_layer_flag = 0; + power_bomb_explosion_status = 0; + power_bomb_flag = 0; + power_bomb_explosion_radius = 0; + fx_tilemap_ptr = 0; + fx_type = 0; + fx_base_y_subpos = 0x8000; + fx_base_y_pos = 0; + fx_target_y_pos = 0; + fx_y_vel = 0; + fx_liquid_options = 0; + fx_timer = 0; + tide_phase = 0; + fx_y_suboffset = 0; + fx_y_offset = 0; + fx_layer_blending_config_a = 2; + reg_BG3HOFS = 0; + reg_BG3VOFS = 0; + layer2_x_pos = 0; + layer2_y_pos = 0; + room_loading_irq_handler = 0; + *(VoidP *)((char *)&pause_hook.addr + 1) = -30720; + *(VoidP *)((char *)&unpause_hook.addr + 1) = -30720; + pause_hook.addr = FUNC16(PauseHook_Empty); + unpause_hook.addr = FUNC16(PauseHook_Empty); + WriteReg(WMADDL, 0xF0); + WriteReg(WMADDM, 0xFFu); + WriteReg(WMADDH, 1u); + reg_HDMAEN = 0; + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + reg_MOSAIC = 0; + reg_TM = 19; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + reg_BG12NBA = 0; + reg_BG34NBA = 4; + reg_BG2SC = 73; + reg_BG3SC = 90; + gameplay_BG3SC = 90; +} + +uint16 SpawnHdmaObjectInner(uint16 k, uint16 *p) { // 0x888477 + uint16 v4; + + int v2 = k >> 1; + hdma_object_pre_instructions[v2] = FUNC16(nullsub_293); + hdma_object_pre_instruction_bank[v2] = 136; + hdma_object_instruction_list_pointers[v2] = p[1]; + hdma_object_instruction_timers[v2] = 1; + hdma_object_timers[v2] = 0; + hdma_object_A[v2] = 0; + hdma_object_B[v2] = 0; + hdma_object_C[v2] = 0; + hdma_object_D[v2] = 0; + LOBYTE(v4) = HIBYTE(R18_); + HIBYTE(v4) = R18_; + hdma_object_channels_bitmask[v2] = v4; + hdma_object_bank_slot[v2] = R24_ | R20_; + WriteRegWord((SnesRegs)(R20_ + 17152), *p); + return k; +} + +uint16 SpawnHdmaObject(uint8 db, const void *p) { // 0x888435 + R24_ = db << 8; + R18_ = 1024; + R20_ = 32; + uint16 v3 = 0; + for (;;) { + if (!hdma_object_channels_bitmask[v3 >> 1]) + return SpawnHdmaObjectInner(v3, (uint16 *)p); + bool v4 = R18_ >> 15; + R18_ *= 2; + if (v4) + return -1; + R20_ += 16; + v3 += 2; + if (v3 == 12) + return -1; + } +} + +void SpawnHdmaObjectToSlot0xA(uint8 db, const void *p) { // 0x88840A + R18_ = 0x8000; + R20_ = 0x70; + R24_ = db << 8; + SpawnHdmaObjectInner(0xa, (uint16 *)p); +} + +void HdmaObjectHandler(void) { // 0x8884B9 + char v1; + + HandleMusicQueue(); + if (!time_is_frozen_flag && (power_bomb_explosion_status & 0x4000) != 0) { + power_bomb_explosion_status = 0x8000; + static const SpawnHdmaObject_Args unk_8884D5 = { 0x40, 0x28, 0x8ace }; + static const SpawnHdmaObject_Args unk_8884DD = { 0x40, 0x29, 0x8b80 }; + SpawnHdmaObject(0x88, &unk_8884D5); + SpawnHdmaObject(0x88, &unk_8884DD); + } + fx_layer_blending_config_c = fx_layer_blending_config_a; + if ((hdma_objects_enable_flag & 0x8000u) != 0) { + reg_HDMAEN = 0; + int i = 0; + do { + hdma_object_index = i; + v1 = *((uint8 *)hdma_object_channels_bitmask + i); + if (v1) { + reg_HDMAEN |= v1; + HdmaobjInstructionHandler(i); + i = hdma_object_index; + } + i += 2; + } while (i != 12); + LayerBlendingHandler(); + } +} + +void CallHdmaobjPreInstr(uint32 ea, uint16 k) { + switch (ea) { + case fnnullsub_56: return; + case fnnullsub_293: return; + case fnnullsub_309: return; + case fnHdmaobjPreInstr_XraySetup: HdmaobjPreInstr_XraySetup(k); return; + case fnHdmaobjPreInstr_Xray: HdmaobjPreInstr_Xray(k); return; + case fnHdmaobjPreInstr_XrayFunc0_NoBeam: HdmaobjPreInstr_XrayFunc0_NoBeam(k); return; + case fnHdmaobjPreInstr_XrayFunc1_BeamWidening: HdmaobjPreInstr_XrayFunc1_BeamWidening(k); return; + case fnHdmaobjPreInstr_XrayFunc2_FullBeam: HdmaobjPreInstr_XrayFunc2_FullBeam(k); return; + case fnHdmaobjPreInstr_XrayFunc3_DeactivateBeam: HdmaobjPreInstr_XrayFunc3_DeactivateBeam(k); return; + case fnHdmaobjPreInstr_XrayFunc4_DeactivateBeam: HdmaobjPreInstr_XrayFunc4_DeactivateBeam(k); return; + case fnHdmaobjPreInstr_XrayFunc5_DeactivateBeam: HdmaobjPreInstr_XrayFunc5_DeactivateBeam(k); return; + case fnHdmaobjPreInstr_PowerBombExplode_SetWindowConf: HdmaobjPreInstr_PowerBombExplode_SetWindowConf(k); return; + case fnHdmaobjPreInstr_PowerBombExplode_Stage5_Afterglow: HdmaobjPreInstr_PowerBombExplode_Stage5_Afterglow(k); return; + case fnHdmaobjPreInstr_PowerBombExplode_ExplosionYellow: HdmaobjPreInstr_PowerBombExplode_ExplosionYellow(k); return; + case fnHdmaobjPreInstr_PowerBombExplode_ExplosionWhite: HdmaobjPreInstr_PowerBombExplode_ExplosionWhite(k); return; + case fnHdmaobjPreInstr_PowerBombExplode_PreExplosionWhite: HdmaobjPreInstr_PowerBombExplode_PreExplosionWhite(k); return; + case fnHdmaobjPreInstr_PowerBombExplode_PreExplosionYellow: HdmaobjPreInstr_PowerBombExplode_PreExplosionYellow(k); return; + case fnHdmaobjPreInstr_CrystalFlash_CustomLayerBlend: HdmaobjPreInstr_CrystalFlash_CustomLayerBlend(k); return; + case fnHdmaobjPreInstr_CrystalFlash_Stage2_AfterGlow: HdmaobjPreInstr_CrystalFlash_Stage2_AfterGlow(k); return; + case fnHdmaobjPreInstr_CrystalFlash_Stage1_Explosion: HdmaobjPreInstr_CrystalFlash_Stage1_Explosion(k); return; + case fnHdmaobjPreInstr_FxType22_BG3Yscroll: HdmaobjPreInstr_FxType22_BG3Yscroll(k); return; + case fnHdmaobjPreInstr_BG3Xscroll: HdmaobjPreInstr_BG3Xscroll(k); return; + case fnHdmaobjPreInstr_SkyLandBG2Xscroll: HdmaobjPreInstr_SkyLandBG2Xscroll(k); return; + case fnHdmaobjPreInstr_SkyLandBG2Xscroll2: HdmaobjPreInstr_SkyLandBG2Xscroll2(k); return; + case fnHdmaobjPreInstr_SkyLandBG2XscrollInner: HdmaobjPreInstr_SkyLandBG2XscrollInner(k); return; + case fnHdmaobjPreInstr_FirefleaBG3XScroll: HdmaobjPreInstr_FirefleaBG3XScroll(k); return; + case fnHdmaobjPreInstr_LavaAcidBG3YScroll: HdmaobjPreInstr_LavaAcidBG3YScroll(k); return; + case fnHdmaobjPreInstr_LavaAcidBG2YScroll: HdmaobjPreInstr_LavaAcidBG2YScroll(k); return; + case fnHdmaobjPreInstr_WaterBG3XScroll: HdmaobjPreInstr_WaterBG3XScroll(k); return; + case fnHdmaobjPreInstr_WaterBG2XScroll: HdmaobjPreInstr_WaterBG2XScroll(k); return; + case fnHdmaobjPreInstr_WaterBG2XScroll_Func2: HdmaobjPreInstr_WaterBG2XScroll_Func2(k); return; + case fnHdmaobjPreInstr_WaterBG2XScroll_Func1: HdmaobjPreInstr_WaterBG2XScroll_Func1(k); return; + case fnHdmaobjPreInstr_RainBg3Scroll: HdmaobjPreInstr_RainBg3Scroll(k); return; + case fnHdmaobjPreInstr_SporesBG3Xscroll: HdmaobjPreInstr_SporesBG3Xscroll(k); return; + case fnHdmaobjPreInstr_FogBG3Scroll: HdmaobjPreInstr_FogBG3Scroll(k); return; + case fnHdmaobjPreInstr_CheckLotsOfEventsHappened: HdmaobjPreInstr_CheckLotsOfEventsHappened(k); return; + case fnHdmaobjPreInstr_DC23: HdmaobjPreInstr_DC23(k); return; + case fnHdmaobjPreInstr_DC69: HdmaobjPreInstr_DC69(k); return; + case fnHdmaobjPreInstr_DCBA: HdmaobjPreInstr_DCBA(k); return; + case fnHdmaobjPreInstr_BombTorizoHazeColorMathBgColor: HdmaobjPreInstr_BombTorizoHazeColorMathBgColor(k); return; + case fnHdmaobjPreInstr_HazeColorMathSubscreen_CeresRidleyAlive: HdmaobjPreInstr_HazeColorMathSubscreen_CeresRidleyAlive(k); return; + case fnHdmaobjPreInstr_HazeColorMathSubscreen_CeresRidleyDead: HdmaobjPreInstr_HazeColorMathSubscreen_CeresRidleyDead(k); return; + case fnHdmaobjPreInstr_HazeColorMathSubscreen_FadingIn: HdmaobjPreInstr_HazeColorMathSubscreen_FadingIn(k); return; + case fnHdmaobjPreInstr_HazeColorMathSubscreen_FadedIn: HdmaobjPreInstr_HazeColorMathSubscreen_FadedIn(k); return; + case fnHdmaobjPreInstr_HazeColorMathSubscreen_FadingOut: HdmaobjPreInstr_HazeColorMathSubscreen_FadingOut(k); return; + case fnHdmaobjPreInstr_DF94: HdmaobjPreInstr_DF94(k); return; + case fnHdmaobjPreInstr_VariaSuitPickup: HdmaobjPreInstr_VariaSuitPickup(k); return; + case fnHdmaobjPreInstr_GravitySuitPickup: HdmaobjPreInstr_GravitySuitPickup(k); return; + case fnHdmaobjPreInstr_E449: HdmaobjPreInstr_E449(k); return; + case fnHdmaobjPreInstr_E567: HdmaobjPreInstr_E567(k); return; + case fnHdmaobjPreInstr_E7BC: HdmaobjPreInstr_E7BC(k); return; + case fnHdmaobjPreInstr_E9E6: HdmaobjPreInstr_E9E6(k); return; + case fnHdmaobjPreInstr_EA3C: HdmaobjPreInstr_EA3C(k); return; + case fnHdmaobjPreInstr_EACB: HdmaobjPreInstr_EACB(k); return; + case fnHdmaobjPreInstr_Backdrop_TitleSequenceGradient: HdmaobjPreInstr_Backdrop_TitleSequenceGradient(k); return; + case fnHdmaobjPreInstr_ColorMathControlB_TitleGradient: HdmaobjPreInstr_ColorMathControlB_TitleGradient(k); return; + case fnHdmaobjPreInstr_IntroCutsceneCrossfade: HdmaobjPreInstr_IntroCutsceneCrossfade(k); return; + case fnnullsub_357: return; + case fnHdmaobjPreInstr_ECB6: HdmaobjPreInstr_ECB6(k); return; + default: Unreachable(); + } +} + +uint16 CallHdmaobjInstr(uint32 ea, uint8 db, uint16 k, uint16 j) { + switch (ea) { + case fnnullsub_112: return j; + case fnHdmaobjInstr_Delete: return HdmaobjInstr_Delete(k, j); + case fnHdmaobjInstr_SetPreInstr: return HdmaobjInstr_SetPreInstr(db, k, j); + case fnHdmaobjInstr_ClearPreInstr: return HdmaobjInstr_ClearPreInstr(k, j); + case fnHdmaobjInstr_CallFarFunc: return HdmaobjInstr_CallFarFunc(db, k, j); + case fnHdmaobjInstr_Goto: return HdmaobjInstr_Goto(db, k, j); + case fnHdmaobjInstr_GotoRel: return HdmaobjInstr_GotoRel(db, k, j); + case fnHdmaobjInstr_DecrementAndGoto: return HdmaobjInstr_DecrementAndGoto(db, k, j); + case fnHdmaobjInstr_DecrementAndGotoRel: return HdmaobjInstr_DecrementAndGotoRel(db, k, j); + case fnHdmaobjInstr_SetTimer: return HdmaobjInstr_SetTimer(db, k, j); + case fnHdmaobjInstr_SetHdmaControl: return HdmaobjInstr_SetHdmaControl(db, k, j); + case fnHdmaobjInstr_SetHdmaTarget: return HdmaobjInstr_SetHdmaTarget(db, k, j); + case fnHdmaobjInstr_SetHdmaTablePtr: return HdmaobjInstr_SetHdmaTablePtr(db, k, j); + case fnHdmaobjInstr_SetHdmaTableBank: return HdmaobjInstr_SetHdmaTableBank(db, k, j); + case fnHdmaobjInstr_SetIndirectHdmaDataBank: return HdmaobjInstr_SetIndirectHdmaDataBank(db, k, j); + case fnHdmaobjInstr_Skip: return HdmaobjInstr_Skip(k, j); + case fnHdmaobjInstr_Sleep: return HdmaobjInstr_Sleep(k, j); + case fnHdmaobjInstr_SetFlagB: return HdmaobjInstr_SetFlagB(k, j); + case fnHdmaobjInstr_SetFlagB_Copy: return HdmaobjInstr_SetFlagB_Copy(k, j); + case fnHdmaobjInstr_SetFlagB_Copy2: return HdmaobjInstr_SetFlagB_Copy2(k, j); + case fnHdmaobjInstr_SetFlagB_Copy3: return HdmaobjInstr_SetFlagB_Copy3(k, j); + case fnHdmaobjInstr_SetVideoMode1: return HdmaobjInstr_SetVideoMode1(k, j); + case fnHdmaobjInstr_1938_RandomNumber: return HdmaobjInstr_1938_RandomNumber(k, j); + case fnHdmaobjInstr_GotoIfEventHappened: return HdmaobjInstr_GotoIfEventHappened(k, j); + case fnHdmaobjInstr_E4BD: return HdmaobjInstr_E4BD(k, j); + case fnHdmaobjInstr_InitMorphBallEyeBeamHdma: return HdmaobjInstr_InitMorphBallEyeBeamHdma(k, j); + case fnHdmaobjInstr_EC9F_ClearVars: return HdmaobjInstr_EC9F_ClearVars(k, j); + case fnHdmaobjInstr_B3A9: return HdmaobjInstr_B3A9(k, j); + case fnHdmaobjInsr_ConfigTitleSequenceGradientHDMA: return HdmaobjInsr_ConfigTitleSequenceGradientHDMA(k, j); + case fnsub_88D916: sub_88D916(); return j; + default: return Unreachable(); + } +} + +void HdmaobjInstructionHandler(uint16 k) { // 0x88851C + int v1 = (uint8)k >> 1; + R18_ = hdma_object_pre_instructions[v1]; + R20_ = hdma_object_pre_instruction_bank[v1]; + CallHdmaobjPreInstr(Load24(&R18_), k); + LOBYTE(k) = hdma_object_index; + int v2 = (uint8)hdma_object_index >> 1; + if (hdma_object_instruction_timers[v2]-- == 1) { + uint8 v8 = *((uint8 *)hdma_object_bank_slot + (uint8)k + 1); + uint16 v4 = hdma_object_instruction_list_pointers[v2]; + uint16 v6; + while (1) { + uint16 *v5 = (uint16 *)RomPtrWithBank(v8, v4); + v6 = *v5; + if ((*v5 & 0x8000u) == 0) + break; + R18_ = *v5; + v4 = CallHdmaobjInstr(v6 | 0x880000, v8, k, v4 + 2); + if (!v4) + return; + } + int v7 = k >> 1; + hdma_object_instruction_timers[v7] = v6; + hdma_object_instruction_list_pointers[v7] = v4 + 4; + hdma_object_table_pointers[v7] = *((uint16 *)RomPtrWithBank(v8, v4) + 1); + } +} + +uint16 HdmaobjInstr_Delete(uint16 k, uint16 j) { // 0x888569 + hdma_object_channels_bitmask[k >> 1] = 0; + return 0; +} + +uint16 HdmaobjInstr_SetPreInstr(uint8 db, uint16 k, uint16 j) { // 0x888570 + uint8 *v2 = RomPtrWithBank(db, j); + hdma_object_pre_instructions[k >> 1] = *(uint16 *)v2; + *((uint8 *)hdma_object_pre_instruction_bank + k) = v2[2]; + return j + 3; +} + +uint16 HdmaobjInstr_ClearPreInstr(uint16 k, uint16 j) { // 0x888584 + hdma_object_pre_instructions[k >> 1] = addr_locret_88858A; + return j; +} + +void CallHdmaobjInstrFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnHdmaobj_PreExplodeWhite: Hdmaobj_PreExplodeWhite(); return; + case fnHdmaobj_PreExplodeYellow: Hdmaobj_PreExplodeYellow(); return; + case fnHdmaobj_ExplodeYellow: Hdmaobj_ExplodeYellow(); return; + case fnHdmaobj_ExplodeWhite: Hdmaobj_ExplodeWhite(); return; + case fnHdmaobj_CleanUpTryCrystalFlash: Hdmaobj_CleanUpTryCrystalFlash(k); return; + case fnCrystalFlashSetupPart1: CrystalFlashSetupPart1(); return; + case fnCrystalFlashSetupPart2: CrystalFlashSetupPart2(); return; + case fnCrystalFlashCleanup: CrystalFlashCleanup(k); return; + case fnnullsub_113: return; + case fnnullsub_114: return; + case fnnullsub_357: return; + case fnInitializeRainbowBeam: InitializeRainbowBeam(); return; + case fnXray_SetupStage1_FreezeTimeBackup: Xray_SetupStage1_FreezeTimeBackup(k); return; + case fnXray_SetupStage2_ReadBg1_2ndScreen: Xray_SetupStage2_ReadBg1_2ndScreen(); return; + case fnXray_SetupStage3_ReadBg1_1stScreen: Xray_SetupStage3_ReadBg1_1stScreen(); return; + case fnXray_SetupStage4: Xray_SetupStage4(); return; + case fnXray_SetupStage5: Xray_SetupStage5(); return; + case fnXray_SetupStage6: Xray_SetupStage6(); return; + case fnXray_SetupStage7: Xray_SetupStage7(); return; + case fnXray_SetupStage8_SetBackdropColor: Xray_SetupStage8_SetBackdropColor(); return; + case fnInitializeSuitPickupHdma: InitializeSuitPickupHdma(); return; + default: Unreachable(); + } +} + +uint16 HdmaobjInstr_CallFarFunc(uint8 db, uint16 k, uint16 j) { // 0x8885B4 + uint8 *v2 = RomPtrWithBank(db, j); + copy24((LongPtr *)&R18_, (LongPtr *)v2); + CallHdmaobjInstrFunc(Load24(&R18_), k); + return j + 3; +} + +uint16 HdmaobjInstr_Goto(uint8 db, uint16 k, uint16 j) { // 0x8885EC + return *(uint16 *)RomPtrWithBank(db, j); +} + +uint16 HdmaobjInstr_GotoRel(uint8 db, uint16 k, uint16 j) { // 0x8885F1 + int16 v2; + + R18_ = j; + LOBYTE(v2) = HIBYTE(*(uint16 *)RomPtrWithBank(db, j - 1)); + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + else + v2 = (uint8)v2; + return R18_ + v2; +} + +uint16 HdmaobjInstr_DecrementAndGoto(uint8 db, uint16 k, uint16 j) { // 0x888607 + int v2 = k >> 1; + if (hdma_object_timers[v2]-- == 1) + return j + 2; + else + return HdmaobjInstr_Goto(db, k, j); +} + +uint16 HdmaobjInstr_DecrementAndGotoRel(uint8 db, uint16 k, uint16 j) { // 0x88860F + int v2 = k >> 1; + if (hdma_object_timers[v2]-- == 1) + return j + 1; + else + return HdmaobjInstr_GotoRel(db, k, j); +} + +uint16 HdmaobjInstr_SetTimer(uint8 db, uint16 k, uint16 j) { // 0x888616 + *((uint8 *)hdma_object_timers + k) = *RomPtrWithBank(db, j); + return j + 1; +} + +uint16 HdmaobjInstr_SetHdmaControl(uint8 db, uint16 k, uint16 j) { // 0x888622 + uint8 *v2 = RomPtrWithBank(db, j); + WriteReg((SnesRegs)(LOBYTE(hdma_object_bank_slot[k >> 1]) + DMAP0), *v2); + return j + 1; +} + +uint16 HdmaobjInstr_SetHdmaTarget(uint8 db, uint16 k, uint16 j) { // 0x888637 + uint8 *v2 = RomPtrWithBank(db, j); + WriteReg((SnesRegs)(LOBYTE(hdma_object_bank_slot[k >> 1]) + BBAD0), *v2); + return j + 1; +} + +uint16 HdmaobjInstr_SetHdmaTablePtr(uint8 db, uint16 k, uint16 j) { // 0x88864C + hdma_object_table_pointers[k >> 1] = *(uint16 *)RomPtrWithBank(db, j); + return j + 2; +} + +uint16 HdmaobjInstr_SetHdmaTableBank(uint8 db, uint16 k, uint16 j) { // 0x888655 + uint8 *v2 = RomPtrWithBank(db, j); + WriteReg((SnesRegs)(LOBYTE(hdma_object_bank_slot[k >> 1]) + A1B0), *v2); + return j + 1; +} + +uint16 HdmaobjInstr_SetIndirectHdmaDataBank(uint8 db, uint16 k, uint16 j) { // 0x88866A + uint8 *v2 = RomPtrWithBank(db, j); + WriteReg((SnesRegs)(LOBYTE(hdma_object_bank_slot[k >> 1]) + DAS00), *v2); + return j + 1; +} + +uint16 HdmaobjInstr_Skip(uint16 k, uint16 j) { // 0x88867F + return j + 2; +} + +uint16 HdmaobjInstr_Sleep(uint16 k, uint16 j) { // 0x888682 + hdma_object_instruction_list_pointers[k >> 1] = j - 2; + return 0; +} + +uint8 RaiseOrLowerFx(void) { // 0x88868C + if ((fx_target_y_pos & 0x8000u) != 0) + return 1; + R22_ = 0; + R24_ = 0; + if ((fx_y_vel & 0x8000u) == 0) { + *(uint16 *)((char *)&R22_ + 1) = fx_y_vel; + uint16 v2 = (__PAIR32__(R24_, R22_) + __PAIR32__(fx_base_y_pos, fx_base_y_subpos)) >> 16; + fx_base_y_subpos += R22_; + if ((v2 & 0x8000u) != 0) + v2 = -1; + fx_base_y_pos = v2; + if (fx_target_y_pos >= v2) { + return 0; + } else { + fx_base_y_pos = fx_target_y_pos; + fx_base_y_subpos = 0; + return 1; + } + } else { + --R24_; + *(uint16 *)((char *)&R22_ + 1) = fx_y_vel; + uint16 v0 = (__PAIR32__(R24_, R22_) + __PAIR32__(fx_base_y_pos, fx_base_y_subpos)) >> 16; + fx_base_y_subpos += R22_; + if ((v0 & 0x8000u) != 0) + v0 = 0; + fx_base_y_pos = v0; + if (fx_target_y_pos >= v0) { + fx_base_y_pos = fx_target_y_pos; + fx_base_y_subpos = 0; + } + return fx_target_y_pos >= v0; + } +} + +static Func_X_V *const kHdmaobjPreInstr_XrayFuncs[6] = { // 0x8886EF + HdmaobjPreInstr_XrayFunc0_NoBeam, + HdmaobjPreInstr_XrayFunc1_BeamWidening, + HdmaobjPreInstr_XrayFunc2_FullBeam, + HdmaobjPreInstr_XrayFunc3_DeactivateBeam, + HdmaobjPreInstr_XrayFunc4_DeactivateBeam, + HdmaobjPreInstr_XrayFunc5_DeactivateBeam, +}; + +void HdmaobjPreInstr_Xray(uint16 k) { + int16 v1; + + v1 = 4096; + if (fx_type != 36) { + v1 = 0x2000; + if ((CanXrayShowBlocks() & 2) == 0) { + v1 = 0x4000; + *(uint16 *)®_COLDATA[0] = 0x27; + *(uint16 *)®_COLDATA[1] = 0x47; + *(uint16 *)®_COLDATA[2] = 0x87; + } + } + fx_layer_blending_config_c |= v1; + kHdmaobjPreInstr_XrayFuncs[demo_input_pre_instr](2 * demo_input_pre_instr); +} + +void HdmaobjPreInstr_XrayFunc0_NoBeam(uint16 k) { // 0x888732 + if ((button_config_run_b & joypad1_lastkeys) != 0) { + CalculateXrayHdmaTable(); + ++demo_input_pre_instr; + } else { + demo_input_pre_instr = 3; + } +} + +void HdmaobjPreInstr_XrayFunc1_BeamWidening(uint16 k) { // 0x888754 + uint32 v1; // kr00_4 + + if ((button_config_run_b & joypad1_lastkeys) != 0) { + v1 = __PAIR32__(demo_input_instr_timer, demo_input_instr_ptr) + 2048; + demo_input_instr_timer = v1 >> 16; + demo_input_instr_ptr = v1; + + bool v2 = __CFADD__uint16((uint16)v1, demo_input_new); + demo_input_new += v1; + demo_input += demo_input_instr_timer + v2; + if (!sign16(demo_input - 11)) { + demo_input_new = 0; + demo_input = 10; + ++demo_input_pre_instr; + } + CalculateXrayHdmaTable(); + } else { + demo_input_pre_instr = 3; + } +} + +void HdmaobjPreInstr_XrayFunc2_FullBeam(uint16 k) { // 0x8887AB + if ((button_config_run_b & joypad1_lastkeys) != 0) { + HandleMovingXrayUpDown(); + CalculateXrayHdmaTable(); + } else { + ++demo_input_pre_instr; + } +} + +void HandleMovingXrayUpDown(void) { // 0x8887C5 + if ((button_config_up & joypad1_lastkeys) != 0) { + MoveXrayUp(); + } else if ((button_config_down & joypad1_lastkeys) != 0) { + MoveXrayDown(); + } +} + +void MoveXrayUp(void) { // 0x8887E0 + bool v0; // cf + int16 v1; + + if (sign16(xray_angle - 128)) { + if (xray_angle != demo_input) { + if ((int16)(xray_angle - demo_input) < 0 + || (v0 = xray_angle != 0, --xray_angle, (int16)(xray_angle - (!v0 + demo_input)) < 0)) { + xray_angle = demo_input; + } + } + } else if (demo_input + xray_angle != 256) { + if ((int16)(demo_input + xray_angle - 256) >= 0 + || (v1 = (__PAIR32__(demo_input, xray_angle) + __PAIR32__(xray_angle, 1)) >> 16, ++xray_angle, v1 != 256) + && (int16)(v1 - 256) >= 0) { + xray_angle = 256 - demo_input; + } + } +} + +void MoveXrayDown(void) { // 0x888835 + int16 v0; + bool v1; // cf + + if (sign16(xray_angle - 128)) { + if (demo_input + xray_angle != 128) { + if ((int16)(demo_input + xray_angle - 128) >= 0 + || (v0 = (__PAIR32__(demo_input, xray_angle) + __PAIR32__(xray_angle, 1)) >> 16, ++xray_angle, v0 != 128) + && (int16)(v0 - 128) >= 0) { + xray_angle = 128 - demo_input; + } + } + } else if (xray_angle - demo_input != 128) { + if ((int16)(xray_angle - demo_input - 128) < 0 + || (v1 = xray_angle != 0, --xray_angle, xray_angle - (!v1 + demo_input) != 128) + && (int16)(xray_angle - (!v1 + demo_input) - 128) < 0) { + xray_angle = demo_input + 128; + } + } +} + +void CalculateXrayHdmaTable(void) { // 0x888896 + int16 v0; + mov24(&R0_, 0x7e9800); + R18_ = xray_angle; + R20_ = demo_input; + if (samus_pose_x_dir == 4) + v0 = (__PAIR32__(samus_x_pos - layer1_x_pos, samus_x_pos) - (layer1_x_pos | 0x30000)) >> 16; + else + v0 = samus_x_pos - layer1_x_pos + 3; + uint16 v1; + if (samus_movement_type == 5) + v1 = (__PAIR32__(samus_y_pos - layer1_y_pos, samus_y_pos) - (layer1_y_pos | 0xC0000)) >> 16; + else + v1 = (__PAIR32__(samus_y_pos - layer1_y_pos, samus_y_pos) - (layer1_y_pos | 0x100000)) >> 16; + if (v0 < 0) { + if (samus_pose_x_dir != 4) { +LABEL_14: + CalculateXrayHdmaTable_OriginOffScreen(v0, v1); + return; + } + } else { + if ((int16)(v0 - 256) < 0) { + CalculateXrayHdmaTable_OriginOnScreen(v0, v1); + return; + } + if (samus_pose_x_dir != 8) + goto LABEL_14; + } + for (int i = 510; i >= 0; i -= 2) + hdma_table_1[i >> 1] = 255; +} + +void HdmaobjPreInstr_XrayFunc3_DeactivateBeam(uint16 k) { // 0x888934 + int16 v1; + VramWriteEntry *v4; + + mov24((LongPtr *)&demo_enable, 0x980001); + *(uint16 *)((char *)&demo_num_input_frames + 1) = 0; + demo_input_prev = 0; + demo_input_prev_new = 0; + demo_backup_prev_controller_input = 0; + hdma_table_1[0] = 255; + v1 = 4096; + if (fx_type != 36) { + v1 = 0x2000; + if ((CanXrayShowBlocks() & 2) == 0) + v1 = 0x4000; + } + fx_layer_blending_config_c |= v1; + palette_buffer[0] = 0; + int v2 = hdma_object_index >> 1; + reg_BG2HOFS = hdma_object_A[v2]; + reg_BG2VOFS = hdma_object_B[v2]; + reg_BG2SC = *((uint8 *)hdma_object_C + hdma_object_index); + uint16 v3 = vram_write_queue_tail; + if ((int16)(vram_write_queue_tail - 240) < 0) { + v4 = gVramWriteEntry(vram_write_queue_tail); + v4->size = 2048; + v4->src.addr = ADDR16_OF_RAM(ram4000) + 4096; + *(uint16 *)&v4->src.bank = 126; + v4->vram_dst = (reg_BG2SC & 0xFC) << 8; + vram_write_queue_tail = v3 + 7; + ++demo_input_pre_instr; + } +} + +void HdmaobjPreInstr_XrayFunc4_DeactivateBeam(uint16 k) { // 0x8889BA + int16 v1; + VramWriteEntry *v3; + + v1 = 4096; + if (fx_type != 36) { + v1 = 0x2000; + if ((CanXrayShowBlocks() & 2) == 0) + v1 = 0x4000; + } + fx_layer_blending_config_c |= v1; + uint16 v2 = vram_write_queue_tail; + if ((int16)(vram_write_queue_tail - 240) < 0) { + v3 = gVramWriteEntry(vram_write_queue_tail); + v3->size = 2048; + v3->src.addr = ADDR16_OF_RAM(ram4000) + 6144; + *(uint16 *)&v3->src.bank = 126; + v3->vram_dst = ((reg_BG2SC & 0xFC) << 8) + 1024; + vram_write_queue_tail = v2 + 7; + ++demo_input_pre_instr; + } +} + +void HdmaobjPreInstr_XrayFunc5_DeactivateBeam(uint16 k) { // 0x888A08 + int16 v1; + v1 = 4096; + if (fx_type != 36) { + v1 = 0x2000; + if ((CanXrayShowBlocks() & 2) == 0) + v1 = 0x4000; + } + fx_layer_blending_config_c |= v1; + if (time_is_frozen_flag) { + time_is_frozen_flag = 0; + demo_input_pre_instr = 0; + demo_input_instr_timer = 0; + demo_input_instr_ptr = 0; + xray_angle = 0; + demo_input = 0; + demo_input_new = 0; + mov24((LongPtr *)&demo_enable, 0x980001); + *(uint16 *)((char *)&demo_num_input_frames + 1) = 0; + demo_input_prev = 0; + demo_input_prev_new = 0; + demo_backup_prev_controller_input = 0; + ResponsibleForXrayStandupGlitch(); + hdma_object_channels_bitmask[hdma_object_index >> 1] = 0; + QueueSfx1_Max6(0xAu); + if ((uint8)fx_type != 36) { + reg_COLDATA[2] = 0x80; + reg_COLDATA[1] = 64; + reg_COLDATA[0] = 32; + } + R0_.bank = 126; + R0_.addr = ADDR16_OF_RAM(*hdma_table_1); + for (int i = 510; i >= 0; i -= 2) + IndirWriteWord(&R0_, i, 0xFFu); + if (samus_auto_cancel_hud_item_index) { + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + } + } +} + +void SpawnPowerBombExplosion(void) { // 0x888AA4 + if (time_is_frozen_flag) { + power_bomb_explosion_status = 0x4000; + } else { + QueueSfx1_Max15(1u); + power_bomb_explosion_status = 0x8000; + + static const SpawnHdmaObject_Args unk_888ABA = { 0x40, 0x28, 0x8ace }; + static const SpawnHdmaObject_Args unk_888AC2 = { 0x40, 0x29, 0x8b80 }; + SpawnHdmaObject(0x88, &unk_888ABA); + SpawnHdmaObject(0x88, &unk_888AC2); + } +} + +static const uint16 kPowerBombPreExplosionRadiusSpeed = 0x3000; +static const uint16 kPowerBombPreExplosionRadiusAccel = 0x80; +static const uint16 g_word_888B96 = 3; +static const uint16 kPowerBombExplosionRadiusSpeed = 0; +static const uint16 kPowerBombExplosionRadiusAccel = 0x30; + +void Hdmaobj_PreExplodeWhite(void) { // 0x888B14 + offscreen_power_bomb_left_hdma = -1; + offscreen_power_bomb_right_hdma = 0; + power_bomb_pre_explosion_flash_radius = 1024; + power_bomb_pre_explosion_radius_speed = kPowerBombPreExplosionRadiusSpeed; +} + +void Hdmaobj_PreExplodeYellow(void) { // 0x888B32 + pre_scaled_power_bomb_explosion_shape_def_ptr = addr_byte_889F06; +} + +void Hdmaobj_ExplodeYellow(void) { // 0x888B39 + power_bomb_explosion_radius = 1024; + power_bomb_pre_explosion_radius_speed = kPowerBombExplosionRadiusSpeed; +} + +void Hdmaobj_ExplodeWhite(void) { // 0x888B47 + pre_scaled_power_bomb_explosion_shape_def_ptr = addr_kPowerBombExplosionShapeDef0; +} + +void Hdmaobj_CleanUpTryCrystalFlash(uint16 v0) { // 0x888B4E + if (samus_x_pos != power_bomb_explosion_x_pos + || samus_y_pos != power_bomb_explosion_y_pos + || Hdmaobj_CrystalFlash() & 1) { + power_bomb_flag = 0; + } + power_bomb_explosion_status = 0; + int v1 = v0 >> 1; + hdma_object_channels_bitmask[v1] = 0; + hdma_object_channels_bitmask[v1 + 1] = 0; + power_bomb_pre_explosion_flash_radius = 0; + power_bomb_explosion_radius = 0; + CallSomeSamusCode(0x1Eu); +} + +void HdmaobjPreInstr_PowerBombExplode_SetWindowConf(uint16 k) { // 0x888B8F + fx_layer_blending_config_c |= 0x8000u; +} + +void HdmaobjPreInstr_PowerBombExplode_Stage5_Afterglow(uint16 k) { // 0x888B98 + if ((power_bomb_explosion_status & 0x8000u) != 0) { + int v1 = (uint8)k >> 1; + if ((--hdma_object_timers[v1] & 0x8000u) != 0) { + if ((*((uint8 *)hdma_object_D + (uint8)k))-- == 1) { + hdma_object_instruction_timers[v1] = 1; + ++hdma_object_instruction_list_pointers[v1]; + ++hdma_object_instruction_list_pointers[v1]; + } else { + if ((reg_COLDATA[0] & 0x1F) != 0) + reg_COLDATA[0] = ((reg_COLDATA[0] & 0x1F) - 1) | 0x20; + if ((reg_COLDATA[1] & 0x1F) != 0) + reg_COLDATA[1] = ((reg_COLDATA[1] & 0x1F) - 1) | 0x40; + if ((reg_COLDATA[2] & 0x1F) != 0) + reg_COLDATA[2] = ((reg_COLDATA[2] & 0x1F) - 1) | 0x80; + *((uint8 *)hdma_object_timers + (uint8)k) = g_word_888B96; + } + } + } +} + +void CalculatePowerBombHdma_LeftOfScreen(uint16 k, uint16 j) { // 0x888BEA + do { + uint8 *v2 = RomPtr_88(j); + if (__CFADD__uint8(*v2, (uint8)power_bomb_explosion_x_pos_plus_0x100)) { + power_bomb_explosion_right_hdma[k] = *v2 + power_bomb_explosion_x_pos_plus_0x100; + power_bomb_explosion_left_hdma[k] = 0; + } else { + power_bomb_explosion_right_hdma[k] = 0; + power_bomb_explosion_left_hdma[k] = 1; + } + ++j; + ++k; + } while (k != 192); +} + +void CalculatePowerBombHdma_OnScreen(uint16 k, uint16 j) { // 0x888C12 + do { + uint8 *v2 = RomPtr_88(j); + uint8 v3 = *v2; + if (!*v2) + break; + bool v4 = __CFADD__uint8((uint8)power_bomb_explosion_x_pos_plus_0x100, v3); + uint8 v5 = power_bomb_explosion_x_pos_plus_0x100 + v3; + if (v4) + v5 = -1; + power_bomb_explosion_right_hdma[k] = v5; + uint8 v6 = power_bomb_explosion_x_pos_plus_0x100 - *v2; + if ((uint8)power_bomb_explosion_x_pos_plus_0x100 < *v2) + v6 = 0; + power_bomb_explosion_left_hdma[k] = v6; + ++j; + ++k; + } while (k != 192); +} + +void CalculatePowerBombHdma_RightOfScreen(uint16 k, uint16 j) { // 0x888C3A + do { + uint8 *v2 = RomPtr_88(j); + if ((uint8)power_bomb_explosion_x_pos_plus_0x100 < *v2) { + power_bomb_explosion_left_hdma[k] = power_bomb_explosion_x_pos_plus_0x100 - *v2; + power_bomb_explosion_right_hdma[k] = -1; + } else { + power_bomb_explosion_left_hdma[k] = -1; + power_bomb_explosion_right_hdma[k] = -2; + } + ++j; + ++k; + } while (k != 192); +} + +void CalculatePowerBombHdmaObjectTablePtrs(uint16 k) { // 0x888C62 + uint16 v1; + if ((power_bomb_explosion_status & 0x8000u) != 0) { + if ((uint16)(power_bomb_explosion_x_pos - layer1_x_pos + 256) >= 0x300u + || (power_bomb_explosion_x_pos_plus_0x100 = power_bomb_explosion_x_pos - layer1_x_pos + 256, + v1 = power_bomb_explosion_y_pos - layer1_y_pos + 256, + v1 >= 0x300u)) { + v1 = 0; + } + power_bomb_explosion_y_pos_rsub_0x1ff = (v1 ^ 0x3FF) - 256; + if ((power_bomb_explosion_radius & 0xFF00) == 0) + power_bomb_explosion_y_pos_rsub_0x1ff = 0; + int v2 = k >> 1; + R22_ = 3 * power_bomb_explosion_y_pos_rsub_0x1ff; + hdma_object_table_pointers[v2] = 3 * power_bomb_explosion_y_pos_rsub_0x1ff + addr_kIndirectHdmaTable_PowerBombExplodeLeft; + hdma_object_table_pointers[v2 + 1] = R22_ + addr_kIndirectHdmaTable_PowerBombExplodeRight; + } +} + +#define g_byte_88A206 ((uint8*)RomPtr(0x88a206)) + +static uint16 k_out; + +uint16 CalculatePowerBombHdmaScaled_LeftOfScreen(uint16 k, uint16 j, uint8 multval) { // 0x888CC6 + char v2; + uint8 v6, v7; + do { + LOBYTE(R20_) = Mult8x8(multval, g_byte_88A206[(uint8)j + 32]) >> 8; + v2 = power_bomb_explosion_x_pos_plus_0x100; + uint8 Reg = Mult8x8(multval, g_byte_88A206[(uint8)j]) >> 8; + bool v4 = __CFADD__uint8(Reg, v2); + uint8 v5 = Reg + v2; + if (v4) { + v6 = v5; + v7 = 0; + } else { + v6 = 0; + v7 = -1; + } + while (1) { + power_bomb_explosion_left_hdma[(uint8)k] = v7; + power_bomb_explosion_right_hdma[(uint8)k] = v6; + if ((uint8)k == (uint8)R20_) + break; + LOBYTE(k) = k - 1; + } + LOBYTE(j) = j + 1; + } while ((j & 0x80) == 0); + k_out = LOBYTE(k); + return v6 << 8 | v7; +} + +uint16 CalculatePowerBombHdmaScaled_OnScreen(uint16 k, uint16 j, uint8 multval) { // 0x888D04 + char v2; + char v5; + uint8 v6, v9; + do { + LOBYTE(R20_) = Mult8x8(multval, g_byte_88A206[(uint8)j + 32]) >> 8; + v2 = power_bomb_explosion_x_pos_plus_0x100; + uint8 Reg = Mult8x8(multval, g_byte_88A206[(uint8)j]) >> 8; + bool v4 = __CFADD__uint8(Reg, v2); + v5 = Reg + v2; + if (v4) + v5 = -1; + v6 = v5; + uint8 v7 = power_bomb_explosion_x_pos_plus_0x100; + uint8 v8 = Reg; + v4 = v7 < v8; + v9 = v7 - v8; + if (v4) + v9 = 0; + while (1) { + power_bomb_explosion_left_hdma[(uint8)k] = v9; + power_bomb_explosion_right_hdma[(uint8)k] = v6; + if ((uint8)k == (uint8)R20_) + break; + LOBYTE(k) = k - 1; + } + LOBYTE(j) = j + 1; + } while ((j & 0x80) == 0); + k_out = LOBYTE(k); + return v6 << 8 | v9; +} + +uint16 CalculatePowerBombHdmaScaled_RightOfScreen(uint16 k, uint16 j, uint8 multval) { // 0x888D46 + char v5; + char v6; // ah + char v7; + char v10; // t2 + uint8 v8, v9; + do { + LOBYTE(R20_) = Mult8x8(multval, g_byte_88A206[(uint8)j + 32]) >> 8; + uint8 v2 = power_bomb_explosion_x_pos_plus_0x100; + uint8 Reg = Mult8x8(multval, g_byte_88A206[(uint8)j]) >> 8; + bool v4 = v2 < Reg; + v5 = v2 - Reg; + if (v4) { + v6 = v5; + v7 = -1; + } else { + v6 = -1; + v7 = 0; + } + v10 = v7; + v8 = v6; + v9 = v10; + while (1) { + power_bomb_explosion_left_hdma[(uint8)k] = v8; + power_bomb_explosion_right_hdma[(uint8)k] = v9; + if ((uint8)k == (uint8)R20_) + break; + LOBYTE(k) = k - 1; + } + LOBYTE(j) = j + 1; + } while ((j & 0x80) == 0); + k_out = LOBYTE(k); + return v9 << 8 | v8; +} +#define g_byte_88A286 ((uint8*)RomPtr(0x88a286)) +#define kPowerBombExplosionColors ((uint8*)RomPtr(0x888d85)) + +void HdmaobjPreInstr_PowerBombExplode_ExplosionYellow(uint16 k) { // 0x888DE9 + int16 v2; + + if ((power_bomb_explosion_status & 0x8000u) == 0) + return; + + uint16 v8 = k; + CalculatePowerBombHdmaObjectTablePtrs(k); + uint16 v1 = 96; + LOBYTE(R18_) = Mult8x8(HIBYTE(power_bomb_explosion_radius), g_byte_88A286[0]) >> 8; + k = LOBYTE(R18_); + + if (HIBYTE(power_bomb_explosion_x_pos_plus_0x100)) { + if (HIBYTE(power_bomb_explosion_x_pos_plus_0x100) == 1) + v2 = CalculatePowerBombHdmaScaled_OnScreen(k, v1, HIBYTE(power_bomb_explosion_radius)); + else + v2 = CalculatePowerBombHdmaScaled_RightOfScreen(k, v1, HIBYTE(power_bomb_explosion_radius)); + } else { + v2 = CalculatePowerBombHdmaScaled_LeftOfScreen(k, v1, HIBYTE(power_bomb_explosion_radius)); + } + k = k_out; + do { + power_bomb_explosion_left_hdma[(uint8)k] = v2; + power_bomb_explosion_right_hdma[(uint8)k] = HIBYTE(v2); + LOBYTE(k) = k - 1; + } while ((k & 0x80) == 0); + uint8 v3 = R18_ + 1; + if ((uint8)R18_ != 0xBF) { + uint8 v4 = -1; + do { + power_bomb_explosion_left_hdma[v3] = v4; + uint8 v5 = v4 + 1; + power_bomb_explosion_right_hdma[v3] = v5; + v4 = v5 - 1; + ++v3; + } while (v3 != 0xC0); + } + LOBYTE(R18_) = HIBYTE(power_bomb_explosion_radius) >> 3; + uint8 v6 = 3 * (HIBYTE(power_bomb_explosion_radius) >> 3); + reg_COLDATA[0] = kPowerBombExplosionColors[v6] | 0x20; + reg_COLDATA[1] = kPowerBombExplosionColors[v6 + 1] | 0x40; + reg_COLDATA[2] = kPowerBombExplosionColors[v6 + 2] | 0x80; + power_bomb_explosion_radius += power_bomb_pre_explosion_radius_speed; + if (power_bomb_explosion_radius < 0x8600u) { + power_bomb_pre_explosion_radius_speed += kPowerBombExplosionRadiusAccel; + } else { + int v7 = v8 >> 1; + hdma_object_instruction_timers[v7] = 1; + ++hdma_object_instruction_list_pointers[v7]; + ++hdma_object_instruction_list_pointers[v7]; + hdma_object_timers[v7] = 0; + } +} + +void HdmaobjPreInstr_PowerBombExplode_ExplosionWhite(uint16 k) { // 0x888EB2 + if ((power_bomb_explosion_status & 0x8000u) == 0) + return; + + CalculatePowerBombHdmaObjectTablePtrs(k); + uint16 v1 = pre_scaled_power_bomb_explosion_shape_def_ptr; + if (HIBYTE(power_bomb_explosion_x_pos_plus_0x100)) { + if (HIBYTE(power_bomb_explosion_x_pos_plus_0x100) == 1) + CalculatePowerBombHdma_OnScreen(0, v1); + else + CalculatePowerBombHdma_RightOfScreen(0, v1); + } else { + CalculatePowerBombHdma_LeftOfScreen(0, v1); + } + LOBYTE(R18_) = HIBYTE(power_bomb_explosion_radius) >> 3; + uint8 v2 = 3 * (HIBYTE(power_bomb_explosion_radius) >> 3); + reg_COLDATA[0] = kPowerBombExplosionColors[v2] | 0x20; + reg_COLDATA[1] = kPowerBombExplosionColors[v2 + 1] | 0x40; + reg_COLDATA[2] = kPowerBombExplosionColors[v2 + 2] | 0x80; + pre_scaled_power_bomb_explosion_shape_def_ptr += 192; + if (pre_scaled_power_bomb_explosion_shape_def_ptr == addr_byte_889F06) { + int v3 = k >> 1; + hdma_object_instruction_timers[v3] = 1; + ++hdma_object_instruction_list_pointers[v3]; + ++hdma_object_instruction_list_pointers[v3]; + hdma_object_timers[v3] = 0; + hdma_object_D[v3] = 32; + } + if (!__CFADD__uint16(power_bomb_pre_explosion_radius_speed, power_bomb_explosion_radius)) { + power_bomb_explosion_radius += power_bomb_pre_explosion_radius_speed; + power_bomb_pre_explosion_radius_speed += kPowerBombExplosionRadiusAccel; + } +} + +void CalculatePowerBombHdmaTablePointers(uint16 v0) { // 0x888F56 + uint16 v1; + if ((power_bomb_explosion_status & 0x8000u) != 0) { + if ((uint16)(power_bomb_explosion_x_pos - layer1_x_pos + 256) >= 0x300u + || (power_bomb_explosion_x_pos_plus_0x100 = power_bomb_explosion_x_pos - layer1_x_pos + 256, + v1 = power_bomb_explosion_y_pos - layer1_y_pos + 256, + v1 >= 0x300u)) { + v1 = 0; + } + power_bomb_explosion_y_pos_rsub_0x1ff = (v1 ^ 0x3FF) - 256; + if ((power_bomb_pre_explosion_flash_radius & 0xFF00) == 0) + power_bomb_explosion_y_pos_rsub_0x1ff = 0; + int v2 = v0 >> 1; + R22_ = 3 * power_bomb_explosion_y_pos_rsub_0x1ff; + hdma_object_table_pointers[v2] = 3 * power_bomb_explosion_y_pos_rsub_0x1ff + addr_kIndirectHdmaTable_PowerBombExplodeLeft; + hdma_object_table_pointers[v2 + 1] = R22_ + addr_kIndirectHdmaTable_PowerBombExplodeRight; + } +} + +#define g_byte_889079 ((uint8*)RomPtr(0x889079)) + +void HdmaobjPreInstr_PowerBombExplode_PreExplosionWhite(uint16 k) { // 0x8890DF + if ((power_bomb_explosion_status & 0x8000u) == 0) + return; + uint16 v7 = k; + CalculatePowerBombHdmaTablePointers(k); + uint16 v1 = 96, v2; + LOBYTE(R18_) = Mult8x8(HIBYTE(power_bomb_pre_explosion_flash_radius), g_byte_88A286[0]) >> 8; + + k = LOBYTE(R18_); + if (HIBYTE(power_bomb_explosion_x_pos_plus_0x100)) { + if (HIBYTE(power_bomb_explosion_x_pos_plus_0x100) == 1) + v2 = CalculatePowerBombHdmaScaled_OnScreen(k, v1, HIBYTE(power_bomb_pre_explosion_flash_radius)); + else + v2 = CalculatePowerBombHdmaScaled_RightOfScreen(k, v1, HIBYTE(power_bomb_pre_explosion_flash_radius)); + } else { + v2 = CalculatePowerBombHdmaScaled_LeftOfScreen(k, v1, HIBYTE(power_bomb_pre_explosion_flash_radius)); + } + k = k_out; + do { + power_bomb_explosion_left_hdma[(uint8)k] = v2; + power_bomb_explosion_right_hdma[(uint8)k] = HIBYTE(v2); + k--; + } while ((k & 0x80) == 0); + uint8 v3 = R18_ + 1; + if ((uint8)R18_ != 0xBF) { + uint8 v4 = -1; + do { + power_bomb_explosion_left_hdma[v3] = v4; + uint8 v5 = v4 + 1; + power_bomb_explosion_right_hdma[v3] = v5; + v4 = v5 - 1; + ++v3; + } while (v3 != 0xC0); + } + LOBYTE(R18_) = (HIBYTE(power_bomb_pre_explosion_flash_radius) >> 3) & 0xF; + reg_COLDATA[0] = g_byte_889079[(uint8)(3 * R18_)] | 0x20; + reg_COLDATA[1] = g_byte_889079[(uint8)(3 * R18_) + 1] | 0x40; + reg_COLDATA[2] = g_byte_889079[(uint8)(3 * R18_) + 2] | 0x80; + power_bomb_pre_explosion_flash_radius += power_bomb_pre_explosion_radius_speed; + if (power_bomb_pre_explosion_flash_radius < 0x9200u) { + power_bomb_pre_explosion_radius_speed -= kPowerBombPreExplosionRadiusAccel; + } else { + int v6 = v7 >> 1; + hdma_object_instruction_timers[v6] = 1; + ++hdma_object_instruction_list_pointers[v6]; + ++hdma_object_instruction_list_pointers[v6]; + hdma_object_timers[v6] = 0; + } +} + +void HdmaobjPreInstr_PowerBombExplode_PreExplosionYellow(uint16 k) { // 0x8891A8 + if ((power_bomb_explosion_status & 0x8000u) == 0) + return; + CalculatePowerBombHdmaTablePointers(k); + uint16 v1 = pre_scaled_power_bomb_explosion_shape_def_ptr; + if (HIBYTE(power_bomb_explosion_x_pos_plus_0x100)) { + if (HIBYTE(power_bomb_explosion_x_pos_plus_0x100) == 1) + CalculatePowerBombHdma_OnScreen(0, v1); + else + CalculatePowerBombHdma_RightOfScreen(0, v1); + } else { + CalculatePowerBombHdma_LeftOfScreen(0, v1); + } + LOBYTE(R18_) = (HIBYTE(power_bomb_pre_explosion_flash_radius) >> 3) & 0xF; + reg_COLDATA[0] = g_byte_889079[(uint8)(3 * R18_)] | 0x20; + reg_COLDATA[1] = g_byte_889079[(uint8)(3 * R18_) + 1] | 0x40; + reg_COLDATA[2] = g_byte_889079[(uint8)(3 * R18_) + 2] | 0x80; + pre_scaled_power_bomb_explosion_shape_def_ptr += 192; + if (pre_scaled_power_bomb_explosion_shape_def_ptr == 0xA206) { + int v2 = k >> 1; + hdma_object_instruction_timers[v2] = 1; + ++hdma_object_instruction_list_pointers[v2]; + ++hdma_object_instruction_list_pointers[v2]; + hdma_object_timers[v2] = 0; + } + if (!__CFADD__uint16(power_bomb_pre_explosion_radius_speed, power_bomb_pre_explosion_flash_radius)) { + power_bomb_pre_explosion_flash_radius += power_bomb_pre_explosion_radius_speed; + power_bomb_pre_explosion_radius_speed -= kPowerBombPreExplosionRadiusAccel; + } +} + +void SpawnCrystalFlashHdmaObjs(void) { // 0x88A2A6 + power_bomb_explosion_status = FUNC16(LayerBlendingHandler); + static const SpawnHdmaObject_Args unk_88A2B0 = { 0x40, 0x28, 0xa2bd }; + static const SpawnHdmaObject_Args unk_88A2B8 = { 0x40, 0x29, 0xa32a }; + SpawnHdmaObject(0x88, &unk_88A2B0); + SpawnHdmaObject(0x88, &unk_88A2B8); +} + +void CrystalFlashSetupPart1(void) { // 0x88A2E4 + offscreen_power_bomb_left_hdma = -1; + offscreen_power_bomb_right_hdma = 0; + power_bomb_pre_explosion_flash_radius = 1024; + power_bomb_pre_explosion_radius_speed = kPowerBombPreExplosionRadiusSpeed; + QueueSfx1_Max6(1u); +} + +void CrystalFlashSetupPart2(void) { // 0x88A309 + power_bomb_explosion_radius = 1024; + power_bomb_pre_explosion_radius_speed = kPowerBombExplosionRadiusSpeed; +} + +void CrystalFlashCleanup(uint16 k) { // 0x88A317 + uint16 v0 = k; + + power_bomb_flag = 0; + power_bomb_explosion_status = 0; + int v1 = v0 >> 1; + hdma_object_channels_bitmask[v1] = 0; + hdma_object_channels_bitmask[v1 + 1] = 0; + power_bomb_pre_explosion_flash_radius = 0; + power_bomb_explosion_radius = 0; +} + +void HdmaobjPreInstr_CrystalFlash_CustomLayerBlend(uint16 k) { // 0x88A339 + reg_W12SEL = 0; + reg_W34SEL = 8; + reg_WOBJSEL = 0x80; + next_gameplay_CGWSEL = 2; + next_gameplay_CGADSUB = 51; + reg_TMW = 0; + reg_TSW = 4; +} + +void HdmaobjPreInstr_CrystalFlash_Stage2_AfterGlow(uint16 k) { // 0x88A35D + if ((power_bomb_explosion_status & 0x8000u) != 0) { + int v1 = k >> 1; + if ((--hdma_object_timers[v1] & 0x8000u) != 0) { + if (((reg_COLDATA[2] | (uint8)(reg_COLDATA[1] | reg_COLDATA[0])) & 0x1F) != 0) { + if ((reg_COLDATA[0] & 0x1F) != 0) + reg_COLDATA[0] = ((reg_COLDATA[0] & 0x1F) - 1) | 0x20; + if ((reg_COLDATA[1] & 0x1F) != 0) + reg_COLDATA[1] = ((reg_COLDATA[1] & 0x1F) - 1) | 0x40; + if ((reg_COLDATA[2] & 0x1F) != 0) + reg_COLDATA[2] = ((reg_COLDATA[2] & 0x1F) - 1) | 0x80; + *((uint8 *)hdma_object_timers + k) = g_word_888B96; + } else { + hdma_object_instruction_timers[v1] = 1; + ++hdma_object_instruction_list_pointers[v1]; + ++hdma_object_instruction_list_pointers[v1]; + } + } + } +} + + +void CalculateCrystalFlashHdmaObjectTablePtrs(uint16 k) { // 0x88A42F + uint16 v0 = k; + uint16 v1; + if ((power_bomb_explosion_status & 0x8000u) != 0) { + if ((uint16)(power_bomb_explosion_x_pos - layer1_x_pos + 256) >= 0x300u + || (power_bomb_explosion_x_pos_plus_0x100 = power_bomb_explosion_x_pos - layer1_x_pos + 256, + v1 = power_bomb_explosion_y_pos - layer1_y_pos + 256, + v1 >= 0x300u)) { + v1 = 0; + } + power_bomb_explosion_y_pos_rsub_0x1ff = (v1 ^ 0x3FF) - 256; + if ((power_bomb_explosion_radius & 0xFF00) == 0) + power_bomb_explosion_y_pos_rsub_0x1ff = 0; + int v2 = v0 >> 1; + R22_ = 3 * power_bomb_explosion_y_pos_rsub_0x1ff; + hdma_object_table_pointers[v2] = 3 * power_bomb_explosion_y_pos_rsub_0x1ff + addr_kIndirectHdmaTable_PowerBombExplodeLeft; + hdma_object_table_pointers[v2 + 1] = R22_ + addr_kIndirectHdmaTable_PowerBombExplodeRight; + } +} + +void CalculateCrystalFlashHdmaDataTablesScaled_LeftOfScreen(uint16 k, uint16 j) { // 0x88A493 + char v2; + + do { + LOBYTE(R20_) = Mult8x8(HIBYTE(power_bomb_explosion_radius), g_byte_88A206[(uint8)j + 32]) >> 8; + v2 = power_bomb_explosion_x_pos_plus_0x100; + uint8 Reg = Mult8x8(HIBYTE(power_bomb_explosion_radius), g_byte_88A206[(uint8)j]) >> 8; + bool v4 = __CFADD__uint8(Reg, v2); + uint8 v5 = Reg + v2; + uint8 v6, v7; + if (v4) { + v6 = v5; + v7 = 0; + } else { + v6 = 0; + v7 = -1; + } + while (1) { + power_bomb_explosion_left_hdma[(uint8)k] = v7; + power_bomb_explosion_right_hdma[(uint8)k] = v6; + if ((uint8)k == (uint8)R20_) + break; + LOBYTE(k) = k - 1; + } + LOBYTE(j) = j + 1; + } while ((j & 0x80) == 0); +} + +void CalculateCrystalFlashHdmaDataTablesScaled_OnScreen(uint16 k, uint16 j) { // 0x88A4D1 + char v2; + char v5; + + do { + LOBYTE(R20_) = Mult8x8(HIBYTE(power_bomb_explosion_radius), g_byte_88A206[(uint8)j + 32]) >> 8; + v2 = power_bomb_explosion_x_pos_plus_0x100; + uint8 Reg = Mult8x8(HIBYTE(power_bomb_explosion_radius), g_byte_88A206[(uint8)j]) >> 8; + bool v4 = __CFADD__uint8(Reg, v2); + v5 = Reg + v2; + if (v4) + v5 = -1; + uint8 v6 = v5; + uint8 v7 = power_bomb_explosion_x_pos_plus_0x100; + uint8 v8 = Reg; + v4 = v7 < v8; + uint8 v9 = v7 - v8; + if (v4) + v9 = 0; + while (1) { + power_bomb_explosion_left_hdma[(uint8)k] = v9; + power_bomb_explosion_right_hdma[(uint8)k] = v6; + if ((uint8)k == (uint8)R20_) + break; + LOBYTE(k) = k - 1; + } + LOBYTE(j) = j + 1; + } while ((j & 0x80) == 0); +} + +void CalculateCrystalFlashHdmaDataTablesScaled_RightOfScreen(uint16 k, uint16 j) { // 0x88A513 + char v5; + char v6; // ah + char v7; + char v10; // t2 + + do { + LOBYTE(R20_) = Mult8x8(HIBYTE(power_bomb_explosion_radius), g_byte_88A206[(uint8)j + 32]) >> 8; + uint8 v2 = power_bomb_explosion_x_pos_plus_0x100; + uint8 Reg = Mult8x8(HIBYTE(power_bomb_explosion_radius), g_byte_88A206[(uint8)j]) >> 8; + bool v4 = v2 < Reg; + v5 = v2 - Reg; + if (v4) { + v6 = v5; + v7 = -1; + } else { + v6 = -1; + v7 = 0; + } + v10 = v7; + uint8 v8 = v6; + uint8 v9 = v10; + while (1) { + power_bomb_explosion_left_hdma[(uint8)k] = v8; + power_bomb_explosion_right_hdma[(uint8)k] = v9; + if ((uint8)k == (uint8)R20_) + break; + LOBYTE(k) = k - 1; + } + LOBYTE(j) = j + 1; + } while ((j & 0x80) == 0); +} + +void HdmaobjPreInstr_CrystalFlash_Stage1_Explosion(uint16 k) { // 0x88A552 + if ((power_bomb_explosion_status & 0x80) != 0) { + CalculateCrystalFlashHdmaObjectTablePtrs(k); + uint16 v1 = 96; + LOBYTE(R18_) = Mult8x8(HIBYTE(power_bomb_explosion_radius), g_byte_88A286[0]) >> 8; + Unreachable(); + if (HIBYTE(power_bomb_explosion_x_pos_plus_0x100)) { + if (HIBYTE(power_bomb_explosion_x_pos_plus_0x100) == 1) + CalculateCrystalFlashHdmaDataTablesScaled_OnScreen(k, v1); + else + CalculateCrystalFlashHdmaDataTablesScaled_RightOfScreen(k, v1); + } else { + CalculateCrystalFlashHdmaDataTablesScaled_LeftOfScreen(k, v1); + } + } +} + +void FxTypeFunc_22_ScrollingSky(void) { // 0x88A61B + fx_y_pos = 1248; + fx_type = 6; + + static const SpawnHdmaObject_Args unk_88A62E = { 0x02, 0x12, 0xad63 }; + static const SpawnHdmaObject_Args unk_88A636 = { 0x42, 0x11, 0xad4e }; + static const SpawnHdmaObject_Args unk_88A63E = { 0x42, 0x0d, 0xad39 }; + SpawnHdmaObject(0x88, &unk_88A62E); + SpawnHdmaObject(0x88, &unk_88A636); + SpawnHdmaObject(0x88, &unk_88A63E); + HdmaobjPreInstr_FxType22_BG3Yscroll(0); +} + +void HdmaobjPreInstr_FxType22_BG3Yscroll(uint16 k) { // 0x88A643 + DamageSamusInTopRow(); + R0_.addr = addr_word_88A8E8; + R3_.addr = addr_word_88A8E8__plus__2; + R6_ = addr_word_88A8E8__plus__4; + *(uint16 *)((char *)&R8_ + 1) = addr_word_88A8E8__plus__6; + R24_ = 78; + assert(0); // k? + k = SetupSomeHdmaTablesBG3(); + *(uint16 *)&mother_brain_indirect_hdma[k] = 0; +} + +uint16 HdmaobjInstr_SetFlagB(uint16 k, uint16 j) { // 0x88A66C + hdma_object_B[k >> 1] = 1; + return j; +} +#define g_word_88A938 ((uint16*)RomPtr(0x88a938)) +static const int16 g_word_88C46E[16] = { // 0x88A673 + 0, 1, 1, 0, 0, -1, -1, 0, + 0, 1, 1, 0, 0, -1, -1, 0, +}; +void HdmaobjPreInstr_BG3Xscroll(uint16 k) { + int16 v8; + int16 v9; + + if (sign16(layer1_y_pos - 1024)) { + if ((nmi_frame_counter_byte & 1) == 0) + g_word_7E0596 = ((uint8)g_word_7E0596 + 2) & 0x1E; + uint16 v1 = g_word_7E0596; + uint16 v2 = 0; + do { + g_word_7E9E80[v2 >> 1] = g_word_88A938[v1 >> 1]; + v2 += 2; + v1 += 2; + } while ((int16)(v1 - 32) < 0); + } else { + int v3 = k >> 1; + if (hdma_object_B[v3]-- == 1) { + hdma_object_B[v3] = 6; + hdma_object_A[v3] = ((uint8)hdma_object_A[v3] + 2) & 0x1F; + } + uint16 v5 = hdma_object_A[v3]; + for (int i = 30; i >= 0; i -= 2) { + g_word_7E9E80[v5 >> 1] = g_word_88C46E[i >> 1] + reg_BG1HOFS; + v5 = ((uint8)v5 - 2) & 0x1F; + } + } + *(uint16 *)&hdma_window_1_left_pos[0].field_0 = 0; + *(uint16 *)scrolling_sky_bg2_indirect_hdma = 0; + *(uint16 *)&hdma_window_1_left_pos[0].field_2 = 31; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[2] = 31; + R18_ = 31; + *(uint16 *)&hdma_window_1_left_pos[1].field_0 = -25088; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[3] = -25088; + if (sign16(layer1_y_pos - 1024)) { + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[2] = 0; + } else { + R20_ = 177; + R22_ = 0; + HdmaFunc_A786(0x105u); + } + uint16 v7 = 5; + R20_ = -24960; + R22_ = 128; + HdmaFunc_A786(5u); + v8 = 224 - R18_; + while ((int16)(v8 - 16) >= 0) { + v8 -= 16; + *(uint16 *)(&hdma_window_1_left_pos[0].field_0 + v7) = 144; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v7] = 144; + *(uint16 *)(&hdma_window_1_left_pos[0].field_1 + v7) = -24960; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v7 + 1] = -24960; + v7 += 3; + } + v9 = v8; + if (v8) + v9 = v8 + 128; + *(uint16 *)(&hdma_window_1_left_pos[0].field_0 + v7) = v9; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v7] = v9; + *(uint16 *)(&hdma_window_1_left_pos[0].field_1 + v7) = -24960; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v7 + 1] = -24960; + *(uint16 *)(&hdma_window_1_left_pos[1].field_0 + v7) = 0; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v7 + 3] = 0; +} + +void HdmaFunc_A786(uint16 k) { // 0x88A786 + uint16 v0 = k; + int16 v2; + + uint16 v1 = 1216 - layer1_y_pos; + R24_ = 1216 - layer1_y_pos; + if ((int16)(1216 - layer1_y_pos) >= 0 && layer1_y_pos != 1216) { + if (sign16(v1 - 128)) { + R18_ = 1216 - layer1_y_pos; + } else { + R18_ = 1216 - layer1_y_pos; + if (!sign16(v1 - 193)) + v1 = 193; + R18_ = v1; + R24_ = v1; + while (1) { + v2 = v1 - 16; + if (v2 < 0) + break; + R24_ = v2; + *(uint16 *)(&hdma_window_1_left_pos[0].field_0 + v0) = R22_ | 0x10; + *(uint16 *)(&hdma_window_1_left_pos[0].field_1 + v0) = R20_; + v1 = R24_; + v0 += 3; + } + } + *(uint16 *)(&hdma_window_1_left_pos[0].field_0 + v0) = R22_ | R24_; + *(uint16 *)(&hdma_window_1_left_pos[0].field_1 + v0) = R20_; + } +} + +static const SpawnHdmaObject_Args unk_88A7EF = { 0x42, 0x0f, 0xad76 }; +static const SpawnHdmaObject_Args unk_88A80B = { 0x42, 0x0f, 0xad89 }; + +void FxTypeFunc_20(void) { // 0x88A7D8 + layer2_scroll_x |= 1u; + layer2_scroll_y |= 1u; + SpawnHdmaObject(0x88, &unk_88A7EF); + set_to_e0_by_scrolling_sky = 224; + UNUSED_word_7E059C = 0; +} + +void RoomSetupAsm_ScrollingSkyOcean(void) { // 0x88A800 + reg_BG2SC = 74; + SpawnHdmaObject(0x88, &unk_88A80B); + set_to_e0_by_scrolling_sky = 224; + UNUSED_word_7E059C = 0; +} + +uint16 SetupSomeHdmaTablesBG3(void) { // 0x88A81C + int16 v1; + + g_word_7E0598 = 32; + *(uint16 *)mother_brain_indirect_hdma = 31; + *(uint16 *)&mother_brain_indirect_hdma[1] = 0; + uint16 v0 = 3; + v1 = layer1_y_pos + 32; + R18_ = layer1_y_pos + 32; + uint16 v2 = 0; + while ((int16)(v1 - *(uint16 *)&RomPtr_88(R0_.addr)[v2]) < 0 + || (int16)(v1 - *(uint16 *)&RomPtr_88(*(uint16 *)((char *)&R8_ + 1))[v2]) >= 0) { + v2 += 6; + if ((int16)(v2 - R24_) >= 0) + return v0; + } + uint16 v3; + if (sign16(R18_ - 1248)) + v3 = R18_ & 0xF; + else + v3 = R18_ & 0x1F; + R22_ = v3; + *(uint16 *)&mother_brain_indirect_hdma[3] = *(uint16 *)&RomPtr_88(R3_.addr)[v2] - v3; + *(uint16 *)&mother_brain_indirect_hdma[4] = R22_ + *(uint16 *)&RomPtr_88(R6_)[v2] - g_word_7E0598; + while (1) { + R20_ = mother_brain_indirect_hdma[v0]; + R18_ += R20_; + v0 += 3; + g_word_7E0598 += R20_; + if (!sign16(g_word_7E0598 - 224)) + break; + while ((int16)(R18_ - *(uint16 *)&RomPtr_88(R0_.addr)[v2]) < 0 + || (int16)(R18_ - *(uint16 *)&RomPtr_88(*(uint16 *)((char *)&R8_ + 1))[v2]) >= 0) { + v2 += 6; + if ((int16)(v2 - R24_) >= 0) + return v0; + } + *(uint16 *)&mother_brain_indirect_hdma[v0] = *(uint16 *)&RomPtr_88(R3_.addr)[v2]; + *(uint16 *)&mother_brain_indirect_hdma[v0 + 1] = *(uint16 *)&RomPtr_88(R6_)[v2] - g_word_7E0598; + } + return v0; +} + +void DamageSamusInTopRow(void) { // 0x88A8C4 + if ((int16)(samus_y_pos - samus_y_radius) < 0 || sign16(samus_y_pos - samus_y_radius - 17)) + samus_periodic_damage = 8; +} + +void HdmaobjPreInstr_SkyLandBG2Xscroll(uint16 k) { // 0x88ADB2 + if (!time_is_frozen_flag) + HdmaobjPreInstr_SkyLandBG2XscrollInner(k); +} + +void HdmaobjPreInstr_SkyLandBG2Xscroll2(uint16 k) { // 0x88ADBA + if (!time_is_frozen_flag) + HdmaobjPreInstr_SkyLandBG2XscrollInner(k); +} +#define kHdmaScrollEntrys ((HdmaScrollEntry*)RomPtr(0x88aec1)) +void HdmaobjPreInstr_SkyLandBG2XscrollInner(uint16 k) { // 0x88ADC2 + uint16 i; + + reg_BG2SC = 74; + uint16 v1 = 0; + do { + uint16 scroll_subspeed = kHdmaScrollEntrys[v1].scroll_subspeed; + uint8 *v3 = RomPtr_7E(kHdmaScrollEntrys[v1].hdma_data_table_entry); + bool v4 = __CFADD__uint16(*(uint16 *)v3, scroll_subspeed); + *(uint16 *)v3 += scroll_subspeed; + *((uint16 *)v3 + 1) += v4 + kHdmaScrollEntrys[v1++].scroll_speed; + } while (sign16(v1 * 8 - 184)); + scrolling_sky_bg2_hdma_data[44] = 0; + scrolling_sky_bg2_hdma_data[45] = 0; + *(uint16 *)scrolling_sky_bg2_indirect_hdma = 31; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[1] = 1438; + R18_ = layer1_y_pos + 32; + R20_ = layer1_y_pos + 224; + uint16 v5 = 0; + uint16 v6 = 3; + do { + while ((int16)(R18_ - kHdmaScrollEntrys[v5].top_pos) >= 0 + && (int16)(R18_ - kHdmaScrollEntrys[v5 + 1].top_pos) < 0) { + uint16 v8 = kHdmaScrollEntrys[v5 + 1].top_pos - R18_; + R24_ = v8; + if (!sign16(v8 - 128)) { + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v6] = 127; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v6 + 1] = kHdmaScrollEntrys[v5].hdma_data_table_entry + 2; + v6 += 3; + v8 = R24_ - 127; + } + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v6] = v8; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v6 + 1] = kHdmaScrollEntrys[v5].hdma_data_table_entry + 2; + R18_ += R24_; + v6 += 3; + if (!sign16(R18_ - R20_)) { + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v6 + 3] = 0; + return; + } + } + ++v5; + } while (sign16(v5 * 8 - 184)); + for (i = 1535 - R18_; ; i = R24_ - 127) { + R24_ = i; + if (sign16(i - 128)) + break; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v6] = 127; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v6 + 1] = 181; + v6 += 3; + } + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v6] = i; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v6 + 1] = 181; + *(uint16 *)&scrolling_sky_bg2_indirect_hdma[v6 + 3] = 0; +} + +void RoomCode_ScrollingSkyLand(void) { // 0x88AF8D + R0_.addr = addr_off_88AD9C; + *(uint16 *)&R0_.bank = 136; + RoomMainAsm_ScrollingSky(); +} + +void RoomMainAsm_ScrollingSkyOcean(void) { // 0x88AF99 + R0_.addr = addr_off_88ADA6; + *(uint16 *)&R0_.bank = 136; + RoomMainAsm_ScrollingSky(); +} + +void RoomMainAsm_ScrollingSky(void) { // 0x88AFA3 + VramWriteEntry *v1; + int16 v2; + VoidP v3; + int16 v4; + VoidP v5; + + if (time_is_frozen_flag) { + WORD(scrolling_sky_bg2_indirect_hdma[0]) = 0; + } else { + reg_BG2VOFS = layer1_y_pos; + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 64; + v1[1].size = 64; + v1[2].size = 64; + v1[3].size = 64; + v2 = 8 * (uint8)((layer1_y_pos & 0xF8) - 16); + v3 = *(uint16 *)IndirPtr( + &R0_, + 2 * (uint8)((uint16)(((layer1_y_pos & 0x7F8) - 16) & 0xFF00) >> 8)) + + v2; + v1->src.addr = v3; + v1[1].src.addr = v3 + 64; + v4 = 8 * (uint8)((layer1_y_pos & 0xF8) - 16); + v5 = *(uint16 *)IndirPtr( + &R0_, + 2 * (uint8)((uint16)(((layer1_y_pos & 0x7F8) + 240) & 0xFF00) >> 8)) + + v4; + v1[2].src.addr = v5; + v1[3].src.addr = v5 + 64; + v1->src.bank = -118; + v1[1].src.bank = -118; + v1[2].src.bank = -118; + v1[3].src.bank = -118; + R18_ = (reg_BG2SC & 0xFC) << 8; + uint16 v6 = R18_ + 4 * ((layer1_y_pos - 16) & 0x1F8); + v1->vram_dst = v6; + v1[1].vram_dst = v6 + 32; + uint16 v7 = R18_ + 4 * ((layer1_y_pos + 240) & 0x1F8); + v1[2].vram_dst = v7; + v1[3].vram_dst = v7 + 32; + vram_write_queue_tail = v0 + 28; + } +} + +static const SpawnHdmaObject_Args unk_88B08C = { 0x42, 0x11, 0xb0ac }; + +static const uint16 kFirefleaFlashingShades[12] = { 0, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x500, 0x400, 0x300, 0x200, 0x100 }; +static const uint16 kFirefleaDarknessShades[6] = { 0, 0x600, 0xc00, 0x1200, 0x1800, 0x1900 }; + +void FxTypeFunc_24(void) { // 0x88B07C + fireflea_flashing_timer = 6; + fireflea_flashing_index = 0; + SpawnHdmaObject(0x88, &unk_88B08C); + *(uint16 *)&hdma_window_1_left_pos[0].field_0 = 0; + UNUSED_word_7E177C = 0; + fireflea_darkness_level = 0; + UNUSED_word_7E1780 = 24; + UNUSED_word_7E1782 = kFirefleaFlashingShades[0]; +} + +void HdmaobjPreInstr_FirefleaBG3XScroll(uint16 k) { // 0x88B0BC + char v2; + uint16 v1; + + fx_layer_blending_config_c = fx_layer_blending_config_c & 0xFF00 | 0xC; + if (!time_is_frozen_flag) { + if (!--fireflea_flashing_timer) { + fireflea_flashing_timer = 6; + if (sign16(fireflea_darkness_level - 10)) { + v1 = fireflea_flashing_index + 1; + if ((uint16)(fireflea_flashing_index + 1) >= 0xCu) + v1 = 0; + } else { + v1 = 6; + } + fireflea_flashing_index = v1; + } + v2 = (uint16)(kFirefleaDarknessShades[fireflea_darkness_level >> 1] + + kFirefleaFlashingShades[fireflea_flashing_index]) >> 8; + reg_COLDATA[1] = v2 | 0x80; + reg_COLDATA[2] = v2 | 0x40; + reg_COLDATA[0] = v2 | 0x20; + } +} + + +void ExpandingContractingHdmaEffect(void) { // 0x88B17F + if (!sign16(++set_to_e0_by_scrolling_sky - 4)) { + set_to_e0_by_scrolling_sky = 0; + if (UNUSED_hdma_contracting_flag) { + message_box_animation_y_radius -= 1024; + if (sign16(message_box_animation_y_radius - 0x2000)) { + message_box_animation_y_radius = 0x2000; + UNUSED_hdma_contracting_flag = 0; + } + } else { + message_box_animation_y_radius += 1024; + if (!sign16(message_box_animation_y_radius + 0x8000)) + ++UNUSED_hdma_contracting_flag; + } + message_box_animation_y0 = 128; + message_box_animation_y1 = 128; + message_box_animation_y2 = 127; + message_box_animation_y3 = 127; + } + uint16 v0 = 2 * message_box_animation_y0; + uint16 v1 = 2 * message_box_animation_y2; + R18_ = 0; + R20_ = 32; + do { + *(uint16 *)&mother_brain_indirect_hdma[v0] = message_box_animation_y1 - message_box_animation_y0; + *(uint16 *)&mother_brain_indirect_hdma[v1] = message_box_animation_y3 - message_box_animation_y2; + R18_ += message_box_animation_y_radius; + if (Unreachable()) { + ++message_box_animation_y1; + --message_box_animation_y3; + } + ++message_box_animation_y0; + --message_box_animation_y2; + v1 -= 2; + v0 += 2; + --R20_; + } while (R20_); +} + +static const uint16 g_word_88B256[17] = { 0x46, 1, 0x46, 3, 0x46, 2, 0x46, 1, 0x46, 1, 0x46, 2, 0x46, 2, 0x46, 1, 0x8000 }; + +void HandleEarthquakeSoundEffect(void) { // 0x88B21D + int16 v1; + + if ((earthquake_sfx_timer & 0x8000u) == 0 && (--earthquake_sfx_timer & 0x8000u) != 0) { + uint16 v0 = earthquake_sfx_index; + v1 = g_word_88B256[earthquake_sfx_index >> 1]; + if (v1 < 0) { + v0 = 0; + v1 = g_word_88B256[0]; + } + QueueSfx2_Max6(v1); + earthquake_sfx_timer = g_word_88B256[(v0 >> 1) + 1] + (v0 & 1) + (random_number & 3); + earthquake_sfx_index = v0 + 4; + } +} + +static const SpawnHdmaObject_Args unk_88B289 = { 0x42, 0x12, 0xc3e1 }; +static const SpawnHdmaObject_Args unk_88B291 = { 0x42, 0x10, 0xc3f0 }; +static const SpawnHdmaObject_Args unk_88B2B1 = { 0x42, 0x12, 0xc3e1 }; +static const SpawnHdmaObject_Args unk_88B2B9 = { 0x42, 0x10, 0xc3f0 }; +void FxTypeFunc_2_Lava(void) { // 0x88B279 + fx_rising_function_bank_88 = FUNC16(FxRisingFunction_LavaAcid); + lava_acid_y_pos = fx_base_y_pos; + SpawnHdmaObject(0x88, &unk_88B289); + SpawnHdmaObject(0x88, &unk_88B291); + SpawnBG3ScrollHdmaObject(); + SpawnAnimtiles(addr_kAnimtiles_Lava); +} + +void FxTypeFunc_4_Acid(void) { // 0x88B2A1 + fx_rising_function_bank_88 = FUNC16(FxRisingFunction_LavaAcid); + lava_acid_y_pos = fx_base_y_pos; + SpawnHdmaObject(0x88, &unk_88B2B1); + SpawnHdmaObject(0x88, &unk_88B2B9); + SpawnBG3ScrollHdmaObject(); + SpawnAnimtiles(addr_kAnimtiles_Acid); +} + +void FxHandleTide(void) { // 0x88B2C9 + uint16 v2, v5; + + if (*(int16 *)((char *)&fx_y_vel + 1) < 0) { + fx_y_suboffset = 0; + fx_y_offset = 0; + int v0 = (uint16)(2 * HIBYTE(tide_phase)) >> 1; + uint16 v1 = 8 * kSinCosTable8bit_Sext[v0]; + if ((kSinCosTable8bit_Sext[v0] & 0x1000) != 0) + --fx_y_offset; + *(uint16 *)((char *)&fx_y_suboffset + 1) = v1; + if ((kSinCosTable8bit_Sext[v0] & 0x8000u) == 0) + v2 = tide_phase + 288; + else + v2 = tide_phase + 192; + tide_phase = v2; + } else if ((*(uint16 *)((char *)&fx_y_vel + 1) & 0x4000) != 0) { + fx_y_suboffset = 0; + fx_y_offset = 0; + int v3 = (uint16)(2 * HIBYTE(tide_phase)) >> 1; + uint16 v4 = 32 * kSinCosTable8bit_Sext[v3]; + if ((kSinCosTable8bit_Sext[v3] & 0x400) != 0) + --fx_y_offset; + *(uint16 *)((char *)&fx_y_suboffset + 1) = v4; + if ((kSinCosTable8bit_Sext[v3] & 0x8000u) == 0) + v5 = tide_phase + 224; + else + v5 = tide_phase + 128; + tide_phase = v5; + } +} + +void FxRisingFunction_LavaAcid(void) { // 0x88B343 + if (fx_y_vel) { + if ((fx_y_vel & 0x8000u) == 0) { + if (fx_target_y_pos < fx_base_y_pos || fx_target_y_pos == fx_base_y_pos) + return; +LABEL_8: + fx_rising_function_bank_88 = FUNC16(FxRisingFunction_LavaAcid_WaitToRise); + return; + } + if (fx_target_y_pos != fx_base_y_pos && fx_target_y_pos < fx_base_y_pos) + goto LABEL_8; + } +} + +void FxRisingFunction_LavaAcid_WaitToRise(void) { // 0x88B367 + HandleEarthquakeSoundEffect(); + earthquake_type = 21; + earthquake_timer |= 0x20u; + if (!--fx_timer) + fx_rising_function_bank_88 = FUNC16(FxRisingFunction_LavaAcid_Raising); +} + +void FxRisingFunction_LavaAcid_Raising(void) { // 0x88B382 + HandleEarthquakeSoundEffect(); + earthquake_type = 21; + earthquake_timer |= 0x20u; + if (RaiseOrLowerFx() & 1) { + fx_y_vel = 0; + fx_rising_function_bank_88 = FUNC16(FxRisingFunction_LavaAcid); + } +} + +uint16 HdmaobjInstr_B3A9(uint16 k, uint16 j) { // 0x88B3A9 + hdma_object_C[k >> 1] = 112; + return j; +} + +void CallFxRisingFunc(uint32 ea) { + switch (ea) { + case fnFxRisingFunction_LavaAcid: FxRisingFunction_LavaAcid(); return; + case fnFxRisingFunction_LavaAcid_WaitToRise: FxRisingFunction_LavaAcid_WaitToRise(); return; + case fnFxRisingFunction_LavaAcid_Raising: FxRisingFunction_LavaAcid_Raising(); return; + case fnFxRisingFunction_C428_WaterNormal: FxRisingFunction_C428_WaterNormal(); return; + case fnFxRisingFunction_WaterWaitToRise: FxRisingFunction_WaterWaitToRise(); return; + case fnFxRisingFunction_WaterRising: FxRisingFunction_WaterRising(); return; + default: Unreachable(); + } +} + +static const uint8 kLavaSoundEffects[8] = { 0x12, 0x13, 0x14, 0x12, 0x13, 0x14, 0x12, 0x13 }; + +void HdmaobjPreInstr_LavaAcidBG3YScroll(uint16 k) { // 0x88B3B0 + unsigned int v1; // kr00_4 + int16 v2; + int16 v3; + int16 v4; + uint16 v7; + int16 v8; + + fx_layer_blending_config_c = fx_layer_blending_config_b; + if (!time_is_frozen_flag) { + CallFxRisingFunc(fx_rising_function_bank_88 | 0x880000); + FxHandleTide(); + v1 = __PAIR32__(fx_y_offset, fx_y_suboffset) + __PAIR32__(fx_base_y_pos, fx_base_y_subpos); + lava_acid_y_pos = HIWORD(v1); + lava_acid_y_subpos = v1; + bg3_xpos = reg_BG1HOFS; + *(uint16 *)mother_brain_indirect_hdma = 0; + bg3_ypos = 0; + v2 = (__PAIR32__(fx_y_offset, fx_y_suboffset) + __PAIR32__(fx_base_y_pos, fx_base_y_subpos)) >> 16; + if (v2 >= 0) { + v3 = v2 - layer1_y_pos; + if (v3 <= 0) { + v4 = ((uint8)v3 ^ 0x1F) & 0x1F | 0x100; +LABEL_8: + *(uint16 *)&mother_brain_indirect_hdma[2] = v4; + if (fx_type == 2 && (lava_acid_y_pos & 0x8000u) == 0) { + int v5 = (uint8)hdma_object_index >> 1; + if (hdma_object_C[v5]-- == 1) { + hdma_object_C[v5] = 112; + QueueSfx2_Max6(kLavaSoundEffects[random_number & 7]); + } + } + LOBYTE(v7) = HIBYTE(random_number); + HIBYTE(v7) = random_number; + random_number = v7; + if ((lava_acid_y_pos & 0x8000u) == 0) { + v8 = lava_acid_y_pos - layer1_y_pos + 256; + if (v8 < 0) { + v8 = 255; +LABEL_17: + R18_ = ((v8 ^ 0x1FF) + 1) & 0x3FF; + hdma_object_table_pointers[(uint8)hdma_object_index >> 1] = 3 * (((v8 ^ 0x1FF) + 1) & 0x3FF) + 0xB62A; + return; + } + if ((uint16)v8 < 0x200u) + goto LABEL_17; + } + v8 = 511; + goto LABEL_17; + } + if ((uint16)v3 < 0x100u) { + v4 = (uint8)~(uint8)v3; + goto LABEL_8; + } + } + v4 = 0; + goto LABEL_8; + } +} + +uint16 HdmaobjInstr_SetFlagB_Copy(uint16 k, uint16 j) { // 0x88B4CE + hdma_object_B[k >> 1] = 1; + return j; +} + +void HdmaobjPreInstr_LavaAcidBG2YScroll(uint16 k) { // 0x88B4D5 + g_word_7E9C44 = reg_BG2VOFS; + if (!time_is_frozen_flag && (fx_liquid_options & 6) != 0) { + if ((fx_liquid_options & 2) != 0) + Handle_LavaAcidBG2YScroll_Func3(k); + else + Handle_LavaAcidBG2YScroll_Func2(k); + } else { + Handle_LavaAcidBG2YScroll_Func1(k); + } + R18_ = reg_BG2VOFS & 0xF; + hdma_object_table_pointers[(uint8)hdma_object_index >> 1] = 3 * (reg_BG2VOFS & 0xF) + 0xC0B1; +} + +void Handle_LavaAcidBG2YScroll_Func1(uint16 v0) { // 0x88B51D + WriteReg((SnesRegs)(*((uint8 *)hdma_object_bank_slot + v0) + 17153), 0x10u); + uint8 v1 = 30; + uint16 v2 = reg_BG2VOFS & 0x1FF; + do { + g_word_7E9C46[v1 >> 1] = v2; + v1 -= 2; + } while ((v1 & 0x80) == 0); +} +#define g_word_88B589 ((uint16*)RomPtr(0x88b589)) +void Handle_LavaAcidBG2YScroll_Func2(uint16 v0) { // 0x88B53B + WriteReg((SnesRegs)(*((uint8 *)hdma_object_bank_slot + v0) + 17153), 0xFu); + int v1 = v0 >> 1; + if (hdma_object_B[v1]-- == 1) { + hdma_object_B[v1] = 6; + hdma_object_A[v1] = ((uint8)hdma_object_A[v1] - 2) & 0x1E; + } + uint8 v3 = *((uint8 *)hdma_object_A + v0); + uint8 v4 = 30; + R18_ = 15; + do { + g_word_7E9C46[v4 >> 1] = (g_word_88B589[v3 >> 1] + reg_BG2HOFS) & 0x1FF; + v3 = (v3 - 2) & 0x1E; + v4 = (v4 - 2) & 0x1E; + --R18_; + } while ((R18_ & 0x8000u) == 0); +} +#define g_word_88B60A ((uint16*)RomPtr(0x88b60a)) +void Handle_LavaAcidBG2YScroll_Func3(uint16 v0) { // 0x88B5A9 + WriteReg((SnesRegs)(*((uint8 *)hdma_object_bank_slot + v0) + BBAD0), 0x10u); + int v1 = v0 >> 1; + if (hdma_object_B[v1]-- == 1) { + hdma_object_B[v1] = 4; + hdma_object_A[v1] = ((uint8)hdma_object_A[v1] - 2) & 0x1E; + } + uint8 v3 = (LOBYTE(hdma_object_A[v1]) + 2 * (reg_BG2VOFS & 0xF)) & 0x1E; + uint8 v4 = (2 * (reg_BG2VOFS & 0xF) + 30) & 0x1E; + R18_ = 15; + do { + g_word_7E9C46[v4 >> 1] = (g_word_88B60A[v3 >> 1] + reg_BG2VOFS) & 0x1FF; + v4 = (v4 - 2) & 0x1E; + v3 = (v3 - 2) & 0x1E; + --R18_; + } while ((R18_ & 0x8000u) == 0); +} +static const SpawnHdmaObject_Args unk_88C40F = { 0x42, 0x11, 0xd856 }; +static const SpawnHdmaObject_Args unk_88C41F = { 0x42, 0x0f, 0xd847 }; +void FxTypeFunc_6_Water(void) { // 0x88C3FF + fx_rising_function_bank_88 = FUNC16(FxRisingFunction_C428_WaterNormal); + fx_y_pos = fx_base_y_pos; + SpawnHdmaObject(0x88, &unk_88C40F); + if ((fx_liquid_options & 2) != 0) + SpawnHdmaObject(0x88, &unk_88C41F); + SpawnBG3ScrollHdmaObject(); +} + +void FxRisingFunction_C428_WaterNormal(void) { // 0x88C428 + if (fx_y_vel) { + if ((fx_y_vel & 0x8000u) == 0) { + if (fx_target_y_pos < fx_base_y_pos || fx_target_y_pos == fx_base_y_pos) + return; +LABEL_8: + fx_rising_function_bank_88 = FUNC16(FxRisingFunction_WaterWaitToRise); + return; + } + if (fx_target_y_pos != fx_base_y_pos && fx_target_y_pos < fx_base_y_pos) + goto LABEL_8; + } +} + +void FxRisingFunction_WaterWaitToRise(void) { // 0x88C44C + if (!--fx_timer) + fx_rising_function_bank_88 = FUNC16(FxRisingFunction_WaterRising); +} + +void FxRisingFunction_WaterRising(void) { // 0x88C458 + if (RaiseOrLowerFx() & 1) { + fx_rising_function_bank_88 = FUNC16(FxRisingFunction_C428_WaterNormal); + fx_y_vel = 0; + } +} + +uint16 HdmaobjInstr_SetFlagB_Copy2(uint16 k, uint16 j) { // 0x88C467 + hdma_object_B[k >> 1] = 1; + return j; +} + +void CallFxRisingFunction(uint32 ea) { + switch (ea) { + case fnFxRisingFunction_LavaAcid: FxRisingFunction_LavaAcid(); return; + case fnFxRisingFunction_LavaAcid_WaitToRise: FxRisingFunction_LavaAcid_WaitToRise(); return; + case fnFxRisingFunction_LavaAcid_Raising: FxRisingFunction_LavaAcid_Raising(); return; + case fnFxRisingFunction_C428_WaterNormal: FxRisingFunction_C428_WaterNormal(); return; + case fnFxRisingFunction_WaterWaitToRise: FxRisingFunction_WaterWaitToRise(); return; + case fnFxRisingFunction_WaterRising: FxRisingFunction_WaterRising(); return; + default: Unreachable(); + } +} + +void HdmaobjPreInstr_WaterBG3XScroll(uint16 k) { // 0x88C48E + unsigned int v1; // kr00_4 + int16 v2; + int16 v3; + int16 v9; + uint16 v4; + + fx_layer_blending_config_c = fx_layer_blending_config_b; + if (!time_is_frozen_flag) { + CallFxRisingFunction(fx_rising_function_bank_88 | 0x880000); + FxHandleTide(); + v1 = __PAIR32__(fx_y_offset, fx_y_suboffset) + __PAIR32__(fx_base_y_pos, fx_base_y_subpos); + fx_y_pos = HIWORD(v1); + fx_y_subpos = v1; + v2 = (__PAIR32__(fx_y_offset, fx_y_suboffset) + __PAIR32__(fx_base_y_pos, fx_base_y_subpos)) >> 16; + if (v2 < 0) + goto LABEL_6; + v3 = v2 - layer1_y_pos; + if (v3 <= 0) { + v4 = ((uint8)v3 ^ 0x1F) & 0x1F | 0x100; + goto LABEL_8; + } + if ((uint16)v3 < 0x100u) + v4 = (uint8)~(uint8)v3; + else + LABEL_6: + v4 = 0; +LABEL_8: + bg3_ypos = v4; + int v5 = (uint8)hdma_object_index >> 1; + R20_ = layer1_x_pos + (int8)HIBYTE(hdma_object_C[v5]); + if (hdma_object_B[v5]-- == 1) { + hdma_object_B[v5] = 10; + hdma_object_A[v5] = ((uint8)hdma_object_A[v5] + 2) & 0x1E; + } + uint8 v7 = hdma_object_A[v5]; + for (int i = 30; (i & 0x80) == 0; i -= 2) { + *(uint16 *)&mother_brain_indirect_hdma[v7 + 4] = g_word_88C46E[i >> 1] + R20_; + v7 = (v7 - 2) & 0x1E; + } + if ((fx_liquid_options & 1) != 0) + hdma_object_C[(uint8)hdma_object_index >> 1] += 64; + if ((fx_y_pos & 0x8000u) == 0) { + v9 = fx_y_pos - layer1_y_pos + 256; + if (v9 < 0) { + v9 = ((uint8)fx_y_pos - (uint8)layer1_y_pos) & 0xF | 0x100; +LABEL_22: + R18_ = ((v9 ^ 0x1FF) + 1) & 0x3FF; + hdma_object_table_pointers[(uint8)hdma_object_index >> 1] = 3 * (((v9 ^ 0x1FF) + 1) & 0x3FF) + 0xC645; + return; + } + if ((uint16)v9 < 0x200u) + goto LABEL_22; + } + v9 = 511; + goto LABEL_22; + } +} + +uint16 HdmaobjInstr_SetFlagB_Copy3(uint16 k, uint16 j) { // 0x88C582 + hdma_object_B[k >> 1] = 1; + return j; +} + +void HdmaobjPreInstr_WaterBG2XScroll(uint16 k) { // 0x88C589 + int16 v1; + + g_word_7E9C44 = reg_BG2HOFS; + if (time_is_frozen_flag) + goto LABEL_4; + if ((fx_liquid_options & 2) == 0) { + hdma_object_channels_bitmask[(uint8)k >> 1] = 0; +LABEL_4: + HdmaobjPreInstr_WaterBG2XScroll_Func1(k); + goto LABEL_6; + } + HdmaobjPreInstr_WaterBG2XScroll_Func2(k); +LABEL_6: + if ((fx_y_pos & 0x8000u) != 0) + goto LABEL_10; + v1 = fx_y_pos - layer1_y_pos + 256; + if (v1 >= 0) { + if ((uint16)v1 < 0x200u) + goto LABEL_11; +LABEL_10: + v1 = 511; + goto LABEL_11; + } + v1 = ((uint8)fx_y_pos - (uint8)layer1_y_pos) & 0xF | 0x100; +LABEL_11: + R18_ = (v1 ^ 0x1FF) & 0x3FF; + hdma_object_table_pointers[(uint8)k >> 1] = 3 * ((v1 ^ 0x1FF) & 0x3FF) - 0x30BA; +} + +void HdmaobjPreInstr_WaterBG2XScroll_Func2(uint16 k) { // 0x88C5E4 + int v1 = (uint8)k >> 1; + if (hdma_object_B[v1]-- == 1) { + hdma_object_B[v1] = 6; + hdma_object_A[v1] = ((uint8)hdma_object_A[v1] + 2) & 0x1E; + } + uint8 v3 = (LOBYTE(hdma_object_A[v1]) + 2 * (reg_BG2VOFS & 0xF)) & 0x1E; + uint8 v4 = (2 * (reg_BG2VOFS & 0xF) + 30) & 0x1E; + R18_ = 15; + do { + g_word_7E9C46[(v4 >> 1) + 1] = g_word_88C46E[v3 >> 1] + reg_BG2HOFS; + v4 = (v4 - 2) & 0x1E; + v3 = (v3 - 2) & 0x1E; + --R18_; + } while ((R18_ & 0x8000u) == 0); +} + +void HdmaobjPreInstr_WaterBG2XScroll_Func1(uint16 k) { // 0x88C636 + uint8 v1 = 30; + uint16 v2 = reg_BG2HOFS; + do { + g_word_7E9C46[(v1 >> 1) + 1] = v2; + v1 -= 2; + } while ((v1 & 0x80) == 0); +} + +void SpawnBG3ScrollHdmaObject(void) { // 0x88D865 + static const SpawnHdmaObject_Args unk_88D869 = { 0x43, 0x11, 0xd8d0 }; + SpawnHdmaObjectToSlot0xA(0x88, &unk_88D869); +} + +void FxTypeFunc_28_CeresRidley(void) { // 0x88D8DE + static const SpawnHdmaObject_Args unk_88D8E2 = { 0x40, 0x05, 0xd906 }; + static const SpawnHdmaObject_Args unk_88D8EA = { 0x00, 0x2c, 0xd91d }; + SpawnHdmaObject(0x88, &unk_88D8E2); + SpawnHdmaObject(0x88, &unk_88D8EA); +} + +void sub_88D916(void) { // 0x88D916 + hdma_data_table_in_ceres = 9; +} + +void FxTypeFunc_CeresElevator(void) { // 0x88D928 + static const SpawnHdmaObject_Args unk_88D92C = { 0x40, 0x05, 0xd939 }; + SpawnHdmaObject(0x88, &unk_88D92C); +} + +uint16 HdmaobjInstr_SetVideoMode1(uint16 k, uint16 j) { // 0x88D949 + hdma_data_table_in_ceres = 9; + return j; +} + +void FxTypeFunc_A_Rain(void) { // 0x88D950 + static const SpawnHdmaObject_Args unk_88D95C = { 0x43, 0x11, 0xd96c }; + gameplay_BG3SC = 92; + SpawnHdmaObject(0x88, &unk_88D95C); + SpawnBG3ScrollHdmaObject(); + SpawnAnimtiles(addr_kAnimtiles_Rain); +} + +#define g_word_88D992 ((uint16*)RomPtr(0x88d992)) + +uint16 HdmaobjInstr_1938_RandomNumber(uint16 k, uint16 j) { // 0x88D981 + hdma_object_D[k >> 1] = g_word_88D992[(uint16)((random_number >> 1) & 6) >> 1]; + return j; +} + +void HdmaobjPreInstr_RainBg3Scroll(uint16 k) { // 0x88D9A1 + gameplay_BG3SC = 92; + fx_layer_blending_config_c = fx_layer_blending_config_b; + if (!time_is_frozen_flag) { + int v1 = (uint8)k >> 1; + R18_ = hdma_object_E[v1] - layer1_y_pos; + bg3_ypos = R18_ + (int8)HIBYTE(hdma_object_A[v1]); + hdma_object_A[v1] -= 1536; + hdma_object_E[v1] = layer1_y_pos; + R18_ = hdma_object_F[v1] - layer1_x_pos; + bg3_xpos = R18_ + (int8)HIBYTE(hdma_object_B[v1]); + hdma_object_B[v1] += hdma_object_D[v1]; + hdma_object_F[v1] = layer1_x_pos; + } +} + +void FxTypeFunc_8_Spores(void) { // 0x88DA11 + gameplay_BG3SC = 92; + static const SpawnHdmaObject_Args unk_88DA1D = { 0x42, 0x11, 0xda2d }; + SpawnHdmaObject(0x88, &unk_88DA1D); + SpawnBG3ScrollHdmaObject(); + SpawnAnimtiles(addr_kAnimtiles_Spores); +} + +void HdmaobjPreInstr_SporesBG3Xscroll(uint16 k) { // 0x88DA47 + gameplay_BG3SC = 92; + fx_layer_blending_config_c = fx_layer_blending_config_b; + if (!time_is_frozen_flag) { + int v1 = (uint8)k >> 1; + bg3_ypos = layer1_y_pos + (int8)HIBYTE(hdma_object_C[v1]); + uint16 v3 = hdma_object_C[v1] - 64; + hdma_object_C[v1] = v3; + R20_ = v3; + bg3_xpos = layer1_x_pos + (int8)HIBYTE(hdma_object_D[v1]); + R18_ = layer1_x_pos + v3; + hdma_object_D[v1] = hdma_object_D[v1]; + } +} +static const uint16 g_word_88DAE8[16] = { 0, 1, 1, 0, 0, 65535, 65535, 0, 0, 1, 1, 0, 0, 65535, 65535, 0 }; +void sub_88DA9F(uint16 k) { // 0x88DA9F + int v1 = (uint8)k >> 1; + if (hdma_object_B[v1]-- == 1) { + hdma_object_B[v1] = 10; + hdma_object_A[v1] = ((uint8)hdma_object_A[v1] + 2) & 0x1F; + } + uint8 v3 = hdma_object_A[v1]; + for (int i = 30; (i & 0x80) == 0; i -= 2) { + *(uint16 *)&mother_brain_indirect_hdma[v3 + 4] = g_word_88DAE8[i >> 1] + (i & 1) + samus_x_pos + R18_; + v3 = (v3 - 2) & 0x1F; + } + R20_ &= 0xFu; + hdma_object_table_pointers[(uint8)hdma_object_index >> 1] = 3 * R20_ + 0xC945; +} + +void FxTypeFunc_C(void) { // 0x88DB08 + gameplay_BG3SC = 92; + static const SpawnHdmaObject_Args unk_88DB14 = { 0x43, 0x11, 0xdb19 }; + SpawnHdmaObject(0x88, &unk_88DB14); +} + +void HdmaobjPreInstr_FogBG3Scroll(uint16 k) { // 0x88DB36 + gameplay_BG3SC = 92; + fx_layer_blending_config_c = fx_layer_blending_config_b; + if (!time_is_frozen_flag) { + int v1 = (uint8)k >> 1; + bg3_ypos = layer1_y_pos + (int8)HIBYTE(hdma_object_A[v1]); + hdma_object_A[v1] -= 64; + bg3_xpos = layer1_x_pos + (int8)HIBYTE(hdma_object_B[v1]); + hdma_object_B[v1] += 80; + } +} + +void FxTypeFunc_26_TourianEntranceStatue(void) { // 0x88DB8A + static const SpawnHardcodedPlmArgs unk_88DB97 = { 0x06, 0x0c, 0xb777 }; + static const SpawnHdmaObject_Args unk_88DBBA = { 0x42, 0x11, 0xd856 }; + static const SpawnHdmaObject_Args unk_88DBC2 = { 0x42, 0x10, 0xdcfa }; + + if (CheckEventHappened(0xAu) & 1) { + SpawnHardcodedPlm(&unk_88DB97); + *(uint16 *)scrolls = 514; + } + reg_BG2SC = 74; + fx_rising_function_bank_88 = FUNC16(FxRisingFunction_C428_WaterNormal); + fx_y_pos = fx_base_y_pos; + SpawnHdmaObject(0x88, &unk_88DBBA); + SpawnHdmaObject(0x88, &unk_88DBC2); + SpawnBG3ScrollHdmaObject(); +} + +void sub_88DBCB(uint16 k) { // 0x88DBCB + *(uint16 *)&hdma_window_1_left_pos[0].field_0 = layer1_y_pos + hdma_object_B[k >> 1]; +} + +void HdmaobjPreInstr_CheckLotsOfEventsHappened(uint16 v0) { // 0x88DBD7 + if (CheckEventHappened(6u) & 1) { + if (CheckEventHappened(7u) & 1) { + if (CheckEventHappened(8u) & 1) { + if (CheckEventHappened(9u) & 1) { + tourian_entrance_statue_animstate |= 0x10u; + if ((tourian_entrance_statue_animstate & 0x8000u) == 0) { + hdma_object_C[v0 >> 1] = 300; + v0 = hdma_object_index; + int v1 = hdma_object_index >> 1; + hdma_object_instruction_timers[v1] = 1; + ++hdma_object_instruction_list_pointers[v1]; + ++hdma_object_instruction_list_pointers[v1]; + } + } + } + } + } + sub_88DBCB(v0); +} + +void HdmaobjPreInstr_DC23(uint16 k) { // 0x88DC23 + uint16 v0 = k; + + HandleEarthquakeSoundEffect(); + earthquake_type = 13; + earthquake_timer |= 0x20u; + int v1 = (uint8)v0 >> 1; + if ((--hdma_object_C[v1] & 0x8000u) != 0) { + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatueDustClouds, 0); // ? + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatueDustClouds, 0); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatueDustClouds, 0); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatueDustClouds, 0); + hdma_object_instruction_timers[v1] = 1; + ++hdma_object_instruction_list_pointers[v1]; + ++hdma_object_instruction_list_pointers[v1]; + } + sub_88DBCB(v0); +} + +void HdmaobjPreInstr_DC69(uint16 k) { // 0x88DC69 + uint16 v0 = k; + + HandleEarthquakeSoundEffect(); + earthquake_type = 13; + earthquake_timer |= 0x20u; + if (!time_is_frozen_flag) { + int v1 = (uint8)v0 >> 1; + uint16 v2 = hdma_object_A[v1]; + hdma_object_A[v1] = v2 - 0x4000; + uint16 v3 = __CFADD__uint16(v2, -16384) + hdma_object_B[v1] - 1; + hdma_object_B[v1] = v3; + if (v3 == 0xFF10) { + static const SpawnHardcodedPlmArgs unk_88DC9D = { 0x06, 0x0c, 0xb773 }; + SpawnHardcodedPlm(&unk_88DC9D); + SetEventHappened(0xAu); + int v4 = (uint8)v0 >> 1; + hdma_object_instruction_timers[v4] = 1; + ++hdma_object_instruction_list_pointers[v4]; + ++hdma_object_instruction_list_pointers[v4]; + } + sub_88DBCB(v0); + } +} + +void HdmaobjPreInstr_DCBA(uint16 v0) { // 0x88DCBA + tourian_entrance_statue_finished = 0x8000; + *(uint16 *)scrolls = 514; + sub_88DBCB(v0); +} + +uint16 HdmaobjInstr_GotoIfEventHappened(uint16 k, uint16 j) { // 0x88DCCB + int v2 = k >> 1; + hdma_object_C[v2] = 0; + hdma_object_A[v2] = 0; + if (CheckEventHappened(0xAu)) { + hdma_object_B[v2] = -240; + *(uint16 *)&hdma_window_1_left_pos[0].field_0 = -240; + return *(uint16 *)RomPtr_88(j); + } else { + hdma_object_B[v2] = 0; + *(uint16 *)&hdma_window_1_left_pos[0].field_0 = 0; + *(uint16 *)scrolls = 1; + return j + 2; + } +} + +void SpawnBombTorizoHaze(void) { // 0x88DD32 + static const SpawnHdmaObject_Args unk_88DD36 = { 0x02, 0x32, 0xdd4a }; + static const SpawnHdmaObject_Args unk_88DD3E = { 0x00, 0x32, 0xdd62 }; + SpawnHdmaObject(0x88, &unk_88DD36); + SpawnHdmaObject(0x88, &unk_88DD3E); +} + +void HdmaobjPreInstr_BombTorizoHazeColorMathBgColor(uint16 k) { // 0x88DD43 + fx_layer_blending_config_c = 44; +} + +void FxTypeFunc_2C_Haze(void) { // 0x88DDC7 + static const SpawnHdmaObject_Args unk_88DDD4 = { 0x40, 0x32, 0xded3 }; + static const SpawnHdmaObject_Args unk_88DDDD = { 0x40, 0x32, 0xdeeb }; + if (CheckBossBitForCurArea(1u) & 1) + SpawnHdmaObject(0x88, &unk_88DDDD); + else + SpawnHdmaObject(0x88, &unk_88DDD4); +} + +void HdmaobjPreInstr_HazeColorMathSubscreen_CeresRidleyAlive(uint16 k) { // 0x88DE10 + sub_88DE18(k, 0x80); +} + +void HdmaobjPreInstr_HazeColorMathSubscreen_CeresRidleyDead(uint16 k) { // 0x88DE15 + sub_88DE18(k, 0x20u); +} + +void sub_88DE18(uint16 k, uint16 a) { // 0x88DE18 + int v2 = (uint8)k >> 1; + hdma_object_B[v2] = a; + hdma_object_A[v2] = 0; + if (door_transition_function == FUNC16(DoorTransition_FadeInScreenAndFinish)) { + hdma_object_pre_instructions[v2] = FUNC16(HdmaobjPreInstr_HazeColorMathSubscreen_FadingIn); + HdmaobjPreInstr_HazeColorMathSubscreen_FadingIn(k); + } +} + +void HdmaobjPreInstr_HazeColorMathSubscreen_FadingIn(uint16 k) { // 0x88DE2D + char v1; + + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + fx_layer_blending_config_c = 44; + if (hdma_object_A[(uint8)k >> 1] == 16) { + hdma_object_pre_instructions[(uint8)k >> 1] = FUNC16(HdmaobjPreInstr_HazeColorMathSubscreen_FadedIn); + } else { + uint8 v3 = k; + LOBYTE(R20_) = *((uint8 *)hdma_object_B + (uint8)k); + v1 = *((uint8 *)hdma_object_A + (uint8)k); + for (int i = 15; i >= 0; --i) { + LOBYTE(R18_) = v1; + *((uint8 *)hdma_table_2 + (uint8)i) = R20_ | v1; + v1 = R18_ - 1; + if ((int8)(R18_ - 1) < 0) + v1 = 0; + } + ++hdma_object_A[v3 >> 1]; + } +} + +void HdmaobjPreInstr_HazeColorMathSubscreen_FadedIn(uint16 k) { // 0x88DE74 + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + fx_layer_blending_config_c = 44; + if (door_transition_function == FUNC16(DoorTransitionFunction_FadeOutScreen)) + hdma_object_pre_instructions[(uint8)k >> 1] = FUNC16(HdmaobjPreInstr_HazeColorMathSubscreen_FadingOut); +} + +void HdmaobjPreInstr_HazeColorMathSubscreen_FadingOut(uint16 k) { // 0x88DE96 + char v1; + + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + fx_layer_blending_config_c = 44; + if (hdma_object_A[(uint8)k >> 1]) { + uint8 v3 = k; + LOBYTE(R20_) = *((uint8 *)hdma_object_B + (uint8)k); + v1 = *((uint8 *)hdma_object_A + (uint8)k); + for (int i = 15; i >= 0; --i) { + LOBYTE(R18_) = v1; + *((uint8 *)hdma_table_2 + (uint8)i) = R20_ | v1; + v1 = R18_ - 1; + if ((int8)(R18_ - 1) < 0) + v1 = 0; + } + --hdma_object_A[v3 >> 1]; + } +} + +static const SpawnHdmaObject_Args unk_88DF38 = { 0x00, 0x2c, 0xdf4f }; +static const SpawnHdmaObject_Args unk_88DF41 = { 0x00, 0x2c, 0xdf6b }; + +static const SpawnHdmaObject_Args unk_88DF4A = { 0x02, 0x12, 0xdf77 }; +void sub_88DF34(void) { // 0x88DF34 + SpawnHdmaObject(0x88, &unk_88DF38); +} + +void sub_88DF3D(void) { // 0x88DF3D + SpawnHdmaObject(0x88, &unk_88DF41); +} + +void sub_88DF46(void) { // 0x88DF46 + SpawnHdmaObject(0x88, &unk_88DF4A); +} + +void HdmaobjPreInstr_DF94(uint16 v0) { // 0x88DF94 + int16 v1; + + if ((enemy_data[0].properties & 0x200) == 0 + && (int16)(enemy_data[0].x_pos - layer1_x_pos + 64) >= 0 + && sign16(enemy_data[0].x_pos - layer1_x_pos - 320) + && (int16)(enemy_data[0].y_pos - layer1_y_pos + 16) >= 0 + && (v1 = enemy_data[0].y_pos - layer1_y_pos, sign16(enemy_data[0].y_pos - layer1_y_pos - 304))) { + if (sign16(v1 - 40)) { + int v2 = v0 >> 1; + hdma_object_instruction_timers[v2] = 1; + hdma_object_instruction_list_pointers[v2] = addr_word_88DF6B; + } else { + int v4 = v0 >> 1; + hdma_object_instruction_timers[v4] = 1; + if (sign16(v1 - 192)) + hdma_object_instruction_list_pointers[v4] = addr_word_88DF5F; + else + hdma_object_instruction_list_pointers[v4] = addr_word_88DF65; + } + } else { + int v3 = v0 >> 1; + hdma_object_instruction_timers[v3] = 1; + hdma_object_instruction_list_pointers[v3] = addr_word_88DF71; + } +} + +static Func_U8 *const off_88E04E[7] = { // 0x88E026 + VariaSuitPickup_0_LightBeamAppears, + VariaSuitPickup_1, + VariaSuitPickup_2_LightBeamWidens, + VariaSuitPickup_3, + VariaSuitPickup_4_LightBeamShrinks, + VariaSuitPickup_5_LightBeamDissipates, + VariaSuitPickup_6, +}; + +void HdmaobjPreInstr_VariaSuitPickup(uint16 k) { + if (off_88E04E[substate]() & 1) { + reg_COLDATA[0] = suit_pickup_color_math_R; + reg_COLDATA[1] = suit_pickup_color_math_G; + reg_COLDATA[2] = suit_pickup_color_math_B; + fx_layer_blending_config_c = 18; + } +} + +static Func_U8 *const off_88E084[7] = { // 0x88E05C + VariaSuitPickup_0_LightBeamAppears, + VariaSuitPickup_1, + VariaSuitPickup_2_LightBeamWidens, + GravitySuitPickup_3, + VariaSuitPickup_4_LightBeamShrinks, + VariaSuitPickup_5_LightBeamDissipates, + GravitySuitPickup_6, +}; + +void HdmaobjPreInstr_GravitySuitPickup(uint16 k) { + if (off_88E084[substate]() & 1) { + reg_COLDATA[0] = suit_pickup_color_math_R; + reg_COLDATA[1] = suit_pickup_color_math_G; + reg_COLDATA[2] = suit_pickup_color_math_B; + fx_layer_blending_config_c = 18; + } +} +static const uint16 g_word_88E0D5 = 0x7878; +uint8 VariaSuitPickup_0_LightBeamAppears(void) { // 0x88E092 + int16 v0; + int16 v3; + + suit_pickup_light_beam_pos += 8; + v0 = suit_pickup_light_beam_pos; + uint16 v1 = 0; + do { + hdma_table_1[v1 >> 1] = g_word_88E0D5; + v1 += 2; + --v0; + } while (v0 > 0); + uint16 v2 = 510; + v3 = suit_pickup_light_beam_pos; + do { + hdma_table_1[v2 >> 1] = g_word_88E0D5; + v2 -= 2; + --v3; + } while (v3 > 0); + if (!sign16(suit_pickup_light_beam_pos - 128)) { + ++substate; + suit_pickup_light_beam_pos = 30840; + } + return 1; +} + +uint8 VariaSuitPickup_1(void) { // 0x88E0D7 + LOBYTE(suit_pickup_light_beam_pos) = suit_pickup_light_beam_pos - HIBYTE(suit_pickup_light_beam_widening_speed); + HIBYTE(suit_pickup_light_beam_pos) += HIBYTE(suit_pickup_light_beam_widening_speed); + for (int i = 510; i >= 0; i -= 2) + hdma_table_1[i >> 1] = suit_pickup_light_beam_pos; + if (sign16((uint8)suit_pickup_light_beam_pos - 97)) { + ++substate; + suit_pickup_light_beam_pos = -31636; + } + return 1; +} + +#define g_byte_88E3C9 ((uint8*)RomPtr(0x88e3c9)) + +uint8 VariaSuitPickup_2_LightBeamWidens(void) { // 0x88E113 + char v1; + int16 v2; + char v4; + char v6; + char v8; + char v10; + + AdvanceSuitPickupColorMathSubscreenToWhite(); + bool v0 = (int8)(suit_pickup_light_beam_pos - HIBYTE(suit_pickup_light_beam_widening_speed)) < 0; + LOBYTE(suit_pickup_light_beam_pos) = suit_pickup_light_beam_pos - HIBYTE(suit_pickup_light_beam_widening_speed); + if (!(uint8)suit_pickup_light_beam_pos || v0) { + suit_pickup_light_beam_pos = -256; + } else { + v1 = HIBYTE(suit_pickup_light_beam_widening_speed) + HIBYTE(suit_pickup_light_beam_pos); + if (__CFADD__uint8(HIBYTE(suit_pickup_light_beam_widening_speed), HIBYTE(suit_pickup_light_beam_pos))) + v1 = -1; + HIBYTE(suit_pickup_light_beam_pos) = v1; + } + v2 = 0; + uint16 v3 = 0; + do { + v4 = suit_pickup_light_beam_pos - g_byte_88E3C9[v3]; + if (v4 < 0) + v4 = 0; + *((uint8 *)hdma_table_1 + (uint16)v2) = v4; + uint16 v5 = v2 + 1; + v6 = g_byte_88E3C9[v3] + HIBYTE(suit_pickup_light_beam_pos); + if (__CFADD__uint8(g_byte_88E3C9[v3], HIBYTE(suit_pickup_light_beam_pos))) + v6 = -1; + *((uint8 *)hdma_table_1 + v5) = v6; + v2 = v5 + 1; + ++v3; + } while (v2 < 0x100); + uint16 v7 = v3 - 1; + do { + v8 = suit_pickup_light_beam_pos - g_byte_88E3C9[v7]; + if (v8 < 0) + v8 = 0; + *((uint8 *)hdma_table_1 + (uint16)v2) = v8; + uint16 v9 = v2 + 1; + v10 = g_byte_88E3C9[v7] + HIBYTE(suit_pickup_light_beam_pos); + if (__CFADD__uint8(g_byte_88E3C9[v7], HIBYTE(suit_pickup_light_beam_pos))) + v10 = -1; + *((uint8 *)hdma_table_1 + v9) = v10; + v2 = v9 + 1; + --v7; + } while (v2 < 0x200); + suit_pickup_light_beam_widening_speed += 96; + if (suit_pickup_light_beam_pos == 0xFF00) { + ++substate; + suit_pickup_light_beam_widening_speed >>= 1; + suit_pickup_light_beam_pos = 0; + } + return 1; +} + +uint8 VariaSuitPickup_4_LightBeamShrinks(void) { // 0x88E1BA + int16 v0; + int16 v3; + + if (suit_pickup_palette_transition_color) + AdvanceSuitPickupColorMathToBlue(); + else + AdvanceSuitPickupColorMathToOrange(); + R18_ = (uint8)((uint16)(suit_pickup_light_beam_widening_speed & 0xFF00) >> 8); + suit_pickup_light_beam_pos += R18_; + v0 = suit_pickup_light_beam_pos; + uint16 v1 = 0; + do { + hdma_table_1[v1 >> 1] = 255; + v1 += 2; + --v0; + } while (v0 > 0); + uint16 v2 = 510; + v3 = suit_pickup_light_beam_pos - 1; + do { + hdma_table_1[v2 >> 1] = 255; + v2 -= 2; + --v3; + } while (v3 > 0); + suit_pickup_light_beam_widening_speed -= 32; + if (sign16(suit_pickup_light_beam_widening_speed - 256)) + suit_pickup_light_beam_widening_speed = 256; + if (!sign16(suit_pickup_light_beam_pos - 128)) { + ++substate; + suit_pickup_light_beam_pos = -1793; + } + return 1; +} + +uint8 VariaSuitPickup_5_LightBeamDissipates(void) { // 0x88E22B + LOBYTE(suit_pickup_light_beam_pos) = suit_pickup_light_beam_pos + 8; + HIBYTE(suit_pickup_light_beam_pos) -= 8; + hdma_table_1[128] = suit_pickup_light_beam_pos; + if (!sign16((uint8)suit_pickup_light_beam_pos - 112)) + ++substate; + return 1; +} + +uint8 VariaSuitPickup_6(void) { // 0x88E258 + QueueMusic_Delayed8(3u); + return GravitySuitPickup_6(); +} + +uint8 GravitySuitPickup_6(void) { // 0x88E25F + reg_COLDATA[2] = 0x80; + reg_COLDATA[1] = 64; + reg_COLDATA[0] = 32; + mov24((LongPtr *)&demo_enable, 0x980001); + *(uint16 *)((char *)&demo_num_input_frames + 1) = 0; + demo_input_prev = 0; + demo_input_prev_new = 0; + demo_backup_prev_controller_input = 0; + hdma_table_1[0] = 255; + substate = 0; + suit_pickup_light_beam_pos = 0; + *(uint16 *)&suit_pickup_color_math_R = 0; + *(uint16 *)&suit_pickup_color_math_B = 0; + int v0 = hdma_object_index >> 1; + hdma_object_instruction_list_pointers[v0] += 2; + hdma_object_instruction_timers[v0] = 1; + CallSomeSamusCode(0xBu); + return 0; +} + +uint8 AdvanceSuitPickupColorMathSubscreenToWhite(void) { // 0x88E2B4 + if (suit_pickup_color_math_R != 63) { + suit_pickup_color_math_R += 2; + if (!sign8(suit_pickup_color_math_R - 64)) + suit_pickup_color_math_R = 63; + } + if (suit_pickup_color_math_G != 95) { + suit_pickup_color_math_G += 2; + if (!sign8(suit_pickup_color_math_G - 96)) + suit_pickup_color_math_G = 95; + } + if (suit_pickup_color_math_B != 0x9F) { + suit_pickup_color_math_B += 2; + if (!sign8(suit_pickup_color_math_B + 96)) + suit_pickup_color_math_B = -97; + } + return 1; +} + +uint8 AdvanceSuitPickupColorMathToOrange(void) { // 0x88E2F9 + if (suit_pickup_color_math_R != 63) + --suit_pickup_color_math_R; + if (suit_pickup_color_math_G != 77) + --suit_pickup_color_math_G; + if (suit_pickup_color_math_B != 0x83) + --suit_pickup_color_math_B; + return 1; +} + +uint8 VariaSuitPickup_3(void) { // 0x88E320 + equipped_items |= 1u; + collected_items |= 1u; + samus_pose = kPose_9B_FaceF_VariaGravitySuit; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + Samus_LoadSuitPalette(); + ++substate; + return 1; +} + +uint8 GravitySuitPickup_3(void) { // 0x88E361 + equipped_items |= 0x20u; + collected_items |= 0x20u; + samus_pose = kPose_9B_FaceF_VariaGravitySuit; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + Samus_LoadSuitPalette(); + ++substate; + return 1; +} + +uint8 AdvanceSuitPickupColorMathToBlue(void) { // 0x88E3A2 + if (suit_pickup_color_math_R != 48) + --suit_pickup_color_math_R; + if (suit_pickup_color_math_G != 73) + --suit_pickup_color_math_G; + if (suit_pickup_color_math_B != 0x90) + --suit_pickup_color_math_B; + return 1; +} + +void HdmaobjPreInstr_E449(uint16 k) { // 0x88E449 + if ((phantom_related_layer_flag & 0x4000) != 0) { + fx_layer_blending_config_c = 26; + } else if (LOBYTE(enemy_data[3].parameter_1)) { + if (LOBYTE(enemy_data[3].parameter_1) == 0xFF) { + fx_layer_blending_config_c = 4; + int v0 = hdma_object_index >> 1; + hdma_object_instruction_list_pointers[v0] += 2; + hdma_object_instruction_timers[v0] = 1; + } + } else { + fx_layer_blending_config_c = 4; + } +} +static const SpawnHdmaObject_Args unk_88E4A0 = { 0x42, 0x0f, 0xe4a8 }; +void sub_88E487(uint16 v0) { // 0x88E487 + enemy_data[2].parameter_1 = v0; + enemy_data[3].ai_var_D = 0; + enemy_data[3].ai_var_E = 0; + enemy_data[3].ai_preinstr = R22_; + SpawnHdmaObject(0x88, &unk_88E4A0); +} + +uint16 HdmaobjInstr_E4BD(uint16 k, uint16 j) { // 0x88E4BD + unsigned int v2; // kr00_4 + unsigned int v3; // kr04_4 + unsigned int v4; // kr08_4 + unsigned int v5; // kr0C_4 + + enemy_data[1].parameter_1 = enemy_data[2].parameter_1; + if ((enemy_data[2].parameter_1 & 1) != 0) { + kraid_unk9000 = 192; + g_word_7E9006 = 192; + v4 = 12620032; + *(uint16 *)((char *)&g_word_7E9002 + 1) = HIWORD(v4); + *(uint16 *)((char *)&kraid_unk9000 + 1) = v4; + g_word_7E9004 = -28288; + v5 = 12620032; + *(uint16 *)((char *)&g_word_7E9008 + 1) = HIWORD(v5); + *(uint16 *)((char *)&g_word_7E9006 + 1) = v5; + g_word_7E900A = addr_loc_889180; + g_word_7E900C = 0; + } else { + kraid_unk9000 = 160; + g_word_7E9006 = 160; + g_word_7E900C = 160; + g_word_7E900F = 160; + g_word_7E9012 = 160; + g_word_7E9015 = 160; + v2 = 10522880; + *(uint16 *)((char *)&g_word_7E9002 + 1) = HIWORD(v2); + *(uint16 *)((char *)&kraid_unk9000 + 1) = v2; + v3 = 10522880; + *(uint16 *)((char *)&g_word_7E9008 + 1) = HIWORD(v3); + *(uint16 *)((char *)&g_word_7E9006 + 1) = v3; + *(uint16 *)((char *)&g_word_7E900C + 1) = -28416; + *(uint16 *)((char *)&g_word_7E9012 + 1) = -28416; + g_word_7E9004 = -28352; + g_word_7E900A = -28352; + *(uint16 *)((char *)&g_word_7E900F + 1) = -28352; + *(uint16 *)((char *)&g_word_7E9015 + 1) = -28352; + g_word_7E9018 = 0; + } + int v6 = k >> 1; + hdma_object_A[v6] = -2; + hdma_object_B[v6] = 1; + hdma_object_C[v6] = 0; + hdma_object_D[v6] = 0; + return j; +} + +void HdmaobjPreInstr_E567(uint16 v0) { // 0x88E567 + int16 v7; + uint16 j; + uint16 v8; + + if (enemy_data[1].parameter_1) { + if ((enemy_data[1].parameter_1 & 1) != 0) { + R28_ = 4; + g_word_7E001E = 128; + } else { + R28_ = 8; + g_word_7E001E = 64; + } + int v2 = v0 >> 1; + if (hdma_object_B[v2]-- == 1) { + hdma_object_B[v2] = 1; + R18_ = 2 * enemy_data[3].ai_preinstr; + hdma_object_A[v2] = (2 * enemy_data[3].ai_preinstr + hdma_object_A[v2]) & 0x1FF; + } + R20_ = hdma_object_A[v2]; + uint16 v4 = 0; + do { + uint16 v11 = v4; + uint16 v5 = R20_; + int v6 = R20_ >> 1; + v7 = kSinCosTable8bit_Sext[v6 + 64]; + if (v7 < 0) { + R18_ = -v7; + R22_ = Mult8x8(-(int8)v7, enemy_data[3].ai_var_D) >> 8; + R22_ += Mult8x8(HIBYTE(R18_), enemy_data[3].ai_var_D); + R24_ = Mult8x8(R18_, HIBYTE(enemy_data[3].ai_var_D)); + uint8 mult = Mult8x8(HIBYTE(R18_), HIBYTE(enemy_data[3].ai_var_D)); + R22_ += R24_; + R18_ = (uint8)((uint16)((R22_ + (mult << 8)) & 0xFF00) >> 8); + R20_ = (R28_ + v5) & 0x1FF; + v8 = v11; + *(uint16 *)((char *)&g_word_7E9100 + v11) = reg_BG2HOFS - R18_; + } else { + R18_ = kSinCosTable8bit_Sext[v6 + 64]; + R22_ = Mult8x8(v7, enemy_data[3].ai_var_D) >> 8; + R22_ += Mult8x8(HIBYTE(R18_), enemy_data[3].ai_var_D); + R24_ = Mult8x8(R18_, HIBYTE(enemy_data[3].ai_var_D)); + uint8 mult = Mult8x8(HIBYTE(R18_), HIBYTE(enemy_data[3].ai_var_D)); + R22_ += R24_; + R18_ = (uint8)((uint16)((R22_ + (mult << 8)) & 0xFF00) >> 8); + R20_ = (R28_ + v5) & 0x1FF; + v8 = v11; + *(uint16 *)((char *)&g_word_7E9100 + v11) = R18_ + reg_BG2HOFS; + } + v4 = v8 + 2; + } while ((int16)(v4 - g_word_7E001E) < 0); + if ((enemy_data[1].parameter_1 & 1) != 0) { + for (int i = 126; i >= 0; i -= 2) + *(uint16 *)((char *)&g_word_7E9180 + i) = reg_BG2HOFS + reg_BG2HOFS - *(uint16 *)((char *)&g_word_7E9100 + i); + } else { + for (j = 62; (j & 0x8000u) == 0; j -= 2) + *(uint16 *)((char *)&g_word_7E9140 + j) = reg_BG2HOFS + reg_BG2HOFS - *(uint16 *)((char *)&g_word_7E9100 + j); + } + } else { + int v1 = hdma_object_index >> 1; + hdma_object_instruction_list_pointers[v1] += 2; + hdma_object_instruction_timers[v1] = 1; + } +} +static const SpawnHdmaObject_Args unk_88E722 = { 0x00, 0x2c, 0xe727 }; +static const SpawnHdmaObject_Args unk_88E74C = { 0x41, 0x26, 0xe751 }; +uint16 MotherBrainRisingHdmaObject(void) { // 0x88E71E + return SpawnHdmaObject(0x88, &unk_88E722); +} + +uint16 SpawnMotherBrainRainbowBeamHdma(void) { // 0x88E748 + return SpawnHdmaObject(0x88, &unk_88E74C); +} + +void InitializeRainbowBeam(void) { // 0x88E767 + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 71; + reg_COLDATA[2] = 0x8f; + fx_layer_blending_config_c = 36; + mother_brain_indirect_hdma[0] = 100; + *(uint16 *)&mother_brain_indirect_hdma[1] = -25344; + *(uint16 *)&mother_brain_indirect_hdma[3] = 0; + hdma_table_2[0] = 0; + hdma_table_2[1] = -32736; + hdma_table_2[2] = 0; + MotherBrain_CalculateRainbowBeamHdma(); +} + +void HdmaobjPreInstr_E7BC(uint16 k) { // 0x88E7BC + if (game_state == 19) { + hdma_object_channels_bitmask[hdma_object_index >> 1] = 0; + } else { + fx_layer_blending_config_c = 36; + if (game_state != 27) { + MotherBrain_CalculateRainbowBeamHdma(); + sub_88E7ED(); + } + } +} + +#define g_word_88E833 ((uint16*)RomPtr(0x88e833)) + +void sub_88E7ED(void) { // 0x88E7ED + uint16 v0 = g_word_88E833[hdma_object_A[0] >> 1]; + if ((v0 & 0x8000u) == 0) { + ++hdma_object_A[0]; + ++hdma_object_A[0]; + ++hdma_object_A[0]; + ++hdma_object_A[0]; + } else { + hdma_object_A[0] = 0; + v0 = g_word_88E833[0]; + } + reg_COLDATA[0] = v0 & 0x1F | 0x20; + reg_COLDATA[1] = (v0 >> 5) & 0x1F | 0x40; + reg_COLDATA[2] = ((uint16)(v0 >> 2) >> 8) & 0x1F | 0x80; +} + +void SpawnMorphBallEyeBeamHdma(void) { // 0x88E8D9 + static const SpawnHdmaObject_Args unk_88E8E4 = { 0x41, 0x26, 0xe8ec }; + SpawnHdmaObject(0x88, &unk_88E8E4); +} + +uint16 HdmaobjInstr_InitMorphBallEyeBeamHdma(uint16 k, uint16 j) { // 0x88E917 + unsigned int v2; // kr00_4 + unsigned int v3; // kr04_4 + + *((uint8 *)hdma_object_A + k) = 48; + reg_COLDATA[0] = 48; + *((uint8 *)hdma_object_A + k + 1) = 80; + reg_COLDATA[1] = 80; + *((uint8 *)hdma_object_B + k) = 0x80; + reg_COLDATA[2] = 0x80; + fx_layer_blending_config_c = 16; + kraid_unk9000 = 228; + v2 = 14979328; + *(uint16 *)((char *)&g_word_7E9002 + 1) = HIWORD(v2); + *(uint16 *)((char *)&kraid_unk9000 + 1) = v2; + g_word_7E9004 = -28216; + g_word_7E9006 = 152; + v3 = 37520; + *(uint16 *)((char *)&g_word_7E9008 + 1) = HIWORD(v3); + *(uint16 *)((char *)&g_word_7E9006 + 1) = v3; + enemy_data[1].ai_var_C = 1; + int v4 = k >> 1; + hdma_object_C[v4] = 0; + hdma_object_D[v4] = 0; + g_word_7E9080 = 0; + g_word_7E9082 = 0; + g_word_7E9090 = 0; + return j; +} + +void sub_88E987(uint16 v0) { // 0x88E987 + uint16 v3 = v0; + R18_ = enemy_data[1].ai_var_D; + R20_ = hdma_object_C[v0 >> 1]; + uint16 v1 = enemy_data[1].y_pos - layer1_y_pos; + uint16 v2 = enemy_data[1].x_pos - layer1_x_pos; + if ((int16)(enemy_data[1].x_pos - layer1_x_pos) >= 0 && sign16(enemy_data[1].x_pos - layer1_x_pos - 256)) { + R0_.bank = 126; + R0_.addr = ADDR16_OF_RAM(g_word_7E9100); + CalculateXrayHdmaTable_OriginOnScreen(v2, v1); + } else { + R0_.bank = 126; + R0_.addr = ADDR16_OF_RAM(g_word_7E9100); + CalculateXrayHdmaTable_OriginOffScreen(v2, v1); + } + reg_COLDATA[0] = *((uint8 *)hdma_object_A + v3); + reg_COLDATA[1] = *((uint8 *)hdma_object_A + v3 + 1); + reg_COLDATA[2] = *((uint8 *)hdma_object_B + v3); +} + +void HdmaobjPreInstr_E9E6(uint16 k) { // 0x88E9E6 + unsigned int v1; // kr00_4 + + fx_layer_blending_config_c = 16; + v1 = __PAIR32__(g_word_7E9080, g_word_7E9082) + 0x4000; + g_word_7E9080 = (__PAIR32__(g_word_7E9080, g_word_7E9082) + 0x4000) >> 16; + g_word_7E9082 = v1; + int v2 = k >> 1; + uint16 v3 = hdma_object_D[v2]; + hdma_object_D[v2] = v1 + v3; + uint16 v4 = g_word_7E9080 + __CFADD__uint16((uint16)v1, v3) + hdma_object_C[v2]; + hdma_object_C[v2] = v4; + if (!sign16(v4 - 4)) { + hdma_object_C[v2] = 4; + int v5 = hdma_object_index >> 1; + hdma_object_instruction_list_pointers[v5] += 2; + hdma_object_instruction_timers[v5] = 1; + } + sub_88E987(k); +} + +#define g_byte_88EA8B ((uint8*)RomPtr(0x88ea8b)) + +void HdmaobjPreInstr_EA3C(uint16 k) { // 0x88EA3C + fx_layer_blending_config_c = 16; + if (enemy_data[1].ai_var_C) { + sub_88E987(k); + uint16 v2 = 4 * g_word_7E9090; + *((uint8 *)hdma_object_A + k) = g_byte_88EA8B[(uint16)(4 * g_word_7E9090)]; + *((uint8 *)hdma_object_A + k + 1) = g_byte_88EA8B[v2 + 1]; + *((uint8 *)hdma_object_B + k) = g_byte_88EA8B[v2 + 2]; + g_word_7E9090 = ((uint8)g_word_7E9090 + 1) & 0xF; + } else { + int v1 = hdma_object_index >> 1; + hdma_object_instruction_list_pointers[v1] += 2; + hdma_object_instruction_timers[v1] = 1; + } +} + +void HdmaobjPreInstr_EACB(uint16 k) { // 0x88EACB + fx_layer_blending_config_c = 16; + if (*((uint8 *)hdma_object_A + k + 1) == 64) { + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + int v1 = k >> 1; + hdma_object_D[v1] = 0; + hdma_object_C[v1] = 0; + for (int i = 510; i >= 0; i -= 2) + *(uint16 *)((char *)&g_word_7E9100 + (uint16)i) = 255; + kraid_unk9000 = 0; + g_word_7E9002 = 0; + g_word_7E9004 = 0; + g_word_7E9006 = 0; + g_word_7E9008 = 0; + int v3 = hdma_object_index >> 1; + hdma_object_instruction_list_pointers[v3] += 2; + hdma_object_instruction_timers[v3] = 1; + } else { + sub_88E987(k); + uint16 v4 = hdma_object_index; + if (*((uint8 *)hdma_object_A + hdma_object_index) != 32) + -- *((uint8 *)hdma_object_A + hdma_object_index); + if (*((uint8 *)hdma_object_A + v4 + 1) != 64) + -- *((uint8 *)hdma_object_A + v4 + 1); + if (*((uint8 *)hdma_object_B + v4) != 0x80) + -- *((uint8 *)hdma_object_B + v4); + } +} + +void SpawnTitleScreenGradientObjs(void) { // 0x88EB58 + static const SpawnHdmaObject_Args unk_88EB6B = { 0x00, 0x31, 0xeb85 }; + static const SpawnHdmaObject_Args unk_88EB63 = { 0x00, 0x32, 0xeb73 }; + SpawnHdmaObject(0x88, &unk_88EB63); + SpawnHdmaObject(0x88, &unk_88EB6B); +} + +uint16 HdmaobjInsr_ConfigTitleSequenceGradientHDMA(uint16 k, uint16 j) { // 0x88EB9F + reg_CGWSEL = 0; + ConfigureTitleSequenceGradientHDMA(); + return j; +} + +void HdmaobjPreInstr_Backdrop_TitleSequenceGradient(uint16 k) { // 0x88EBB0 + ConfigureTitleSequenceGradientHDMA(); + if (cinematic_function == FUNC16(CinematicFunctionOpening)) { + int v1 = hdma_object_index >> 1; + hdma_object_instruction_list_pointers[v1] += 2; + hdma_object_instruction_timers[v1] = 1; + } +} + +void HdmaobjPreInstr_ColorMathControlB_TitleGradient(uint16 k) { // 0x88EBD2 + if (cinematic_function == FUNC16(CinematicFunctionOpening)) { + int v1 = hdma_object_index >> 1; + hdma_object_instruction_list_pointers[v1] += 2; + hdma_object_instruction_timers[v1] = 1; + } +} + +void SpawnIntroCutsceneCrossfadeHdma(void) { // 0x88EBF0 + static const SpawnHdmaObject_Args unk_88EBFB = { 0x00, 0x31, 0xec03 }; + SpawnHdmaObject(0x88, &unk_88EBFB); +} + +void HdmaobjPreInstr_IntroCutsceneCrossfade(uint16 k) { // 0x88EC1D + if (enemy_projectile_x_pos[0] == 1) { + int v1 = hdma_object_index >> 1; + hdma_object_instruction_list_pointers[v1] += 2; + hdma_object_instruction_timers[v1] = 1; + } +} + +void CinematicFunction_Intro_Func133(void) { // 0x88EC3B + unsigned int v0; // kr00_4 + unsigned int v1; // kr04_4 + + g_word_7E0D9C = 1; + *(uint16 *)&g_byte_7E0D9E = 0x4000; + loop_counter_transfer_enemies_to_vram = 8; + grapple_beam_tmpD82 = 192; + grapple_beam_y_quarter_vel = 192; + v0 = 12621824; + *(uint16 *)((char *)&grapple_beam_tmpD84 + 1) = HIWORD(v0); + *(uint16 *)((char *)&grapple_beam_tmpD82 + 1) = v0; + grapple_beam_y_quarter_subvel = -26496; + v1 = 12621824; + *(uint16 *)((char *)&grapple_beam_tmpD8A + 1) = HIWORD(v1); + *(uint16 *)((char *)&grapple_beam_y_quarter_vel + 1) = v1; + grapple_beam_varD8C = -26496; + grapple_beam_varD8E = 0; + static const SpawnHdmaObject_Args unk_88EC82 = { 0x42, 0x11, 0xec8a }; + SpawnHdmaObject(0x88, &unk_88EC82); +} + +uint16 HdmaobjInstr_EC9F_ClearVars(uint16 k, uint16 j) { // 0x88EC9F + int v2 = k >> 1; + hdma_object_A[v2] = -2; + hdma_object_B[v2] = 1; + hdma_object_C[v2] = 0; + hdma_object_D[v2] = 0; + return j; +} + +void HdmaobjPreInstr_ECB6(uint16 k) { // 0x88ECB6 + int16 v7; + uint16 v8; + + if (g_word_7E0D9C) { + R28_ = 4; + g_word_7E001E = 128; + R18_ = 2 * loop_counter_transfer_enemies_to_vram; + int v3 = k >> 1; + hdma_object_A[v3] = (2 * loop_counter_transfer_enemies_to_vram + hdma_object_A[v3]) & 0x1FF; + R20_ = hdma_object_A[v3]; + uint16 v4 = 0; + do { + uint16 v10 = v4; + uint16 v5 = R20_; + int v6 = R20_ >> 1; + v7 = kSinCosTable8bit_Sext[v6 + 64]; + if (v7 < 0) { + R18_ = -v7; + R22_ = Mult8x8(-(int8)v7, g_byte_7E0D9E) >> 8; + R22_ += Mult8x8(HIBYTE(R18_), g_byte_7E0D9E); + R24_ = Mult8x8(R18_, g_byte_7E0D9F); + uint8 mult = Mult8x8(HIBYTE(R18_), g_byte_7E0D9F); + R22_ += R24_; + R18_ = (uint8)((uint16)((R22_ + (mult << 8)) & 0xFF00) >> 8); + R20_ = (R28_ + v5) & 0x1FF; + v8 = v10; + hdma_table_1[v10 >> 1] = reg_BG3HOFS - R18_; + } else { + R18_ = kSinCosTable8bit_Sext[v6 + 64]; + R22_ = Mult8x8(v7, g_byte_7E0D9E) >> 8; + R22_ += Mult8x8(HIBYTE(R18_), g_byte_7E0D9E); + R24_ = Mult8x8(R18_, g_byte_7E0D9F); + uint8 mult = Mult8x8(HIBYTE(R18_), g_byte_7E0D9F); + R22_ += R24_; + R18_ = (uint8)((uint16)((R22_ + (mult << 8)) & 0xFF00) >> 8); + R20_ = (R28_ + v5) & 0x1FF; + v8 = v10; + hdma_table_1[v10 >> 1] = R18_ + reg_BG3HOFS; + } + v4 = v8 + 2; + } while ((int16)(v4 - g_word_7E001E) < 0); + for (int i = 126; i >= 0; i -= 2) + hdma_table_1[(i >> 1) + 64] = reg_BG3HOFS + reg_BG3HOFS - hdma_table_1[i >> 1]; + } else { + int v2 = hdma_object_index >> 1; + hdma_object_instruction_list_pointers[v2] += 2; + hdma_object_instruction_timers[v2] = 1; + } +} diff --git a/src/sm_89.c b/src/sm_89.c new file mode 100644 index 0000000..295cb77 --- /dev/null +++ b/src/sm_89.c @@ -0,0 +1,182 @@ +// Item PLM graphics, FX loader + +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" + +#define g_word_89AA02 ((uint16*)RomPtr(0x89aa02)) +void LoadFxEntry(uint16 v0) { // 0x89AB02 + FxDef *FxDef; + + current_fx_entry_offset = 16 * (v0 & 7); + current_fx_entry_ptr = room_layer3_asm_ptr + current_fx_entry_offset; + FxDef = get_FxDef(room_layer3_asm_ptr + current_fx_entry_offset); + fx_base_y_pos = FxDef->base_y_pos; + fx_target_y_pos = FxDef->target_y_pos; + fx_y_vel = FxDef->y_vel; + fx_timer = FxDef->timer; + fx_layer_blending_config_a = FxDef->default_layer_blend; + fx_layer_blending_config_b = FxDef->layer3_layer_blend; + fx_liquid_options = FxDef->fx_liquid_options_; + if (FxDef->palette_blend) { + int v2 = FxDef->palette_blend >> 1; + palette_buffer[25] = g_word_89AA02[v2]; + palette_buffer[26] = g_word_89AA02[v2 + 1]; + palette_buffer[27] = g_word_89AA02[v2 + 2]; + } else { + palette_buffer[27] = 0; + } +} + +void nullsub_106(void) {} + +#define kFxTypeTilemapPtrs ((uint16*)RomPtr(0x83abf0)) +static Func_V *const kFxTypeFuncPtrs[23] = { // 0x89AB82 + nullsub_106, + FxTypeFunc_2_Lava, + FxTypeFunc_4_Acid, + FxTypeFunc_6_Water, + FxTypeFunc_8_Spores, + FxTypeFunc_A_Rain, + FxTypeFunc_C, + nullsub_106, + nullsub_106, + nullsub_106, + nullsub_106, + nullsub_106, + nullsub_106, + nullsub_106, + nullsub_106, + nullsub_106, + FxTypeFunc_20, + FxTypeFunc_22_ScrollingSky, + FxTypeFunc_24, + FxTypeFunc_26_TourianEntranceStatue, + FxTypeFunc_28_CeresRidley, + FxTypeFunc_CeresElevator, + FxTypeFunc_2C_Haze, +}; +#define kAreaPalFxListPointers ((uint16*)RomPtr(0x83ac46)) +#define kAreaAnimtilesListPtrs ((uint16*)RomPtr(0x83ac56)) +void LoadFXHeader(void) { + int i; + FxDef *v6; + FxDef *v8; + uint16 j; + char v10; // cf + FxDef *v12; + uint16 k; + FxDef *FxDef; + + uint16 v0 = room_layer3_asm_ptr; + if (room_layer3_asm_ptr) { + for (i = 0; ; i += 16) { + uint16 door_ptr = get_FxDef(v0)->door_ptr; + if (!door_ptr) + break; + if (door_ptr == 0xFFFF) + return; + if (door_ptr == door_def_ptr) + break; + v0 += 16; + } + current_fx_entry_offset = i; + current_fx_entry_ptr = v0; + FxDef = get_FxDef(v0); + fx_base_y_pos = FxDef->base_y_pos; + fx_target_y_pos = FxDef->target_y_pos; + fx_y_vel = FxDef->y_vel; + fx_timer = FxDef->timer; + fx_layer_blending_config_a = FxDef->default_layer_blend; + fx_layer_blending_config_b = FxDef->layer3_layer_blend; + fx_liquid_options = FxDef->fx_liquid_options_; + if (FxDef->palette_blend) { + int v4 = FxDef->palette_blend >> 1; + target_palettes[25] = g_word_89AA02[v4]; + target_palettes[26] = g_word_89AA02[v4 + 1]; + target_palettes[27] = g_word_89AA02[v4 + 2]; + } else { + target_palettes[27] = 0; + } + uint16 type = get_FxDef(current_fx_entry_ptr)->type; + fx_type = type; + if (type) + fx_tilemap_ptr = kFxTypeTilemapPtrs[type >> 1]; + v6 = get_FxDef(current_fx_entry_ptr); + uint16 v7 = v6->type; + if (v6->type) { + *(uint16 *)((char *)&R18_ + 1) = -30720; + kFxTypeFuncPtrs[v7 >> 1](); + } + v8 = get_FxDef(current_fx_entry_ptr); + if (v8->palette_fx_bitset) { + current_fx_palette_fx_bitset = v8->palette_fx_bitset; + current_region_animated_palette_fx = kAreaPalFxListPointers[area_index]; + for (j = 0; j != 16; j += 2) { + while (1) { + v10 = current_fx_palette_fx_bitset & 1; + current_fx_palette_fx_bitset >>= 1; + if (!v10) + break; + uint8 *v11 = RomPtr_83(current_region_animated_palette_fx); + SpawnPalfxObject(*(uint16 *)&v11[j]); + j += 2; + } + } + } + v12 = get_FxDef(current_fx_entry_ptr); + if (v12->animtiles_bitset) { + current_fx_palette_fx_bitset = v12->animtiles_bitset; + current_region_animated_palette_fx = kAreaAnimtilesListPtrs[area_index]; + for (k = 0; k != 16; k += 2) { + while (1) { + v10 = current_fx_palette_fx_bitset & 1; + current_fx_palette_fx_bitset >>= 1; + if (!v10) + break; + uint8 *v14 = RomPtr_83(current_region_animated_palette_fx); + SpawnAnimtiles(*(uint16 *)&v14[k]); + k += 2; + } + } + } + } +} +#define g_word_89AD5F ((uint16*)RomPtr(0x89ad5f)) +void RoomCode_CeresElevatorShaft(void) { // 0x89ACC3 + int16 v1; + + if ((ceres_status & 0x8000u) != 0) { + if ((int16)(112 - samus_x_pos) < 0 + && (int16)(144 - samus_x_pos) >= 0 + && sign16(samus_y_pos - 128) + && !sign16(samus_y_pos - 75) + && !samus_y_speed + && !samus_y_subspeed + && game_state == kGameState_8_MainGameplay) { + CallSomeSamusCode(2u); + screen_fade_delay = 0; + screen_fade_counter = 0; + game_state = 32; + } + -- *(uint16 *)&room_main_asm_variables[2]; + if (*(int16 *)&room_main_asm_variables[2] < 0) { + int v0 = (uint16)(6 * *(uint16 *)room_main_asm_variables) >> 1; + *(uint16 *)&room_main_asm_variables[2] = g_word_89AD5F[v0]; + reg_M7B = g_word_89AD5F[v0 + 1]; + reg_M7C = -reg_M7B; + reg_M7A = g_word_89AD5F[v0 + 2]; + reg_M7D = reg_M7A; + if (*(int16 *)room_main_asm_variables < 0) { + v1 = *(uint16 *)room_main_asm_variables - 1; + if (*(uint16 *)room_main_asm_variables == 0x8001) + v1 = 0; + } else { + v1 = *(uint16 *)room_main_asm_variables + 1; + if (*(uint16 *)room_main_asm_variables == 67) + v1 = -32700; + } + *(uint16 *)room_main_asm_variables = v1; + } + } +} diff --git a/src/sm_8b.c b/src/sm_8b.c new file mode 100644 index 0000000..288039a --- /dev/null +++ b/src/sm_8b.c @@ -0,0 +1,6882 @@ +// Non gameplay routines +#include "sm_rtl.h" +#include "ida_types.h" +#include "funcs.h" +#include "variables.h" + +#define kPalettes_Intro ((uint16*)RomPtr(0x8ce3e9)) +#define kPalettes_Intro2 ((uint16*)RomPtr(0x8ce5e9)) +#define kPalettes_Intro4 ((uint16*)RomPtr(0x8ce7e9)) +#define kPalettes_Intro5 ((uint16*)RomPtr(0x8ce9e9)) +#define kPalettes_Intro6 ((uint16*)RomPtr(0x8cebe9)) +#define kPalettes_Intro3 ((uint16*)RomPtr(0x8cede9)) +#define g_word_8CD81B ((uint16*)RomPtr(0x8cd81b)) +#define g_word_8BA72B ((uint16*)RomPtr(0x8ba72b)) +#define kLevelData_MotherBrainRoomFromCutscene ((uint16*)RomPtr(0x8cbec3)) +#define kLevelData_RoomWithBabyMetroidHatching ((uint16*)RomPtr(0x8cc083)) +#define g_word_8CDC9B ((uint16*)RomPtr(0x8cdc9b)) +#define g_word_8CDEDB ((uint16*)RomPtr(0x8cdedb)) +#define g_word_8CEFE9 ((uint16*)RomPtr(0x8cefe9)) +#define g_off_8BE70D ((uint16*)RomPtr(0x8be70d)) +#define g_word_8BE717 ((uint16*)RomPtr(0x8be717)) +#define g_word_8BE721 ((uint16*)RomPtr(0x8be721)) +#define g_word_8BE737 ((uint16*)RomPtr(0x8be737)) +#define g_word_8BE741 ((uint16*)RomPtr(0x8be741)) +#define g_word_8BE9CF ((uint16*)RomPtr(0x8be9cf)) +#define kCinematicFunction_Intro_Func142_Tab0 ((uint16*)RomPtr(0x8be45a)) +#define kCinematicFunction_Intro_Func144_Tab0 ((uint16*)RomPtr(0x8be5e7)) +#define g_word_8CDF5B ((uint16*)RomPtr(0x8cdf5b)) +#define g_word_8BE9A7 ((uint16*)RomPtr(0x8be9a7)) +#define g_word_8BF6B8 ((uint16*)RomPtr(0x8bf6b8)) +#define g_word_8BF6D8 ((uint16*)RomPtr(0x8bf6d8)) +#define g_word_8CE1E9 ((uint16*)RomPtr(0x8ce1e9)) + +void SetupPpuForTitleSequence(void) { // 0x8B8000 + WriteReg(INIDISP, 0x80); + reg_INIDISP = 0x80; + WriteReg(OBSEL, 3u); + reg_OBSEL = 3; + WriteReg(BGMODE, 7u); + reg_BGMODE = 7; + WriteReg(M7SEL, 0x80); + reg_M7SEL = 0x80; + reg_BG1SC = 0; + WriteReg(BG1SC, 0); + reg_BG2SC = 0; + WriteReg(BG2SC, 0); + reg_BG3SC = 0; + WriteReg(BG3SC, 0); + reg_BG4SC = 0; + WriteReg(BG4SC, 0); + reg_BG12NBA = 0; + WriteReg(BG12NBA, 0); + reg_BG34NBA = 0; + WriteReg(BG34NBA, 0); + WriteReg(TM, 0x10u); + reg_TM = 16; + WriteReg(TS, 0); + reg_TS = 0; + WriteReg(TMW, 0); + reg_TMW = 0; + WriteReg(VMAIN, 0); + WriteReg(CGWSEL, 0); + next_gameplay_CGWSEL = 0; + WriteReg(CGADSUB, 0); + next_gameplay_CGADSUB = 0; + WriteReg(COLDATA, 0xE0u); + WriteReg(SETINI, 0); + reg_SETINI = 0; + memset7E(0x3000u, 0, 0x7FEu); + oam_next_ptr = 0; + menu_option_index = 0; + screen_fade_delay = 0; + screen_fade_counter = 0; + pausemenu_start_lr_pressed_highlight_timer = 0; + pausemenu_lr_animation_timer = 0; + pausemenu_item_selector_animation_timer = 0; + pausemenu_reserve_tank_animation_timer = 0; + UNUSED_word_7E0731 = 0; + UNUSED_word_7E073D = 0; + pausemenu_lr_animation_frame = 0; + pausemenu_item_selector_animation_frame = 0; + pausemenu_reserve_tank_animation_frame = 0; + UNUSED_word_7E0745 = 0; + pausemenu_shoulder_button_highlight = 0; + pausemenu_button_label_mode = 0; + pausemenu_equipment_category_item = 0; + pausemenu_reserve_tank_delay_ctr = 0; + UNUSED_word_7E0759 = 0; + samus_reserve_health = 0; + samus_reserve_missiles = 0; + cinematic_var5 = 0; + cinematic_var6 = 256; + cinematic_var7 = 0; + cinematic_var8 = 0; + cinematic_var9 = 0; + cinematic_var10 = 0; + g_word_7E1999 = 0; + g_word_7E199B = 0; + g_word_7E199D = 0; + g_word_7E199F = 0; +} + +void SetupPpu_Intro(void) { // 0x8B80DA + WriteReg(INIDISP, 0x80); + reg_INIDISP = 0x80; + WriteReg(OBSEL, 3u); + reg_OBSEL = 3; + WriteReg(BGMODE, 9u); + reg_BGMODE = 9; + WriteReg(M7SEL, 0); + reg_M7SEL = 0; + reg_BG1SC = 80; + WriteReg(BG1SC, 0x50u); + reg_BG2SC = 72; + WriteReg(BG2SC, 0x48u); + reg_BG3SC = 76; + WriteReg(BG3SC, 0x4Cu); + reg_BG4SC = 0; + WriteReg(BG4SC, 0); + reg_BG12NBA = 0; + WriteReg(BG12NBA, 0); + reg_BG34NBA = 4; + WriteReg(BG34NBA, 4u); + WriteReg(TM, 4u); + reg_TM = 4; + WriteReg(TS, 0); + reg_TS = 0; + WriteReg(TMW, 0); + reg_TMW = 0; + WriteReg(VMAIN, 0); + WriteReg(CGWSEL, 0); + next_gameplay_CGWSEL = 0; + WriteReg(CGADSUB, 0); + next_gameplay_CGADSUB = 0; + WriteReg(COLDATA, 0xE0u); + WriteReg(SETINI, 0); + reg_SETINI = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + reg_MOSAIC = 0; + memset7E(0x3000u, 0x2Fu, 0x7FEu); + oam_next_ptr = 0; + cinematic_var5 = 0; + cinematic_var6 = 256; + cinematic_var7 = 0; + cinematic_var8 = 0; + cinematic_var9 = 0; + cinematic_var10 = 0; + g_word_7E1999 = 0; + g_word_7E199B = 0; + g_word_7E199D = 0; + g_word_7E199F = 0; + fx_layer_blending_config_a = 0; + reg_BG2HOFS = 0; + reg_BG2VOFS = 0; + reg_BG3HOFS = 0; + reg_BG3VOFS = 0; +} + +void SetupPpu_3_Mode7(void) { // 0x8B819B + WriteReg(INIDISP, 0x80); + reg_INIDISP = 0x80; + WriteReg(OBSEL, 3u); + reg_OBSEL = 3; + WriteReg(BGMODE, 7u); + reg_BGMODE = 7; + WriteReg(M7SEL, 0x80); + reg_M7SEL = 0x80; + reg_BG1SC = 0; + WriteReg(BG1SC, 0); + reg_BG2SC = 0; + WriteReg(BG2SC, 0); + reg_BG3SC = 0; + WriteReg(BG3SC, 0); + reg_BG4SC = 0; + WriteReg(BG4SC, 0); + reg_BG12NBA = 0; + WriteReg(BG12NBA, 0); + reg_BG34NBA = 0; + WriteReg(BG34NBA, 0); + WriteReg(TM, 0x11u); + reg_TM = 17; + WriteReg(TS, 0); + reg_TS = 0; + WriteReg(TMW, 0); + reg_TMW = 0; + WriteReg(VMAIN, 0); + WriteReg(CGWSEL, 0); + next_gameplay_CGWSEL = 0; + WriteReg(CGADSUB, 0); + next_gameplay_CGADSUB = 0; + WriteReg(COLDATA, 0xE0u); + reg_CGWSEL = 0; + reg_CGADSUB = 0; + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + reg_MOSAIC = 0; + cinematic_var7 = 0; + cinematic_var8 = 0; + cinematic_var9 = 0; + cinematic_var10 = 0; + g_word_7E1999 = 0; + g_word_7E199B = 0; + g_word_7E199D = 0; + g_word_7E199F = 0; + fx_layer_blending_config_a = 0; +} + +void SetupPpu_4_Mode1(void) { // 0x8B8230 + WriteReg(INIDISP, 0x80); + reg_INIDISP = 0x80; + WriteReg(OBSEL, 3u); + reg_OBSEL = 3; + WriteReg(BGMODE, 1u); + reg_BGMODE = 1; + WriteReg(M7SEL, 0); + reg_M7SEL = 0; + reg_BG1SC = 92; + WriteReg(BG1SC, 0x5Cu); + reg_BG2SC = 0; + WriteReg(BG2SC, 0); + reg_BG3SC = 0; + WriteReg(BG3SC, 0); + reg_BG4SC = 0; + WriteReg(BG4SC, 0); + reg_BG12NBA = 6; + WriteReg(BG12NBA, 6u); + reg_BG34NBA = 0; + WriteReg(BG34NBA, 0); + WriteReg(TM, 0x11u); + reg_TM = 17; + WriteReg(TS, 0); + reg_TS = 0; + reg_W12SEL = 0; + reg_W34SEL = 0; + reg_WOBJSEL = 0; + reg_TMW = 0; + reg_TSW = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + reg_BG1HOFS = 0; + reg_BG1VOFS = 0; +} + +void SetupPpu_5_Mode7(void) { // 0x8B8293 + WriteReg(INIDISP, 0x80); + reg_INIDISP = 0x80; + WriteReg(OBSEL, 0xA3u); + reg_OBSEL = -93; + WriteReg(BGMODE, 7u); + reg_BGMODE = 7; + WriteReg(M7SEL, 0); + reg_M7SEL = 0; + reg_BG1SC = 0; + WriteReg(BG1SC, 0); + reg_BG2SC = 0; + WriteReg(BG2SC, 0); + reg_BG3SC = 0; + WriteReg(BG3SC, 0); + reg_BG4SC = 0; + WriteReg(BG4SC, 0); + reg_BG12NBA = 0; + WriteReg(BG12NBA, 0); + reg_BG34NBA = 0; + WriteReg(BG34NBA, 0); + WriteReg(TM, 0x11u); + reg_TM = 17; + WriteReg(TS, 0); + reg_TS = 0; + WriteReg(TMW, 0); + reg_TMW = 0; + WriteReg(VMAIN, 0); + WriteReg(CGWSEL, 0); + next_gameplay_CGWSEL = 0; + WriteReg(CGADSUB, 0); + next_gameplay_CGADSUB = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + WriteReg(COLDATA, 0xE0u); + WriteReg(SETINI, 0); + reg_SETINI = 0; + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + oam_next_ptr = 0; + screen_fade_delay = 0; + screen_fade_counter = 0; + cinematic_var5 = 0; + cinematic_var6 = 256; + cinematic_var7 = 0; + cinematic_var8 = 0; + cinematic_var9 = 0; + cinematic_var10 = 0; + g_word_7E1999 = 0; + g_word_7E199B = 0; + g_word_7E199D = 0; + g_word_7E199F = 0; +} + +void SetupPpu_6_Mode1(void) { // 0x8B833A + WriteReg(INIDISP, 0x80); + reg_INIDISP = 0x80; + WriteReg(OBSEL, 2u); + reg_OBSEL = 2; + WriteReg(BGMODE, 1u); + reg_BGMODE = 1; + WriteReg(M7SEL, 0); + reg_M7SEL = 0; + reg_BG1SC = 112; + WriteReg(BG1SC, 0x70u); + reg_BG2SC = 120; + WriteReg(BG2SC, 0x78u); + reg_BG3SC = 0; + WriteReg(BG3SC, 0); + reg_BG4SC = 0; + WriteReg(BG4SC, 0); + reg_BG12NBA = 68; + WriteReg(BG12NBA, 0x44u); + reg_BG34NBA = 0; + WriteReg(BG34NBA, 0); + WriteReg(TM, 0x10u); + reg_TM = 16; + WriteReg(TS, 0); + reg_TS = 0; + WriteReg(TMW, 0); + reg_TMW = 0; + WriteReg(VMAIN, 0); + WriteReg(CGWSEL, 0); + next_gameplay_CGWSEL = 0; + WriteReg(CGADSUB, 0); + next_gameplay_CGADSUB = 0; + WriteReg(COLDATA, 0xE0u); + reg_CGWSEL = 0; + reg_CGADSUB = 0; + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + reg_MOSAIC = 0; + cinematic_var7 = 0; + cinematic_var8 = 0; + cinematic_var9 = 0; + cinematic_var10 = 0; + g_word_7E1999 = 0; + g_word_7E199B = 0; + g_word_7E199D = 0; + g_word_7E199F = 0; + fx_layer_blending_config_a = 0; + reg_BG2HOFS = 0; + reg_BG2VOFS = 0; +} + +void SetupPpu_7_Mode1(void) { // 0x8B83D3 + WriteReg(INIDISP, 0x80); + reg_INIDISP = 0x80; + WriteReg(OBSEL, 0); + reg_OBSEL = 0; + WriteReg(BGMODE, 1u); + reg_BGMODE = 1; + WriteReg(M7SEL, 0); + reg_M7SEL = 0; + reg_BG1SC = 72; + WriteReg(BG1SC, 0x48u); + reg_BG2SC = 76; + WriteReg(BG2SC, 0x4Cu); + reg_BG3SC = 36; + WriteReg(BG3SC, 0x24u); + reg_BG4SC = 0; + WriteReg(BG4SC, 0); + reg_BG12NBA = 84; + WriteReg(BG12NBA, 0x54u); + reg_BG34NBA = 2; + WriteReg(BG34NBA, 2u); + WriteReg(TM, 1u); + reg_TM = 1; + WriteReg(TS, 0); + reg_TS = 0; + reg_W12SEL = 0; + reg_W34SEL = 0; + reg_WOBJSEL = 0; + reg_TMW = 0; + reg_TSW = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + oam_next_ptr = 0; + WriteRegWord(M7A, 0x100u); + reg_M7A = 256; + WriteRegWord(M7B, 0); + reg_M7B = 0; + WriteRegWord(M7C, 0); + reg_M7C = 0; + WriteRegWord(M7D, 0x100u); + reg_M7D = 256; + WriteRegWord(M7X, 0x80); + reg_M7X = 128; + WriteRegWord(M7Y, 0x80); + reg_M7Y = 128; + cinematic_var5 = 0; + cinematic_var6 = 1; + reg_BG1HOFS = 0; + reg_BG1VOFS = 0; + reg_BG2HOFS = 0; + reg_BG2VOFS = 0; + cinematic_var7 = 0; + cinematic_var8 = 0; + cinematic_var9 = 0; + cinematic_var10 = 0; +} + +void HandleMode7TransformationNoRotation(void) { // 0x8B8518 + reg_M7A = cinematic_var6; + reg_M7D = cinematic_var6; + reg_M7B = 0; + reg_M7C = 0; + reg_BG1HOFS = cinematic_var8; + reg_BG1VOFS = cinematic_var10; +} + +void HandleMode7TransformationMatrix(void) { // 0x8B8532 + uint16 v0; + uint16 v1; + + R38 = kSinCosTable8bit_Sext[((uint16)(2 * (uint8)(cinematic_var5 + 64)) >> 1) + 64]; + R40 = cinematic_var6; + Smult16x16Shr16(); + HIBYTE(v0) = R42; + LOBYTE(v0) = HIBYTE(R44); + reg_M7A = v0; + reg_M7D = v0; + R38 = kSinCosTable8bit_Sext[((uint16)(2 * (uint8)cinematic_var5) >> 1) + 64]; + R40 = cinematic_var6; + Smult16x16Shr16(); + HIBYTE(v1) = R42; + LOBYTE(v1) = HIBYTE(R44); + reg_M7B = v1; + reg_M7C = -v1; + reg_BG1HOFS = cinematic_var8; + reg_BG1VOFS = cinematic_var10; +} + + +void Smult16x16Shr16(void) { // 0x8B858F + if ((R38 & 0x8000u) == 0) { + if ((R40 & 0x8000u) != 0) { + R40 = -R40; + Umult16x16Shr16(); + Negate32(&R42, &R44, &R42, &R44); + } else { + Umult16x16Shr16(); + } + } else { + R38 = -R38; + if ((R40 & 0x8000u) != 0) { + R40 = -R40; + Umult16x16Shr16(); + } else { + Umult16x16Shr16(); + Negate32(&R42, &R44, &R42, &R44); + } + } +} + +void Umult16x16Shr16(void) { // 0x8B85EE + R44 = Mult8x8(R38, R40); + R46 = Mult8x8(HIBYTE(R38), R40); + R48 = Mult8x8(R38, HIBYTE(R40)); + uint16 RegWord = Mult8x8(HIBYTE(R38), HIBYTE(R40)); + R42 = RegWord; + R46 += R48; + bool v1 = __CFADD__uint8(HIBYTE(R44), (uint8)R46); + HIBYTE(R44) += R46; + LOBYTE(R42) = RegWord + v1 + HIBYTE(R46); + if (__CFADD__uint8(v1, HIBYTE(R46)) | __CFADD__uint8((uint8)RegWord, v1 + HIBYTE(R46))) + ++HIBYTE(R42); +} + +void HandleFadeIn_(void) { // 0x8B8666 + HandleFadeIn(); +} + +void SetPpuBackdropSomeColor(void) { // 0x8B866B + reg_CGWSEL = 0; + reg_CGADSUB = -127; + reg_COLDATA[0] = 56; + reg_COLDATA[1] = 88; + reg_COLDATA[2] = 0x80; +} + +void SetPpuBackdropBlack(void) { // 0x8B8682 + reg_CGWSEL = 0; + reg_CGADSUB = 0; + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; +} + +void UpdateCinematicBgTilemap(void) { // 0x8B87A0 + if (reg_BGMODE != 7) { + uint16 v0 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 1920; + v0 += 2; + gVramWriteEntry(v0)->size = 12288; + v0 += 2; + LOBYTE(gVramWriteEntry(v0++)->size) = 126; + gVramWriteEntry(v0)->size = cinematicbg_var3; + vram_write_queue_tail = v0 + 2; + } +} + +void UpdateSamusEyesTilemap(void) { // 0x8B87D3 + if (reg_BGMODE != 7) { + uint16 v0 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 128; + v0 += 2; + gVramWriteEntry(v0)->size = ADDR16_OF_RAM(ram3800) + 832; + v0 += 2; + LOBYTE(gVramWriteEntry(v0++)->size) = 126; + gVramWriteEntry(v0)->size = 18848; + vram_write_queue_tail = v0 + 2; + } +} + +void CinematicUpdateSomeBg(void) { // 0x8B8806 + if (reg_BGMODE != 7) { + uint16 v0 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 2048; + v0 += 2; + gVramWriteEntry(v0)->size = ADDR16_OF_RAM(ram3000); + v0 += 2; + LOBYTE(gVramWriteEntry(v0++)->size) = 126; + gVramWriteEntry(v0)->size = cinematicbg_var3; + vram_write_queue_tail = v0 + 2; + } +} + +void CallProcessCinematicBgObject(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnProcessCinematicBgObject_Nothing: ProcessCinematicBgObject_Nothing(k, j); return; + case fnProcessCinematicBgObject_DrawChar: ProcessCinematicBgObject_DrawChar(k, j); return; + case fnProcessCinematicBgObject_DrawToTextTilemap: ProcessCinematicBgObject_DrawToTextTilemap(k, j); return; + case fnProcessCinematicBgObject_DrawToBgTilemap: ProcessCinematicBgObject_DrawToBgTilemap(k, j); return; + case fnProcessCinematicBgObject_Unk1: ProcessCinematicBgObject_Unk1(k, j); return; + case fnProcessCinematicBgObject_Unk2: ProcessCinematicBgObject_Unk2(k, j); return; + default: Unreachable(); + } +} +void ProcessCinematicBgObject(uint16 v0) { // 0x8B8839 + uint16 j = cinematicbg_arr1[v0 >> 1]; + R28_ = *(uint16 *)RomPtr_8C(j); + CallProcessCinematicBgObject(R28_ | 0x8B0000, v0, j); +} + +void ProcessCinematicBgObject_DrawChar(uint16 k, uint16 j) { // 0x8B884D + int16 v3; + + cinematicbg_var1 = cinematicbg_var1 == 0; + SpawnTextGlowObject(j); + uint8 *v2 = RomPtr_8C(cinematicbg_instr_ptr[k >> 1]); + if (*((int16 *)v2 + 3) < 0) { + cinematicbg_arr7[15] = 8; + v3 = 8 * (v2[3] + 2); + } else { + cinematicbg_arr7[15] = 8 * v2[8]; + v3 = 8 * v2[9]; + } + cinematicbg_arr8[15] = v3 - 8; + if (*((uint16 *)v2 + 2) != 0xD67D && cinematicbg_var1) + QueueSfx3_Max6(0xDu); + ProcessCinematicBgObject_DrawToTextTilemap(0x1Eu, j); +} + +void ProcessCinematicBgObject_DrawToTextTilemap(uint16 k, uint16 j) { // 0x8B88B7 + uint16 jorg = j; + + uint16 TilemapOffsetForTile = CinematicGetTilemapOffsetForTile(); + uint8 *v3 = RomPtr_8C(j); + R18_ = v3[2]; + R24_ = R18_; + R20_ = v3[3]; + while (1) { + do { + *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + TilemapOffsetForTile) = *((uint16 *)RomPtr_8C(j) + 2); + j += 2; + TilemapOffsetForTile += 2; + --R18_; + } while (R18_); + R18_ = R24_; + if (!--R20_) + break; + R22_ += 64; + TilemapOffsetForTile = R22_; + } +} + +void ProcessCinematicBgObject_Nothing(uint16 k, uint16 j) { // 0x8B8849 +} + +void ProcessCinematicBgObject_DrawToBgTilemap(uint16 k, uint16 j) { // 0x8B88FD + uint16 jorg = j; + + uint16 TilemapOffsetForTile = CinematicGetTilemapOffsetForTile(); + uint8 *v3 = RomPtr_8C(j); + R18_ = v3[2]; + R24_ = R18_; + R20_ = v3[3]; + while (1) { + do { + *(uint16 *)((char *)ram3800.cinematic_bg_tilemap + TilemapOffsetForTile) = *((uint16 *)RomPtr_8C(j) + 2); + j += 2; + TilemapOffsetForTile += 2; + --R18_; + } while (R18_); + R18_ = R24_; + if (!--R20_) + break; + R22_ += 64; + TilemapOffsetForTile = R22_; + } +} + +uint16 CinematicGetTilemapOffsetForTile(void) { // 0x8B8943 + R20_ = 2 * (uint8)R18_; + R22_ = R20_ + HIBYTE(R18_) * 0x40; + return R22_; +} + +void ProcessCinematicBgObject_Unk1(uint16 k, uint16 j) { // 0x8B896B + Mult0x80Add(); + uint8 *v2 = RomPtr_8C(j); + R18_ = v2[2]; + R20_ = v2[3]; + uint16 v3 = j + 4; + uint16 v4 = mode7_vram_write_queue_tail; + do { + *(uint16 *)(&mode7_write_queue[0].field_0 + v4) = 128; + *(uint16 *)((char *)&mode7_write_queue[0].field_1 + v4) = v3; + *(uint16 *)&mode7_write_queue[0].gap3[v4] = 139; + *(uint16 *)&mode7_write_queue[0].gap3[v4 + 1] = R18_; + *(uint16 *)&mode7_write_queue[0].gap3[v4 + 3] = R22_; + *(uint16 *)((char *)&mode7_write_queue[1].field_1 + v4) = 0; + v4 += 9; + v3 += R18_; + R22_ += 128; + --R20_; + } while (R20_); + mode7_vram_write_queue_tail = v4; +} + +void ProcessCinematicBgObject_Unk2(uint16 k, uint16 j) { // 0x8B89CF + Mult0x80Add(); + uint8 *v2 = RomPtr_8C(j); + R18_ = v2[2]; + R20_ = v2[3]; + uint16 v3 = j + 4; + uint16 v4 = mode7_vram_write_queue_tail; + do { + *(uint16 *)(&mode7_write_queue[0].field_0 + v4) = 128; + *(uint16 *)((char *)&mode7_write_queue[0].field_1 + v4) = v3; + *(uint16 *)&mode7_write_queue[0].gap3[v4] = 139; + *(uint16 *)&mode7_write_queue[0].gap3[v4 + 1] = R20_; + *(uint16 *)&mode7_write_queue[0].gap3[v4 + 3] = R22_; + *(uint16 *)((char *)&mode7_write_queue[1].field_1 + v4) = 2; + v4 += 9; + v3 += R20_; + ++R22_; + --R18_; + } while (R18_); + mode7_vram_write_queue_tail = v4; +} + +void Mult0x80Add(void) { // 0x8B8A2C + R20_ = (uint8)R18_; + R22_ = R20_ + (0x80 * HIBYTE(R18_)); +} + +void Samus_CalcPos_Mode7(void) { // 0x8B8A52 + uint16 v0; + int16 v1; + uint16 v2; + int16 v3; + + R34 = samus_x_pos - reg_M7X; + R36 = reg_M7Y - samus_y_pos; + R38 = samus_x_pos - reg_M7X; + R40 = reg_M7A; + Smult16x16Shr16(); + HIBYTE(v0) = R42; + LOBYTE(v0) = HIBYTE(R44); + R26_ = v0; + R38 = reg_M7B; + R40 = R36; + Smult16x16Shr16(); + HIBYTE(v1) = R42; + LOBYTE(v1) = HIBYTE(R44); + R26_ += v1; + samus_x_pos = R26_ + reg_M7X; + R38 = reg_M7C; + R40 = R34; + Smult16x16Shr16(); + HIBYTE(v2) = R42; + LOBYTE(v2) = HIBYTE(R44); + R26_ = v2; + R38 = reg_M7A; + R40 = R36; + Smult16x16Shr16(); + HIBYTE(v3) = R42; + LOBYTE(v3) = HIBYTE(R44); + R26_ += v3; + samus_y_pos = reg_M7Y - R26_; +} + +void CalcExplosion_Mode7(uint16 k) { // 0x8B8AD9 + uint16 v2; + int16 v3; + uint16 v4; + int16 v5; + + int v1 = k >> 1; + R34 = projectile_x_pos[v1] - reg_M7X; + R36 = reg_M7Y - projectile_y_pos[v1]; + R38 = R34; + R40 = reg_M7A; + Smult16x16Shr16(); + HIBYTE(v2) = R42; + LOBYTE(v2) = HIBYTE(R44); + R26_ = v2; + R38 = reg_M7B; + R40 = R36; + Smult16x16Shr16(); + HIBYTE(v3) = R42; + LOBYTE(v3) = HIBYTE(R44); + R26_ += v3; + R20_ = R26_ + reg_M7X - layer1_x_pos; + R38 = reg_M7C; + R40 = R34; + Smult16x16Shr16(); + HIBYTE(v4) = R42; + LOBYTE(v4) = HIBYTE(R44); + R26_ = v4; + R38 = reg_M7A; + R40 = R36; + Smult16x16Shr16(); + HIBYTE(v5) = R42; + LOBYTE(v5) = HIBYTE(R44); + R26_ += v5; + R18_ = reg_M7Y - R26_ - layer1_y_pos; +} + +void CalcCeresSteamPos_Mode7(void) { // 0x8B8B66 + uint16 v0; + int16 v1; + uint16 v2; + int16 v3; + + R34 = R18_ - reg_M7X; + R36 = reg_M7Y - R20_; + R38 = R18_ - reg_M7X; + R40 = reg_M7A; + Smult16x16Shr16(); + HIBYTE(v0) = R42; + LOBYTE(v0) = HIBYTE(R44); + R26_ = v0; + R38 = reg_M7B; + R40 = R36; + Smult16x16Shr16(); + HIBYTE(v1) = R42; + LOBYTE(v1) = HIBYTE(R44); + R26_ += v1; + R18_ = R26_ + reg_M7X; + R38 = reg_M7C; + R40 = R34; + Smult16x16Shr16(); + HIBYTE(v2) = R42; + LOBYTE(v2) = HIBYTE(R44); + R26_ = v2; + R38 = reg_M7A; + R40 = R36; + Smult16x16Shr16(); + HIBYTE(v3) = R42; + LOBYTE(v3) = HIBYTE(R44); + R26_ += v3; + R20_ = reg_M7Y - R26_; +} + +void CopyPalettesToFadingPalettes(void) { // 0x8B8BE9 + int16 v0; + + v0 = 256; + uint16 v1 = 0; + do { + tilemap_stuff[(v1 >> 1) + 256] = palette_buffer[v1 >> 1]; + v1 += 2; + --v0; + } while (v0); +} + +void DecomposePaletteDataForFading(void) { // 0x8B8C09 + int16 v1; + uint16 v3; + char v5; // t2 + char v7; // tt + + uint16 v0 = 0; + v1 = 256; + do { + int v2 = v0 >> 1; + R18_ = tilemap_stuff[v2 + 256]; + LOBYTE(v3) = 0; + HIBYTE(v3) = R18_ & 0x1F; + tilemap_stuff[v2 + 512] = v3; + tilemap_stuff[v2 + 1280] = 8 * HIBYTE(v3); + uint16 v4 = 8 * (R18_ & 0x3E0); + tilemap_stuff[v2 + 768] = v4; + v5 = v4; + LOBYTE(v4) = HIBYTE(v4); + HIBYTE(v4) = v5; + tilemap_stuff[v2 + 1536] = 8 * v4; + uint16 v6 = (uint16)(R18_ & 0x7C00) >> 2; + tilemap_stuff[v2 + 1024] = v6; + v7 = v6; + LOBYTE(v6) = HIBYTE(v6); + HIBYTE(v6) = v7; + tilemap_stuff[v2 + 1792] = 8 * v6; + v0 += 2; + --v1; + } while (v1); +} + +void ClearYColorsFromIndexX(uint16 k, uint16 j) { // 0x8B8C5E + do { + int v2 = k >> 1; + tilemap_stuff[v2 + 256] = 0; + tilemap_stuff[v2 + 512] = 0; + tilemap_stuff[v2 + 768] = 0; + tilemap_stuff[v2 + 1024] = 0; + k += 2; + --j; + } while (j); +} + +void FadeOutYColorsFromIndexX(uint16 k, uint16 j) { // 0x8B8C83 + do { + int v2 = k >> 1; + tilemap_stuff[v2 + 512] -= tilemap_stuff[v2 + 1280]; + tilemap_stuff[v2 + 768] -= tilemap_stuff[v2 + 1536]; + tilemap_stuff[v2 + 1024] -= tilemap_stuff[v2 + 1792]; + k += 2; + --j; + } while (j); +} + +void FadeInYColorsFromIndexX(uint16 k, uint16 j) { // 0x8B8CB2 + do { + int v2 = k >> 1; + tilemap_stuff[v2 + 512] = (tilemap_stuff[v2 + 1280] + tilemap_stuff[v2 + 512]) & 0x1FFF; + tilemap_stuff[v2 + 768] = (tilemap_stuff[v2 + 1536] + tilemap_stuff[v2 + 768]) & 0x1FFF; + tilemap_stuff[v2 + 1024] = (tilemap_stuff[v2 + 1792] + tilemap_stuff[v2 + 1024]) & 0x1FFF; + k += 2; + --j; + } while (j); +} + +void ComposeFadingPalettes(void) { // 0x8B8CEA + int16 v1; + + uint16 v0 = 0; + v1 = 256; + do { + int v2 = v0 >> 1; + R18_ = HIBYTE(tilemap_stuff[v2 + 512]) & 0x1F; + R18_ |= (tilemap_stuff[v2 + 768] >> 3) & 0x3E0; + uint16 v3 = R18_ | (4 * tilemap_stuff[v2 + 1024]) & 0x7C00; + tilemap_stuff[v2] = v3; + palette_buffer[v2] = v3; + v0 += 2; + --v1; + } while (v1); +} + +void CinematicFunction_Intro_Func20(uint16 j) { // 0x8B8D23 + uint16 *tt = (uint16 *)RomPtr_8B(j); + uint16 v2 = tt[0]; + R18_ = tt[1]; + uint16 *dst = ram4000.intro_japanese_text_tiles; + do { + R22_ = tt[2]; + memcpy(dst + (v2 >> 1), (uint16 *)RomPtr_7F(R22_ + 0xa000), 16); + R22_ = tt[3]; + memcpy(dst + ((v2 + 768) >> 1), (uint16 *)RomPtr_7F(R22_ + 0xa000), 16); + v2 += 16; + tt += 2; + } while (--R18_); +} + +void TransferJapaneseTextTilesToVram(void) { // 0x8B8DE6 + uint16 v0 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 1536; + v0 += 2; + gVramWriteEntry(v0)->size = 0x4000; + v0 += 2; + LOBYTE(gVramWriteEntry(v0++)->size) = 126; + gVramWriteEntry(v0)->size = 16768; + vram_write_queue_tail = v0 + 2; +} + +void HandleSamusDuringIntro(void) { // 0x8B8E0D + if (cinematic_var15) { + HandleControllerInputForGamePhysics(); + HandleSamusMovementAndPause(); + if (samus_invincibility_timer) + --samus_invincibility_timer; + if (samus_knockback_timer) + --samus_knockback_timer; + } +} + +void DrawIntroSprites(void) { // 0x8B8E2D + if (cinematic_var15) { + if ((cinematic_var15 & 0x8000u) != 0) { + DrawSamusAndProjectiles(); + DrawPlayerExplosions2(); + DrawCinematicSpriteObjects_Intro(); + } else { + DrawCinematicSpriteObjects_Intro(); + DrawSamusAndProjectiles(); + DrawPlayerExplosions2(); + } + } else { + DrawCinematicSpriteObjects_Intro(); + } +} + +void CalcSinCos(uint16 a, uint16 j) { // 0x8B8E52 + int16 v3; + uint16 v2; + uint16 v4; + + R24_ = a; + R26_ = j; + if (sign16(j - 128)) + v2 = CalcSinMult(2 * j); + else + v2 = -CalcSinMult(2 * (uint8)(j + 0x80)); + R20_ = v2; + v3 = (uint8)(R26_ - 64); + if (sign16(v3 - 128)) + v4 = CalcSinMult(2 * v3); + else + v4 = -CalcSinMult(2 * (uint8)(v3 + 0x80)); + R22_ = v4; +} + +uint16 CalcSinMult(uint16 k) { // 0x8B8EA3 + R18_ = Mult8x8(*((uint8 *)&kSinCosTable8bit_Sext[64] + k), R24_) >> 8; + return R18_ + *((uint8 *)&kSinCosTable8bit_Sext[64] + k + 1) * (uint8)R24_; +} + +static const uint16 kMoveUnusedSpritesMasks[8] = { 0x5555, 0x5554, 0x5550, 0x5540, 0x5500, 0x5400, 0x5000, 0x4000 }; + +void MoveUnusedSpritesOffScreen(void) { + if (oam_next_ptr >= 0x200) + return; + int j = oam_next_ptr >> 2; + int i = (oam_next_ptr >> 5); + oam_ext[i++] |= kMoveUnusedSpritesMasks[j & 7]; + for (; i < 16; i++) + oam_ext[i] = 0x5555; + for (int i = oam_next_ptr >> 2; i < 0x80; i++) + *(uint16 *)&oam_ent[i].xcoord = 0x80; +} + +uint8 AdvanceFastScreenFadeOut(void) { // 0x8B90B8 + if ((reg_INIDISP & 0xF) != 0) { + if ((int8)((reg_INIDISP & 0xF) - screen_fade_counter) > 0) { + reg_INIDISP = (reg_INIDISP & 0xF) - screen_fade_counter; + return 0; + } + reg_INIDISP = 0x80; + } + return 1; +} + +uint8 AdvanceSlowScreenFadeOut(void) { // 0x8B90D5 + bool v0 = (int8)(screen_fade_delay - 1) < 0; + LOBYTE(screen_fade_delay) = screen_fade_delay - 1; + if ((uint8)screen_fade_delay && !v0) + return 0; + if ((reg_INIDISP & 0xF) != 0) { + if ((reg_INIDISP & 0xF) != 1) { + reg_INIDISP = (reg_INIDISP & 0xF) - 1; + LOBYTE(screen_fade_delay) = screen_fade_counter; + return 0; + } + reg_INIDISP = 0x80; + LOBYTE(screen_fade_delay) = 0; + LOBYTE(screen_fade_counter) = 0; + } + return 1; +} + +uint8 AdvanceFastScreenFadeIn(void) { // 0x8B9100 + if (sign8(((screen_fade_counter + reg_INIDISP) & 0x1F) - 15)) { + reg_INIDISP = (screen_fade_counter + reg_INIDISP) & 0x1F; + return 0; + } else { + reg_INIDISP = 15; + return 1; + } +} + +uint8 AdvanceSlowScreenFadeIn(void) { // 0x8B911B + bool v0 = (int8)(screen_fade_delay - 1) < 0; + LOBYTE(screen_fade_delay) = screen_fade_delay - 1; + if ((uint8)screen_fade_delay && !v0) + return 0; + if (sign8(((reg_INIDISP + 1) & 0x1F) - 15)) { + reg_INIDISP = (reg_INIDISP + 1) & 0x1F; + LOBYTE(screen_fade_delay) = screen_fade_counter; + return 0; + } + reg_INIDISP = 15; + LOBYTE(screen_fade_delay) = 0; + LOBYTE(screen_fade_counter) = 0; + return 1; +} + +CoroutineRet InitializeIoDisplayLogo_Async(void) { // 0x8B9146 + COROUTINE_BEGIN(coroutine_state_1, 0); + WriteReg(INIDISP, 0x8Fu); + reg_INIDISP = 0x8f; + oam_next_ptr = 0; + ClearOamExt(); + ClearUnusedOam(); + nmi_copy_samus_halves = 0; + nmi_copy_samus_top_half_src = 0; + nmi_copy_samus_bottom_half_src = 0; + WriteReg(NMITIMEN, 1u); + reg_NMITIMEN = 1; + WriteReg(WRIO, 0); + WriteReg(WRMPYA, 0); + WriteReg(WRMPYB, 0); + WriteReg(WRDIVL, 0); + WriteReg(WRDIVH, 0); + WriteReg(WRDIVB, 0); + WriteReg(HTIMEL, 0); + WriteReg(HTIMEH, 0); + WriteReg(VTIMEL, 0); + WriteReg(VTIMEH, 0); + WriteReg(MDMAEN, 0); + WriteReg(HDMAEN, 0); + reg_HDMAEN = 0; + WriteReg(MEMSEL, 1u); + reg_MEMSEL = 1; + WriteReg(OBSEL, 3u); + reg_OBSEL = 3; + WriteReg(OAMADDL, 0); + LOBYTE(reg_OAMaddr_UNUSED) = 0; + WriteReg(OAMADDH, 0x80); + HIBYTE(reg_OAMaddr_UNUSED) = 0x80; + WriteReg(OAMDATA, 0); + WriteReg(OAMDATA, 0); + WriteReg(BGMODE, 1u); + reg_BGMODE = 1; + WriteReg(MOSAIC, 0); + reg_MOSAIC = 0; + WriteReg(BG1SC, 0); + reg_BG1SC = 0; + WriteReg(BG2SC, 0); + reg_BG2SC = 0; + WriteReg(BG3SC, 0); + reg_BG3SC = 0; + WriteReg(BG4SC, 0); + reg_BG4SC = 0; + WriteReg(BG12NBA, 0); + reg_BG12NBA = 0; + WriteReg(BG34NBA, 0); + reg_BG34NBA = 0; + WriteReg(BG1HOFS, 0); + WriteReg(BG1HOFS, 0); + WriteReg(BG1VOFS, 0); + WriteReg(BG1VOFS, 0); + WriteReg(BG2HOFS, 0); + WriteReg(BG2HOFS, 0); + WriteReg(BG2VOFS, 0); + WriteReg(BG2VOFS, 0); + WriteReg(BG3HOFS, 0); + WriteReg(BG3HOFS, 0); + WriteReg(BG3VOFS, 0); + WriteReg(BG3VOFS, 0); + WriteReg(BG4HOFS, 0); + WriteReg(BG4HOFS, 0); + WriteReg(BG4VOFS, 0); + WriteReg(BG4VOFS, 0); + WriteReg(VMAIN, 0); + WriteReg(M7SEL, 0); + reg_M7SEL = 0; + WriteReg(M7A, 0); + WriteReg(M7B, 0); + WriteReg(M7C, 0); + WriteReg(M7D, 0); + WriteReg(M7X, 0); + WriteReg(M7Y, 0); + WriteReg(W12SEL, 0); + reg_W12SEL = 0; + WriteReg(W34SEL, 0); + reg_W34SEL = 0; + WriteReg(WOBJSEL, 0); + reg_WOBJSEL = 0; + WriteReg(WH0, 0); + reg_WH0 = 0; + WriteReg(WH1, 0); + reg_WH1 = 0; + WriteReg(WH2, 0); + reg_WH2 = 0; + WriteReg(WH3, 0); + reg_WH3 = 0; + WriteReg(WBGLOG, 0); + reg_WBGLOG = 0; + WriteReg(WOBJLOG, 0); + reg_WOBJLOG = 0; + WriteReg(TM, 0x10u); + reg_TM = 16; + WriteReg(TMW, 0); + reg_TMW = 0; + WriteReg(TS, 0); + reg_TS = 0; + WriteReg(TSW, 0); + reg_TSW = 0; + WriteReg(CGWSEL, 0); + next_gameplay_CGWSEL = 0; + WriteReg(CGADSUB, 0); + next_gameplay_CGADSUB = 0; + WriteReg(COLDATA, 0xE0u); + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + WriteReg(SETINI, 0); + reg_SETINI = 0; + mov24(&decompress_src, 0x9580D8u); + { + static const LongPtr unk_8B92A1 = LONGPTR(0x7f5000); + DecompressToMem_IpArg(&unk_8B92A1); + } + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + { + static const StartDmaCopy unk_8B92B9 = { 1, 1, 0x18, LONGPTR(0x7f5000), 0x4000 }; + SetupDmaTransfer(&unk_8B92B9); + } + WriteReg(MDMAEN, 2u); + reg_INIDISP = 0x80; + { + uint16 v0 = 0; + do { + palette_buffer[v0 >> 1] = g_word_8CE1E9[v0 >> 1]; + v0 += 2; + } while ((int16)(v0 - 512) < 0); + } + EnableNMI(); + screen_fade_delay = 1; + screen_fade_counter = 1; + while (1) { + ClearOamExt(); + oam_next_ptr = 0; + AddNintentoLogoToOam(); + if (AdvanceFastScreenFadeIn() & 1) + break; + ClearUnusedOam(); + COROUTINE_AWAIT(1, WaitForNMI_Async()); + } + ClearUnusedOam(); + COROUTINE_AWAIT(2, WaitForNMI_Async()); + game_options_screen_index = 120; + while (1) { + ClearOamExt(); + oam_next_ptr = 0; + AddNintentoLogoToOam(); + if (!--game_options_screen_index) + break; + ClearUnusedOam(); + COROUTINE_AWAIT(3, WaitForNMI_Async()); + } + ClearUnusedOam(); + COROUTINE_AWAIT(4, WaitForNMI_Async()); + screen_fade_delay = 1; + screen_fade_counter = 1; + while (1) { + ClearOamExt(); + oam_next_ptr = 0; + AddNintentoLogoToOam(); + if (AdvanceFastScreenFadeOut() & 1) + break; + ClearUnusedOam(); + COROUTINE_AWAIT(5, WaitForNMI_Async()); + } + ClearUnusedOam(); + COROUTINE_AWAIT(6, WaitForNMI_Async()); + WriteReg(INIDISP, 0x8Fu); + reg_INIDISP = 0x8f; + + COROUTINE_END(0); +} + +void AddNintentoLogoToOam(void) { // 0x8B936B + R22_ = 0; + R20_ = 128; + R18_ = 112; + DrawSpritemap(0x8Cu, addr_kSpriteMap_NintendoLogo); +} + +uint8 SpawnCinematicSpriteObject(uint16 j, uint16 a) { // 0x8B938A + cinematic_spawn_param = a; + for (int i = 30; i >= 0; i -= 2) { + if (!cinematicspr_instr_ptr[i >> 1]) + return SpawnCimenaticSpriteObjectInner(j, i); + } + return 1; +} + +uint8 SpawnCinematicSpriteObjectToR18(uint16 j, uint16 a) { // 0x8B93A2 + cinematic_spawn_param = a; + return SpawnCimenaticSpriteObjectInner(j, R18_); +} + +void CallCinematicSpriteObjectSetup(uint32 ea, uint16 j) { + switch (ea) { + case fnCinematicFunction_nullsub_116: return; + case fnCinematicSpriteInit_7: CinematicSpriteInit_7(j); return; + case fnCinematicSpriteInit_8: CinematicSpriteInit_8(j); return; + case fnCinematicSpriteInit_9: CinematicSpriteInit_9(j); return; + case fnCinematicSpriteInit_0: CinematicSpriteInit_0(j); return; + case fnCinematicSpriteInit_1: CinematicSpriteInit_1(j); return; + case fnCinematicSpriteInit_2: CinematicSpriteInit_2(j); return; + case fnCinematicSpriteInit_3: CinematicSpriteInit_3(j); return; + case fnCinematicSpriteInit_4: CinematicSpriteInit_4(j); return; + case fnCinematicSpriteInit_5: CinematicSpriteInit_5(j); return; + case fnCinematicSpriteInit_6: CinematicSpriteInit_6(j); return; + case fnSetSomeStuffForSpriteObject_2: SetSomeStuffForSpriteObject_2(j); return; + case fnSetSomeStuffForSpriteObject_3: SetSomeStuffForSpriteObject_3(j); return; + case fnSetSomeStuffForSpriteObject_6: SetSomeStuffForSpriteObject_6(j); return; + case fnSetSomeStuffForSpriteObject_8: SetSomeStuffForSpriteObject_8(j); return; + case fnSetSomeStuffForSpriteObject_10: SetSomeStuffForSpriteObject_10(j); return; + case fnSetSomeStuffForSpriteObject_12: SetSomeStuffForSpriteObject_12(j); return; + case fnSetSomeStuffForSpriteObject_17: SetSomeStuffForSpriteObject_17(j); return; + case fnCinematicFunction_Intro_Func35: CinematicFunction_Intro_Func35(j); return; + case fnCinematicFunction_Intro_Func42: CinematicFunction_Intro_Func42(j); return; + case fnCinematicFunction_Intro_Func46: CinematicFunction_Intro_Func46(j); return; + case fnCinematicFunction_Intro_Func47: CinematicFunction_Intro_Func47(j); return; + case fnCinematicFunction_Intro_Func49: CinematicFunction_Intro_Func49(j); return; + case fnCinematicFunction_Intro_Func57: CinematicFunction_Intro_Func57(j); return; + case fnCinematicFunction_Intro_Func59: CinematicFunction_Intro_Func59(j); return; + case fnCinematicFunction_Intro_Func61: CinematicFunction_Intro_Func61(j); return; + case fnCinematicFunction_Intro_Func63: CinematicFunction_Intro_Func63(j); return; + case fnCinematicFunction_Intro_Func65: CinematicFunction_Intro_Func65(j); return; + case fnCinematicFunction_Intro_Func68: CinematicFunction_Intro_Func68(j); return; + case fnCinematicFunction_Intro_Func71: CinematicFunction_Intro_Func71(j); return; + case fnCinematicFunction_Intro_Func78: CinematicFunction_Intro_Func78(j); return; + case fnCinematicFunction_Intro_Func80: CinematicFunction_Intro_Func80(j); return; + case fnCinematicFunction_Intro_Func81: CinematicFunction_Intro_Func81(j); return; + case fnCinematicFunction_Intro_Func83: CinematicFunction_Intro_Func83(j); return; + case fnCinematicFunction_Intro_Func89: CinematicFunction_Intro_Func89(j); return; + case fnCinematicFunction_Intro_Func92: CinematicFunction_Intro_Func92(j); return; + case fnCinematicFunction_Intro_Func98: CinematicFunction_Intro_Func98(j); return; + case fnCinematicFunction_Intro_Func99: CinematicFunction_Intro_Func99(j); return; + case fnCinematicFunction_Intro_Func100: CinematicFunction_Intro_Func100(j); return; + case fnCinematicFunction_Intro_Func101: CinematicFunction_Intro_Func101(j); return; + case fnCinematicFunction_Intro_Func102: CinematicFunction_Intro_Func102(j); return; + case fnCinematicFunction_Intro_Func104: CinematicFunction_Intro_Func104(j); return; + case fnCinematicFunction_Intro_Func150: CinematicFunction_Intro_Func150(j); return; + case fnCinematicFunction_Intro_Func152: CinematicFunction_Intro_Func152(j); return; + case fnCinematicFunction_Intro_Func153: CinematicFunction_Intro_Func153(j); return; + case fnCinematicFunction_Intro_Func154: CinematicFunction_Intro_Func154(j); return; + case fnCinematicFunction_Intro_Func155: CinematicFunction_Intro_Func155(j); return; + case fnCinematicFunction_Intro_Func156: CinematicFunction_Intro_Func156(j); return; + case fnCinematicFunction_Intro_Func157: CinematicFunction_Intro_Func157(j); return; + case fnCinematicFunction_Intro_Func159: CinematicFunction_Intro_Func159(j); return; + case fnCinematicFunction_Intro_Func161: CinematicFunction_Intro_Func161(j); return; + case fnCinematicFunction_Intro_Func162: CinematicFunction_Intro_Func162(j); return; + case fnCinematicFunction_Intro_Func163: CinematicFunction_Intro_Func163(j); return; + case fnCinematicFunction_Intro_Func164: CinematicFunction_Intro_Func164(j); return; + case fnCinematicFunction_Intro_Func165: CinematicFunction_Intro_Func165(j); return; + case fnCinematicFunction_Intro_Func166: CinematicFunction_Intro_Func166(j); return; + case fnCinematicFunction_Intro_Func167: CinematicFunction_Intro_Func167(j); return; + case fnCinematicFunction_Intro_Func168: CinematicFunction_Intro_Func168(j); return; + case fnCinematicFunction_Intro_Func169: CinematicFunction_Intro_Func169(j); return; + case fnCinematicFunction_Intro_Func170: CinematicFunction_Intro_Func170(j); return; + case fnCinematicFunction_Intro_Func171: CinematicFunction_Intro_Func171(j); return; + case fnCinematicFunction_Intro_Func172: CinematicFunction_Intro_Func172(j); return; + case fnCinematicFunction_Intro_Func173: CinematicFunction_Intro_Func173(j); return; + case fnCinematicFunction_Intro_Func174: CinematicFunction_Intro_Func174(j); return; + case fnCinematicFunction_Intro_Func175: CinematicFunction_Intro_Func175(j); return; + case fnCinematicFunction_Intro_Func176: CinematicFunction_Intro_Func176(j); return; + case fnCinematicFunction_Intro_Func177: CinematicFunction_Intro_Func177(j); return; + case fnCinematicFunction_Intro_Func178: CinematicFunction_Intro_Func178(j); return; + default: Unreachable(); + } +} + +uint8 SpawnCimenaticSpriteObjectInner(uint16 k, uint16 j) { // 0x8B93AC + uint8 *v2 = RomPtr_8B(k); + int v3 = j >> 1; + cinematicspr_preinstr_func[v3] = *((uint16 *)v2 + 1); + cinematicspr_instr_ptr[v3] = *((uint16 *)v2 + 2); + cinematicspr_instr_timer[v3] = 1; + cinematicspr_whattodraw[v3] = 0; + cinematicspr_goto_timer[v3] = 0; + cinematicspr_arr6[v3] = 0; + cinematicspr_arr7[v3] = 0; + CallCinematicSpriteObjectSetup(*(uint16 *)v2 | 0x8B0000, j); + return 0; +} + +void ClearCinematicSprites(void) { // 0x8B93DA + for (int i = 30; i >= 0; i -= 2) { + int v1 = i >> 1; + cinematicspr_instr_ptr[v1] = 0; + cinematicspr_whattodraw[v1] = 0; + } +} + +void HandleCinematicSprites(void) { // 0x8B93EF + for (int i = 30; i >= 0; i -= 2) { + cinematic_obj_index = i; + if (cinematicspr_instr_ptr[i >> 1]) { + ProcessCinematicSpriteInstructionList(i); + i = cinematic_obj_index; + } + } +} + +uint16 CallCinematicSprInstr(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnCinematicSprInstr_Delete: return CinematicSprInstr_Delete(k, j); + case fnCinematicSprInstr_Sleep: return CinematicSprInstr_Sleep(k, j); + case fnCinematicSprInstr_SetPreInstr: return CinematicSprInstr_SetPreInstr(k, j); + case fnCinematicSprInstr_ClearPreInstr: return CinematicSprInstr_ClearPreInstr(k, j); + case fnCinematicSprInstr_GotoRel: return CinematicSprInstr_GotoRel(k, j); + case fnCinematicSprInstr_Goto: return CinematicSprInstr_Goto(k, j); + case fnCinematicSprInstr_DecTimerGoto: return CinematicSprInstr_DecTimerGoto(k, j); + case fnCinematicSprInstr_DecTimerGotoRel: return CinematicSprInstr_DecTimerGotoRel(k, j); + case fnCinematicSprInstr_SetTimer: return CinematicSprInstr_SetTimer(k, j); + case fnCinematicSprInstr_9CE1: return CinematicSprInstr_9CE1(k, j); + case fnCinematicSprInstr_9D5D: return CinematicSprInstr_9D5D(k, j); + case fnCinematicSprInstr_9DD6: return CinematicSprInstr_9DD6(k, j); + case fnCinematicSprInstr_Func8: return CinematicSprInstr_Func8(k, j); + case fnCinematicSprInstr_Func9: return CinematicSprInstr_Func9(k, j); + case fnCinematicSprInstr_sub_8B9EF0: return CinematicSprInstr_sub_8B9EF0(k, j); + case fnCinematicSprInstr_9F19: return CinematicSprInstr_9F19(k, j); + case fnCinematicSprInstr_SpawnMetroidEggParticles: return CinematicSprInstr_SpawnMetroidEggParticles(k, j); + case fnCinematicSprInstr_StartIntroPage2: return CinematicSprInstr_StartIntroPage2(k, j); + case fnCinematicSprInstr_StartIntroPage3: return CinematicSprInstr_StartIntroPage3(k, j); + case fnCinematicSprInstr_StartIntroPage4: return CinematicSprInstr_StartIntroPage4(k, j); + case fnCinematicSprInstr_StartIntroPage5: return CinematicSprInstr_StartIntroPage5(k, j); + case fnCinematicSprInstr_Func43: return CinematicSprInstr_Func43(k, j); + case fnCinematicSprInstr_SpawnIntroRinkas01: return CinematicSprInstr_SpawnIntroRinkas01(k, j); + case fnCinematicSprInstr_SpawnIntroRinkas23: return CinematicSprInstr_SpawnIntroRinkas23(k, j); + case fnCinematicCommonInstr_Func69: return CinematicCommonInstr_Func69(k, j); + case fnCinematicCommonInstr_Func70: return CinematicCommonInstr_Func70(k, j); + case fnCinematicSprInstr_SpawnCeresExplosions1: return CinematicSprInstr_SpawnCeresExplosions1(k, j); + case fnCinematicSprInstr_SpawnCeresExplosions3: return CinematicSprInstr_SpawnCeresExplosions3(k, j); + case fnCinematicSprInstr_C9A5: return CinematicSprInstr_C9A5(k, j); + case fnCinematicSprInstr_C9AF: return CinematicSprInstr_C9AF(k, j); + case fnCinematicSprInstr_C9BD: return CinematicSprInstr_C9BD(k, j); + case fnCinematicSprInstr_C9C7: return CinematicSprInstr_C9C7(k, j); + case fnCinematicSprInstr_Func181: return CinematicSprInstr_Func181(k, j); + case fnCinematicSprInstr_Func182: return CinematicSprInstr_Func182(k, j); + case fnCinematicSprInstr_Func183: return CinematicSprInstr_Func183(k, j); + case fnCinematicSprInstr_Func185: return CinematicSprInstr_Func185(k, j); + case fnCinematicSprInstr_Func186: return CinematicSprInstr_Func186(k, j); + case fnCinematicSprInstr_Func187: return CinematicSprInstr_Func187(k, j); + case fnCinematicSprInstr_Func190: return CinematicSprInstr_Func190(k, j); + case fnCinematicSprInstr_Func192: return CinematicSprInstr_Func192(k, j); + case fnCinematicSprInstr_Func193: return CinematicSprInstr_Func193(k, j); + case fnCinematicSprInstr_Func194: return CinematicSprInstr_Func194(k, j); + case fnCinematicSprInstr_Func195: return CinematicSprInstr_Func195(k, j); + case fnCinematicSprInstr_Func196: return CinematicSprInstr_Func196(k, j); + case fnCinematicSprInstr_Func197: return CinematicSprInstr_Func197(k, j); + case fnCinematicSprInstr_Func198: return CinematicSprInstr_Func198(k, j); + case fnCinematicSprInstr_Func208: return CinematicSprInstr_Func208(k, j); + case fnCinematicSprInstr_Func211: return CinematicSprInstr_Func211(k, j); + case fnCinematicSprInstr_Func213: return CinematicSprInstr_Func213(k, j); + case fnCinematicSprInstr_Func214: return CinematicSprInstr_Func214(k, j); + case fnCinematicSprInstr_Func217: return CinematicSprInstr_Func217(k, j); + case fnCinematicSprInstr_Func218: return CinematicSprInstr_Func218(k, j); + default: return Unreachable(); + } +} +void CallCinematicSprPreInstr(uint32 ea, uint16 j) { + switch (ea) { + case fnCinematicSprPreInstr_nullsub_300: return; + case fnCinematicFunction_nullsub_116: return; + case fnCinematicFunction_nullsub_298: return; + case fnsub_8B9CCF: sub_8B9CCF(j); return; + case fnnullsub_122: return; + case fnSetSomeStuffForSpriteObject_4_MetroidEgg: SetSomeStuffForSpriteObject_4_MetroidEgg(j); return; + case fnCinematicSprPreInstr_A903: CinematicSprPreInstr_A903(j); return; + case fnSetSomeStuffForSpriteObject_7: SetSomeStuffForSpriteObject_7(j); return; + case fnSetSomeStuffForSpriteObject_9: SetSomeStuffForSpriteObject_9(j); return; + case fnSetSomeStuffForSpriteObject_11: SetSomeStuffForSpriteObject_11(j); return; + case fnSetSomeStuffForSpriteObject_13: SetSomeStuffForSpriteObject_13(j); return; + case fnSetSomeStuffForSpriteObject_18: SetSomeStuffForSpriteObject_18(j); return; + case fnCinematicFunction_Intro_Func36: CinematicFunction_Intro_Func36(j); return; + case fnCinematicFunction_Intro_Func39: CinematicFunction_Intro_Func39(j); return; + case fnCinematicSprPreInstr_B82E: CinematicSprPreInstr_B82E(j); return; + case fnCinematicFunction_Intro_Func44: CinematicFunction_Intro_Func44(j); return; + case fnCinematicFunction_Intro_Func45: CinematicFunction_Intro_Func45(j); return; + case fnCinematicFunction_Intro_Func48: CinematicFunction_Intro_Func48(j); return; + case fnCinematicFunction_Intro_Func50: CinematicFunction_Intro_Func50(j); return; + case fnCinematicFunction_Intro_Func51: CinematicFunction_Intro_Func51(j); return; + case fnCinematicFunction_Intro_Func52: CinematicFunction_Intro_Func52(j); return; + case fnCinematicFunction_Intro_Func53: CinematicFunction_Intro_Func53(j); return; + case fnCinematicFunction_Intro_Func58: CinematicFunction_Intro_Func58(j); return; + case fnCinematicFunction_Intro_Func60: CinematicFunction_Intro_Func60(j); return; + case fnCinematicFunction_Intro_Func62: CinematicFunction_Intro_Func62(j); return; + case fnCinematicFunction_Intro_Func64: CinematicFunction_Intro_Func64(j); return; + case fnCinematicFunction_Intro_Func66: CinematicFunction_Intro_Func66(j); return; + case fnCinematicSprPreInstr_C489: CinematicSprPreInstr_C489(j); return; + case fnCinematicFunction_Intro_Func82: CinematicFunction_Intro_Func82(j); return; + case fnCinematicFunction_Intro_Func90: CinematicFunction_Intro_Func90(j); return; + case fnCinematicFunction_Intro_Func91: CinematicFunction_Intro_Func91(j); return; + case fnCinematicFunction_Intro_Func93: CinematicFunction_Intro_Func93(j); return; + case fnCinematicFunction_Intro_Func94: CinematicFunction_Intro_Func94(j); return; + case fnCinematicFunction_Intro_Func96: CinematicFunction_Intro_Func96(j); return; + case fnCinematicFunction_Intro_Func97: CinematicFunction_Intro_Func97(j); return; + case fnCinematicFunction_Intro_Func151: CinematicFunction_Intro_Func151(j); return; + case fnCinematicFunction_Intro_Func179: CinematicFunction_Intro_Func179(j); return; + case fnCinematicFunction_Intro_Func180: CinematicFunction_Intro_Func180(j); return; + case fnCinematicFunction_Intro_Func184: CinematicFunction_Intro_Func184(j); return; + case fnCinematicSprPreInstr_F35A: CinematicSprPreInstr_F35A(j); return; + case fnCinematicFunction_Intro_Func189: CinematicFunction_Intro_Func189(j); return; + case fnCinematicFunction_Intro_Func189b: CinematicFunction_Intro_Func189b(j); return; + case fnCinematicFunction_Intro_Func191: CinematicFunction_Intro_Func191(j); return; + case fnCinematicFunction_Intro_Func199: CinematicFunction_Intro_Func199(j); return; + case fnCinematicFunction_Intro_Func200: CinematicFunction_Intro_Func200(j); return; + case fnCinematicFunction_Intro_Func201: CinematicFunction_Intro_Func201(j); return; + case fnCinematicFunction_Intro_Func202: CinematicFunction_Intro_Func202(j); return; + case fnCinematicFunction_Intro_Func203: CinematicFunction_Intro_Func203(j); return; + case fnCinematicFunction_Intro_Func204: CinematicFunction_Intro_Func204(j); return; + case fnCinematicFunction_Intro_Func205: CinematicFunction_Intro_Func205(j); return; + case fnCinematicFunction_Intro_Func206: CinematicFunction_Intro_Func206(j); return; + case fnCinematicFunction_Intro_Func207: CinematicFunction_Intro_Func207(j); return; + case fnnullsub_128: return; + case fnCinematicSprPreInstr_F528: CinematicSprPreInstr_F528(j); return; + case fnCinematicSprPreInstr_F57F: CinematicSprPreInstr_F57F(j); return; + case fnCinematicFunction_Intro_Func215: CinematicFunction_Intro_Func215(j); return; + default: Unreachable(); + } +} +void ProcessCinematicSpriteInstructionList(uint16 k) { // 0x8B9409 + CallCinematicSprPreInstr(cinematicspr_preinstr_func[k >> 1] | 0x8B0000, k); + uint16 v1 = cinematic_obj_index; + int v2 = cinematic_obj_index >> 1; + if (cinematicspr_instr_timer[v2]-- == 1) { + uint16 v4 = cinematicspr_instr_ptr[v2], v6; + while (1) { + uint16 *v5 = (uint16 *)RomPtr_8B(v4); + v6 = *v5; + if ((*v5 & 0x8000u) == 0) + break; + R18_ = *v5; + v4 = CallCinematicSprInstr(v6 | 0x8B0000, v1, v4 + 2); + if (!v4) + return; + } + int v7 = v1 >> 1; + cinematicspr_instr_timer[v7] = v6; + cinematicspr_whattodraw[v7] = *((uint16 *)RomPtr_8B(v4) + 1); + cinematicspr_instr_ptr[v7] = v4 + 4; + } +} + +uint16 CinematicSprInstr_Delete(uint16 k, uint16 j) { // 0x8B9438 + int v2 = k >> 1; + cinematicspr_whattodraw[v2] = 0; + cinematicspr_instr_ptr[v2] = 0; + return 0; +} + +uint16 CinematicSprInstr_Sleep(uint16 k, uint16 j) { // 0x8B9442 + cinematicspr_instr_ptr[k >> 1] = j - 2; + return 0; +} + +uint16 CinematicSprInstr_SetPreInstr(uint16 k, uint16 j) { // 0x8B944C + cinematicspr_preinstr_func[k >> 1] = *(uint16 *)RomPtr_8B(j); + return j + 2; +} + +uint16 CinematicSprInstr_ClearPreInstr(uint16 k, uint16 j) { // 0x8B9457 + cinematicspr_preinstr_func[k >> 1] = FUNC16(CinematicFunction_nullsub_298); + return j; +} + + +uint16 CinematicSprInstr_GotoRel(uint16 k, uint16 j) { // 0x8B94A2 + int16 v2; + + R18_ = j; + LOBYTE(v2) = HIBYTE(*(uint16 *)RomPtr_8B(j - 1)); + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + else + v2 = (uint8)v2; + return R18_ + v2; +} + +uint16 CinematicSprInstr_Goto(uint16 k, uint16 j) { // 0x8B94BC + return *(uint16 *)RomPtr_8B(j); +} + +uint16 CinematicSprInstr_DecTimerGoto(uint16 k, uint16 j) { // 0x8B94C3 + int v2 = k >> 1; + if (cinematicspr_goto_timer[v2]-- == 1) + return j + 2; + else + return CinematicSprInstr_Goto(k, j); +} + +uint16 CinematicSprInstr_DecTimerGotoRel(uint16 k, uint16 j) { // 0x8B94CD + int v2 = k >> 1; + if (cinematicspr_goto_timer[v2]-- == 1) + return j + 1; + else + return CinematicSprInstr_GotoRel(k, j); +} + +uint16 CinematicSprInstr_SetTimer(uint16 k, uint16 j) { // 0x8B94D6 + cinematicspr_goto_timer[k >> 1] = *(uint16 *)RomPtr_8B(j); + return j + 2; +} + +void sub_8B94E1(void) { // 0x8B94E1 + ; +} + +void CallCinematicSpriteInit(uint32 ea, uint16 j) { + switch (ea) { + case fnCinematicSpriteInit_7: CinematicSpriteInit_7(j); return; + case fnCinematicSpriteInit_8: CinematicSpriteInit_8(j); return; + case fnCinematicSpriteInit_9: CinematicSpriteInit_9(j); return; + case fnCinematicSpriteInit_0: CinematicSpriteInit_0(j); return; + case fnCinematicSpriteInit_1: CinematicSpriteInit_1(j); return; + case fnCinematicSpriteInit_2: CinematicSpriteInit_2(j); return; + case fnCinematicSpriteInit_3: CinematicSpriteInit_3(j); return; + case fnCinematicSpriteInit_4: CinematicSpriteInit_4(j); return; + case fnCinematicSpriteInit_5: CinematicSpriteInit_5(j); return; + case fnCinematicSpriteInit_6: CinematicSpriteInit_6(j); return; + case fnCinematicFunction_nullsub_116: return; + default: Unreachable(); + } +} + +uint8 SpawnMode7Object(uint16 j, uint16 a) { // 0x8B94E4 + Mode7ObjectDef *Mode7ObjectDef; + + mode7_spawn_param = a; + uint16 v3 = 2; + while (mode7_obj_instr_ptr[v3 >> 1]) { + v3 -= 2; + if ((v3 & 0x8000u) != 0) + return 1; + } + Mode7ObjectDef = get_Mode7ObjectDef(j); + int v6 = v3 >> 1; + mode7_obj_preinstr_func[v6] = Mode7ObjectDef->field_2; + mode7_obj_instr_ptr[v6] = Mode7ObjectDef->field_4; + mode7_obj_instr_timer[v6] = 1; + mode7_obj_goto_timer[v6] = 0; + CallCinematicSpriteInit(Mode7ObjectDef->field_0 | 0x8B0000, v6); + return 0; +} + +void HandleMode7Objects(void) { // 0x8B951D + for (int i = 2; i >= 0; i -= 2) { + mode7_cur_index = i; + if (mode7_obj_instr_ptr[i >> 1]) { + ProcessMode7ObjectInstructions(i); + i = mode7_cur_index; + } + } +} +uint16 CallMode7Instr(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnMode7Instr_Delete: return Mode7Instr_Delete(k, j); + case fnMode7Instr_SetPreInstr: return Mode7Instr_SetPreInstr(k, j); + case fnMode7Instr_ClearPreInstr: return Mode7Instr_ClearPreInstr(k, j); + case fnMode7Instr_Goto: return Mode7Instr_Goto(k, j); + case fnMode7Instr_DecTimerAndGoto: return Mode7Instr_DecTimerAndGoto(k, j); + case fnMode7Instr_SetTimer: return Mode7Instr_SetTimer(k, j); + case fnPlayBabyMetroidCry1: return PlayBabyMetroidCry1(k, j); + case fnPlayBabyMetroidCry2: return PlayBabyMetroidCry2(k, j); + case fnPlayBabyMetroidCry3: return PlayBabyMetroidCry3(k, j); + case fnCinematicSetPal1: return CinematicSetPal1(k, j); + case fnCinematicSetPal2: return CinematicSetPal2(k, j); + case fnCinematicSetPal3: return CinematicSetPal3(k, j); + case fnCinematicSetPal4: return CinematicSetPal4(k, j); + case fnsub_8BB51E: return sub_8BB51E(k, j); + case fnEnableCinematicBgTilemapUpdates__0: return EnableCinematicBgTilemapUpdates__0(k, j); + case fnCinematicFunction_Intro_Func21: return CinematicFunction_Intro_Func21(k, j); + case fnCinematicFunction_Intro_ThenWaitInputSetupBabyMetroid: return CinematicFunction_Intro_ThenWaitInputSetupBabyMetroid(k, j); + case fnCinematicFunction_Intro_Func23: return CinematicFunction_Intro_Func23(k, j); + case fnCinematicFunction_Intro_Func25: return CinematicFunction_Intro_Func25(k, j); + case fnCinematicFunction_Intro_Func26: return CinematicFunction_Intro_Func26(k, j); + case fnCinematicFunction_Intro_Func28: return CinematicFunction_Intro_Func28(k, j); + case fnCinematicFunction_Intro_Func29: return CinematicFunction_Intro_Func29(k, j); + case fnCinematicFunction_Intro_Func31: return CinematicFunction_Intro_Func31(k, j); + case fnCinematicFunction_Intro_Func32: return CinematicFunction_Intro_Func32(k, j); + case fnEnableCinematicBgTilemapUpdates__: return EnableCinematicBgTilemapUpdates__(k, j); + default: return Unreachable(); + } +} + + +void CallMode7PreInstr(uint32 ea, uint16 k) { + switch (ea) { + case fnCinematicFunction_nullsub_116: return; + case fnCinematicFunction_Intro_Func22: CinematicFunction_Intro_Func22(k); return; + case fnCinematicFunction_Intro_Func24: CinematicFunction_Intro_Func24(k); return; + case fnCinematicFunction_Intro_Func27: CinematicFunction_Intro_Func27(k); return; + case fnCinematicFunction_Intro_Func30: CinematicFunction_Intro_Func30(k); return; + default: Unreachable(); + } +} + +void ProcessMode7ObjectInstructions(uint16 k) { // 0x8B9537 + CallMode7PreInstr(mode7_obj_preinstr_func[k >> 1] | 0x8B0000, k); + uint16 v1 = mode7_cur_index; + int v2 = mode7_cur_index >> 1; + if (mode7_obj_instr_timer[v2]-- == 1) { + uint16 v4 = mode7_obj_instr_ptr[v2], v6; + while (1) { + uint16 *v5 = (uint16 *)RomPtr_8B(v4); + v6 = *v5; + if ((*v5 & 0x8000u) == 0) + break; + R18_ = *v5; + v4 = CallMode7Instr(v6 | 0x8B0000, v1, v4 + 2); + if (!v4) + return; + } + mode7_obj_instr_timer[v1 >> 1] = v6; + uint8 *v7 = RomPtr_8B(v4); + QueueMode7Transfers(0x8b, *((uint16 *)v7 + 1)); + mode7_obj_instr_ptr[v1 >> 1] = v4 + 4; + } +} + +uint16 Mode7Instr_Delete(uint16 k, uint16 j) { // 0x8B956B + mode7_obj_instr_ptr[k >> 1] = 0; + return 0; +} + +uint16 Mode7Instr_SetPreInstr(uint16 k, uint16 j) { // 0x8B9572 + mode7_obj_preinstr_func[k >> 1] = *(uint16 *)RomPtr_8B(j); + return j + 2; +} + +uint16 Mode7Instr_ClearPreInstr(uint16 k, uint16 j) { // 0x8B957D + mode7_obj_preinstr_func[k >> 1] = FUNC16(locret_8B9585); + return j; +} + +uint16 Mode7Instr_Goto(uint16 k, uint16 j) { // 0x8B9586 + return *(uint16 *)RomPtr_8B(j); +} + +uint16 Mode7Instr_DecTimerAndGoto(uint16 k, uint16 j) { // 0x8B958D + int v2 = k >> 1; + if (mode7_obj_goto_timer[v2]-- == 1) + return j + 2; + else + return Mode7Instr_Goto(k, j); +} + +uint16 Mode7Instr_SetTimer(uint16 k, uint16 j) { // 0x8B9597 + mode7_obj_goto_timer[k >> 1] = *(uint16 *)RomPtr_8B(j); + return j + 2; +} + +void EnableCinematicBgObjects(void) { // 0x8B95A2 + cinematic_enable_objs |= 0x8000u; +} + +void DisableCinematicBgObjects(void) { // 0x8B95AD + cinematic_enable_objs &= ~0x8000u; +} + +void EnableCinematicBgTilemapUpdates(void) { // 0x8B95B8 + cinematic_enable_bg_tilemap |= 0x8000u; +} + +void DisableCinematicBgTilemapUpdates(void) { // 0x8B95C3 + cinematic_enable_bg_tilemap &= ~0x8000u; +} + +void ClearCinematicBgObjects(uint16 a) { // 0x8B95CE + uint16 j; + + for (int i = 2046; i >= 0; i -= 2) + *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + (uint16)i) = a; + for (j = 6; (j & 0x8000u) == 0; j -= 2) { + int v3 = j >> 1; + cinematicbg_arr1[v3] = 0; + cinematicbg_instr_ptr[v3] = 0; + } + cinematicbg_var1 = 0; +} + + +void CallCinematicBgObjectSetup(uint32 ea, uint16 j) { + switch (ea) { + case fnCinematicFunction_nullsub_116: return; + default: Unreachable(); + } +} +uint8 SpawnCinematicBgObject(uint16 j, uint16 a) { // 0x8B95F0 + cinematicbg_var3 = a; + uint16 v3 = 6; + while (cinematicbg_instr_ptr[v3 >> 1]) { + v3 -= 2; + if ((v3 & 0x8000u) != 0) + return 1; + } + uint8 *v5 = RomPtr_8B(j); + int v6 = v3 >> 1; + cinematicbg_preinstr[v6] = *((uint16 *)v5 + 1); + cinematicbg_instr_ptr[v6] = *((uint16 *)v5 + 2); + cinematicbg_instr_timer[v6] = 1; + cinematicbg_arr1[v6] = 0; + cinematicbg_arr6[v6] = 0; + CallCinematicBgObjectSetup(*(uint16 *)v5 | 0x8B0000, v3); + return 0; +} + +void HandleCinematicBgObjects(void) { // 0x8B962F + if ((cinematic_enable_objs & 0x8000u) != 0) { + for (int i = 6; i >= 0; i -= 2) { + cinematicbg_var2 = i; + if (cinematicbg_instr_ptr[i >> 1]) { + ProcessCinematicBgObjectsInstrs(i); + i = cinematicbg_var2; + } + } + if ((cinematic_enable_bg_tilemap & 0x8000u) != 0) + UpdateCinematicBgTilemap(); + UpdateSamusEyesTilemap(); + } +} + +void CallCinematicBgPreInstr(uint32 ea, uint16 j) { + switch (ea) { + case fnCinematicFunction_nullsub_116: return; + case fnCinematicBgPreInstr_SamusBlink: CinematicBgPreInstr_SamusBlink(j); return; + default: Unreachable(); + } +} + +uint16 CallCinematicBgInstr(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnCinematicBgInstr_Delete: return CinematicBgInstr_Delete(k, j); + case fnCinematicBgInstr_Goto: return CinematicBgInstr_Goto(k, j); + case fnCinematicBgInstr_SetSomeStuffForSpriteObject_14: return CinematicBgInstr_SetSomeStuffForSpriteObject_14(k, j); + case fnCinematicBgInstr_HandleCreateJpnText_Page1: return CinematicBgInstr_HandleCreateJpnText_Page1(k, j); + case fnCinematicBgInstr_SpawnMarkerWaitInput_Page1: return CinematicBgInstr_SpawnMarkerWaitInput_Page1(k, j); + case fnCinematicBgInstr_HandleCreateJpnText_Page2: return CinematicBgInstr_HandleCreateJpnText_Page2(k, j); + case fnCinematicBgInstr_SpawnMarkerWaitInput_Page2: return CinematicBgInstr_SpawnMarkerWaitInput_Page2(k, j); + case fnCinematicBgInstr_HandleCreateJpnText_Page3: return CinematicBgInstr_HandleCreateJpnText_Page3(k, j); + case fnCinematicBgInstr_SpawnMarkerWaitInput_Page3: return CinematicBgInstr_SpawnMarkerWaitInput_Page3(k, j); + case fnCinematicBgInstr_HandleCreateJpnText_Page4: return CinematicBgInstr_HandleCreateJpnText_Page4(k, j); + case fnCinematicBgInstr_SpawnMarkerWaitInput_Page4: return CinematicBgInstr_SpawnMarkerWaitInput_Page4(k, j); + case fnCinematicBgInstr_HandleCreateJpnText_Page5: return CinematicBgInstr_HandleCreateJpnText_Page5(k, j); + case fnCinematicBgInstr_SpawnMarkerWaitInput_Page5: return CinematicBgInstr_SpawnMarkerWaitInput_Page5(k, j); + case fnCinematicBgInstr_Func16: return CinematicBgInstr_Func16(k, j); + case fnCinematicBgInstr_Func17: return CinematicBgInstr_Func17(k, j); + case fnCinematicCommonInstr_Func69: return CinematicCommonInstr_Func69(k, j); + case fnCinematicCommonInstr_Func70: return CinematicCommonInstr_Func70(k, j); + case fnCalcItemPercentageCount: return CalcItemPercentageCount(k, j); + case fnCinematicFunction_Intro_Func146: return CinematicFunction_Intro_Func146(k, j); + case fnCinematicFunction_Intro_Func147: return CinematicFunction_Intro_Func147(k, j); + + default: return Unreachable(); + } +} + +void ProcessCinematicBgObjectsInstrs(uint16 k) { // 0x8B9659 + CallCinematicBgPreInstr(cinematicbg_preinstr[k >> 1] | 0x8B0000, k); + uint16 v1 = cinematicbg_var2; + int v2 = cinematicbg_var2 >> 1; + if (cinematicbg_instr_timer[v2]-- == 1) { + uint16 v4 = cinematicbg_instr_ptr[v2], v6; + while (1) { + uint16 *v5 = (uint16 *)RomPtr_8C(v4); + v6 = *v5; + if ((*v5 & 0x8000u) == 0) + break; + R18_ = *v5; + v4 = CallCinematicBgInstr(v6 | 0x8B0000, v1, v4 + 2); + if (!v4) + return; + } + int v7 = v1 >> 1; + cinematicbg_instr_timer[v7] = v6; + uint8 *v8 = RomPtr_8C(v4); + R18_ = *((uint16 *)v8 + 1); + cinematicbg_arr1[v7] = *((uint16 *)v8 + 2); + ProcessCinematicBgObject(v1); + cinematicbg_instr_ptr[v7] = v4 + 6; + } +} + +uint16 CinematicBgInstr_Delete(uint16 k, uint16 j) { // 0x8B9698 + int v2 = k >> 1; + cinematicbg_arr1[v2] = 0; + cinematicbg_instr_ptr[v2] = 0; + return 0; +} + +uint16 CinematicBgInstr_Goto(uint16 k, uint16 j) { // 0x8B971E + return *(uint16 *)RomPtr_8C(j); +} + +void sub_8B9743(void) { // 0x8B9743 + ; +} + +void DrawCinematicSpriteObjects_Intro(void) { // 0x8B9746 + for (int i = 30; i >= 0; i -= 2) { + int v1 = i >> 1; + if (cinematicspr_whattodraw[v1]) { + uint16 v2 = cinematicspr_whattodraw[v1]; + R22_ = cinematicbg_arr9[v1]; + R20_ = cinematicbg_arr7[v1] - layer1_x_pos; + uint16 v3 = cinematicbg_arr8[v1] - layer1_y_pos; + R18_ = v3; + if ((v3 & 0xFF00) != 0) { + if ((uint16)(v3 + 128) < 0x1FFu) + DrawSpritemapOffScreen(v2); + } else if ((uint16)(v3 + 128) < 0x1FFu) { + DrawSpritemap(0x8Cu, v2); + } + } + } +} + +void DrawCinematicSpriteObjects_Ending(void) { // 0x8B9799 + for (int i = 30; i >= 0; i -= 2) { + int v1 = i >> 1; + if (cinematicspr_whattodraw[v1]) { + uint16 v2 = cinematicspr_whattodraw[v1]; + R22_ = cinematicbg_arr9[v1]; + R20_ = cinematicbg_arr7[v1] - layer1_x_pos; + uint16 v3 = cinematicbg_arr8[v1] - layer1_y_pos; + R18_ = v3; + if ((v3 & 0xFF00) != 0) { + if ((uint16)(v3 + 128) < 0x1FFu) + DrawSpritemapOffScreen(v2); + } else if ((uint16)(v3 + 128) < 0x1FFu) { + DrawSpritemap(0x8Cu, v2); + } + } + } + if (sign16(cinematic_function - FUNC16(CinematicFunction_Intro_Func116))) + MoveUnusedSpritesOffScreen(); +} + +void SpawnTextGlowObject(uint16 j) { // 0x8B97F7 + uint16 v1 = 14; + while (*(uint16 *)((char *)&cinematic_var21 + v1)) { + v1 -= 2; + if ((v1 & 0x8000u) != 0) + return; + } + *(uint16 *)((char *)&cinematic_var21 + v1) = j; + int v2 = v1 >> 1; + enemy_projectile_pre_instr[v2 + 2] = 1; + enemy_projectile_pre_instr[v2 + 10] = (uint8)R18_; + *(uint16 *)((char *)enemy_projectile_1A27 + v1) = HIBYTE(R18_); + *(uint16 *)((char *)&cinematic_var20 + v1) = 0; +} + +void HandleTextGlowObjects(void) { // 0x8B9828 + for (int i = 14; i >= 0; i -= 2) { + cinematic_var19 = i; + if (*(uint16 *)((char *)&cinematic_var21 + (uint16)i)) { + ProcessTextGlowObject(); + i = cinematic_var19; + } + } +} + +void ProcessTextGlowObject(void) { // 0x8B9849 + uint16 v0 = cinematic_var19; + int v1 = cinematic_var19 >> 1; + if (enemy_projectile_pre_instr[v1 + 2]-- == 1) { + R28_ = *(uint16 *)((char *)&cinematic_var20 + v0); + uint16 v3 = *(uint16 *)((char *)&cinematic_var21 + v0); + R20_ = 2 * LOBYTE(enemy_projectile_pre_instr[v1 + 10]); + R22_ = R20_ + Mult8x8(*((uint8 *)enemy_projectile_1A27 + v0), 0x40); + uint16 v4 = R22_; + uint8 *v5 = RomPtr_8C(v3); + R18_ = v5[2]; + R24_ = R18_; + R20_ = v5[3]; + while (1) { + do { + *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + v4) = R28_ | *(uint16 *)((uint8 *)ram3000.pause_menu_map_tilemap + + v4) & 0xE3FF; + v3 += 2; + v4 += 2; + --R18_; + } while (R18_); + R18_ = R24_; + if (!--R20_) + break; + R22_ += 64; + v4 = R22_; + } + uint16 v6 = cinematic_var19; + if (*(uint16 *)((char *)&cinematic_var20 + cinematic_var19) == 3072) { + *(uint16 *)((char *)&cinematic_var21 + cinematic_var19) = 0; + } else { + *(uint16 *)((char *)&cinematic_var20 + cinematic_var19) += 1024; + enemy_projectile_pre_instr[(v6 >> 1) + 2] = 5; + } + } +} + +void EnableTextGlowObjects_(void) { + cinematic_var25 |= 0x8000u; +} + +void DisableTextGlowObjects_(void) { + cinematic_var25 &= ~0x8000u; +} + +void CinematicFunction_Intro_Func128(uint16 a) { // 0x8B98F9 + for (int i = 2046; i >= 0; i -= 2) + *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + (uint16)i) = a; + cinematic_var26 = 0; + cinematic_var21 = 0; + cinematic_var22 = 0; + cinematic_var23 = 0; + cinematic_var24 = 0; + cinematicbg_var3 = 18432; + enemy_projectile_pre_instr[0] = 0; + cinematic_var7 = 0; + cinematic_var8 = 0; + cinematic_var9 = 0; + cinematic_var10 = 0; +} + +void CallCreditsObjectFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnCinematicFunction_nullsub_116: return; + case fnCinematicBgPreInstr_SamusBlink: CinematicBgPreInstr_SamusBlink(k); return; + default: Unreachable(); + } +} + +void CreditsObject_Init(uint16 j) { // 0x8B9932 + uint8 *v1 = RomPtr_8B(j); + cinematic_var24 = *((uint16 *)v1 + 1); + cinematic_var21 = *((uint16 *)v1 + 2); + cinematic_var22 = 1; + cinematic_var23 = 0; + CallCreditsObjectFunc(*(uint16 *)v1 | 0x8B0000, 0); +} + +void CreditsObject_Process(void) { // 0x8B9955 + if ((cinematic_var25 & 0x8000u) != 0) { + if (cinematic_var21) + CreditsObject_ProcessOne(); + CinematicUpdateSomeBg(); + } +} + +uint16 CallIntroObjectInstr(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnIntroObject_Delete: return IntroObject_Delete(k, j); + case fnIntroObject_Goto: return IntroObject_Goto(k, j); + case fnIntroObject_DecTimerGoto: return IntroObject_DecTimerGoto(k, j); + case fnIntroObject_SetTimer: return IntroObject_SetTimer(k, j); + case fnCinematicFunction_Intro_Func219: return CinematicFunction_Intro_Func219(k, j); + default: return Unreachable(); + } +} + +void CreditsObject_ProcessOne(void) { // 0x8B996A + int i; + + CallCreditsObjectFunc(cinematic_var24 | 0x8B0000, 0); + uint16 v0 = (__PAIR32__(cinematic_var10, cinematic_var9) + 0x8000) >> 16; + cinematic_var9 += 0x8000; + cinematic_var10 = v0; + if (!sign16(v0 - enemy_projectile_pre_instr[0] - 8)) { + enemy_projectile_pre_instr[0] = cinematic_var10; + for (i = cinematic_var21; ; ) { + uint16 *v2 = (uint16 *)RomPtr_8C(i); + uint16 v3 = *v2; + if ((*v2 & 0x8000u) == 0) + break; + R18_ = *v2; + i = CallIntroObjectInstr(v3 | 0x8B0000, 0, i + 2); + if (!i) + return; + } + CreditsObject_Func1(i); + cinematic_var26 = ((uint8)cinematic_var26 + 1) & 0x1F; + cinematic_var21 = i + 4; + } +} + +void CreditsObject_Func1(uint16 j) { // 0x8B99C1 + *(VoidP *)((char *)&R0_.addr + 1) = 32512; + R0_.addr = 0; + uint16 RegWord = Mult8x8(cinematic_var26, 0x40); + R20_ = 31; + uint16 v2 = *((uint16 *)RomPtr_8C(j) + 1); + do { + *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + RegWord) = *(uint16 *)IndirPtr(&R0_, v2); + RegWord += 2; + v2 += 2; + --R20_; + } while ((R20_ & 0x8000u) == 0); +} + +uint16 IntroObject_Delete(uint16 k, uint16 j) { // 0x8B99FE + cinematic_var21 = 0; + return 0; +} + +uint16 IntroObject_Goto(uint16 k, uint16 j) { // 0x8B9A06 + return *(uint16 *)RomPtr_8C(j); +} + +uint16 IntroObject_DecTimerGoto(uint16 k, uint16 j) { // 0x8B9A0D + if (--cinematic_var23) + return IntroObject_Goto(k, j); + else + return j + 2; +} + +uint16 IntroObject_SetTimer(uint16 k, uint16 j) { // 0x8B9A17 + cinematic_var23 = *(uint16 *)RomPtr_8C(j); + return j + 2; +} + +void CallCinematicFunction(uint32 ea) { + switch (ea) { + case fnCinematicFunctionNone: CinematicFunctionNone(); return; + case fnCinematicFunctionOpening: CinematicFunctionOpening(); return; + case fnCinematicFunc_Func2: CinematicFunc_Func2(); return; + case fnCinematicFunc_Func4: CinematicFunc_Func4(); return; + case fnCinematicFunc_Func5: CinematicFunc_Func5(); return; + case fnCinematicFunc_Func7: CinematicFunc_Func7(); return; + case fnnullsub_117: return; + case fnCinematicFunc_Func1: CinematicFunc_Func1(); return; + case fnCinematicFunc_Func10: CinematicFunc_Func10(); return; + case fnCinematicFunc_Func9: CinematicFunc_Func9(); return; + case fnnullsub_120: return; + case fnnullsub_121: return; + case fnCinematicFunc_Nothing: CinematicFunc_Nothing(); return; + case fnCinematicFunction_Intro_Initial: CinematicFunction_Intro_Initial(); return; + case fnCinematicFunction_Intro_FadeIn: CinematicFunction_Intro_FadeIn(); return; + case fnCinematicFunction_Intro_DrawInitJpn: CinematicFunction_Intro_DrawInitJpn(); return; + case fnCinematicFunction_Intro_LastMetroidCaptivity: CinematicFunction_Intro_LastMetroidCaptivity(); return; + case fnCinematicFunc_Intro_QueueGalaxyIsAtPeace: CinematicFunc_Intro_QueueGalaxyIsAtPeace(); return; + case fnCinematicFunc_Intro_WaitForQueueWait4secs: CinematicFunc_Intro_WaitForQueueWait4secs(); return; + case fnCinematicFunc_Intro_FadeOut: CinematicFunc_Intro_FadeOut(); return; + case fnCinematicFunc_Intro_WaitForFadeOut: CinematicFunc_Intro_WaitForFadeOut(); return; + case fnCinematicFunc_Intro_SetupTextPage2: CinematicFunc_Intro_SetupTextPage2(); return; + case fnCinematicFunc_Intro_WaitFadeinShowText: CinematicFunc_Intro_WaitFadeinShowText(); return; + case fnCinematicFunc_Intro_WaitForFadeinSleep: CinematicFunc_Intro_WaitForFadeinSleep(); return; + case fnCinematicFunction_Intro_WaitInputSetupMotherBrainFight: CinematicFunction_Intro_WaitInputSetupMotherBrainFight(); return; + case fnCinematicFunction_Intro_WaitInputSetupBabyMetroid: CinematicFunction_Intro_WaitInputSetupBabyMetroid(); return; + case fnCinematicFunction_Intro_Func11: CinematicFunction_Intro_Func11(); return; + case fnCinematicFunction_Intro_Func12: CinematicFunction_Intro_Func12(); return; + case fnCinematicFunction_Intro_Func15: CinematicFunction_Intro_Func15(); return; + case fnCinematicFunction_Intro_Func15b: CinematicFunction_Intro_Func15b(); return; + case fnCinematicFunction_Intro_XfadeGameplayFade: CinematicFunction_Intro_XfadeGameplayFade(); return; + case fnCinematicFunction_Intro_XfadeScientistFade: CinematicFunction_Intro_XfadeScientistFade(); return; + case fnCinematicFunction_Intro_Page2: CinematicFunction_Intro_Page2(); return; + case fnCinematicFunction_Intro_Page3: CinematicFunction_Intro_Page3(); return; + case fnCinematicFunction_Intro_Page4: CinematicFunction_Intro_Page4(); return; + case fnCinematicFunction_Intro_Page5: CinematicFunction_Intro_Page5(); return; + case fnCinematicFunction_Intro_Fadestuff: CinematicFunction_Intro_Fadestuff(); return; + case fnCinematicFunction_Intro_Fadestuff2: CinematicFunction_Intro_Fadestuff2(); return; + case fnCinematicFunction_Intro_Func34: CinematicFunction_Intro_Func34(); return; + case fnCinematicFunction_Intro_Func54: CinematicFunction_Intro_Func54(); return; + case fnCinematicFunction_Intro_Func55: CinematicFunction_Intro_Func55(); return; + case fnCinematicFunction_Intro_Func56: CinematicFunction_Intro_Func56(); return; + case fnCinematicFunction_Intro_Func67: CinematicFunction_Intro_Func67(); return; + case fnCinematicFunction_Intro_Func72: CinematicFunction_Intro_Func72(); return; + case fnCinematicFunction_Intro_Func73: CinematicFunction_Intro_Func73(); return; + case fnCinematicFunctionBlackoutFromCeres: CinematicFunctionBlackoutFromCeres(); return; + case fnCinematicFunction_Intro_Func74: CinematicFunction_Intro_Func74(); return; + case fnCinematicFunction_Intro_Func75: CinematicFunction_Intro_Func75(); return; + case fnCinematicFunction_Intro_Func76: CinematicFunction_Intro_Func76(); return; + case fnCinematicFunction_Intro_Func77: CinematicFunction_Intro_Func77(); return; + case fnCinematicFunction_Intro_Func84: CinematicFunction_Intro_Func84(); return; + case fnCinematicFunction_Intro_Func85: CinematicFunction_Intro_Func85(); return; + case fnCinematicFunction_Intro_Func86: CinematicFunction_Intro_Func86(); return; + case fnCinematicFunction_Intro_Func87: CinematicFunction_Intro_Func87(); return; + case fnCinematicFunction_Intro_Func88: CinematicFunction_Intro_Func88(); return; + case fnCinematicFunction_Intro_Func105: CinematicFunction_Intro_Func105(); return; + case fnCinematicFunction_Intro_Func106: CinematicFunction_Intro_Func106(); return; + case fnCinematicFunction_Intro_Func107: CinematicFunction_Intro_Func107(); return; + case fnCinematicFunction_Intro_Func108: CinematicFunction_Intro_Func108(); return; + case fnnullsub_124: return; + case fnCinematicFunction_Intro_Func95: CinematicFunction_Intro_Func95(); return; + case fnCinematicFunctionEscapeFromCebes: CinematicFunctionEscapeFromCebes(); return; + case fnCinematicFunction_Intro_Func109: CinematicFunction_Intro_Func109(); return; + case fnCinematicFunction_Intro_Func110: CinematicFunction_Intro_Func110(); return; + case fnCinematicFunction_Intro_Func111: CinematicFunction_Intro_Func111(); return; + case fnCinematicFunction_Intro_Func112: CinematicFunction_Intro_Func112(); return; + case fnCinematicFunction_Intro_Func113: CinematicFunction_Intro_Func113(); return; + case fnCinematicFunction_Intro_Func114: CinematicFunction_Intro_Func114(); return; + case fnCinematicFunction_Intro_Func115: CinematicFunction_Intro_Func115(); return; + case fnCinematicFunction_Intro_Func116: CinematicFunction_Intro_Func116(); return; + case fnCinematicFunction_Intro_Func117: CinematicFunction_Intro_Func117(); return; + case fnCinematicFunction_Intro_Func118: CinematicFunction_Intro_Func118(); return; + case fnnullsub_125: return; + case fnCinematicFunction_Intro_Func119: CinematicFunction_Intro_Func119(); return; + case fnCinematicFunction_Intro_Func120: CinematicFunction_Intro_Func120(); return; + case fnCinematicFunction_Intro_Func121: CinematicFunction_Intro_Func121(); return; + case fnCinematicFunction_Intro_Func123: CinematicFunction_Intro_Func123(); return; + case fnCinematicFunction_Intro_Func124: CinematicFunction_Intro_Func124(); return; + case fnnullsub_126: return; + case fnCinematicFunction_Intro_Func125: CinematicFunction_Intro_Func125(); return; + case fnCinematicFunction_Intro_Func126: CinematicFunction_Intro_Func126(); return; + case fnCinematicFunction_Intro_Func129: CinematicFunction_Intro_Func129(); return; + case fnCinematicFunction_Intro_Func130: CinematicFunction_Intro_Func130(); return; + case fnCinematicFunction_Intro_Func131: CinematicFunction_Intro_Func131(); return; + case fnCinematicFunction_Intro_Func132: CinematicFunction_Intro_Func132(); return; + case fnCinematicFunction_Intro_Func134: CinematicFunction_Intro_Func134(); return; + case fnCinematicFunction_Intro_Func136: CinematicFunction_Intro_Func136(); return; + case fnCinematicFunction_Intro_Func135: CinematicFunction_Intro_Func135(); return; + case fnCinematicFunction_Intro_Func137: CinematicFunction_Intro_Func137(); return; + case fnCinematicFunction_Intro_Func138: CinematicFunction_Intro_Func138(); return; + case fnCinematicFunction_Intro_Func145: CinematicFunction_Intro_Func145(); return; + case fnCinematicFunction_Intro_Func139: CinematicFunction_Intro_Func139(); return; + case fnCinematicFunction_Intro_Func141: CinematicFunction_Intro_Func141(); return; + case fnCinematicFunction_Intro_Func143: CinematicFunction_Intro_Func143(); return; + case fnCinematicFunction_Intro_Func144: CinematicFunction_Intro_Func144(); return; + case fnCinematicFunction_Intro_Func148: CinematicFunction_Intro_Func148(); return; + case fnnullsub_127: return; + default: Unreachable(); + } +} + +CoroutineRet GameState_1_OpeningCinematic_(void) { // 0x8B9A22 + CallCinematicFunction(cinematic_function | 0x8b0000); + HandleCinematicSprites(); + HandleMode7Objects(); + PaletteFxHandler(); + DrawCinematicSpriteObjects_Intro(); + MaybeSkipCinematics(); + HandleCinematicsTransitions(); + HandleMode7TransformationNoRotation(); + return kCoroutineNone; +} + +void CinematicFunctionNone(void) { // 0x8B9A47 + ; +} + +void MaybeSkipCinematics(void) { // 0x8B9A48 + if (sign16(cinematic_function + 0x60D8) + && (joypad1_newkeys & (uint16)(kButton_B | kButton_Start | kButton_A)) != 0 + && !cinematic_var18) { + cinematic_var18 = 1; + screen_fade_delay = 0; + screen_fade_counter = 2; + } +} + +static Func_V *const off_8B9A7B[4] = { // 0x8B9A6C + 0, + HandleCinematicsTransitions_1, + HandleCinematicsTransitions_2, + HandleCinematicsTransitions_3, +}; + +void HandleCinematicsTransitions(void) { + if (cinematic_var18) + off_8B9A7B[cinematic_var18](); +} + +void HandleCinematicsTransitions_1(void) { // 0x8B9A83 + if (AdvanceFastScreenFadeOut() & 1) { + cinematic_var18 = 2; + cinematic_function = FUNC16(nullsub_117); + QueueMusic_Delayed8(6u); + } +} + +void HandleCinematicsTransitions_2(void) { // 0x8B9A9C + ClearCinematicSprites(); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BA119, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BA125, 0); + screen_fade_delay = 0; + screen_fade_counter = 2; + cinematic_var6 = 256; + cinematic_var8 = 0; + cinematic_var7 = 0; + cinematic_var10 = 0; + cinematic_var9 = 0; + g_word_7E199B = 0; + g_word_7E1999 = 0; + g_word_7E199F = 0; + g_word_7E199D = 0; + cinematic_var18 = 3; + uint16 v2 = 256; + do { + palette_buffer[v2 >> 1] = g_word_8CE1E9[v2 >> 1]; + v2 += 2; + } while ((int16)(v2 - 512) < 0); + palette_buffer[201] = 0x7FFF; + palette_buffer[202] = 32128; + ClearPaletteFXObjects(); + SpawnPalfxObject(addr_kPalfx_E1A0); + SpawnPalfxObject(addr_kPalfx_E1A4); + SetPpuBackdropBlack(); + reg_TM = 17; + SpawnTitleScreenGradientObjs(); +} + +void CinematicSpriteInit_7(uint16 j) { // 0x8B9B1A + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 48; + cinematicbg_arr9[v1] = 1024; +} + +void CinematicSpriteInit_8(uint16 j) { // 0x8B9B2D + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 81; + cinematicbg_arr9[v1] = 0; +} + +void CinematicSpriteInit_9(uint16 j) { // 0x8B9B40 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 196; + cinematicbg_arr9[v1] = 2048; +} + +void HandleCinematicsTransitions_3(void) { // 0x8B9B53 + if (AdvanceFastScreenFadeIn() & 1) { + cinematic_var18 = 0; + demo_timer = 900; + cinematic_function = FUNC16(CinematicFunc_Func1); + } +} + +void CinematicFunctionOpening(void) { // 0x8B9B68 + LoadTitleSequenceGraphics(); + QueueMusic_Delayed8(0xFF03u); + cinematic_function = FUNC16(CinematicFunctionNone); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BA0EF, FUNC16(CinematicFunctionNone)); + QueueMusic_Delayed8(5u); +} + +void LoadTitleSequenceGraphics(void) { // 0x8B9B87 + int16 v1; + + SetupPpuForTitleSequence(); + cur_irq_handler = 0; + irqhandler_next_handler = 0; + uint16 v0 = 0; + do { + palette_buffer[v0 >> 1] = g_word_8CE1E9[v0 >> 1]; + v0 += 2; + } while ((int16)(v0 - 512) < 0); + mov24(&decompress_src, 0x94E000u); + static const LongPtr unk_8B9BB4 = LONGPTR(0x7f0000); + static const LongPtr unk_8B9BC5 = LONGPTR(0x7f4000); + static const LongPtr unk_8B9BD6 = LONGPTR(0x7f5000); + static const LongPtr unk_8B9BE7 = LONGPTR(0x7f9000); + DecompressToMem_IpArg(&unk_8B9BB4); + mov24(&decompress_src, 0x96FC04u); + DecompressToMem_IpArg(&unk_8B9BC5); + mov24(&decompress_src, 0x9580D8u); + DecompressToMem_IpArg(&unk_8B9BD6); + mov24(&decompress_src, 0x95A5E1u); + DecompressToMem_IpArg(&unk_8B9BE7); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8B9BFF = { 1, 0, 0x19, LONGPTR(0x7f0000), 0x4000 }; + SetupDmaTransfer(&unk_8B9BFF); + WriteReg(MDMAEN, 2u); + WriteReg(VMAIN, 0); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + v1 = 0x4000; + do { + WriteReg(VMDATAL, 0xFFu); + --v1; + } while (v1); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0); + static const StartDmaCopy unk_8B9C37 = { 1, 0, 0x18, LONGPTR(0x7f4000), 0x1000 }; + SetupDmaTransfer(&unk_8B9C37); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8B9C57 = { 1, 1, 0x18, LONGPTR(0x7f5000), 0x4000 }; + SetupDmaTransfer(&unk_8B9C57); + WriteReg(MDMAEN, 2u); + WriteRegWord(M7A, 0x100u); + reg_M7A = 256; + WriteRegWord(M7B, 0); + reg_M7B = 0; + WriteRegWord(M7C, 0); + reg_M7C = 0; + WriteRegWord(M7D, 0x100u); + reg_M7D = 256; + WriteRegWord(M7X, 0x80); + reg_M7X = 128; + WriteRegWord(M7Y, 0x80); + reg_M7Y = 128; + EnableNMI(); + screen_fade_delay = 1; + screen_fade_counter = 1; + EnableHdmaObjects(); + EnablePaletteFx(); + fx_layer_blending_config_a = 0; + SpawnPalfxObject(addr_kPalfx_E1A0); + SpawnPalfxObject(addr_kPalfx_E1A4); + uint16 v2 = 0; // undefined + SpawnMode7Object(addr_kMode7ObjBabyMetroidInTitle, v2); +} + +void CinematicSpriteInit_0(uint16 j) { // 0x8B9CBC + int v1 = j >> 1; + cinematicbg_arr7[v1] = 129; + cinematicbg_arr8[v1] = 112; + cinematicbg_arr9[v1] = 512; +} + +void sub_8B9CCF(uint16 k) { // 0x8B9CCF + reg_INIDISP = 15; + cinematicspr_preinstr_func[k >> 1] = FUNC16(CinematicFunction_nullsub_116); +} + +void sub_8B9CDE(void) { // 0x8B9CDE + ; +} + +uint16 CinematicSprInstr_9CE1(uint16 k, uint16 j) { // 0x8B9CE1 + reg_TM = 17; + cinematic_function = FUNC16(CinematicFunc_Func2); + cinematic_var6 = 72; + cinematic_var8 = 315; + cinematic_var7 = 0; + cinematic_var10 = 225; + cinematic_var9 = 0; + g_word_7E199B = -2; + g_word_7E1999 = 0x8000; + SetPpuBackdropSomeColor(); + return j; +} + +void CinematicFunc_Func2(void) { // 0x8B9D17 + uint16 v0 = (__PAIR32__(g_word_7E199B, g_word_7E1999) + __PAIR32__(cinematic_var8, cinematic_var7)) >> 16; + cinematic_var7 += g_word_7E1999; + cinematic_var8 = v0; + if (sign16(v0 + 7)) { + reg_TM = 16; + cinematic_function = FUNC16(CinematicFunctionNone); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BA0F5, FUNC16(CinematicFunctionNone)); + SetPpuBackdropBlack(); + } + MaybeSkipCinematics(); +} + +void CinematicSpriteInit_1(uint16 j) { // 0x8B9D4A + int v1 = j >> 1; + cinematicbg_arr7[v1] = 129; + cinematicbg_arr8[v1] = 112; + cinematicbg_arr9[v1] = 512; +} + +uint16 CinematicSprInstr_9D5D(uint16 k, uint16 j) { // 0x8B9D5D + reg_TM = 17; + cinematic_function = FUNC16(CinematicFunc_Func4); + cinematic_var6 = 96; + cinematic_var8 = 44; + cinematic_var7 = 0; + cinematic_var10 = -155; + cinematic_var9 = 0; + g_word_7E199B = -2; + g_word_7E1999 = 0x8000; + return j; +} + +void CinematicFunc_Func4(void) { // 0x8B9D90 + uint16 v0 = (__PAIR32__(g_word_7E199B, g_word_7E1999) + __PAIR32__(cinematic_var8, cinematic_var7)) >> 16; + cinematic_var7 += g_word_7E1999; + cinematic_var8 = v0; + if (sign16(v0 + 176)) { + reg_TM = 16; + cinematic_function = FUNC16(CinematicFunctionNone); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BA0FB, FUNC16(CinematicFunctionNone)); + SetPpuBackdropBlack(); + } + MaybeSkipCinematics(); +} + +void CinematicSpriteInit_2(uint16 j) { // 0x8B9DC3 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 129; + cinematicbg_arr8[v1] = 112; + cinematicbg_arr9[v1] = 512; +} + +uint16 CinematicSprInstr_9DD6(uint16 k, uint16 j) { // 0x8B9DD6 + reg_TM = 17; + cinematic_function = FUNC16(CinematicFunc_Func5); + cinematic_var6 = 96; + cinematic_var8 = -177; + cinematic_var7 = 0; + cinematic_var10 = -160; + cinematic_var9 = 0; + g_word_7E199B = 0; + g_word_7E1999 = 0; + g_word_7E199F = 1; + g_word_7E199D = 0x8000; + SetPpuBackdropSomeColor(); + return j; +} + +void CinematicFunc_Func5(void) { // 0x8B9E12 + uint16 v0 = (__PAIR32__(g_word_7E199F, g_word_7E199D) + __PAIR32__(cinematic_var10, cinematic_var9)) >> 16; + cinematic_var9 += g_word_7E199D; + cinematic_var10 = v0; + if (!sign16(v0 - 163)) { + reg_TM = 16; + cinematic_function = FUNC16(CinematicFunctionNone); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BA101, FUNC16(CinematicFunctionNone)); + SetPpuBackdropBlack(); + } + MaybeSkipCinematics(); +} + +void CinematicSpriteInit_3(uint16 j) { // 0x8B9E45 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 129; + cinematicbg_arr8[v1] = 112; + cinematicbg_arr9[v1] = 512; +} + +uint16 CinematicSprInstr_Func8(uint16 k, uint16 j) { // 0x8B9E58 + reg_TM = 17; + cinematic_function = FUNC16(CinematicFunc_Func7); + cinematic_var6 = 67; + cinematic_var8 = 0; + cinematic_var7 = 0; + cinematic_var10 = 0; + cinematic_var9 = 0; + g_word_7E199B = 0; + g_word_7E1999 = 0; + g_word_7E199F = 0; + g_word_7E199D = 0; + SpawnTitleScreenGradientObjs(); + return j; +} + + +void CinematicFunc_Func7(void) { // 0x8B9E8B + if ((nmi_frame_counter_word & 1) == 0) { + if (sign16(cinematic_var6 - 256)) { + ++cinematic_var6; + } else { + cinematic_var6 = 256; + cinematic_function = FUNC16(nullsub_117); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BA107, FUNC16(nullsub_117)); + } + } +} + +void CinematicSpriteInit_4(uint16 j) { // 0x8B9EB3 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 48; + cinematicbg_arr9[v1] = 1024; + SpawnPalfxObject(addr_kPalfx_E194); +} + +uint16 CinematicSprInstr_Func9(uint16 k, uint16 j) { // 0x8B9ECD + uint16 v0 = 0x9ecd; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BA113, v0); + return j; +} + +void CinematicSpriteInit_5(uint16 j) { // 0x8B9ED6 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 81; + cinematicbg_arr9[v1] = 512; + SpawnPalfxObject(addr_kPalfx_E198); +} + +uint16 CinematicSprInstr_sub_8B9EF0(uint16 k, uint16 j) { // 0x8B9EF0 + cinematicbg_arr9[k >> 1] = 0; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BA113, 0); + return j; +} + +void CinematicSpriteInit_6(uint16 j) { // 0x8B9EFF + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 196; + cinematicbg_arr9[v1] = 2048; + SpawnPalfxObject(addr_kPalfx_E19C); +} + +uint16 CinematicSprInstr_9F19(uint16 k, uint16 j) { // 0x8B9F19 + demo_timer = 900; + cinematic_function = FUNC16(CinematicFunc_Func1); + return j; +} + +void CinematicFunc_Func1(void) { // 0x8B9F29 + bool v0 = (--demo_timer & 0x8000u) != 0; + if (!demo_timer || v0) { + cinematic_function = FUNC16(CinematicFunc_Func9); +LABEL_6: + screen_fade_delay = 2; + screen_fade_counter = 2; + goto LABEL_7; + } + if ((joypad1_newkeys & (uint16)(kButton_B | kButton_Start | kButton_A)) != 0) { + cinematic_function = FUNC16(CinematicFunc_Func10); + goto LABEL_6; + } +LABEL_7:; +} + +void CinematicFunc_Func10(void) { // 0x8B9F52 + uint16 j; + + if (AdvanceSlowScreenFadeOut() & 1) { + EnableNMI(); + reg_BGMODE = 1; + screen_fade_delay = 0; + screen_fade_counter = 0; + reg_BG2HOFS = 0; + reg_BG3HOFS = 0; + reg_BG2VOFS = 0; + reg_BG3VOFS = 0; + cinematic_var5 = 0; + cinematic_function = FUNC16(CinematicFunctionOpening); + DisablePaletteFx(); + ClearPaletteFXObjects(); + for (int i = 656; i >= 0; i -= 2) + *(uint16 *)((char *)&cinematic_var5 + (uint16)i) = 0; + for (j = 510; (j & 0x8000u) == 0; j -= 2) + hdma_table_1[j >> 1] = 0; + game_state = 4; + game_options_screen_index = 0; + } +} + +void CinematicFunc_Func9(void) { // 0x8B9FAE + uint16 j; + + if (AdvanceSlowScreenFadeOut() & 1) { + EnableNMI(); + reg_BGMODE = 1; + screen_fade_delay = 0; + screen_fade_counter = 0; + reg_BG2HOFS = 0; + reg_BG3HOFS = 0; + reg_BG2VOFS = 0; + reg_BG3VOFS = 0; + cinematic_var5 = 0; + cinematic_function = FUNC16(CinematicFunctionOpening); + DisablePaletteFx(); + ClearPaletteFXObjects(); + for (int i = 656; i >= 0; i -= 2) + *(uint16 *)((char *)&cinematic_var5 + (uint16)i) = 0; + for (j = 510; (j & 0x8000u) == 0; j -= 2) + hdma_table_1[j >> 1] = 0; + game_state = 40; + demo_scene = 0; + } +} + +void ConfigureTitleSequenceGradientHDMA(void) { // 0x8BA00A +#define g_off_8CBC5D ((uint16*)RomPtr(0x8cbc5d)) + uint16 v0 = g_off_8CBC5D[(uint16)((uint8)(cinematic_var6 & 0xF0) >> 3) >> 1]; + for (int i = 0; ; i += 2) { + uint16 v2 = *(uint16 *)RomPtr_8C(v0); + hdma_table_1[i >> 1] = v2; + if (!v2) + break; + v0 += 2; + } +} + +uint16 PlayBabyMetroidCry1(uint16 k, uint16 j) { // 0x8BA25B + QueueSfx3_Max6(0x23u); + return j; +} + +uint16 PlayBabyMetroidCry2(uint16 k, uint16 j) { // 0x8BA263 + QueueSfx3_Max6(0x26u); + return j; +} + +uint16 PlayBabyMetroidCry3(uint16 k, uint16 j) { // 0x8BA26B + QueueSfx3_Max6(0x27u); + return j; +} +static const uint16 kCinematicPal1[16] = { 0x1000, 0x6bf5, 0x2e41, 0x2da1, 0x2d01, 0x5e5f, 0x183f, 0x1014, 0x80a, 0x404, 0x4f9f, 0x3ed8, 0x2e12, 0x6f70, 0x7fff, 0x5ee0 }; +static const uint16 kCinematicPal2[16] = { 0x3800, 0x6bf5, 0x6e1, 0x641, 0x5a1, 0x5e5f, 0x183f, 0x1014, 0x80a, 0x404, 0x4f9f, 0x3ed8, 0x2e12, 0x6f70, 0x7fff, 0x5ee0 }; +static const uint16 kCinematicPal3[16] = { 0x3800, 0x77f8, 0x1344, 0x12a4, 0x1204, 0x6abf, 0x249f, 0x1c77, 0x146d, 0x1067, 0x5bff, 0x4b38, 0x3a72, 0x7bd3, 0x7fff, 0x6b43 }; +static const uint16 kCinematicPal4[16] = { 0x3800, 0x7ffb, 0x1fa7, 0x1f07, 0x1e67, 0x771f, 0x30ff, 0x28da, 0x20d0, 0x1cca, 0x67ff, 0x579b, 0x46d5, 0x7bd6, 0x7fff, 0x77a6 }; +uint16 CinematicSetPal1(uint16 k, uint16 j) { // 0x8BA273 + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 48] = kCinematicPal1[i >> 1]; + return j; +} + +uint16 CinematicSetPal2(uint16 k, uint16 j) { // 0x8BA284 + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 48] = kCinematicPal2[i >> 1]; + return j; +} + +uint16 CinematicSetPal3(uint16 k, uint16 j) { // 0x8BA295 + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 48] = kCinematicPal3[i >> 1]; + return j; +} + +uint16 CinematicSetPal4(uint16 k, uint16 j) { // 0x8BA2A6 + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 48] = kCinematicPal4[i >> 1]; + return j; +} + +CoroutineRet GameState_37_CeresGoesBoomWithSamus_(void) { // 0x8BA35B + CallCinematicFunction(cinematic_function | 0x8B0000); + if ((cinematic_var11 & 0x8000u) == 0) + ++cinematic_var11; + ++cinematic_var12; + HandleSamusDuringIntro(); + HandleCinematicSprites(); + HandleMode7Objects(); + HandleCinematicBgObjects(); + HandleTextGlowObjects(); + PaletteFxHandler(); + DrawIntroSprites(); + HandleMode7TransformationMatrix(); + return kCoroutineNone; +} + +void CinematicFunc_Nothing(void) { // 0x8BA391 +} + +void CinematicFunction_Intro_Initial(void) { // 0x8BA395 + uint16 j; + uint16 k; + + SetupPpu_Intro(); + cur_irq_handler = 0; + irqhandler_next_handler = 0; + area_index = 0; + room_width_in_blocks = 16; + room_height_in_blocks = 16; + Samus_Initialize(); + UpdateBeamTilesAndPalette(); + samus_max_missiles = 900; + samus_missiles = 900; + cinematic_var15 = 0; + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + ResetButtonAssignmentsToDefault(); + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + for (int i = 656; i >= 0; i -= 2) + *(uint16 *)((char *)&cinematic_var5 + (uint16)i) = 0; + uint16 v1 = 0; + do { + palette_buffer[v1 >> 1] = kPalettes_Intro[v1 >> 1]; + v1 += 2; + } while ((int16)(v1 - 512) < 0); + static const LongPtr unk_8BA3FC = LONGPTR(0x7f0000); + static const LongPtr unk_8BA40D = LONGPTR(0x7f8000); + static const LongPtr unk_8BA41E = LONGPTR(0x7f9000); + static const LongPtr unk_8BA42F = LONGPTR(0x7f9800); + static const LongPtr unk_8BA440 = LONGPTR(0x7fb800); + static const LongPtr unk_8BA451 = LONGPTR(0x7fe000); + + mov24(&decompress_src, 0x95f90e); + DecompressToMem_IpArg(&unk_8BA3FC); + mov24(&decompress_src, 0x95d089); + DecompressToMem_IpArg(&unk_8BA40D); + mov24(&decompress_src, 0x9788cc); + DecompressToMem_IpArg(&unk_8BA41E); + mov24(&decompress_src, 0x96ff14); + DecompressToMem_IpArg(&unk_8BA42F); + mov24(&decompress_src, 0x95e4c2); + DecompressToMem_IpArg(&unk_8BA440); + mov24(&decompress_src, 0x978d12); + DecompressToMem_IpArg(&unk_8BA451); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BA469 = { 1, 1, 0x18, LONGPTR(0x7f0000), 0x8000 }; + SetupDmaTransfer(&unk_8BA469); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x40u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BA489 = { 1, 1, 0x18, LONGPTR(0x7f8000), 0x0900 }; + SetupDmaTransfer(&unk_8BA489); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x48u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BA4A9 = { 1, 1, 0x18, LONGPTR(0x7f9000), 0x0800 }; + SetupDmaTransfer(&unk_8BA4A9); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x4Cu); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BA4C9 = { 1, 1, 0x18, LONGPTR(0x7fe000), 0x0800 }; + SetupDmaTransfer(&unk_8BA4C9); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x50u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BA4E9 = { 1, 1, 0x18, LONGPTR(0x7f9800), 0x2000 }; + SetupDmaTransfer(&unk_8BA4E9); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BA509 = { 1, 1, 0x18, LONGPTR(0x9ad200), 0x2000 }; + SetupDmaTransfer(&unk_8BA509); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x6Eu); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BA529 = { 1, 1, 0x18, LONGPTR(0x7fb800), 0x2400 }; + SetupDmaTransfer(&unk_8BA529); + WriteReg(MDMAEN, 2u); + mov24(&decompress_src, 0x95D713u); + static const LongPtr unk_8BA546 = LONGPTR(0x7fa000); + DecompressToMem_IpArg(&unk_8BA546); + EnableNMI(); + screen_fade_delay = 3; + screen_fade_counter = 3; + EnableHdmaObjects(); + ClearPaletteFXObjects(); + EnablePaletteFx(); + door_def_ptr = 0; + layer1_x_pos = 0; + layer1_y_pos = 0; + cinematic_var16 = 0; + for (j = 1023; (j & 0x8000u) == 0; --j) + ram3800.cinematic_bg_tilemap[j] = *(uint16 *)&BTS[j * 2 + 11262]; + for (k = 127; (k & 0x8000u) == 0; --k) + ram3000.pause_menu_map_tilemap[k] = *(uint16 *)((char *)g_word_8CD81B + k * 2); + cinematic_var11 = -1; + cinematic_function = FUNC16(CinematicFunction_Intro_FadeIn); + QueueMusic_Delayed8(0); + QueueMusic_Delayed8(0xFF3Fu); +} + +void CinematicFunction_Intro_FadeIn(void) { // 0x8BA5A7 + if (!(HasQueuedMusic() & 1)) { + cinematic_function = FUNC16(CinematicFunction_Intro_DrawInitJpn); + screen_fade_delay = 2; + screen_fade_counter = 2; + } +} + +void CinematicFunction_Intro_DrawInitJpn(void) { // 0x8BA5BD + if (AdvanceSlowScreenFadeIn() & 1) { + cinematic_function = FUNC16(CinematicFunction_Intro_LastMetroidCaptivity); + cinematic_var4 = 60; + if (japanese_text_flag) { + uint16 v0 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 256; + v0 += 2; + gVramWriteEntry(v0)->size = 12288; + v0 += 2; + LOBYTE(gVramWriteEntry(v0++)->size) = 126; + gVramWriteEntry(v0)->size = 20192; + vram_write_queue_tail = v0 + 2; + } + } +} + +void CinematicFunction_Intro_LastMetroidCaptivity(void) { // 0x8BA5F8 + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) { + cinematic_function = FUNC16(CinematicFunc_Intro_QueueGalaxyIsAtPeace); + cinematic_var4 = 200; + QueueMusic_Delayed8(5u); + } +} + +void CinematicFunc_Intro_QueueGalaxyIsAtPeace(void) { // 0x8BA613 + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) { + QueueMusic_Delayed8(0); + QueueMusic_Delayed8(0xFF42u); + QueueMusic_DelayedY(5u, 0xEu); + cinematic_function = FUNC16(CinematicFunc_Intro_WaitForQueueWait4secs); + } +} + +void CinematicFunc_Intro_WaitForQueueWait4secs(void) { // 0x8BA639 + if (!(HasQueuedMusic() & 1)) { + cinematic_function = FUNC16(CinematicFunc_Intro_FadeOut); + cinematic_var4 = 240; + } +} + +void CinematicFunc_Intro_FadeOut(void) { // 0x8BA64C + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) { + cinematic_function = FUNC16(CinematicFunc_Intro_WaitForFadeOut); + screen_fade_delay = 2; + screen_fade_counter = 2; + } +} + +void CinematicFunc_Intro_WaitForFadeOut(void) { // 0x8BA663 + if (AdvanceSlowScreenFadeOut() & 1) + cinematic_function = FUNC16(CinematicFunc_Intro_SetupTextPage2); +} + +void CinematicFunc_Intro_SetupTextPage2(void) { // 0x8BA66F + ClearJapaneseTextTiles(); + WriteReg(VMADDL, 0x80); + WriteReg(VMADDH, 0x41u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BA689 = { 1, 1, 0x18, LONGPTR(0x7e4000), 0x0600 }; + SetupDmaTransfer(&unk_8BA689); + WriteReg(MDMAEN, 2u); + WriteReg(TM, 0x16u); + reg_TM = 22; + ClearCinematicBgObjects(0x2F); + EnableCinematicBgObjects(); + EnableCinematicBgTilemapUpdates(); + cinematicbg_var3 = addr_unk_604C00; + for (int i = 127; i >= 0; --i) { + ram3000.pause_menu_map_tilemap[i] = 15401; + ram3000.pause_menu_map_tilemap[i + 896] = 15401; + } + uint16 v1 = 768; + uint16 v2 = 0; + do { + ram3000.pause_menu_map_tilemap[v1] = g_word_8BA72B[v2 >> 1]; + v2 += 2; + ++v1; + } while ((int16)(v1 * 2 - 1792) < 0); + *(uint32 *)&ram3000.menu.menu_tilemap[286] = 472456233; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE6D, 0x1C29u); + cinematic_var4 = 127; + SpawnCinematicBgObject(addr_kCinematicBgObjectDef_8BCF63, 0x4C00u); + cinematic_var10 = 8; + reg_BG2VOFS = 8; + reg_BG3VOFS = 8; + ClearEnglishTextTilemap(); + SetSomeStuffForSpriteObject_16(); + QueueMusic_Delayed8(0); + QueueMusic_Delayed8(0xFF36u); + QueueMusic_DelayedY(5u, 0xEu); + cinematic_function = FUNC16(CinematicFunc_Intro_WaitFadeinShowText); +} + +void CinematicFunc_Intro_WaitFadeinShowText(void) { // 0x8BA82B + if (!(HasQueuedMusic() & 1)) { + cinematic_function = FUNC16(CinematicFunc_Intro_WaitForFadeinSleep); + screen_fade_delay = 2; + screen_fade_counter = 2; + SpawnCinematicBgObject(addr_kCinematicBgObjectDef_8BCF3F, 0x4C00u); + } +} + +void CinematicFunc_Intro_WaitForFadeinSleep(void) { // 0x8BA84A + if (AdvanceSlowScreenFadeIn() & 1) + cinematic_function = FUNC16(CinematicFunc_Nothing); +} + +void ClearEnglishTextTilemap(void) { // 0x8BA856 + uint16 v0 = 128; + do + ram3000.pause_menu_map_tilemap[v0++] = 47; + while ((int16)(v0 * 2 - 1536) < 0); +} + +void ClearJapaneseTextTiles(void) { // 0x8BA86A + uint16 v0 = 0; + do { + ram4000.xray_tilemaps[v0] = *(uint16 *)&BTS[7822]; + ram4000.xray_tilemaps[v0 + 1] = *(uint16 *)&BTS[7824]; + ram4000.xray_tilemaps[v0 + 2] = *(uint16 *)&BTS[7826]; + ram4000.xray_tilemaps[v0 + 3] = *(uint16 *)&BTS[7828]; + ram4000.xray_tilemaps[v0 + 4] = *(uint16 *)&BTS[7830]; + ram4000.xray_tilemaps[v0 + 5] = *(uint16 *)&BTS[7832]; + ram4000.xray_tilemaps[v0 + 6] = *(uint16 *)&BTS[7834]; + ram4000.xray_tilemaps[v0 + 7] = *(uint16 *)&BTS[7836]; + v0 += 8; + } while ((int16)(v0 * 2 - 1536) < 0); +} + +void SetSomeStuffForSpriteObject_2(uint16 v0) { // 0x8BA8C1 + int v1 = v0 >> 1; + cinematicbg_arr7[v1] = 8; + cinematicbg_arr8[v1] = 24; + cinematicbg_arr9[v1] = 3072; +} + +void SetSomeStuffForSpriteObject_3(uint16 j) { // 0x8BA8D5 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 112; + cinematicbg_arr8[v1] = 155; + cinematicbg_arr9[v1] = 3584; +} + +void SetSomeStuffForSpriteObject_4_MetroidEgg(uint16 k) { // 0x8BA8E8 + if (sign16(samus_x_pos - 169)) { + int v1 = k >> 1; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_word_8BCB3B; + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_nullsub_116); + } +} + +void CinematicSprPreInstr_A903(uint16 k) { // 0x8BA903 + if (!cinematic_var13) { + int v1 = k >> 1; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + cinematic_var15 = 0; + } +} + +uint16 CinematicSprInstr_SpawnMetroidEggParticles(uint16 k, uint16 j) { // 0x8BA918 + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCECD, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCED3, 1u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCED9, 2u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEDF, 3u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEE5, 4u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEEB, 5u); + QueueSfx2_Max6(0xBu); + return j; +} +static const int16 kSetSomeStuffForSpriteObject_6_Tab[12] = { 0x5c, 0x58, 0x63, 0x58, 0x59, 0x5d, 0x60, 0x5b, 0x66, 0x5e, 0x63, 0x60 }; +void SetSomeStuffForSpriteObject_6(uint16 j) { // 0x8BA958 + uint16 v1 = cinematic_spawn_param; + int v2 = j >> 1; + cinematicspr_goto_timer[v2] = cinematic_spawn_param; + int v3 = (uint16)(4 * v1) >> 1; + cinematicbg_arr7[v2] = kSetSomeStuffForSpriteObject_6_Tab[v3] + 16; + cinematicbg_arr8[v2] = kSetSomeStuffForSpriteObject_6_Tab[v3 + 1] + 59; + cinematicbg_arr9[v2] = 3584; +} +static const int16 kSetSomeStuffForSpriteObject_7_Tab0[12] = { -1, 0x4000, 0, 0x4000, -1, -0x8000, -1, 0x2000, 0, -0x8000, 0, 0x2000 }; +static const uint16 kSetSomeStuffForSpriteObject_7_Tab1[82] = { // 0x8BA994 + 0xfffe, 0, 0xfffe, 0xc000, 0xfffe, 0xa000, 0xfffe, 0x8000, 0xfffe, 0x6000, 0xfffe, 0x4000, + 0xfffe, 0x2000, 0xffff, 0, 0xffff, 0xc000, 0xffff, 0xa000, 0xffff, 0x8000, 0xffff, 0x6000, + 0xffff, 0x4000, 0xffff, 0x2000, 0, 0, 0, 0x2000, 0, 0x4000, 0, 0x6000, + 0, 0x8000, 0, 0xa000, 0, 0xc000, 0, 0xe000, 1, 0, 1, 0x2000, + 1, 0x4000, 1, 0x6000, 1, 0x8000, 1, 0xa000, 1, 0xc000, 1, 0xe000, + 2, 0, 2, 0x2000, 2, 0x4000, 2, 0x6000, 2, 0x8000, 2, 0xa000, + 2, 0xc000, 2, 0xe000, 0x9dad, 0x991b, 0x1b7d,0x97ad, 0x991a, 0x1a7d, +}; +void SetSomeStuffForSpriteObject_7(uint16 k) { + + int v1 = k >> 1; + uint16 v2 = cinematicspr_arr6[v1]; + int v3 = (uint16)(4 * LOBYTE(cinematicspr_goto_timer[v1])) >> 1; + assert(v3 + 1 < 12); + bool v4 = __CFADD__uint16(kSetSomeStuffForSpriteObject_7_Tab0[v3 + 1], v2); + cinematicspr_arr6[v1] = kSetSomeStuffForSpriteObject_7_Tab0[v3 + 1] + v2; + cinematicbg_arr7[v1] += kSetSomeStuffForSpriteObject_7_Tab0[v3] + v4; + uint16 v5 = cinematicspr_arr7[v1]; + int v6 = (uint16)(4 * HIBYTE(cinematicspr_goto_timer[v1])) >> 1; + assert(v6 + 1 < 82); + v4 = __CFADD__uint16(kSetSomeStuffForSpriteObject_7_Tab1[v6 + 1], v5); + cinematicspr_arr7[v1] = kSetSomeStuffForSpriteObject_7_Tab1[v6 + 1] + v5; + uint16 v7 = kSetSomeStuffForSpriteObject_7_Tab1[v6] + v4 + cinematicbg_arr8[v1]; + cinematicbg_arr8[v1] = v7; + if (sign16(v7 - 168)) { + cinematicspr_goto_timer[v1] += 256; + } else { + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + } +} + +void SetSomeStuffForSpriteObject_8(uint16 j) { // 0x8BAA9A + int v1 = j >> 1; + cinematicspr_goto_timer[v1] = cinematic_spawn_param; + cinematicbg_arr7[v1] = cinematicbg_arr7[13]; + cinematicbg_arr8[v1] = cinematicbg_arr8[13]; + cinematicbg_arr9[v1] = 3584; +} + +static const int16 kSetSomeStuffForSpriteObject_9_Tab0[10] = { -1, 0, -1, -0x8000, 1, 0, 0, -0x8000, -1, -0x8000 }; +static const int16 kSetSomeStuffForSpriteObject_9_Tab2[124] = { // 0x8BAAB3 + -2, 0, -2, -0x4000, -2, -0x6000, -2, -0x8000, -2, 0x6000, -2, 0x4000, + -2, 0x2000, -1, 0, -1, -0x4000, -1, -0x6000, -1, -0x8000, -1, 0x6000, + -1, 0x4000, -1, 0x2000, 0, 0, 0, 0x2000, 0, 0x4000, 0, 0x6000, + 0, -0x8000, 0, -0x6000, 0, -0x4000, 0, -0x2000, 1, 0, 1, 0x2000, + 1, 0x4000, 1, 0x6000, 1, -0x8000, 1, -0x6000, 1, -0x4000, 1, -0x2000, + 2, 0, 2, 0x2000, 2, 0x4000, 2, 0x6000, 2, -0x8000, 2, -0x6000, + 2, -0x4000, 2, -0x2000, 3, 0, 3, 0x2000, 3, 0x4000, 3, 0x6000, + 3, -0x8000, 3, -0x6000, 3, -0x4000, 3, -0x2000, 4, 0, 4, 0x2000, + 4, 0x4000, 4, 0x6000, 4, -0x8000, 4, -0x6000, 4, -0x4000, 4, -0x2000, + 5, 0, 5, 0x2000, 5, 0x4000, 5, 0x6000, 5, -0x8000, 5, -0x6000, + 5, -0x4000, 5, -0x2000, +}; +static const int16 kSetSomeStuffForSpriteObject_9_Tab1[138] = { + -3, 0, -3, -0x4000, -3, -0x6000, -3, -0x8000, -3, 0x6000, -3, 0x4000, + -3, 0x2000, -2, 0, -2, -0x4000, -2, -0x6000, -2, -0x8000, -2, 0x6000, + -2, 0x4000, -2, 0x2000, -1, 0, -1, -0x4000, -1, -0x6000, -1, -0x8000, + -1, 0x6000, -1, 0x4000, -1, 0x2000, 0, 0, 0, 0x2000, 0, 0x4000, + 0, 0x6000, 0, -0x8000, 0, -0x6000, 0, -0x4000, 0, -0x2000, 1, 0, + 1, 0x2000, 1, 0x4000, 1, 0x6000, 1, -0x8000, 1, -0x6000, 1, -0x4000, + 1, -0x2000, 2, 0, 2, 0x2000, 2, 0x4000, 2, 0x6000, 2, -0x8000, + 2, -0x6000, 2, -0x4000, 2, -0x2000, 3, 0, 3, 0x2000, 3, 0x4000, + 3, 0x6000, 3, -0x8000, 3, -0x6000, 3, -0x4000, 3, -0x2000, 4, 0, + 4, 0x2000, 4, 0x4000, 4, 0x6000, 4, -0x8000, 4, -0x6000, 4, -0x4000, + 4, -0x2000, 5, 0, 5, 0x2000, 5, 0x4000, 5, 0x6000, 5, -0x8000, + 5, -0x6000, 5, -0x4000, 5, -0x2000, +}; + +void SetSomeStuffForSpriteObject_9(uint16 k) { + + int v1 = k >> 1; + uint16 v2 = cinematicspr_arr6[v1]; + int v3 = (uint16)(4 * LOBYTE(cinematicspr_goto_timer[v1])) >> 1; + assert(v3 + 1 < 10); + bool v4 = __CFADD__uint16(kSetSomeStuffForSpriteObject_9_Tab0[v3 + 1], v2); + cinematicspr_arr6[v1] = kSetSomeStuffForSpriteObject_9_Tab0[v3 + 1] + v2; + cinematicbg_arr7[v1] += kSetSomeStuffForSpriteObject_9_Tab0[v3] + v4; + uint16 v5 = cinematicspr_goto_timer[v1]; + if ((v5 & 1) != 0) { + uint16 v10, v11; + v10 = 4 * HIBYTE(v5); + v11 = cinematicspr_arr7[v1]; + int v12; + v12 = v10 >> 1; + assert(v12 + 1 < 124); + v4 = __CFADD__uint16(kSetSomeStuffForSpriteObject_9_Tab2[v12 + 1], v11); + cinematicspr_arr7[v1] = kSetSomeStuffForSpriteObject_9_Tab2[v12 + 1] + v11; + uint16 v13; + v13 = kSetSomeStuffForSpriteObject_9_Tab2[v12] + v4 + cinematicbg_arr8[v1]; + cinematicbg_arr8[v1] = v13; + if (!sign16(v13 - 168)) { +LABEL_5: + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_word_8BCD71; + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_nullsub_116); + return; + } + } else { + uint16 v6 = 4 * HIBYTE(v5); + uint16 v7 = cinematicspr_arr7[v1]; + int v8 = v6 >> 1; + assert(v8 + 1 < 138); + v4 = __CFADD__uint16(kSetSomeStuffForSpriteObject_9_Tab1[v8 + 1], v7); + cinematicspr_arr7[v1] = kSetSomeStuffForSpriteObject_9_Tab1[v8 + 1] + v7; + uint16 v9 = kSetSomeStuffForSpriteObject_9_Tab1[v8] + v4 + cinematicbg_arr8[v1]; + cinematicbg_arr8[v1] = v9; + if (!sign16(v9 - 168)) + goto LABEL_5; + } + cinematicspr_goto_timer[v1] += 256; +} + +void SetSomeStuffForSpriteObject_10(uint16 j) { // 0x8BAD55 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 84; + cinematicbg_arr8[v1] = 139; + cinematicbg_arr9[v1] = 3072; +} + +void SetSomeStuffForSpriteObject_11(uint16 k) { // 0x8BAD68 + if (cinematic_var13) { + if ((cinematic_var4 & 3) == 0) { + if (cinematic_var8) { + --cinematic_var8; + ++cinematicbg_arr7[k >> 1]; + } + } + } else { + int v1 = k >> 1; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + } +} + +void SetSomeStuffForSpriteObject_12(uint16 j) { // 0x8BAD93 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 112; + cinematicbg_arr8[v1] = 111; + cinematicbg_arr9[v1] = 3072; +} + +void SetSomeStuffForSpriteObject_13(uint16 k) { // 0x8BADA6 + if (cinematic_var13) { + if ((cinematic_var4 & 3) == 0) { + if (sign16(cinematic_var10 - 8)) { + ++cinematic_var10; + --cinematicbg_arr8[k >> 1]; + } + } + } else { + int v1 = k >> 1; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + } +} + +uint16 CinematicBgInstr_SetSomeStuffForSpriteObject_14(uint16 k, uint16 j) { // 0x8BADD4 + cinematicspr_instr_ptr[15] = addr_unk_8BCC03; + cinematicspr_instr_timer[15] = 1; + return j; +} + +void SetSomeStuffForSpriteObject_15(void) { // 0x8BADE1 + cinematicbg_arr7[15] = 8; + cinematicbg_arr8[15] = 248; +} + +void SetSomeStuffForSpriteObject_16(void) { // 0x8BADEE + cinematicbg_arr7[15] = 8; + cinematicbg_arr8[15] = 24; + cinematicspr_instr_ptr[15] = addr_word_8BCBFB; + cinematicspr_instr_timer[15] = 1; +} + +void SetSomeStuffForSpriteObject_17(uint16 j) { // 0x8BAE07 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 216; + cinematicbg_arr9[v1] = 3072; +} + +void SetSomeStuffForSpriteObject_18(uint16 k) { // 0x8BAE1A + if (cinematic_var16 == 59) { + int v1 = k >> 1; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_word_8BCC23; + } + if (cinematic_var13 == 127) { + int v2 = k >> 1; + cinematicspr_instr_timer[v2] = 1; + cinematicspr_instr_ptr[v2] = addr_off_8BCE53; + } +} + +uint16 CinematicBgInstr_HandleCreateJpnText_Page1(uint16 k, uint16 j) { // 0x8BAE43 + cinematicbg_var1 = 0; + if (japanese_text_flag) + SpawnMode7Object(addr_kMode7ObjectDef_8BD401, japanese_text_flag); + return j; +} + +uint16 CinematicBgInstr_SpawnMarkerWaitInput_Page1(uint16 k, uint16 j) { // 0x8BAE5B + j = CinematicBgInstr_SetSomeStuffForSpriteObject_14(k, j); + if (japanese_text_flag) + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE73, japanese_text_flag); + cinematic_function = FUNC16(CinematicFunction_Intro_WaitInputSetupMotherBrainFight); + return j; +} + +uint16 CinematicBgInstr_HandleCreateJpnText_Page2(uint16 k, uint16 j) { // 0x8BAE79 + cinematicbg_var1 = 0; + if (japanese_text_flag) + SpawnMode7Object(addr_kMode7ObjectDef_8BD407, japanese_text_flag); + return j; +} + +uint16 CinematicBgInstr_SpawnMarkerWaitInput_Page2(uint16 k, uint16 j) { // 0x8BAE91 + j = CinematicBgInstr_SetSomeStuffForSpriteObject_14(k, j); + if (japanese_text_flag) { + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE73, japanese_text_flag); + SpawnMode7Object(addr_kMode7ObjectDef_8BD40D, 0); // a undefined + } else { + cinematic_function = FUNC16(CinematicFunction_Intro_WaitInputSetupBabyMetroid); + } + return j; +} + +void CinematicFunction_Intro_WaitInputSetupMotherBrainFight(void) { // 0x8BAEB8 + if (cinematic_var16) { + --cinematic_var16; + } else if (joypad1_newkeys) { + reg_BG1SC = 80; + samus_pose = kPose_02_FaceL_Normal; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + samus_x_pos = 155; + samus_prev_x_pos = 155; + samus_y_pos = 115; + samus_prev_y_pos = 115; + cinematic_var8 = 0; + cinematic_var13 = 127; + R18_ = 0; + SpawnCinematicSpriteObjectToR18(addr_kCinematicSpriteObjectDef_8BCE55, 0x7Fu); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF27, 0); + uint16 v1 = 0; + do { + level_data[v1 >> 1] = kLevelData_MotherBrainRoomFromCutscene[v1 >> 1]; + v1 += 2; + } while ((int16)(v1 - 448) < 0); + uint16 v2 = 0; + do { + *(uint16 *)&BTS[v2] = 0; + v2 += 2; + } while ((int16)(v2 - 512) < 0); + hud_item_index = 1; + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func12); + frame_handler_beta = FUNC16(Samus_Func15); + ResetDemoData(); + EnableDemoInput(); + LoadDemoInputObject(0, addr_stru_918784); // undefined + cinematic_var15 = -1; + CinematicFunction_Intro_SetupTransitionToGameplay(); + } +} + +void CinematicFunction_Intro_WaitInputSetupBabyMetroid(void) { // 0x8BAF6C + if (cinematic_var16) { + --cinematic_var16; + } else if (joypad1_newkeys) { + reg_BG1SC = 84; + room_width_in_blocks = 32; + room_height_in_blocks = 16; + samus_pose = kPose_02_FaceL_Normal; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + samus_x_pos = 376; + samus_prev_x_pos = 376; + samus_y_pos = 147; + samus_prev_y_pos = 147; + cinematic_var8 = 0; + cinematic_var13 = 127; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE5B, 0x7Fu); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE79, 0); + cinematic_var11 = 0; + uint16 v1 = 0; + do { + level_data[v1 >> 1] = kLevelData_RoomWithBabyMetroidHatching[v1 >> 1]; + v1 += 2; + } while ((int16)(v1 - 768) < 0); + hud_item_index = 0; + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func12); + frame_handler_beta = FUNC16(Samus_Func15); + ResetDemoData(); + EnableDemoInput(); + LoadDemoInputObject(0, addr_stru_91877E); // a undefined + cinematic_var15 = 1; + CinematicFunction_Intro_SetupTransitionToGameplay(); + } +} + +void CinematicFunction_Intro_SetupTransitionToGameplay(void) { // 0x8BB018 + reg_TM = 6; + reg_TS = 17; + reg_CGWSEL = 2; + reg_CGADSUB = 0; + SpawnIntroCutsceneCrossfadeHdma(); + SetSomeStuffForSpriteObject_15(); + cinematic_function = FUNC16(CinematicFunction_Intro_XfadeGameplayFade); + uint16 v0 = 0; + do { + tilemap_stuff[(v0 >> 1) + 256] = kPalettes_Intro[v0 >> 1]; + v0 += 2; + } while ((int16)(v0 - 512) < 0); + DecomposePaletteDataForFading(); + ClearYColorsFromIndexX(0x28u, 3u); + ClearYColorsFromIndexX(0xE0u, 0x10u); + ClearYColorsFromIndexX(0x180u, 0x20u); + ClearYColorsFromIndexX(0x1E0u, 0x10u); + ComposeFadingPalettes(); +} + +uint16 CinematicBgInstr_HandleCreateJpnText_Page3(uint16 k, uint16 j) { // 0x8BB074 + cinematicbg_var1 = 0; + if (japanese_text_flag) + SpawnMode7Object(addr_kMode7ObjectDef_8BD413, japanese_text_flag); + return j; +} + +uint16 CinematicBgInstr_SpawnMarkerWaitInput_Page3(uint16 k, uint16 j) { // 0x8BB08C + j = CinematicBgInstr_SetSomeStuffForSpriteObject_14(k, j); + if (japanese_text_flag) { + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE73, japanese_text_flag); + SpawnMode7Object(addr_kMode7ObjectDef_8BD419, 0); + } else { + cinematic_function = FUNC16(CinematicFunction_Intro_Func11); + } + return j; +} + +uint16 CinematicBgInstr_HandleCreateJpnText_Page4(uint16 k, uint16 j) { // 0x8BB0B3 + cinematicbg_var1 = 0; + if (japanese_text_flag) + SpawnMode7Object(addr_kMode7ObjectDef_8BD41F, japanese_text_flag); + return j; +} + +uint16 CinematicBgInstr_SpawnMarkerWaitInput_Page4(uint16 k, uint16 j) { // 0x8BB0CB + j = CinematicBgInstr_SetSomeStuffForSpriteObject_14(k, j); + if (japanese_text_flag) { + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE73, japanese_text_flag); + SpawnMode7Object(addr_kMode7ObjectDef_8BD425, 0); + } else { + cinematic_function = FUNC16(CinematicFunction_Intro_Func12); + } + return j; +} + +void CinematicFunction_Intro_Func11(void) { // 0x8BB0F2 + if (cinematic_var16) { + --cinematic_var16; + } else if (joypad1_newkeys) { + reg_BG1SC = 88; + cinematic_var8 = 32; + cinematic_var10 = 8; + cinematic_var13 = 127; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE61, 0x7Fu); + CinematicFunction_Intro_Func13(); + } +} + +void CinematicFunction_Intro_Func12(void) { // 0x8BB123 + if (cinematic_var16) { + --cinematic_var16; + } else if (joypad1_newkeys) { + reg_BG1SC = 92; + cinematic_var8 = 0; + cinematic_var10 = -24; + cinematic_var13 = 127; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE67, 0x7Fu); + CinematicFunction_Intro_Func13(); + } +} + +void CinematicFunction_Intro_Func13(void) { // 0x8BB151 + reg_TM = 6; + reg_TS = 17; + reg_CGWSEL = 2; + reg_CGADSUB = 0; + SpawnIntroCutsceneCrossfadeHdma(); + SetSomeStuffForSpriteObject_15(); + cinematic_function = FUNC16(CinematicFunction_Intro_XfadeScientistFade); + uint16 v0 = 0; + do { + tilemap_stuff[(v0 >> 1) + 256] = kPalettes_Intro[v0 >> 1]; + v0 += 2; + } while ((int16)(v0 - 512) < 0); + DecomposePaletteDataForFading(); + ClearYColorsFromIndexX(0x40u, 0x10u); + ClearYColorsFromIndexX(0x1C0u, 9u); + ComposeFadingPalettes(); +} + +uint16 CinematicBgInstr_HandleCreateJpnText_Page5(uint16 k, uint16 j) { // 0x8BB19B + cinematicbg_var1 = 0; + if (japanese_text_flag) + SpawnMode7Object(addr_kMode7ObjectDef_8BD42B, japanese_text_flag); + return j; +} + +uint16 CinematicBgInstr_SpawnMarkerWaitInput_Page5(uint16 k, uint16 j) { // 0x8BB1B3 + j = CinematicBgInstr_SetSomeStuffForSpriteObject_14(k, j); + if (japanese_text_flag) { + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE73, japanese_text_flag); + SpawnMode7Object(addr_kMode7ObjectDef_8BD431, 0); + } else { + cinematic_function = FUNC16(CinematicFunction_Intro_Func15); + } + return j; +} + +void CinematicFunction_Intro_Func15(void) { // 0x8BB1DA + if (cinematic_var16) { + --cinematic_var16; + } else if (joypad1_newkeys) { + cinematic_var13 = 127; + if (japanese_text_flag) { + cinematic_function = FUNC16(CinematicFunction_Intro_Func15b); + DisableCinematicBgTilemapUpdates(); + ClearJapaneseTextTiles(); + TransferJapaneseTextTilesToVram(); + } else { + CinematicFunction_Intro_Func15b(); + } + } +} + +void CinematicFunction_Intro_Func15b(void) { // 0x8BB207 + EnableCinematicBgTilemapUpdates(); + ClearEnglishTextTilemap(); + SpawnCinematicBgObject(addr_kCinematicBgObjectDef_8BCF5D, 0x4C00u); + cinematic_function = FUNC16(nullsub_121); + SetSomeStuffForSpriteObject_16(); + QueueMusic_Delayed8(0); +} + +uint16 CinematicBgInstr_Func16(uint16 k, uint16 j) { // 0x8BB228 + cinematicbg_var1 = 0; + if (japanese_text_flag) + SpawnMode7Object(addr_kMode7ObjectDef_8BD437, japanese_text_flag); + return j; +} + +uint16 CinematicBgInstr_Func17(uint16 k, uint16 j) { // 0x8BB240 + cinematic_function = FUNC16(CinematicFunction_Intro_Func34); + screen_fade_delay = 1; + screen_fade_counter = 1; + return j; +} + +void CinematicFunction_Intro_XfadeGameplayFade(void) { // 0x8BB250 + if ((cinematic_var4 & 3) == 0) { + FadeOutYColorsFromIndexX(0, 0x14u); + FadeOutYColorsFromIndexX(0x60u, 0x10u); + FadeOutYColorsFromIndexX(0x1D2u, 6u); + FadeInYColorsFromIndexX(0x28u, 3u); + FadeInYColorsFromIndexX(0xE0u, 0x10u); + FadeInYColorsFromIndexX(0x180u, 0x20u); + FadeInYColorsFromIndexX(0x1E0u, 0x10u); + ComposeFadingPalettes(); + } + if ((--cinematic_var4 & 0x8000u) != 0) { + reg_TM = 21; + reg_TS = 0; + reg_CGWSEL = 0; + uint16 v0 = 128; + do + ram3000.pause_menu_map_tilemap[v0++] = 47; + while ((int16)(v0 * 2 - 1536) < 0); + ClearJapaneseTextTiles(); + cinematic_function = FUNC16(CinematicFunc_Nothing); + if ((cinematic_var15 & 0x8000u) != 0) + SpawnPalfxObject(addr_kPalfx_E1BC); + } +} + +void CinematicFunction_Intro_XfadeScientistFade(void) { // 0x8BB2D2 + if ((cinematic_var4 & 3) == 0) { + FadeOutYColorsFromIndexX(0, 0x14u); + FadeOutYColorsFromIndexX(0x60u, 0x10u); + FadeOutYColorsFromIndexX(0x1D2u, 6u); + FadeInYColorsFromIndexX(0x40u, 0x10u); + FadeInYColorsFromIndexX(0x1C0u, 9u); + ComposeFadingPalettes(); + } + if ((--cinematic_var4 & 0x8000u) != 0) { + reg_TM = 21; + reg_TS = 0; + reg_CGWSEL = 0; + uint16 v0 = 128; + do + ram3000.pause_menu_map_tilemap[v0++] = 47; + while ((int16)(v0 * 2 - 1536) < 0); + ClearJapaneseTextTiles(); + cinematic_function = FUNC16(CinematicFunc_Nothing); + } +} + +uint16 CinematicSprInstr_StartIntroPage2(uint16 k, uint16 j) { // 0x8BB336 + cinematic_function = FUNC16(CinematicFunction_Intro_Page2); + Instr_StartIntroPage_Common(); + return j; +} + +uint16 CinematicSprInstr_StartIntroPage3(uint16 k, uint16 j) { // 0x8BB33E + cinematic_function = FUNC16(CinematicFunction_Intro_Page3); + Instr_StartIntroPage_Common(); + return j; +} + +uint16 CinematicSprInstr_StartIntroPage4(uint16 k, uint16 j) { // 0x8BB346 + cinematic_function = FUNC16(CinematicFunction_Intro_Page4); + Instr_StartIntroPage_Common(); + return j; +} + +uint16 CinematicSprInstr_StartIntroPage5(uint16 k, uint16 j) { // 0x8BB34E + cinematic_function = FUNC16(CinematicFunction_Intro_Page5); + Instr_StartIntroPage_Common(); + return j; +} + +void Instr_StartIntroPage_Common(void) { // 0x8BB354 + DisableCinematicBgTilemapUpdates(); + ClearJapaneseTextTiles(); + TransferJapaneseTextTilesToVram(); +} + +void CinematicFunction_Intro_Page2(void) { // 0x8BB35F + SpawnCinematicBgObject(addr_kCinematicBgObjectDef_8BCF45, 0x4C00u); + cinematic_function = FUNC16(CinematicFunction_Intro_Fadestuff); + CinematicFunction_Intro_SetupStuff(); +} + +void CinematicFunction_Intro_Page3(void) { // 0x8BB370 + SpawnCinematicBgObject(addr_kCinematicBgObjectDef_8BCF4B, 0x4C00u); + cinematic_function = FUNC16(CinematicFunction_Intro_Fadestuff); + CinematicFunction_Intro_SetupStuff(); +} + +void CinematicFunction_Intro_Page4(void) { // 0x8BB381 + SpawnCinematicBgObject(addr_kCinematicBgObjectDef_8BCF51, 0x4C00u); + cinematic_function = FUNC16(CinematicFunction_Intro_Fadestuff2); + CinematicFunction_Intro_SetupStuff(); +} + +void CinematicFunction_Intro_Page5(void) { // 0x8BB392 + SpawnCinematicBgObject(addr_kCinematicBgObjectDef_8BCF57, 0x4C00u); + cinematic_function = FUNC16(CinematicFunction_Intro_Fadestuff2); + CinematicFunction_Intro_SetupStuff(); +} + +void CinematicFunction_Intro_SetupStuff(void) { // 0x8BB3A1 + reg_TM = 6; + reg_TS = 17; + reg_CGWSEL = 2; + reg_CGADSUB = 0; + uint16 v0 = 0; + do { + tilemap_stuff[(v0 >> 1) + 256] = kPalettes_Intro[v0 >> 1]; + v0 += 2; + } while ((int16)(v0 - 512) < 0); + DecomposePaletteDataForFading(); + ClearYColorsFromIndexX(0, 0x10u); + ClearYColorsFromIndexX(0x60u, 0x10u); + ClearYColorsFromIndexX(0x1D2u, 6u); + ComposeFadingPalettes(); + cinematic_var4 = 127; + EnableCinematicBgTilemapUpdates(); + SetSomeStuffForSpriteObject_16(); +} + +void CinematicFunction_Intro_Fadestuff(void) { // 0x8BB3F4 + if ((cinematic_var13 & 3) == 0) { + FadeInYColorsFromIndexX(0, 0x10u); + FadeInYColorsFromIndexX(0x60u, 0x10u); + FadeInYColorsFromIndexX(0x1D2u, 6u); + FadeOutYColorsFromIndexX(0x28u, 3u); + FadeOutYColorsFromIndexX(0xE0u, 0x10u); + FadeOutYColorsFromIndexX(0x180u, 0x20u); + FadeOutYColorsFromIndexX(0x1E0u, 0x10u); + ComposeFadingPalettes(); + } + if ((--cinematic_var13 & 0x8000u) != 0) { + reg_TM = 22; + reg_TS = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + cinematic_function = FUNC16(CinematicFunc_Nothing); + } +} + +void CinematicFunction_Intro_Fadestuff2(void) { // 0x8BB458 + if ((cinematic_var13 & 3) == 0) { + FadeInYColorsFromIndexX(0, 0x10u); + FadeInYColorsFromIndexX(0x60u, 0x10u); + FadeInYColorsFromIndexX(0x1D2u, 6u); + FadeOutYColorsFromIndexX(0x40u, 0x10u); + FadeOutYColorsFromIndexX(0x1C0u, 9u); + ComposeFadingPalettes(); + } + if ((--cinematic_var13 & 0x8000u) != 0) { + reg_TM = 22; + reg_TS = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + uint16 v0 = 0; + do { + palette_buffer[(v0 >> 1) + 224] = kPalettes_Intro[(v0 >> 1) + 224]; + v0 += 2; + } while ((int16)(v0 - 14) < 0); + cinematic_function = FUNC16(CinematicFunc_Nothing); + } +} + +void CinematicBgPreInstr_SamusBlink(uint16 k) { // 0x8BB4BC + if (cinematic_function == (uint16)FUNC16(CinematicFunction_Intro_Func15b) + || cinematic_function == (uint16)FUNC16(nullsub_121)) { + int v1 = k >> 1; + cinematicbg_instr_ptr[v1] = -10733; + cinematicbg_instr_timer[v1] = 1; + cinematicbg_preinstr[v1] = FUNC16(CinematicFunction_nullsub_116); + } +} + +void CinematicFunction_Intro_Func19(uint16 k) { // 0x8BB4DC + if (!sign16(cinematicspr_instr_ptr[15] + 0x33FD)) + cinematicbg_instr_timer[k >> 1] = 1; +} + +void CinematicFunction_Intro_Func18(void) { // 0x8BB4EB + DisableCinematicBgTilemapUpdates(); + palette_buffer[17] = kPalettes_Intro[17]; + palette_buffer[18] = kPalettes_Intro[18]; + palette_buffer[19] = kPalettes_Intro[19]; + CinematicFunction_Intro_Func20(addr_word_8BD389); + CinematicFunction_Intro_Func20(addr_word_8BD389); + TransferJapaneseTextTilesToVram(); +} + +void EnableCinematicBgTilemapUpdates_(void) { // 0x8BB519 + EnableCinematicBgTilemapUpdates(); +} + +uint16 sub_8BB51E(uint16 k, uint16 j) { // 0x8BB51E + DisableCinematicBgTilemapUpdates(); + palette_buffer[17] = kPalettes_Intro[17]; + palette_buffer[18] = kPalettes_Intro[18]; + palette_buffer[19] = kPalettes_Intro[19]; + ClearJapaneseTextTiles(); + CinematicFunction_Intro_Func20(addr_word_8BCF75); + CinematicFunction_Intro_Func20(addr_word_8BCFBD); + TransferJapaneseTextTilesToVram(); + return j; +} + +uint16 EnableCinematicBgTilemapUpdates__0(uint16 k, uint16 j) { // 0x8BB54F + EnableCinematicBgTilemapUpdates(); + return j; +} + +uint16 CinematicFunction_Intro_Func21(uint16 k, uint16 j) { // 0x8BB554 + DisableCinematicBgTilemapUpdates(); + palette_buffer[17] = kPalettes_Intro[17]; + palette_buffer[18] = kPalettes_Intro[18]; + palette_buffer[19] = kPalettes_Intro[19]; + ClearJapaneseTextTiles(); + CinematicFunction_Intro_Func20(addr_word_8BCFFD); + CinematicFunction_Intro_Func20(addr_word_8BD055); + TransferJapaneseTextTilesToVram(); + return j; +} + +void CinematicFunction_Intro_Func22(uint16 k) { // 0x8BB585 + if (joypad1_newkeys) { + int v1 = k >> 1; + mode7_obj_instr_ptr[v1] = -11355; + mode7_obj_instr_timer[v1] = 1; + mode7_obj_preinstr_func[v1] = FUNC16(CinematicFunction_nullsub_116); + DisableCinematicBgTilemapUpdates(); + ClearJapaneseTextTiles(); + CinematicFunction_Intro_Func20(addr_word_8BD085); + CinematicFunction_Intro_Func20(addr_word_8BD0E1); + TransferJapaneseTextTilesToVram(); + cinematic_var16 = 60; + } +} + +uint16 CinematicFunction_Intro_ThenWaitInputSetupBabyMetroid(uint16 k, uint16 j) { // 0x8BB5B8 + EnableCinematicBgTilemapUpdates(); + cinematic_function = FUNC16(CinematicFunction_Intro_WaitInputSetupBabyMetroid); + return j; +} + +uint16 CinematicFunction_Intro_Func23(uint16 k, uint16 j) { // 0x8BB5C3 + DisableCinematicBgTilemapUpdates(); + palette_buffer[17] = kPalettes_Intro[17]; + palette_buffer[18] = kPalettes_Intro[18]; + palette_buffer[19] = kPalettes_Intro[19]; + ClearJapaneseTextTiles(); + CinematicFunction_Intro_Func20(addr_word_8BD0F9); + TransferJapaneseTextTilesToVram(); + return j; +} + +void CinematicFunction_Intro_Func24(uint16 k) { // 0x8BB5EE + if (joypad1_newkeys) { + int v1 = k >> 1; + mode7_obj_instr_ptr[v1] = -11333; + mode7_obj_instr_timer[v1] = 1; + mode7_obj_preinstr_func[v1] = FUNC16(CinematicFunction_nullsub_116); + DisableCinematicBgTilemapUpdates(); + ClearJapaneseTextTiles(); + CinematicFunction_Intro_Func20(addr_word_8BD15D); + TransferJapaneseTextTilesToVram(); + cinematic_var16 = 60; + } +} + +uint16 CinematicFunction_Intro_Func25(uint16 k, uint16 j) { // 0x8BB61B + EnableCinematicBgTilemapUpdates(); + cinematic_function = FUNC16(CinematicFunction_Intro_Func11); + return j; +} + +uint16 CinematicFunction_Intro_Func26(uint16 k, uint16 j) { // 0x8BB626 + DisableCinematicBgTilemapUpdates(); + palette_buffer[17] = kPalettes_Intro[17]; + palette_buffer[18] = kPalettes_Intro[18]; + palette_buffer[19] = kPalettes_Intro[19]; + ClearJapaneseTextTiles(); + CinematicFunction_Intro_Func20(addr_word_8BD1B9); + CinematicFunction_Intro_Func20(addr_word_8BD215); + TransferJapaneseTextTilesToVram(); + return j; +} + +void CinematicFunction_Intro_Func27(uint16 k) { // 0x8BB657 + if (joypad1_newkeys) { + int v1 = k >> 1; + mode7_obj_instr_ptr[v1] = -11311; + mode7_obj_instr_timer[v1] = 1; + mode7_obj_preinstr_func[v1] = FUNC16(CinematicFunction_nullsub_116); + DisableCinematicBgTilemapUpdates(); + ClearJapaneseTextTiles(); + CinematicFunction_Intro_Func20(addr_word_8BD259); + CinematicFunction_Intro_Func20(addr_word_8BD2A5); + TransferJapaneseTextTilesToVram(); + cinematic_var16 = 60; + } +} + +uint16 CinematicFunction_Intro_Func28(uint16 k, uint16 j) { // 0x8BB68A + EnableCinematicBgTilemapUpdates(); + cinematic_function = FUNC16(CinematicFunction_Intro_Func12); + return j; +} + +uint16 CinematicFunction_Intro_Func29(uint16 k, uint16 j) { // 0x8BB695 + DisableCinematicBgTilemapUpdates(); + palette_buffer[17] = kPalettes_Intro[17]; + palette_buffer[18] = kPalettes_Intro[18]; + palette_buffer[19] = kPalettes_Intro[19]; + ClearJapaneseTextTiles(); + CinematicFunction_Intro_Func20(addr_word_8BD2D5); + TransferJapaneseTextTilesToVram(); + return j; +} + +void CinematicFunction_Intro_Func30(uint16 k) { // 0x8BB6C0 + if (joypad1_newkeys) { + int v1 = k >> 1; + mode7_obj_instr_ptr[v1] = addr_off_8BD3E7; + mode7_obj_instr_timer[v1] = 1; + mode7_obj_preinstr_func[v1] = FUNC16(CinematicFunction_nullsub_116); + DisableCinematicBgTilemapUpdates(); + ClearJapaneseTextTiles(); + CinematicFunction_Intro_Func20(addr_word_8BD30D); + TransferJapaneseTextTilesToVram(); + cinematic_var16 = 60; + } +} + +uint16 CinematicFunction_Intro_Func31(uint16 k, uint16 j) { // 0x8BB6ED + EnableCinematicBgTilemapUpdates(); + cinematic_function = FUNC16(CinematicFunction_Intro_Func15); + return j; +} + +uint16 CinematicFunction_Intro_Func32(uint16 k, uint16 j) { // 0x8BB6F8 + DisableCinematicBgTilemapUpdates(); + ClearJapaneseTextTiles(); + CinematicFunction_Intro_Func20(addr_word_8BD371); + TransferJapaneseTextTilesToVram(); + return j; +} + +uint16 EnableCinematicBgTilemapUpdates__(uint16 k, uint16 j) { // 0x8BB70B + EnableCinematicBgTilemapUpdates(); + return j; +} + +void CinematicFunction_Intro_Func33(void) { // 0x8BB711 + if ((nmi_frame_counter_word & 1) != 0) + reg_TM &= ~2u; + else + reg_TM |= 2u; +} + +void CinematicFunction_Intro_Func34(void) { // 0x8BB72F + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + reg_BG2HOFS = 0; + reg_BG3HOFS = 0; + reg_BG2VOFS = 0; + reg_BG3VOFS = 0; + cinematic_var5 = 0; + for (int i = 656; i >= 0; i -= 2) + *(uint16 *)((char *)&cinematic_var5 + (uint16)i) = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func54); + RevertButtonConfig(); + samus_max_missiles = 0; + samus_missiles = 0; + } +} + +void CinematicFunction_Intro_Func35(uint16 j) { // 0x8BB773 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 56; + cinematicbg_arr8[v1] = 111; + cinematicbg_arr9[v1] = 3584; +} + +void CinematicFunction_Intro_Func36(uint16 k) { // 0x8BB786 + CinematicFunction_Intro_Func37(k); + uint16 v1 = 8; + while ((projectile_type[v1 >> 1] & 0xFFF) != 256) { + v1 -= 2; + if ((v1 & 0x8000u) != 0) + return; + } + if (sign16(projectile_x_pos[v1 >> 1] - 84)) { + KillProjectile(v1); + int v2 = k >> 1; + cinematicspr_arr6[v2] = 8; + uint16 v3 = cinematicspr_goto_timer[v2] + 1; + cinematicspr_goto_timer[v2] = v3; + if (v3 == 4) { + cinematicspr_goto_timer[v2] = 0; + cinematicspr_preinstr_func[v2] = FUNC16(CinematicFunction_Intro_Func39); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF1B, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF1B, 1u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF1B, 2u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF15, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF15, 1u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF15, 2u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF15, 3u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF15, 4u); + } + } +} + +void CinematicFunction_Intro_Func39(uint16 k) { // 0x8BB80F + CinematicFunction_Intro_Func37(k); + CinematicFunction_Intro_Func40(); + int v1 = k >> 1; + uint16 v2 = cinematicspr_goto_timer[v1] + 1; + cinematicspr_goto_timer[v1] = v2; + if (!sign16(v2 - 128)) { + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCB19; + } +} + +void CinematicSprPreInstr_B82E(uint16 k) { // 0x8BB82E + CinematicFunction_Intro_Func40(); + if (!cinematic_var13) { + int v1 = k >> 1; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + cinematic_var15 = 0; + } +} + +void CinematicFunction_Intro_Func37(uint16 k) { // 0x8BB846 + uint16 j, v3; + uint16 v1 = cinematicspr_arr6[k >> 1]; + if (v1) { + if ((v1 & 1) != 0) { + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 240] = kPalettes_Intro[(i >> 1) + 240]; + v3 = k; + } else { + for (j = 30; (j & 0x8000u) == 0; j -= 2) + palette_buffer[(j >> 1) + 240] = 0x7FFF; + v3 = k; + } + --cinematicspr_arr6[v3 >> 1]; + } +} + +void CinematicFunction_Intro_Func40(void) { // 0x8BB877 + if ((cinematic_var12 & 1) != 0) + cinematic_var10 -= 4; + else + cinematic_var10 += 4; +} +static const uint16 kCinematicFunction_Intro_Func42_Tab0[4] = { 0x70, 0xc0, 0x80, 0xe8 }; +static const uint16 kCinematicFunction_Intro_Func42_Tab1[4] = { 0x50, 0x40, 0x38, 0x58 }; +void CinematicFunction_Intro_Func42(uint16 j) { // 0x8BB896 + uint16 v1 = cinematic_spawn_param; + int v2 = j >> 1; + cinematicspr_goto_timer[v2] = cinematic_spawn_param; + int v3 = v1; + cinematicbg_arr7[v2] = kCinematicFunction_Intro_Func42_Tab0[v3]; + cinematicbg_arr8[v2] = kCinematicFunction_Intro_Func42_Tab1[v3] - 8; + cinematicbg_arr9[v2] = 3584; +} + +uint16 CinematicSprInstr_Func43(uint16 k, uint16 j) { // 0x8BB8C5 + int v1 = k >> 1; + if (cinematicspr_goto_timer[v1]) + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_Intro_Func45); + else + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_Intro_Func44); + return j; +} + +void CinematicFunction_Intro_Func44(uint16 k) { // 0x8BB8D8 + int v1 = k >> 1; + uint16 v2 = cinematicspr_arr6[v1]; + cinematicspr_arr6[v1] = v2 + 0x8000; + cinematicbg_arr7[v1] += __CFADD__uint16(v2, 0x8000); + uint16 v3 = cinematicspr_arr7[v1]; + cinematicspr_arr7[v1] = v3 + 0x8000; + cinematicbg_arr8[v1] += __CFADD__uint16(v3, 0x8000); + R18_ = samus_x_pos - 5; + if (sign16(cinematicbg_arr7[v1] + 8 - (samus_x_pos - 5))) { + if (cinematicspr_preinstr_func[0] != (uint16)FUNC16(CinematicFunction_Intro_Func39)) + return; + } else { + samus_invincibility_timer = 11; + samus_knockback_timer = 11; + knockback_x_dir = 1; + } + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; +} +static const uint16 kCinematicFunction_Intro_Func45_Tab0[4] = { 0, 0xffff, 0, 0xffff }; +void CinematicFunction_Intro_Func45(uint16 k) { // 0x8BB93B + int v1 = k >> 1; + uint16 v2 = 2 * cinematicspr_goto_timer[v1]; + cinematicbg_arr7[v1] += kCinematicFunction_Intro_Func45_Tab0[v2 >> 1] + __CFADD__uint16(cinematicspr_arr6[v1], 0x8000); + cinematicspr_arr6[v1] += 0x8000; + + uint16 v3 = cinematicspr_arr7[v1]; + cinematicspr_arr7[v1] = v3 + 0x8000; + uint16 v4 = __CFADD__uint16(v3, 0x8000) + cinematicbg_arr8[v1]; + cinematicbg_arr8[v1] = v4; + if (sign16(v4 - 16) + || !sign16(v4 - 208) + || cinematicspr_preinstr_func[0] == FUNC16(CinematicFunction_Intro_Func39)) { + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + } +} +static const uint16 kCinematicFunction_Intro_Func46_Tab0[5] = { 0, 0x10, 0xfff0, 0xfff8, 8 }; +static const uint16 kCinematicFunction_Intro_Func46_Tab1[5] = { 0, 0xfff0, 8, 0xfff0, 8 }; +static const uint16 kCinematicFunction_Intro_Func46_Tab2[5] = { 1, 0x10, 0x20, 0x30, 0x40 }; +void CinematicFunction_Intro_Func46(uint16 j) { // 0x8BB98D + uint16 v1 = cinematic_spawn_param; + int v2 = j >> 1; + cinematicspr_goto_timer[v2] = cinematic_spawn_param; + int v3 = v1; + cinematicbg_arr7[v2] = kCinematicFunction_Intro_Func46_Tab0[v3] + 56; + cinematicbg_arr8[v2] = kCinematicFunction_Intro_Func46_Tab1[v3] + 111; + cinematicspr_instr_timer[v2] = kCinematicFunction_Intro_Func46_Tab2[v3]; + cinematicbg_arr9[v2] = 2560; +} +static const uint16 kCinematicFunction_Intro_Func47_Tab0[3] = { 0x10, 0xfff0, 0xfff0 }; +static const uint16 kCinematicFunction_Intro_Func47_Tab1[3] = { 0, 4, 0xfff8 }; +static const uint16 kCinematicFunction_Intro_Func47_Tab2[3] = { 1, 8, 0x10 }; +void CinematicFunction_Intro_Func47(uint16 j) { // 0x8BB9D4 + uint16 v1 = cinematic_spawn_param; + int v2 = j >> 1; + cinematicspr_goto_timer[v2] = cinematic_spawn_param; + int v3 = v1; + cinematicbg_arr7[v2] = kCinematicFunction_Intro_Func47_Tab0[v3] + 56; + cinematicbg_arr8[v2] = kCinematicFunction_Intro_Func47_Tab1[v3] + 111; + cinematicspr_instr_timer[v2] = kCinematicFunction_Intro_Func47_Tab2[v3]; + cinematicbg_arr9[v2] = 2560; +} + +void CinematicFunction_Intro_Func48(uint16 k) { // 0x8BBA0F + if (!cinematic_var13) { + int v1 = k >> 1; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + } +} + +uint16 CinematicSprInstr_SpawnIntroRinkas01(uint16 k, uint16 j) { // 0x8BBA21 + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF21, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF21, 1u); + return j; +} + +uint16 CinematicSprInstr_SpawnIntroRinkas23(uint16 k, uint16 j) { // 0x8BBA36 + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF21, 2u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF21, 3u); + return j; +} + +void CinematicFunction_Intro_Func49(uint16 j) { // 0x8BBA4B + int v1 = j >> 1; + cinematicbg_arr7[v1] = 112; + cinematicbg_arr8[v1] = 155; + cinematicbg_arr9[v1] = 3584; +} + +void CinematicFunction_Intro_Func50(uint16 k) { // 0x8BBA5E + int v1 = k >> 1; + if (!sign16(cinematicspr_instr_ptr[v1 + 1] + 0x3487)) { + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_Intro_Func51); + cinematic_var14 = 0; + cinematic_var17 = 0; + } +} + +void CinematicFunction_Intro_Func51(uint16 k) { // 0x8BBA73 + int16 v2; + + int v1 = k >> 1; + if (cinematicbg_arr8[v1] == 145) { + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEF1, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEF1, 1u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEF1, 2u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEF1, 3u); + QueueSfx3_Max6(0x23u); + } + if ((int16)(samus_y_pos - 32 - cinematicbg_arr8[v1]) < 0) { + if (!sign16(cinematic_var17 + 543)) + cinematic_var17 -= 32; + } else if (sign16(cinematic_var17 - 544)) { + cinematic_var17 += 32; + } + LOBYTE(v2) = HIBYTE(cinematic_var17); + HIBYTE(v2) = cinematic_var17; + R20_ = v2 & 0xFF00; + uint16 v3 = HIBYTE(cinematic_var17); + if ((cinematic_var17 & 0x8000u) != 0) + v3 = HIBYTE(cinematic_var17) | 0xFF00; + R18_ = v3; + uint16 v4 = cinematicspr_arr7[v1]; + bool v5 = __CFADD__uint16(R20_, v4); + cinematicspr_arr7[v1] = R20_ + v4; + cinematicbg_arr8[v1] += R18_ + v5; + if ((cinematic_var17 & 0x8000u) == 0) { + cinematic_var14 = 128; + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_Intro_Func52); + } +} + +void CinematicFunction_Intro_Func52(uint16 k) { // 0x8BBB0D + bool v1 = (--cinematic_var14 & 0x8000u) != 0; + if (!cinematic_var14 || v1) { + int v2 = k >> 1; + cinematicspr_preinstr_func[v2] = FUNC16(CinematicFunction_Intro_Func53); + cinematic_var14 = 0; + cinematic_var17 = 0; + cinematicspr_goto_timer[v2] = 0; + } +} + +void CinematicFunction_Intro_Func53(uint16 k) { // 0x8BBB24 + int16 v4; + int16 v5; + int16 v8; + + if (cinematic_var13) { + int v2 = k >> 1; + if (sign16(cinematicspr_goto_timer[v2] - 128)) { + uint16 v3 = cinematicspr_goto_timer[v2] + 1; + cinematicspr_goto_timer[v2] = v3; + if ((v3 & 0x3F) == 0) + QueueSfx3_Max6(0x23u); + } + if ((int16)(samus_x_pos - cinematicbg_arr7[v2]) < 0) { + if (!sign16(cinematic_var14 + 639)) + cinematic_var14 -= 32; + } else if (sign16(cinematic_var14 - 640)) { + cinematic_var14 += 32; + } + LOBYTE(v4) = HIBYTE(cinematic_var14); + HIBYTE(v4) = cinematic_var14; + R20_ = v4 & 0xFF00; + v5 = HIBYTE(cinematic_var14); + if ((cinematic_var14 & 0x8000u) != 0) + v5 = HIBYTE(cinematic_var14) | 0xFF00; + R18_ = v5; + if (v5 >= 0) + cinematic_var15 = -1; + else + cinematic_var15 = 1; + uint16 v6 = cinematicspr_arr6[v2]; + bool v7 = __CFADD__uint16(R20_, v6); + cinematicspr_arr6[v2] = R20_ + v6; + cinematicbg_arr7[v2] += R18_ + v7; + if ((int16)(samus_y_pos - 8 - cinematicbg_arr8[v2]) < 0) { + if (!sign16(cinematic_var17 + 543)) + cinematic_var17 -= 32; + } else if (sign16(cinematic_var17 - 544)) { + cinematic_var17 += 32; + } + LOBYTE(v8) = HIBYTE(cinematic_var17); + HIBYTE(v8) = cinematic_var17; + R20_ = v8 & 0xFF00; + uint16 v9 = HIBYTE(cinematic_var17); + if ((cinematic_var17 & 0x8000u) != 0) + v9 = HIBYTE(cinematic_var17) | 0xFF00; + R18_ = v9; + uint16 v10 = cinematicspr_arr7[v2]; + v7 = __CFADD__uint16(R20_, v10); + cinematicspr_arr7[v2] = R20_ + v10; + cinematicbg_arr8[v2] += R18_ + v7; + } else { + int v1 = k >> 1; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + cinematic_var15 = 0; + } +} + +void ResetButtonAssignmentsToDefault(void) { // 0x8BBC08 + button_config_up = kButton_Up; + button_config_down = kButton_Down; + button_config_left = kButton_Left; + button_config_right = kButton_Right; + grapple_beam_tmpD82 = button_config_shoot_x; + grapple_beam_tmpD84 = button_config_jump_a; + grapple_beam_y_quarter_subvel = button_config_run_b; + grapple_beam_y_quarter_vel = button_config_itemcancel_y; + grapple_beam_tmpD8A = button_config_itemswitch; + grapple_beam_varD8C = button_config_aim_down_L; + grapple_beam_varD8E = button_config_aim_up_R; + button_config_shoot_x = kButton_X; + button_config_jump_a = kButton_A; + button_config_run_b = kButton_B; + button_config_itemcancel_y = kButton_Y; + button_config_itemswitch = kButton_Select; + button_config_aim_down_L = kButton_L; + button_config_aim_up_R = kButton_R; +} + +void RevertButtonConfig(void) { // 0x8BBC75 + button_config_shoot_x = grapple_beam_tmpD82; + button_config_jump_a = grapple_beam_tmpD84; + button_config_run_b = grapple_beam_y_quarter_subvel; + button_config_itemcancel_y = grapple_beam_y_quarter_vel; + button_config_itemswitch = grapple_beam_tmpD8A; + button_config_aim_down_L = grapple_beam_varD8C; + button_config_aim_up_R = grapple_beam_varD8E; +} + +void CinematicFunction_Intro_Func54(void) { // 0x8BBCA0 + int16 v1; + + SetupPpu_3_Mode7(); + ClearCinematicSprites(); + cur_irq_handler = 0; + irqhandler_next_handler = 0; + uint16 v0 = 0; + do { + palette_buffer[v0 >> 1] = kPalettes_Intro2[v0 >> 1]; + v0 += 2; + } while ((int16)(v0 - 512) < 0); + static const DecompressToParams unk_8BBCCA = { LONGPTR(0x7f0000) }; + static const DecompressToParams unk_8BBCDB = { LONGPTR(0x7f4000) }; + static const DecompressToParams unk_8BBCEC = { LONGPTR(0x7f5000) }; + mov24(&decompress_src, 0x95A82F); + DecompressToMem_IpArg(&unk_8BBCCA); + mov24(&decompress_src, 0x96FE69u); + DecompressToMem_IpArg(&unk_8BBCDB); + mov24(&decompress_src, 0x96D10Au); + DecompressToMem_IpArg(&unk_8BBCEC); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BBD04 = { 1, 0, 0x19, LONGPTR(0x7f0000), 0x4000 }; + SetupDmaTransfer(&unk_8BBD04); + WriteReg(MDMAEN, 2u); + WriteReg(VMAIN, 0); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + v1 = 0x4000; + do { + WriteReg(VMDATAL, 0x8Cu); + --v1; + } while (v1); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0); + static const StartDmaCopy unk_8BBD3C = { 1, 0, 0x18, LONGPTR(0x7f4000), 0x0300 }; + SetupDmaTransfer(&unk_8BBD3C); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BBD5C = { 1, 1, 0x18, LONGPTR(0x7f5000), 0x4000 }; + SetupDmaTransfer(&unk_8BBD5C); + WriteReg(MDMAEN, 2u); + WriteRegWord(M7A, 0x100u); + reg_M7A = 256; + WriteRegWord(M7B, 0); + reg_M7B = 0; + WriteRegWord(M7C, 0); + reg_M7C = 0; + WriteRegWord(M7D, 0x100u); + reg_M7D = 256; + WriteRegWord(M7X, 0x38u); + reg_M7X = 56; + WriteRegWord(M7Y, 0x18u); + reg_M7Y = 24; + cinematic_var8 = -72; + cinematic_var10 = -104; + cinematic_var5 = 224; + cinematic_var6 = 512; + ClearPaletteFXObjects(); + EnablePaletteFx(); + ClearCinematicBgObjects(0); + cinematicbg_var3 = 23552; + EnableNMI(); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF0F, 0); + cinematic_function = FUNC16(CinematicFunction_Intro_Func55); + QueueMusic_Delayed8(0xFF2Du); + QueueMusic_DelayedY(5u, 0xEu); +} + +void CinematicFunction_Intro_Func55(void) { // 0x8BBDE4 + if (!(HasQueuedMusic() & 1)) { + reg_INIDISP = 15; + cinematic_function = FUNC16(CinematicFunction_Intro_Func56); + } +} + +void CinematicFunction_Intro_Func56(void) { // 0x8BBDF9 + if (sign16(cinematic_var6 - 32)) { + reg_CGWSEL = 0; + reg_CGADSUB = 49; + reg_COLDATA[0] = 63; + reg_COLDATA[1] = 95; + reg_COLDATA[2] = -97; + ClearCinematicSprites(); + QueueMode7Transfers(0x8b, addr_kCinematicFunction_Intro_Func56_M7); + cinematic_var8 = -32; + cinematic_var10 = -128; + cinematic_var5 = 32; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF39, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE85, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE8B, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE91, 1u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF0F, 1u); + cinematic_function = FUNC16(CinematicFunction_Intro_Func67); + SpawnPalfxObject(addr_kPalfx_E1A8); + SpawnPalfxObject(addr_kPalfx_E1AC); + } else { + cinematic_var6 -= 16; + } +} + +void CinematicFunction_Intro_Func57(uint16 j) { // 0x8BBE7E + int v1 = j >> 1; + if (cinematic_spawn_param) { + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_Intro_Func66); + cinematicbg_arr7[v1] = -32; + } else { + cinematicspr_goto_timer[v1] = -1024; + cinematicbg_arr7[v1] = 112; + } + cinematicbg_arr8[v1] = 87; + cinematicbg_arr9[v1] = 2048; +} + +void CinematicFunction_Intro_Func58(uint16 k) { // 0x8BBEB5 + char v3; // t0 + unsigned int v8; // kr08_4 + unsigned int v9; // kr0C_4 + uint16 v4; + + if (cinematic_function == (uint16)FUNC16(CinematicFunction_Intro_Func56)) { + int v1 = k >> 1; + uint16 v2 = cinematicspr_goto_timer[v1] + 128; + cinematicspr_goto_timer[v1] = v2; + v3 = v2; + LOBYTE(v4) = HIBYTE(v2); + HIBYTE(v4) = v3; + R20_ = v4 & 0xFF00; + v4 = (uint8)v4; + if ((v4 & 0x80) != 0) + v4 |= 0xFF00u; + R18_ = v4; + uint16 v5 = cinematicspr_arr7[v1]; + bool v6 = __CFADD__uint16(R20_, v5); + cinematicspr_arr7[v1] = R20_ + v5; + cinematicbg_arr8[v1] += R18_ + v6; + uint16 v7 = cinematicspr_arr6[v1]; + v6 = __CFADD__uint16(R20_, v7); + cinematicspr_arr6[v1] = R20_ + v7; + cinematicbg_arr7[v1] += R18_ + v6; + v8 = __PAIR32__(R18_, R20_) + __PAIR32__(cinematic_var8, cinematic_var7); + cinematic_var8 = HIWORD(v8); + cinematic_var7 = v8; + v9 = __PAIR32__(R18_, R20_) + __PAIR32__(cinematic_var10, cinematic_var9); + cinematic_var10 = HIWORD(v9); + cinematic_var9 = v9; + } +} + +void CinematicFunction_Intro_Func59(uint16 j) { // 0x8BBF22 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 80; + cinematicbg_arr8[v1] = 159; + cinematicbg_arr9[v1] = 2048; +} + +void CinematicFunction_Intro_Func60(uint16 k) { // 0x8BBF35 + int v1 = k >> 1; + uint16 v2 = cinematicspr_arr6[v1]; + cinematicspr_arr6[v1] = v2 + 0x4000; + cinematicbg_arr7[v1] = (__CFADD__uint16(v2, 0x4000) + cinematicbg_arr7[v1]) & 0x1FF; +} + +void CinematicFunction_Intro_Func61(uint16 j) { // 0x8BBF4C + int v1 = j >> 1; + cinematicbg_arr7[v1] = 116; + cinematicbg_arr8[v1] = 160; + cinematicbg_arr9[v1] = 3072; +} + +void CinematicFunction_Intro_Func62(uint16 k) { // 0x8BBF5F + int v1 = k >> 1; + uint16 v2 = cinematicspr_arr6[v1]; + cinematicspr_arr6[v1] = v2 + 4096; + cinematicbg_arr7[v1] = (__CFADD__uint16(v2, 4096) + cinematicbg_arr7[v1]) & 0x1FF; +} + +void CinematicFunction_Intro_Func63(uint16 j) { // 0x8BBF76 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 96; + cinematicbg_arr9[v1] = 2048; +} + +void CinematicFunction_Intro_Func64(uint16 k) { // 0x8BBF89 + int v1 = k >> 1; + uint16 v2 = cinematicspr_arr6[v1]; + cinematicspr_arr6[v1] = v2 + 2048; + cinematicbg_arr7[v1] = (__CFADD__uint16(v2, 2048) + cinematicbg_arr7[v1]) & 0x1FF; +} + +void CinematicFunction_Intro_Func65(uint16 j) { // 0x8BBFA0 + if (cinematic_spawn_param) { + cinematicbg_arr7[j >> 1] = 224; + } else { + int v1 = j >> 1; + cinematicbg_arr7[v1] = 112; + cinematicspr_preinstr_func[v1] = FUNC16(CinematicSprPreInstr_nullsub_300); + } + int v2 = j >> 1; + cinematicbg_arr8[v2] = 87; + cinematicbg_arr9[v2] = 2048; +} + +void CinematicFunction_Intro_Func66(uint16 k) { // 0x8BBFC6 + int v1 = k >> 1; + uint16 v2 = cinematicspr_arr6[v1]; + cinematicspr_arr6[v1] = v2 - 0x2000; + cinematicbg_arr7[v1] = (__PAIR32__(cinematicbg_arr7[v1], v2) - 0x2000) >> 16; +} + +void CinematicFunction_Intro_Func67(void) { // 0x8BBFDA + unsigned int v0; // kr00_4 + + if (sign8(--reg_COLDATA[0] - 32)) + reg_COLDATA[0] = 32; + if (sign8(--reg_COLDATA[1] - 64)) + reg_COLDATA[1] = 64; + if (sign8(--reg_COLDATA[2] + 0x80)) + reg_COLDATA[2] = 0x80; + v0 = __PAIR32__(cinematic_var8, cinematic_var7) - 0x2000; + cinematic_var8 = HIWORD(v0); + cinematic_var7 = v0; + if (sign16(cinematic_var6 - 3072)) { + cinematic_var6 += 16; + } else if (sign16(cinematic_var6 - 0x2000)) { + cinematic_var6 += 32; + } else { + reg_TM = 17; + reg_BGMODE = 1; + reg_M7SEL = 0; + reg_BG1SC = 92; + reg_BG12NBA = 6; + cinematic_var6 = 256; + cinematic_var5 = 0; + cinematic_var7 = 0; + cinematic_var8 = 0; + cinematic_var9 = 0; + cinematic_var10 = 0; + EnableCinematicBgObjects(); + EnableCinematicBgTilemapUpdates(); + SpawnCinematicBgObject(addr_kCinematicBgObjectDef_8BCF69, 0x5C00u); + cinematic_function = FUNC16(nullsub_120); + } +} + +void CinematicFunction_Intro_Func68(uint16 j) { // 0x8BC083 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 124; + cinematicbg_arr8[v1] = 186; + cinematicbg_arr9[v1] = 0; +} + +uint16 CinematicCommonInstr_Func69(uint16 k, uint16 j) { // 0x8BC096 + if (!japanese_text_flag) + j += 6; + return j; +} + +uint16 CinematicCommonInstr_Func70(uint16 k, uint16 j) { // 0x8BC0A2 + cinematic_function = FUNC16(CinematicFunction_Intro_Func72); + screen_fade_delay = 1; + screen_fade_counter = 1; + return j; +} + +void CinematicFunction_Intro_Func71(uint16 j) { // 0x8BC0B2 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 124; + cinematicbg_arr8[v1] = 204; + cinematicbg_arr9[v1] = 0; +} + +void CinematicFunction_Intro_Func72(void) { // 0x8BC0C5 + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + reg_BG2HOFS = 0; + reg_BG3HOFS = 0; + reg_BG2VOFS = 0; + reg_BG3VOFS = 0; + cinematic_var5 = 0; + for (int i = 656; i >= 0; i -= 2) + *(uint16 *)((char *)&cinematic_var5 + (uint16)i) = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func73); + } +} + +void CinematicFunction_Intro_Func73(void) { // 0x8BC100 + loading_game_state = kGameState_31_SetUpNewGame; + game_state = kGameState_31_SetUpNewGame; + area_index = 6; + load_station_index = 0; + SaveToSram(selected_save_slot); +} + +void CinematicFunctionBlackoutFromCeres(void) { // 0x8BC11B + int16 j; + int16 v3; + + SetupPpu_3_Mode7(); + for (j = 656; j >= 0; j -= 2) + *(uint16 *)((char *)&cinematic_var5 + (uint16)j) = 0; + door_def_ptr = 0; + layer1_x_pos = 0; + layer1_y_pos = 0; + uint16 v2 = 0; + do { + palette_buffer[v2 >> 1] = kPalettes_Intro2[v2 >> 1]; + v2 += 2; + } while ((int16)(v2 - 512) < 0); + static const DecompressToParams unk_8BC162 = { LONGPTR(0x7f0000) }; + static const DecompressToParams unk_8BC173 = { LONGPTR(0x7f4000) }; + static const DecompressToParams unk_8BC184 = { LONGPTR(0x7f5000) }; + mov24(&decompress_src, 0x95A82F); + DecompressToMem_IpArg(&unk_8BC162); + mov24(&decompress_src, 0x96FE69); + DecompressToMem_IpArg(&unk_8BC173); + mov24(&decompress_src, 0x96D10A); + DecompressToMem_IpArg(&unk_8BC184); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BC19C = { 1, 0, 0x19, LONGPTR(0x7f0000), 0x4000 }; + SetupDmaTransfer(&unk_8BC19C); + WriteReg(MDMAEN, 2u); + WriteReg(VMAIN, 0); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + v3 = 0x4000; + do { + WriteReg(VMDATAL, 0x8Cu); + --v3; + } while (v3); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0); + static const StartDmaCopy unk_8BC1D4 = { 1, 0, 0x18, LONGPTR(0x7f4600), 0x0600 }; + SetupDmaTransfer(&unk_8BC1D4); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BC1F4 = { 1, 1, 0x18, LONGPTR(0x7f5000), 0x4000 }; + SetupDmaTransfer(&unk_8BC1F4); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BC214 = { 1, 1, 0x18, LONGPTR(0x9ad200), 0x1a00 }; + SetupDmaTransfer(&unk_8BC214); + WriteReg(MDMAEN, 2u); + WriteRegWord(M7A, 0x100u); + reg_M7A = 256; + WriteRegWord(M7B, 0); + reg_M7B = 0; + WriteRegWord(M7C, 0); + reg_M7C = 0; + WriteRegWord(M7D, 0x100u); + reg_M7D = 256; + WriteRegWord(M7X, 0x34u); + reg_M7X = 52; + WriteRegWord(M7Y, 0x30u); + reg_M7Y = 48; + cinematic_var8 = -44; + cinematic_var10 = -112; + cinematic_var5 = 0; + cinematic_var6 = 256; + DisableHdmaObjects(); + WaitUntilEndOfVblankAndClearHdma(); + ClearPaletteFXObjects(); + EnablePaletteFx(); + ClearCinematicBgObjects(0x2f); + cinematicbg_var3 = 0; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCE7F, 0); + R18_ = 2; + SpawnCinematicSpriteObjectToR18(addr_kCinematicSpriteObjectDef_8BCE8B, 2u); + R18_ = 0; + SpawnCinematicSpriteObjectToR18(addr_kCinematicSpriteObjectDef_8BCE91, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF33, 0); + SpawnPalfxObject(addr_kPalfx_E1B8); + EnableNMI(); + screen_fade_delay = 1; + screen_fade_counter = 1; + cinematic_function = FUNC16(CinematicFunction_Intro_Func74); + QueueMusic_Delayed8(0); + QueueMusic_Delayed8(0xFF2Du); + if (game_state == kGameState_37_CeresGoesBoomWithSamus) + QueueMusic_DelayedY(8u, 0xEu); + else + QueueMusic_DelayedY(7u, 0xEu); +} + +void CinematicFunction_Intro_Func74(void) { // 0x8BC2E4 + if (!(HasQueuedMusic() & 1)) + cinematic_function = FUNC16(CinematicFunction_Intro_Func75); +} + +void CinematicFunction_Intro_Func75(void) { // 0x8BC2F1 + uint16 v0 = (__PAIR32__(cinematic_var10, cinematic_var9) + 4096) >> 16; + cinematic_var9 += 4096; + cinematic_var10 = v0; + uint16 v1 = (__PAIR32__(cinematic_var8, cinematic_var7) - 0x4000) >> 16; + cinematic_var7 -= 0x4000; + cinematic_var8 = v1; + ++cinematic_var6; + HandleFadeIn(); + if (reg_INIDISP == 15) { + screen_fade_delay = 0; + screen_fade_counter = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func76); + cinematic_var4 = 1; + cinematic_var13 = 0; + } +} + +void CinematicFunction_Intro_Func76(void) { // 0x8BC345 + uint16 v0 = (__PAIR32__(cinematic_var10, cinematic_var9) + 4096) >> 16; + cinematic_var9 += 4096; + cinematic_var10 = v0; + uint16 v1 = (__PAIR32__(cinematic_var8, cinematic_var7) - 0x4000) >> 16; + cinematic_var7 -= 0x4000; + cinematic_var8 = v1; + if (sign16(cinematic_var6 - 640)) { + ++cinematic_var6; + } else { + power_bomb_explosion_x_pos = reg_M7X - cinematic_var8; + power_bomb_explosion_y_pos = reg_M7Y - cinematic_var10; + EnableHdmaObjects(); + SpawnPowerBombExplosion(); + reg_CGWSEL = 16; + reg_CGADSUB = 55; + cinematic_var6 = 768; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF2D, 0); + if (game_state == 37) + QueueMode7Transfers(0x8b, addr_kCinematicFunction_Intro_Func76_M7_2); + else + QueueMode7Transfers(0x8b, addr_kCinematicFunction_Intro_Func76_M7_0); + QueueMode7Transfers(0x8b, addr_kCinematicFunction_Intro_Func76_M7_1); + cinematic_function = FUNC16(CinematicFunction_Intro_Func77); + } +} + +uint16 CinematicSprInstr_SpawnCeresExplosions1(uint16 k, uint16 j) { // 0x8BC404 + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEBB, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEBB, 1u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEBB, 2u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEBB, 3u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEBB, 4u); + return j; +} +static const uint16 kCinematicFunction_Intro_Func78_Tab0[5] = { 1, 16, 32, 48, 64 }; +static const int16 kCinematicFunction_Intro_Func78_Tab1[5] = { 16, -16, 16, -16, 0 }; +static const int16 kCinematicFunction_Intro_Func78_Tab2[5] = { -16, 16, 16, -16, 0 }; +void CinematicFunction_Intro_Func78(uint16 j) { // 0x8BC434 + uint16 v1 = cinematic_spawn_param; + int v2 = j >> 1; + cinematicspr_goto_timer[v2] = cinematic_spawn_param; + int v3 = v1; + cinematicspr_instr_timer[v2] = kCinematicFunction_Intro_Func78_Tab0[v3]; + cinematicbg_arr7[v2] = kCinematicFunction_Intro_Func78_Tab1[v3] + reg_M7X - cinematic_var8; + cinematicbg_arr8[v2] = kCinematicFunction_Intro_Func78_Tab2[v3] + reg_M7Y - cinematic_var10; + cinematicbg_arr9[v2] = 2560; +} + +void CinematicSprPreInstr_C489(uint16 k) { // 0x8BC489 + if (cinematic_function == (uint16)FUNC16(CinematicFunction_Intro_Func77)) { + cinematicspr_preinstr_func[k >> 1] = FUNC16(CinematicFunction_nullsub_116); + } else { + bool v1 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v1) { + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEC1, cinematic_var13); + cinematic_var4 = 12; + cinematic_var13 = ((uint8)cinematic_var13 + 1) & 7; + } + } +} +static const int16 g_word_8BC4EB[16] = { // 0x8BC4B9 + 14, -8, 8, 12, -16, 12, -8, -14, 0, 0, 16, 14, + -12, 4, -8, -16, +}; +void CinematicFunction_Intro_Func80(uint16 j) { + + uint16 v1 = cinematic_spawn_param; + int v2 = j >> 1; + cinematicspr_goto_timer[v2] = cinematic_spawn_param; + int v3 = (uint16)(4 * v1) >> 1; + cinematicbg_arr7[v2] = g_word_8BC4EB[v3] + reg_M7X - cinematic_var8; + cinematicbg_arr8[v2] = g_word_8BC4EB[v3 + 1] + reg_M7Y - cinematic_var10; + cinematicbg_arr9[v2] = 2560; +} + +uint16 CinematicSprInstr_SpawnCeresExplosions3(uint16 k, uint16 j) { // 0x8BC50C + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEC7, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEC7, 1u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEC7, 2u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEC7, 3u); + return j; +} +static const int16 kCinematicFunction_Intro_Func81_Tab0[4] = { 1, 4, 8, 16 }; +static const int16 kCinematicFunction_Intro_Func81_Tab1[4] = { 8, 12, -8, -12 }; +static const int16 kCinematicFunction_Intro_Func81_Tab2[4] = { -4, 8, -10, 12 }; +void CinematicFunction_Intro_Func81(uint16 j) { // 0x8BC533 + uint16 v1 = cinematic_spawn_param; + int v2 = j >> 1; + cinematicspr_goto_timer[v2] = cinematic_spawn_param; + int v3 = v1; + cinematicspr_instr_timer[v2] = kCinematicFunction_Intro_Func81_Tab0[v3]; + cinematicbg_arr7[v2] = kCinematicFunction_Intro_Func81_Tab1[v3] + reg_M7X - cinematic_var8; + cinematicbg_arr8[v2] = kCinematicFunction_Intro_Func81_Tab2[v3] + reg_M7Y - cinematic_var10; + cinematicbg_arr9[v2] = 2560; +} + +void CinematicFunction_Intro_Func82(uint16 k) { // 0x8BC582 + int v1 = k >> 1; + uint16 v2 = cinematicspr_arr7[v1]; + cinematicspr_arr7[v1] = v2 - 4096; + cinematicbg_arr8[v1] = (__PAIR32__(cinematicbg_arr8[v1], v2) - 4096) >> 16; + uint16 v3 = cinematicspr_arr6[v1]; + cinematicspr_arr6[v1] = v3 + 0x4000; + cinematicbg_arr7[v1] += __CFADD__uint16(v3, 0x4000); +} + +void CinematicFunction_Intro_Func83(uint16 j) { // 0x8BC5A9 + int v1 = j >> 1; + cinematicbg_arr7[v1] = reg_M7X - cinematic_var8; + cinematicbg_arr8[v1] = reg_M7Y - cinematic_var10; + cinematicbg_arr9[v1] = 2560; +} + +void CinematicFunction_Intro_Func77(void) { // 0x8BC5CA + reg_CGWSEL = 16; + reg_CGADSUB = 55; + cinematic_var8 += 2; + cinematic_var5 = (uint8)(cinematic_var5 - 1); + if (sign16(cinematic_var6 - 16)) { + cinematic_function = FUNC16(CinematicFunction_Intro_Func84); + cinematic_var4 = 192; + } else { + cinematic_var6 -= 16; + } +} + +void CinematicFunction_Intro_Func84(void) { // 0x8BC610 + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) { + screen_fade_delay = 1; + screen_fade_counter = 1; + cinematic_function = FUNC16(CinematicFunction_Intro_Func85); + } +} + +void CinematicFunction_Intro_Func85(void) { // 0x8BC627 + HandleFadeOut(); + if (reg_INIDISP == 0x80) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + if (game_state == kGameState_37_CeresGoesBoomWithSamus) { + QueueMusic_Delayed8(0); + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + WaitUntilEndOfVblankAndClearHdma(); + DisableIrqInterrupts(); + fx_layer_blending_config_a = 0; + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = 0; + reg_TM = 16; + reg_TS = 0; + reg_TMW = 0; + reg_TSW = 0; + reg_BGMODE = 9; + game_options_screen_index = 0; + menu_index = 0; + for (int i = 254; i >= 0; i -= 2) + cinematicbg_arr7[(i >> 1) + 8] = 0; + game_state = kGameState_25_SamusNoHealth; + } else { + cinematic_function = FUNC16(CinematicFunction_Intro_Func86); + } + } +} + +void CinematicFunction_Intro_Func86(void) { // 0x8BC699 + static const DecompressToParams unk_8BC6BB = { LONGPTR(0x7f9000) }; + static const DecompressToParams unk_8BC6CC = { LONGPTR(0x7f5000) }; + SetupPpu_4_Mode1(); + for (int i = 656; i >= 0; i -= 2) + *(uint16 *)((char *)&cinematic_var5 + (uint16)i) = 0; + mov24(&decompress_src, 0x978ADB); + DecompressToMem_IpArg(&unk_8BC6BB); + mov24(&decompress_src, 0x96EC76); + DecompressToMem_IpArg(&unk_8BC6CC); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0); + static const StartDmaCopy unk_8BC6E4 = { 1, 0, 0x18, LONGPTR(0x7f4300), 0x0300 }; + SetupDmaTransfer(&unk_8BC6E4); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x5Cu); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BC704 = { 1, 1, 0x18, LONGPTR(0x7f9000), 0x0800 }; + SetupDmaTransfer(&unk_8BC704); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BC724 = { 1, 1, 0x18, LONGPTR(0x7f5000), 0x4000 }; + SetupDmaTransfer(&unk_8BC724); + WriteReg(MDMAEN, 2u); + WriteRegWord(M7A, 0x100u); + reg_M7A = 256; + WriteRegWord(M7B, 0); + reg_M7B = 0; + WriteRegWord(M7C, 0); + reg_M7C = 0; + WriteRegWord(M7D, 0x100u); + reg_M7D = 256; + WriteRegWord(M7X, 0x38u); + reg_M7X = 56; + WriteRegWord(M7Y, 0x18u); + reg_M7Y = 24; + cinematic_var8 = 0; + cinematic_var10 = 0; + cinematic_var5 = 0; + cinematic_var6 = 256; + DisableHdmaObjects(); + WaitUntilEndOfVblankAndClearHdma(); + ClearPaletteFXObjects(); + EnablePaletteFx(); + reg_MOSAIC = -127; + SpawnPalfxObject(addr_kPalfx_E1A8); + cinematic_function = FUNC16(CinematicFunction_Intro_Func87); + EnableNMI(); + screen_fade_delay = 1; + screen_fade_counter = 1; +} + +void CinematicFunction_Intro_Func87(void) { // 0x8BC79C + if ((cinematic_var12 & 3) == 0) + reg_MOSAIC -= 16; + HandleFadeIn(); + if (reg_INIDISP == 15) { + screen_fade_delay = 0; + screen_fade_counter = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func88); + } +} + +void CinematicFunction_Intro_Func88(void) { // 0x8BC7CA + if ((cinematic_var12 & 3) == 0) { + reg_MOSAIC -= 16; + if ((reg_MOSAIC & 0xF0) == 0) { + reg_BGMODE = 7; + reg_M7SEL = 0x80; + reg_BG1SC = 0; + reg_BG12NBA = 0; + reg_TM = 17; + cinematic_var8 = 128; + cinematic_var10 = -104; + cinematic_var5 = 32; + cinematic_var6 = 256; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEA3, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEF7, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEFD, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF03, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCF09, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEAF, 0); + cinematic_function = FUNC16(nullsub_120); + } + } +} + +void CinematicFunction_Intro_Func89(uint16 j) { // 0x8BC83B + int v1 = j >> 1; + cinematicbg_arr7[v1] = 136; + cinematicbg_arr8[v1] = 111; + cinematicbg_arr9[v1] = 3584; +} + +void CinematicFunction_Intro_Func90(uint16 k) { // 0x8BC84E + if (cinematic_function == (uint16)FUNC16(nullsub_124)) + cinematicspr_preinstr_func[k >> 1] = FUNC16(CinematicFunction_Intro_Func91); +} + +void CinematicFunction_Intro_Func91(uint16 k) { // 0x8BC85D + char v3; // t0 + + int v1 = k >> 1; + uint16 v2 = cinematicspr_goto_timer[v1] + 64; + cinematicspr_goto_timer[v1] = v2; + v3 = v2; + LOBYTE(v2) = HIBYTE(v2); + HIBYTE(v2) = v3; + R20_ = v2 & 0xFF00; + R18_ = (uint8)v2; + uint16 v4 = cinematicspr_arr7[v1]; + bool v5 = v4 < R20_; + cinematicspr_arr7[v1] = v4 - R20_; + uint16 v6 = cinematicbg_arr8[v1] - (v5 + R18_); + cinematicbg_arr8[v1] = v6; + if (sign16(v6 + 128)) { + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + } +} + +void CinematicFunction_Intro_Func92(uint16 j) { // 0x8BC897 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 127; + cinematicbg_arr9[v1] = 2048; +} + +void CinematicFunction_Intro_Func93(uint16 k) { // 0x8BC8AA + if (cinematic_function == (uint16)FUNC16(nullsub_124)) + cinematicspr_preinstr_func[k >> 1] = FUNC16(CinematicFunction_Intro_Func94); +} + +void CinematicFunction_Intro_Func94(uint16 k) { // 0x8BC8B9 + char v3; // t0 + + int v1 = k >> 1; + uint16 v2 = cinematicspr_goto_timer[v1] + 32; + cinematicspr_goto_timer[v1] = v2; + v3 = v2; + LOBYTE(v2) = HIBYTE(v2); + HIBYTE(v2) = v3; + R20_ = v2 & 0xFF00; + R18_ = (uint8)v2; + uint16 v4 = cinematicspr_arr7[v1]; + bool v5 = v4 < R20_; + cinematicspr_arr7[v1] = v4 - R20_; + uint16 v6 = cinematicbg_arr8[v1] - (v5 + R18_); + cinematicbg_arr8[v1] = v6; + if (sign16(v6 + 128)) { + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + cinematic_function = FUNC16(CinematicFunction_Intro_Func95); + } +} + +void CinematicFunction_Intro_Func96(uint16 k) { // 0x8BC8F9 + if (cinematic_function == (uint16)FUNC16(nullsub_124)) + cinematicspr_preinstr_func[k >> 1] = FUNC16(CinematicFunction_Intro_Func97); +} + +void CinematicFunction_Intro_Func97(uint16 k) { // 0x8BC908 + char v3; // t0 + + int v1 = k >> 1; + uint16 v2 = cinematicspr_goto_timer[v1] + 32; + cinematicspr_goto_timer[v1] = v2; + v3 = v2; + LOBYTE(v2) = HIBYTE(v2); + HIBYTE(v2) = v3; + R20_ = v2 & 0xFF00; + R18_ = (uint8)v2; + uint16 v4 = cinematicspr_arr7[v1]; + bool v5 = v4 < R20_; + cinematicspr_arr7[v1] = v4 - R20_; + uint16 v6 = cinematicbg_arr8[v1] - (v5 + R18_); + cinematicbg_arr8[v1] = v6; + if (sign16(v6 + 128)) { + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BCE53; + } +} + +void CinematicFunction_Intro_Func98(uint16 j) { // 0x8BC942 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 48; + cinematicbg_arr8[v1] = 47; + cinematicbg_arr9[v1] = 2048; +} + +void CinematicFunction_Intro_Func99(uint16 j) { // 0x8BC956 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 208; + cinematicbg_arr8[v1] = 47; + cinematicbg_arr9[v1] = 2048; +} + +void CinematicFunction_Intro_Func100(uint16 j) { // 0x8BC96A + int v1 = j >> 1; + cinematicbg_arr7[v1] = 48; + cinematicbg_arr8[v1] = 207; + cinematicbg_arr9[v1] = 2048; +} + +void CinematicFunction_Intro_Func101(uint16 j) { // 0x8BC97E + int v1 = j >> 1; + cinematicbg_arr7[v1] = 208; + cinematicbg_arr8[v1] = 207; + cinematicbg_arr9[v1] = 2048; +} + +void CinematicFunction_Intro_Func102(uint16 j) { // 0x8BC992 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 186; + cinematicbg_arr9[v1] = 0; +} + +uint16 CinematicSprInstr_C9A5(uint16 k, uint16 j) { // 0x8BC9A5 + SpawnPalfxObject(addr_kPalfx_E1B0); + return j; +} + +uint16 CinematicSprInstr_C9AF(uint16 k, uint16 j) { // 0x8BC9AF + if (japanese_text_flag) + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BCEB5, japanese_text_flag); + return j; +} + +uint16 CinematicSprInstr_C9BD(uint16 k, uint16 j) { // 0x8BC9BD + SpawnPalfxObject(addr_loc_8BE1B4); + return j; +} + +uint16 CinematicSprInstr_C9C7(uint16 k, uint16 j) { // 0x8BC9C7 + cinematic_var8 = 62; + cinematic_var10 = -112; + cinematic_var5 = 32; + cinematic_var6 = 16; + cinematic_function = FUNC16(CinematicFunction_Intro_Func105); + return j; +} + +void CinematicFunction_Intro_Func104(uint16 j) { // 0x8BC9E6 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 204; + cinematicbg_arr9[v1] = 0; +} + +void CinematicFunction_Intro_Func105(void) { // 0x8BC9F9 + unsigned int v0; // kr00_4 + + v0 = __PAIR32__(cinematic_var10, cinematic_var9) + 0x2000; + cinematic_var10 = HIWORD(v0); + cinematic_var9 = v0; + bool v1 = cinematic_var7 >= 0x8000u; + cinematic_var7 += 0x8000; + cinematic_var8 -= !v1; + if (sign16(cinematic_var6 - 1152)) + cinematic_var6 += 4; + else + cinematic_function = FUNC16(CinematicFunction_Intro_Func106); +} + +void CinematicFunction_Intro_Func106(void) { // 0x8BCA36 + unsigned int v0; // kr00_4 + + v0 = __PAIR32__(cinematic_var10, cinematic_var9) + 0x2000; + cinematic_var10 = HIWORD(v0); + cinematic_var9 = v0; + bool v1 = cinematic_var7 >= 0x8000u; + cinematic_var7 += 0x8000; + cinematic_var8 -= !v1; + if (sign16(cinematic_var8 + 128)) { + cinematic_function = FUNC16(CinematicFunction_Intro_Func107); + } else { + cinematic_var6 += 16; + if (cinematic_var5 != 224) + cinematic_var5 = (uint8)(cinematic_var5 - 1); + } +} + +void CinematicFunction_Intro_Func107(void) { // 0x8BCA85 + unsigned int v0; // kr00_4 + unsigned int v1; // kr04_4 + + v0 = __PAIR32__(cinematic_var10, cinematic_var9) + 0x2000; + cinematic_var10 = HIWORD(v0); + cinematic_var9 = v0; + v1 = __PAIR32__(cinematic_var8, cinematic_var7) + 0x2000; + cinematic_var8 = HIWORD(v1); + cinematic_var7 = v1; + if (sign16(cinematic_var6 - 0x2000)) { + cinematic_var6 += 32; + } else { + reg_TM = 16; + cinematic_function = FUNC16(CinematicFunction_Intro_Func108); + cinematic_var4 = 64; + } +} + +void CinematicFunction_Intro_Func108(void) { // 0x8BCAD0 + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) + cinematic_function = FUNC16(nullsub_124); +} + +void CinematicFunction_Intro_Func95(void) { // 0x8BCADF + reg_INIDISP = 0x80; + for (int i = 656; i >= 0; i -= 2) + *(uint16 *)((char *)&cinematic_var5 + (uint16)i) = 0; + game_state = kGameState_6_LoadingGameData; + samus_health = samus_max_health; +} + +CoroutineRet GameState_39_EndingAndCredits_(void) { // 0x8BD443 + CallCinematicFunction(cinematic_function | 0x8B0000); + if ((cinematic_var11 & 0x8000u) == 0) + ++cinematic_var11; + ++cinematic_var12; + HandleCinematicSprites(); + MaybeHandleCinematicBgObjects(); + CreditsObject_Process(); + PaletteFxHandler(); + DrawCinematicSpriteObjects_Ending(); + CinematicFunction_Intro_Func149(); + HandleMode7TransformationMatrix(); + return kCoroutineNone; +} + +void MaybeHandleCinematicBgObjects(void) { // 0x8BD474 + if (!sign16(cinematic_function + 0x1AFC)) + HandleCinematicBgObjects(); +} + +void CinematicFunctionEscapeFromCebes(void) { // 0x8BD480 + int16 j; + + cur_irq_handler = 0; + irqhandler_next_handler = 0; + SetupPpu_5_Mode7(); + for (j = 656; j >= 0; j -= 2) + *(uint16 *)((char *)&cinematic_var5 + (uint16)j) = 0; + uint16 v2 = 0; + do { + palette_buffer[v2 >> 1] = kPalettes_Intro3[v2 >> 1]; + v2 += 2; + } while ((int16)(v2 - 512) < 0); + static const DecompressToParams unk_8BD4C2 = { LONGPTR(0x7f0000) }; + static const DecompressToParams unk_8BD4D3 = { LONGPTR(0x7f4000) }; + static const DecompressToParams unk_8BD4E4 = { LONGPTR(0x7f8000) }; + mov24(&decompress_src, 0x98bcd6); + DecompressToMem_IpArg(&unk_8BD4C2); + mov24(&decompress_src, 0x99a56f); + DecompressToMem_IpArg(&unk_8BD4D3); + mov24(&decompress_src, 0x99d17e); + DecompressToMem_IpArg(&unk_8BD4E4); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD4FC = { 1, 1, 0x18, LONGPTR(0x7f8000), 0x4000 }; + SetupDmaTransfer(&unk_8BD4FC); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x20u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD51C = { 1, 1, 0x18, LONGPTR(0x7f8000), 0x4000 }; + SetupDmaTransfer(&unk_8BD51C); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD53C = { 1, 1, 0x18, LONGPTR(0x7f4000), 0x4000 }; + SetupDmaTransfer(&unk_8BD53C); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD55C = { 1, 0, 0x19, LONGPTR(0x7f0000), 0x4000 }; + SetupDmaTransfer(&unk_8BD55C); + WriteReg(MDMAEN, 2u); + static const DecompressToParams unk_8BD579 = { LONGPTR(0x7f8000) }; + static const DecompressToParams unk_8BD58A = { LONGPTR(0x7f0000) }; + static const DecompressToParams unk_8BD59B = { LONGPTR(0x7f4000) }; + static const DecompressToParams unk_8BD5BD = { LONGPTR(0x7fe000) }; + static const DecompressToParams unk_8BD5CE = { LONGPTR(0x7fe800) }; + static const DecompressToParams unk_8BD5DF = { LONGPTR(0x7ff000) }; + static const DecompressToParams unk_8BD5F0 = { LONGPTR(0x7ff800) }; + static const DecompressToParams unk_8BD601 = { LONGPTR(0x7ea000) }; + static const DecompressToParams unk_8BD612 = { LONGPTR(0x7e2000) }; + static const DecompressToParams unk_8BD623 = { LONGPTR(0x7e6000) }; + mov24(&decompress_src, 0x988304); + DecompressToMem_IpArg(&unk_8BD579); + mov24(&decompress_src, 0x95a82f); + DecompressToMem_IpArg(&unk_8BD58A); + mov24(&decompress_src, 0x96fe69); + DecompressToMem_IpArg(&unk_8BD59B); + uint16 v3 = 768; + do { + *(uint16 *)((char *)&g_ram[0x14000] + v3) = 0x8c8c; + v3 += 2; + } while ((int16)(v3 - 0x4000) < 0); + mov24(&decompress_src, 0x98b5c1); + DecompressToMem_IpArg(&unk_8BD5BD); + mov24(&decompress_src, 0x98b857); + DecompressToMem_IpArg(&unk_8BD5CE); + mov24(&decompress_src, 0x98baed); + DecompressToMem_IpArg(&unk_8BD5DF); + mov24(&decompress_src, 0x98bccd); + DecompressToMem_IpArg(&unk_8BD5F0); + mov24(&decompress_src, 0x97e7de); + DecompressToMem_IpArg(&unk_8BD601); + mov24(&decompress_src, 0x99d65b); + DecompressToMem_IpArg(&unk_8BD612); + mov24(&decompress_src, 0x99d932); + DecompressToMem_IpArg(&unk_8BD623); + WriteRegWord(M7A, 0x100u); + reg_M7A = 256; + WriteRegWord(M7B, 0); + reg_M7B = 0; + WriteRegWord(M7C, 0); + reg_M7C = 0; + WriteRegWord(M7D, 0x100u); + reg_M7D = 256; + WriteRegWord(M7X, 0x80); + reg_M7X = 128; + WriteRegWord(M7Y, 0x80); + reg_M7Y = 128; + cinematic_var5 = 32; + cinematic_var6 = 64; + cinematic_var8 = 0; + cinematic_var10 = 0; + door_def_ptr = 0; + layer1_x_pos = 0; + layer1_y_pos = 0; + ClearPaletteFXObjects(); + EnablePaletteFx(); + EnableNMI(); + enemy_projectile_pre_instr[1] = 0; + reg_TM = 17; + reg_TS = 1; + reg_CGWSEL = 2; + reg_CGADSUB = 17; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEEB, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEF1, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEEB, 1u); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEF1, 1u); + screen_fade_delay = 0; + screen_fade_counter = 2; + cinematic_function = FUNC16(CinematicFunction_Intro_Func109); + QueueMusic_Delayed8(0); + QueueMusic_Delayed8(0xFF33u); + QueueMusic_DelayedY(5u, 0xEu); +} + +void CinematicFunction_Intro_Func109(void) { // 0x8BD6D7 + if (!(HasQueuedMusic() & 1)) { + SpawnPalfxObject(addr_kPalfx_E1D8); + SpawnPalfxObject(addr_kPalfx_E1DC); + cinematic_function = FUNC16(CinematicFunction_Intro_Func110); + } +} + +void CinematicFunction_Intro_Func110(void) { // 0x8BD6F2 + CinematicFunction_Intro_Func111(); + if (AdvanceFastScreenFadeIn() & 1) + cinematic_function = FUNC16(CinematicFunction_Intro_Func111); +} + +void CinematicFunction_Intro_Func111(void) { // 0x8BD701 + if ((cinematic_var12 & 1) == 0) + cinematic_var5 = (uint8)(cinematic_var5 - 1); + cinematic_var6 += 2; + if (!sign16(cinematic_var6 - 384)) { + if (AdvanceFastScreenFadeOut() & 1) + cinematic_function = FUNC16(CinematicFunction_Intro_Func112); + } +} + +void CinematicFunction_Intro_Func112(void) { // 0x8BD731 + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD746 = { 1, 1, 0x18, LONGPTR(0x7e2000), 0x4000 }; + SetupDmaTransfer(&unk_8BD746); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x20u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD766 = { 1, 1, 0x18, LONGPTR(0x7e2000), 0x4000 }; + SetupDmaTransfer(&unk_8BD766); + WriteReg(MDMAEN, 2u); + mov24(&decompress_src, 0x98ED4Fu); + static const DecompressToParams unk_8BD783 = { LONGPTR(0x7e2000) }; + DecompressToMem_IpArg(&unk_8BD783); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD79B = { 1, 0, 0x19, LONGPTR(0x7e2000), 0x4000 }; + SetupDmaTransfer(&unk_8BD79B); + WriteReg(MDMAEN, 2u); + ClearPaletteFXObjects(); + ClearCinematicSprites(); + SpawnPalfxObject(addr_kPalfx_E1E0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEED3, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEED9, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEDF, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEE5, 0); + cinematic_var5 = 32; + cinematic_var6 = 64; + cinematic_var8 = 0; + cinematic_var10 = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func113); +} + +void CinematicFunction_Intro_Func113(void) { // 0x8BD7F8 + CinematicFunction_Intro_Func114(); + if (AdvanceFastScreenFadeIn() & 1) + cinematic_function = FUNC16(CinematicFunction_Intro_Func114); +} + +void CinematicFunction_Intro_Func114(void) { // 0x8BD807 + if ((cinematic_var12 & 1) == 0) + cinematic_var5 = (uint8)(cinematic_var5 - 1); + cinematic_var6 += 3; + if (!sign16(cinematic_var6 - 384)) { + if (AdvanceFastScreenFadeOut() & 1) + cinematic_function = FUNC16(CinematicFunction_Intro_Func115); + } +} + +void CinematicFunction_Intro_Func115(void) { // 0x8BD837 + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD84C = { 1, 1, 0x18, LONGPTR(0x7e6000), 0x4000 }; + SetupDmaTransfer(&unk_8BD84C); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x20u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD86C = { 1, 1, 0x18, LONGPTR(0x7e6000), 0x4000 }; + SetupDmaTransfer(&unk_8BD86C); + WriteReg(MDMAEN, 2u); + mov24(&decompress_src, 0x999101u); + static const DecompressToParams unk_8BD889 = { LONGPTR(0x7e6000) }; + DecompressToMem_IpArg(&unk_8BD889); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD8A1 = { 1, 0, 0x19, LONGPTR(0x7e6000), 0x4000 }; + SetupDmaTransfer(&unk_8BD8A1); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x40u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD8C1 = { 1, 1, 0x18, LONGPTR(0x7f8000), 0x6000 }; + SetupDmaTransfer(&unk_8BD8C1); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x70u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD8E1 = { 1, 1, 0x18, LONGPTR(0x7fe000), 0x0800 }; + SetupDmaTransfer(&unk_8BD8E1); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x74u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD901 = { 1, 1, 0x18, LONGPTR(0x7fe800), 0x0800 }; + SetupDmaTransfer(&unk_8BD901); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x78u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD921 = { 1, 1, 0x18, LONGPTR(0x7ff000), 0x0800 }; + SetupDmaTransfer(&unk_8BD921); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x7Cu); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD941 = { 1, 1, 0x18, LONGPTR(0x7ff800), 0x0800 }; + SetupDmaTransfer(&unk_8BD941); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x50u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BD961 = { 1, 1, 0x18, LONGPTR(0x7ea000), 0x1000 }; + SetupDmaTransfer(&unk_8BD961); + WriteReg(MDMAEN, 2u); + reg_OBSEL = 2; + ClearPaletteFXObjects(); + ClearCinematicSprites(); + uint16 v0 = 256; + do { + int v1 = v0 >> 1; + uint16 v2 = kPalettes_Intro6[v1]; + palette_buffer[v1] = v2; + v0 += 2; + } while ((int16)(v0 - 512) < 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEE9D, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEAF, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEA3, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEA9, 0); + cinematic_var5 = 0; + cinematic_var6 = 64; + reg_M7A = 256; + reg_M7B = 0; + reg_M7C = 0; + reg_M7D = 256; + reg_M7X = 128; + reg_M7Y = 128; + cinematic_var8 = 0; + cinematic_var10 = 0; + reg_TM = 1; + reg_TS = 16; + reg_CGWSEL = 2; + reg_CGADSUB = 33; + CopyPalettesToFadingPalettes(); + DecomposePaletteDataForFading(); + ClearYColorsFromIndexX(0x1A0u, 0x10u); + ClearYColorsFromIndexX(0x1E0u, 0x10u); + ComposeFadingPalettes(); + cinematic_var4 = 63; + cinematic_function = FUNC16(CinematicFunction_Intro_Func116); +} + +void CinematicFunction_Intro_Func116(void) { // 0x8BDA02 + CinematicFunction_Intro_Func117(); + if (AdvanceFastScreenFadeIn() & 1) { + screen_fade_delay = 2; + screen_fade_counter = 2; + cinematic_function = FUNC16(CinematicFunction_Intro_Func117); + } +} + +void CinematicFunction_Intro_Func117(void) { // 0x8BDA1A + cinematic_var6 += 4; + if ((cinematic_var4 & 1) == 0) { + FadeOutYColorsFromIndexX(0xE0u, 0x10u); + FadeInYColorsFromIndexX(0x1A0u, 0x10u); + FadeInYColorsFromIndexX(0x1E0u, 0x10u); + ComposeFadingPalettes(); + } + if ((--cinematic_var4 & 0x8000u) != 0) { + uint16 v0 = 0; + do { + palette_buffer[v0 >> 1] = kPalettes_Intro6[v0 >> 1]; + v0 += 2; + } while ((int16)(v0 - 256) < 0); + reg_M7SEL = 0; + reg_BG1SC = 112; + reg_BG2SC = 120; + reg_BG3SC = 0; + reg_BG4SC = 0; + reg_BG12NBA = 68; + reg_BG34NBA = 0; + reg_TM = 16; + reg_TS = 0; + reg_TMW = 0; + reg_TSW = 0; + next_gameplay_CGWSEL = 0; + next_gameplay_CGADSUB = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + WriteReg(COLDATA, 0xE0u); + reg_COLDATA[0] = 32; + reg_COLDATA[1] = 64; + reg_COLDATA[2] = 0x80; + reg_MOSAIC = 0; + cinematic_var7 = 0; + cinematic_var8 = 0; + cinematic_var9 = 0; + cinematic_var10 = 0; + g_word_7E1999 = 0; + g_word_7E199B = 0; + g_word_7E199D = 0; + g_word_7E199F = 0; + fx_layer_blending_config_a = 0; + reg_BG2HOFS = 0; + reg_BG2VOFS = 0; + screen_fade_delay = 0; + screen_fade_counter = 2; + cinematic_function = FUNC16(CinematicFunction_Intro_Func118); + cinematic_var4 = 0; + } +} +static const uint16 kCinematicFunction_Intro_Func118_Tab0[16] = { // 0x8BDAD3 + 0, 0x800, 0x1000, 0x1800, + 0x2000, 0x2800, 0x3000, 0x3800, + 0x4000, 0x4800, 0x5000, 0x5800, + 0x6000, 0x6800, 0x7000, 0x7800, +}; +static const uint16 kCinematicFunction_Intro_Func118_Tab1[16] = { + 0, 0x800, 0x1000, 0x1800, + 0x2000, 0x2800, 0x3000, 0x3800, + 0, 0x800, 0x1000, 0x1800, + 0x2000, 0x2800, 0x3000, 0x3800, +}; +void CinematicFunction_Intro_Func118(void) { + unsigned int v2; + + uint16 v0 = cinematic_var4; + uint16 v1 = mode7_vram_write_queue_tail; + v2 = mode7_vram_write_queue_tail; + if (sign16(cinematic_var4 - 8)) { + *(uint16 *)(&mode7_write_queue[0].field_0 + mode7_vram_write_queue_tail) = 192; + int v3 = v0; + *(uint16 *)((char *)&mode7_write_queue[0].field_1 + v2) = kCinematicFunction_Intro_Func118_Tab0[v3]; + *(uint16 *)&mode7_write_queue[0].gap3[v1] = 127; + *(uint16 *)&mode7_write_queue[0].gap3[v1 + 1] = 2048; + *(uint16 *)&mode7_write_queue[0].gap3[v1 + 3] = kCinematicFunction_Intro_Func118_Tab1[v3]; + *(uint16 *)((char *)&mode7_write_queue[1].field_1 + v1) = 128; + } else { + *(uint16 *)(&mode7_write_queue[0].field_0 + mode7_vram_write_queue_tail) = 128; + int v4 = v0; + *(uint16 *)((char *)&mode7_write_queue[0].field_1 + v2) = kCinematicFunction_Intro_Func118_Tab0[v4]; + *(uint16 *)&mode7_write_queue[0].gap3[v1] = 127; + *(uint16 *)&mode7_write_queue[0].gap3[v1 + 1] = 2048; + *(uint16 *)&mode7_write_queue[0].gap3[v1 + 3] = kCinematicFunction_Intro_Func118_Tab1[v4]; + *(uint16 *)((char *)&mode7_write_queue[1].field_1 + v1) = 0; + } + mode7_vram_write_queue_tail = v1 + 9; + if (!sign16(++cinematic_var4 - 16)) { + reg_BGMODE = 1; + cinematic_var4 = 0; + cinematic_function = FUNC16(nullsub_125); + } +} + +void CinematicFunction_Intro_Func119(void) { // 0x8BDB9E + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) { + QueueMusic_Delayed8(0); + QueueMusic_Delayed8(0xFF3Cu); + QueueMusic_DelayedY(5u, 0xEu); + cinematic_function = FUNC16(CinematicFunction_Intro_Func120); + } +} + +void CinematicFunction_Intro_Func120(void) { // 0x8BDBC4 + if (!(HasQueuedMusic() & 1)) { + reg_BGMODE = 7; + reg_M7SEL = 0x80; + reg_TM = 17; + reg_TS = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 48; + reg_COLDATA[0] = 63; + reg_COLDATA[1] = 95; + reg_COLDATA[2] = -97; + reg_BG1SC = 0; + reg_BG12NBA = 0; + palette_buffer[0] = 0; + palette_buffer[16] = 0; + palette_buffer[128] = 0; + SpawnPalfxObject(addr_kPalfx_E1D4); + SpawnPalfxObject(addr_kPalfx_E1E4); + reg_M7X = 56; + reg_M7Y = 24; + cinematic_var8 = -72; + cinematic_var10 = -104; + cinematic_var6 = 3072; + cinematic_var5 = -112; + cinematic_var4 = 1; + cinematic_var13 = 192; + cinematic_var14 = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func121); + } +} + +void CinematicFunction_Intro_Func122(void) { // 0x8BDC4C + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) { + if (sign8(--reg_COLDATA[0] - 32)) + reg_COLDATA[0] = 32; + if (sign8(--reg_COLDATA[1] - 64)) + reg_COLDATA[1] = 64; + if (sign8(--reg_COLDATA[2] + 0x80)) + reg_COLDATA[2] = 0x80; + if (reg_COLDATA[0] == 32 && reg_COLDATA[1] == 64 && reg_COLDATA[2] == 0x80) { + reg_CGWSEL = 0; + reg_CGADSUB = 0; + } + cinematic_var4 = 8; + } +} +static const uint16 kCinematicFunction_Intro_Func121_Tab0[32] = { // 0x8BDCA5 + 0, 0x8000, 0, 0x8000, 0, 0x8000, 0, 0x8000, 0xffff, 0x8000, 0xffff, 0x8000, 0, 0x8000, 0, 0x8000, + 0, 0x8000, 0, 0x8000, 0xffff, 0x8000, 0xffff, 0x8000, 0, 0x8000, 0, 0x8000, 0xffff, 0x8000, 0xffff, 0x8000, +}; +void CinematicFunction_Intro_Func121(void) { + int16 v1; + + if (cinematic_var13) + --cinematic_var13; + else + CinematicFunction_Intro_Func122(); + cinematic_var5 = (uint8)(cinematic_var5 - 4); + int v0 = (uint16)(4 * cinematic_var14) >> 1; + v1 = (kCinematicFunction_Intro_Func121_Tab0[v0 + 1] + __PAIR32__(cinematic_var8, cinematic_var7)) >> 16; + cinematic_var7 += kCinematicFunction_Intro_Func121_Tab0[v0 + 1]; + cinematic_var8 = kCinematicFunction_Intro_Func121_Tab0[v0] + v1; + cinematic_var14 = ((uint8)cinematic_var14 + 1) & 0xF; + cinematic_var6 -= 8; + if (sign16(cinematic_var6 - 1456)) { + cinematic_var13 = 1; + cinematic_var14 = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func123); + } +} +static const uint16 kCinematicFunction_Intro_Func123_Tab0[16] = { 1, 0, 1, 0, 1, 0, 0xffff, 0, 0xffff, 0, 1, 0, 1, 0, 0xffff, 0 }; +void CinematicFunction_Intro_Func123(void) { // 0x8BDD42 + int16 v1; + + CinematicFunction_Intro_Func122(); + if (cinematic_var5 != 224) + cinematic_var5 = (uint8)(cinematic_var5 - 1); + int v0 = (uint16)(4 * cinematic_var14) >> 1; + v1 = (kCinematicFunction_Intro_Func123_Tab0[v0 + 1] + __PAIR32__(cinematic_var8, cinematic_var7)) >> 16; + cinematic_var7 += kCinematicFunction_Intro_Func123_Tab0[v0 + 1]; + cinematic_var8 = kCinematicFunction_Intro_Func123_Tab0[v0] + v1; + cinematic_var14 = ((uint8)cinematic_var14 + 1) & 7; + cinematic_var6 -= 2; + if (sign16(cinematic_var6 - 1184)) { + cinematic_function = FUNC16(CinematicFunction_Intro_Func124); + cinematic_var14 = 0x8000; + cinematic_var13 = 0; + if (CheckEventHappened(0xFu)) { + R18_ = 4; + SpawnCinematicSpriteObjectToR18(0xEF21u, 4u); + } + } +} +static const uint16 g_word_8BDE43[16] = { 0, 0x6f7b, 0x4a52, 0x1ce7, 0, 0x5ad6, 0x4a52, 0x35ad, 0x2529, 0x7fff, 0x56b5, 0x294a, 0x4210, 0x2d6b, 0x18c6, 0x7fff }; +void CinematicFunction_Intro_Func124(void) { // 0x8BDDCD + unsigned int v2; // kr04_4 + + CinematicFunction_Intro_Func122(); + uint16 v0 = (__PAIR32__(cinematic_var13, cinematic_var14) - 256) >> 16; + cinematic_var14 -= 256; + cinematic_var13 = v0; + v2 = __PAIR32__(v0, cinematic_var14) + __PAIR32__(cinematic_var8, cinematic_var7); + uint16 v1 = (__PAIR32__(v0, cinematic_var14) + __PAIR32__(cinematic_var8, cinematic_var7)) >> 16; + cinematic_var7 = v2; + cinematic_var8 = v1; + if (sign16(cinematic_var6 - 384) && (cinematic_var12 & 3) == 0 && cinematic_var5 != 16) + cinematic_var5 = (uint8)(cinematic_var5 + 2); + if (sign16(cinematic_var6 - 32)) { + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEC7, cinematic_var6); + cinematic_function = FUNC16(nullsub_126); + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 80] = g_word_8BDE43[i >> 1]; + } else { + cinematic_var6 -= 4; + } +} + +void CinematicFunction_Intro_Func125(void) { // 0x8BDE64 + screen_fade_counter = 1; + if (AdvanceFastScreenFadeOut() & 1) { + EnableNMI(); + screen_fade_delay = 0; + screen_fade_counter = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func126); + } +} + +void CinematicFunction_Intro_Func126(void) { // 0x8BDE80 + SetupPpu_7_Mode1(); + ClearCinematicSprites(); + ClearPaletteFXObjects(); + uint16 v0 = 0; + do { + palette_buffer[v0 >> 1] = kPalettes_Intro5[v0 >> 1]; + v0 += 2; + } while ((int16)(v0 - 256) < 0); + static const DecompressToParams unk_8BDEAA = { LONGPTR(0x7f0000) }; + static const DecompressToParams unk_8BDEBB = { LONGPTR(0x7e2000) }; + static const DecompressToParams unk_8BDECC = { LONGPTR(0x7e6000) }; + static const DecompressToParams unk_8BDEDD = { LONGPTR(0x7fc000) }; + static const DecompressToParams unk_8BDEEE = { LONGPTR(0x7fe000) }; + static const DecompressToParams unk_8BDEFF = { LONGPTR(0x7f4000) }; + static const DecompressToParams unk_8BDF10 = { LONGPTR(0x7fe800) }; + static const DecompressToParams unk_8BDF21 = { LONGPTR(0x7ff000) }; + mov24(&decompress_src, 0x979803u); + DecompressToMem_IpArg(&unk_8BDEAA); + mov24(&decompress_src, 0x97B957u); + DecompressToMem_IpArg(&unk_8BDEBB); + mov24(&decompress_src, 0x97D7FCu); + DecompressToMem_IpArg(&unk_8BDECC); + mov24(&decompress_src, 0x97E7DEu); + DecompressToMem_IpArg(&unk_8BDEDD); + mov24(&decompress_src, 0x9796F4u); + DecompressToMem_IpArg(&unk_8BDEEE); + mov24(&decompress_src, 0x97F987u); + DecompressToMem_IpArg(&unk_8BDEFF); + mov24(&decompress_src, 0x99DA9Fu); + DecompressToMem_IpArg(&unk_8BDF10); + mov24(&decompress_src, 0x99DAB1u); + DecompressToMem_IpArg(&unk_8BDF21); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x20u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BDF39 = { 1, 1, 0x18, LONGPTR(0x7fe800), 0x0100 }; + SetupDmaTransfer(&unk_8BDF39); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x24u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BDF59 = { 1, 1, 0x18, LONGPTR(0x7ff000), 0x0800 }; + SetupDmaTransfer(&unk_8BDF59); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x40u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BDF79 = { 1, 1, 0x18, LONGPTR(0x7fc000), 0x1000 }; + SetupDmaTransfer(&unk_8BDF79); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x60u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BDF99 = { 1, 1, 0x18, LONGPTR(0x7e6000), 0x4000 }; + SetupDmaTransfer(&unk_8BDF99); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x50u); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BDFB9 = { 1, 1, 0x18, LONGPTR(0x7f0000), 0x2000 }; + SetupDmaTransfer(&unk_8BDFB9); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x4Cu); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BDFD9 = { 1, 1, 0x18, LONGPTR(0x7fe000), 0x0800 }; + SetupDmaTransfer(&unk_8BDFD9); + WriteReg(MDMAEN, 2u); + + mov24(&decompress_src, 0x99E089u); + static const DecompressToParams unk_8BDFF6 = { LONGPTR(0x7e6000) }; + DecompressToMem_IpArg(&unk_8BDFF6); + mov24(&decompress_src, 0x99ECC4u); + static const DecompressToParams unk_8BE007 = { LONGPTR(0x7e8000) }; + DecompressToMem_IpArg(&unk_8BE007); + if (sign16(game_time_hours - 3)) { + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BE027 = { 1, 1, 0x18, LONGPTR(0x7e2000), 0x4000 }; + SetupDmaTransfer(&unk_8BE027); + WriteReg(MDMAEN, 2u); + } else { + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0); + WriteReg(VMAIN, 0x80); + static const StartDmaCopy unk_8BE04B = { 1, 1, 0x18, LONGPTR(0x7f0000), 0x4000 }; + SetupDmaTransfer(&unk_8BE04B); + WriteReg(MDMAEN, 2u); + } + WriteRegWord(M7A, 0x100u); + reg_M7A = 256; + WriteRegWord(M7B, 0); + reg_M7B = 0; + WriteRegWord(M7C, 0); + reg_M7C = 0; + WriteRegWord(M7D, 0x100u); + reg_M7D = 256; + WriteRegWord(M7X, 0x68u); + reg_M7X = 104; + WriteRegWord(M7Y, 0x70u); + reg_M7Y = 112; + cinematic_var8 = -8; + cinematic_var10 = -24; + cinematic_var5 = 0; + cinematic_var6 = 2304; + EnableNMI(); + reg_INIDISP = 15; + layer1_x_pos = 0; + layer1_y_pos = 0; + EnableHdmaObjects(); + for (int i = 510; i >= 0; i -= 2) + hdma_table_1[i >> 1] = 0; + CinematicFunction_Intro_Func127(); + mov24(&decompress_src, 0x97EEFFu); + static const DecompressToParams unk_8BE0CB = { LONGPTR(0x7f0000) }; + DecompressToMem_IpArg(&unk_8BE0CB); + ClearCinematicBgObjects(0x7F); + CinematicFunction_Intro_Func128(0x7F); + EnableTextGlowObjects_(); + screen_fade_delay = 3; + screen_fade_counter = 3; + CreditsObject_Init(addr_stru_8BF6F8); + cinematic_function = FUNC16(nullsub_125); +} + +void CinematicFunction_Intro_Func129(void) { // 0x8BE0F4 + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) { + cinematic_function = FUNC16(CinematicFunction_Intro_Func130); + cinematic_var4 = 120; + reg_TM = 16; + } +} + +void CinematicFunction_Intro_Func130(void) { // 0x8BE110 + HandleFadeIn(); + if (reg_INIDISP == 15) { + reg_TM = 2; + reg_TS = 16; + reg_CGWSEL = 2; + reg_CGADSUB = 34; + screen_fade_delay = 0; + screen_fade_counter = 0; + CopyPalettesToFadingPalettes(); + DecomposePaletteDataForFading(); + ClearYColorsFromIndexX(0x40u, 0x10u); + ComposeFadingPalettes(); + cinematic_var4 = 32; + cinematic_function = FUNC16(CinematicFunction_Intro_Func131); + } +} + +void CinematicFunction_Intro_Func131(void) { // 0x8BE158 + FadeInYColorsFromIndexX(0x40u, 0x10u); + ComposeFadingPalettes(); + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) { + reg_TM = 18; + reg_TS = 4; + reg_CGWSEL = 2; + reg_CGADSUB = 2; + cinematic_var4 = 180; + cinematic_function = FUNC16(CinematicFunction_Intro_Func132); + CinematicFunction_Intro_Func133(); + } +} + +void CinematicFunction_Intro_Func132(void) { // 0x8BE190 + reg_BG3VOFS += 2; + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) { + uint16 v1 = 0; + do { + ram3000.pause_menu_map_tilemap[v1 + 288] = g_word_8CDC9B[v1]; + ++v1; + } while ((int16)(v1 * 2 - 576) < 0); + CinematicUpdateSomeBg(); + reg_TM = 1; + reg_TS = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + cinematic_var4 = 180; + cinematic_function = FUNC16(CinematicFunction_Intro_Func134); + g_word_7E0D9C = 0; + } +} + +void CinematicFunction_Intro_Func134(void) { // 0x8BE1D2 + if (!--cinematic_var4) { + cinematic_var4 = 127; + if (sign16(game_time_hours - 3)) { + CopyPalettesToFadingPalettes(); + DecomposePaletteDataForFading(); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF27, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF2D, 0); + } else { + if (!sign16(game_time_hours - 10)) { + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF4B, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF45, 0); + cinematic_function = FUNC16(CinematicFunction_Intro_Func135); + reg_TM = 16; + reg_TS = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + return; + } + CopyPalettesToFadingPalettes(); + DecomposePaletteDataForFading(); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF51, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF45, 0); + ClearYColorsFromIndexX(0x1C0u, 0x10u); + } + ClearYColorsFromIndexX(0x1A0u, 0x10u); + ComposeFadingPalettes(); + reg_TM = 2; + reg_TS = 16; + reg_CGWSEL = 2; + reg_CGADSUB = 34; + cinematic_function = FUNC16(CinematicFunction_Intro_Func136); + } +} + +void CinematicFunction_Intro_Func136(void) { // 0x8BE265 + if ((cinematic_var4 & 3) != 0) { + CinematicFunction_Intro_Func135(); + } else { + FadeOutYColorsFromIndexX(0x40u, 0x10u); + if (!sign16(game_time_hours - 3)) + FadeInYColorsFromIndexX(0x1C0u, 0x10u); + FadeInYColorsFromIndexX(0x1A0u, 0x10u); + ComposeFadingPalettes(); + CinematicFunction_Intro_Func135(); + } +} + +void CinematicFunction_Intro_Func135(void) { // 0x8BE293 + if (sign16(--cinematic_var4 - 65)) { + for (int i = 574; i >= 0; i -= 2) + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[288] + (uint16)i) = 127; + uint16 v1 = 0; + do { + ram3000.pause_menu_map_tilemap[v1 + 384] = g_word_8CDEDB[v1]; + ++v1; + } while ((int16)(v1 * 2 - 128) < 0); + CinematicUpdateSomeBg(); + reg_TM = 1; + reg_TS = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + cinematic_var13 = 180; + cinematic_function = FUNC16(CinematicFunction_Intro_Func137); + } +} + +void CinematicFunction_Intro_Func137(void) { // 0x8BE2DD + bool v0 = (--cinematic_var13 & 0x8000u) != 0; + if (!cinematic_var13 || v0) { + if (sign16(game_time_hours - 3) || sign16(game_time_hours - 10)) { + reg_TM = 2; + reg_TS = 16; + reg_CGWSEL = 2; + reg_CGADSUB = 34; + cinematic_function = FUNC16(CinematicFunction_Intro_Func138); + } else { + cinematic_function = FUNC16(CinematicFunction_Intro_Func145); + } + } +} + +void CinematicFunction_Intro_Func138(void) { // 0x8BE314 + if ((cinematic_var4 & 3) != 0) { + CinematicFunction_Intro_Func145(); + } else { + FadeOutYColorsFromIndexX(0x40u, 0x10u); + if (!sign16(game_time_hours - 3)) + FadeInYColorsFromIndexX(0x1C0u, 0x10u); + FadeInYColorsFromIndexX(0x1A0u, 0x10u); + ComposeFadingPalettes(); + CinematicFunction_Intro_Func145(); + } +} + +void CinematicFunction_Intro_Func145(void) { // 0x8BE342 + if ((--cinematic_var4 & 0x8000u) != 0) { + reg_TM = 16; + reg_TS = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 0; + reg_BGMODE = 7; + reg_M7SEL = 0x80; + reg_BG1SC = 0; + reg_BG12NBA = 0; + cinematic_function = FUNC16(nullsub_125); + cinematic_var14 = 0; + if (sign16(game_time_hours - 3)) { + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF33, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF39, 0); + } else { + if (sign16(game_time_hours - 10)) + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF69, 0); + else + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF63, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF5D, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF57, 0); + } + } +} + +void CinematicFunction_Intro_Func139(void) { // 0x8BE3AE + if (cinematic_var14) { + --cinematic_var14; + FadeOutYColorsFromIndexX(0x180u, 0x10u); + if (cinematic_var4) + ComposeFadingPalettes(); + } + if (cinematic_var4) + --cinematic_var4; + else + CinematicFunction_Intro_Func140(); + cinematic_var5 = (uint8)(cinematic_var5 - 8); + cinematic_var6 -= 64; + if (sign16(cinematic_var6 - 24)) { + cinematic_var6 = 24; + cinematic_function = FUNC16(CinematicFunction_Intro_Func141); + cinematic_var4 = 180; + cinematic_var14 = 0; + } +} + +void CinematicFunction_Intro_Func140(void) { // 0x8BE409 + if (cinematic_var17) { + --cinematic_var17; + FadeOutYColorsFromIndexX(0x1E0u, 0x10u); + ComposeFadingPalettes(); + } +} + +void CinematicFunction_Intro_Func142(void) { // 0x8BE41F + if (!cinematic_var17) { + if (sign16(cinematic_var14 - 6)) { + uint16 v0 = 4 * cinematic_var14; + uint16 v1 = vram_write_queue_tail; + int v2 = (uint16)(8 * cinematic_var14) >> 1; + gVramWriteEntry(vram_write_queue_tail)->size = kCinematicFunction_Intro_Func142_Tab0[v2]; + v1 += 2; + gVramWriteEntry(v1)->size = kCinematicFunction_Intro_Func142_Tab0[v2 + 1]; + v1 += 2; + LOBYTE(gVramWriteEntry(v1++)->size) = kCinematicFunction_Intro_Func142_Tab0[v0 + 2]; + gVramWriteEntry(v1)->size = kCinematicFunction_Intro_Func142_Tab0[v2 + 3]; + vram_write_queue_tail = v1 + 2; + ++cinematic_var14; + } + } +} + +void CinematicFunction_Intro_Func141(void) { // 0x8BE48A + CinematicFunction_Intro_Func140(); + CinematicFunction_Intro_Func142(); + if (!--cinematic_var4) { + reg_BGMODE = 1; + reg_TM = 17; + reg_TS = 0; + reg_CGWSEL = 0; + reg_CGADSUB = 49; + reg_COLDATA[0] = 63; + reg_COLDATA[1] = 95; + reg_COLDATA[2] = -97; + reg_M7SEL = 0; + reg_BG1SC = 78; + reg_BG12NBA = 84; + uint16 v0 = 384; + do { + palette_buffer[v0 >> 1] = kPalettes_Intro4[v0 >> 1]; + v0 += 2; + } while ((int16)(v0 - 416) < 0); + cinematic_var8 = 0; + cinematic_var10 = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func143); + cinematic_var4 = 32; + EnableCinematicBgObjects(); + EnableCinematicBgTilemapUpdates(); + cinematicbg_var3 = 19456; + for (int i = 126; i >= 0; i -= 2) + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[384] + (uint16)i) = 127; + CinematicUpdateSomeBg(); + } +} + +void CinematicFunction_Intro_Func143(void) { // 0x8BE504 + uint16 j; + + if (sign8(--reg_COLDATA[0] - 32)) + reg_COLDATA[0] = 32; + if (sign8(--reg_COLDATA[1] - 64)) + reg_COLDATA[1] = 64; + if (sign8(--reg_COLDATA[2] + 0x80)) + reg_COLDATA[2] = 0x80; + bool v0 = (--cinematic_var4 & 0x8000u) != 0; + if (!cinematic_var4 || v0) { + cinematic_function = FUNC16(nullsub_127); + cinematicbg_var3 = 20480; + CinematicUpdateSomeBg(); + layer1_x_pos = 256; + layer1_y_pos = 256; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF81, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF87, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF8D, 0); + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF93, 0); + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 16] = 0; + for (j = 30; (j & 0x8000u) == 0; j -= 2) + palette_buffer[(j >> 1) + 240] = g_word_8CEFE9[j >> 1]; + } +} + +void CinematicFunction_Intro_Func144(void) { // 0x8BE58A + uint16 j; + + int v0 = (uint16)(4 * cinematic_var4) >> 1; + uint16 v5 = kCinematicFunction_Intro_Func144_Tab0[v0 + 1]; + uint16 v1 = kCinematicFunction_Intro_Func144_Tab0[v0]; + for (int i = 30; i >= 0; i -= 2) { + palette_buffer[(i >> 1) + 16] = *(uint16 *)RomPtr_8C(v1); + v1 -= 2; + } + uint16 v3 = v5; + for (j = 30; (j & 0x8000u) == 0; j -= 2) { + palette_buffer[(j >> 1) + 240] = *(uint16 *)RomPtr_8C(v3); + v3 -= 2; + } + if (!sign16(++cinematic_var4 - 16)) { + cinematic_function = FUNC16(nullsub_127); + ClearCinematicSprites(); + SpawnCinematicBgObject(addr_kCinematicBgObjectDef_8BF74E, 0x4C00u); + } +} + +uint16 CalcItemPercentageCount(uint16 k, uint16 instrp) { // 0x8BE627 + uint16 j; + + uint16 v0 = 4; + R18_ = 0; + do { + uint16 *v1 = (uint16 *)RomPtr_RAM(g_off_8BE70D[v0]); + R18_ += SnesDivide(*v1, g_word_8BE717[v0]); + --v0; + } while ((v0 & 0x8000u) == 0); + for (int i = 20; i >= 0; i -= 2) { + if ((g_word_8BE721[i >> 1] & collected_items) != 0) + ++R18_; + } + for (j = 8; (j & 0x8000u) == 0; j -= 2) { + if ((g_word_8BE737[j >> 1] & collected_beams) != 0) + ++R18_; + } + uint16 RegWord = R18_ / 10; + R22_ = R18_ % 10; + R18_ = RegWord / 10; + R20_ = RegWord % 10; + if (R18_) { + int v5 = (uint16)(4 * R18_) >> 1; + ram3000.pause_menu_map_tilemap[462] = g_word_8BE741[v5]; + ram3000.pause_menu_map_tilemap[494] = g_word_8BE741[v5 + 1]; + } + uint16 v6 = R20_; + if (R20_) + goto LABEL_16; + if (R18_) { + v6 = R20_; +LABEL_16:; + int v7 = (uint16)(4 * v6) >> 1; + ram3000.pause_menu_map_tilemap[463] = g_word_8BE741[v7]; + ram3000.pause_menu_map_tilemap[495] = g_word_8BE741[v7 + 1]; + } + int v8 = (uint16)(4 * R22_) >> 1; + ram3000.pause_menu_map_tilemap[464] = g_word_8BE741[v8]; + ram3000.pause_menu_map_tilemap[496] = g_word_8BE741[v8 + 1]; + ram3000.pause_menu_map_tilemap[465] = 14442; + ram3000.pause_menu_map_tilemap[497] = 14458; + + return instrp; +} + +uint16 CinematicFunction_Intro_Func146(uint16 k, uint16 j) { // 0x8BE769 + if (japanese_text_flag) { + for (int i = 63; i >= 0; --i) + ram3000.pause_menu_map_tilemap[i + 736] = g_word_8CDF5B[i]; + } + return j; +} + +uint16 CinematicFunction_Intro_Func147(uint16 k, uint16 j) { // 0x8BE780 + for (int i = 126; i >= 0; i -= 2) + *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[736] + (uint16)i) = 127; + cinematic_function = FUNC16(CinematicFunction_Intro_Func148); + return j; +} + +void CinematicFunction_Intro_Func148(void) { // 0x8BE797 + cinematic_var10 -= 2; + if (sign16(cinematic_var10 + 79)) { + SpawnCinematicBgObject(addr_kCinematicBgObjectDef_8BF748, 0x4C00u); + cinematic_function = FUNC16(nullsub_127); + CopySuperMetroidString(); + } +} + +void CinematicFunction_Intro_Func127(void) { // 0x8BE7BB + int16 v1; + int16 v4; + + uint16 v0 = ADDR16_OF_RAM(*g_byte_7E0E0C); + v1 = 0; + R18_ = 0; + do { + v4 = v1; + uint8 *v2 = RomPtr_RAM(v0); + *(uint16 *)v2 = v1; + *((uint16 *)v2 + 6) = 0; + *((uint16 *)v2 + 7) = 0; + uint16 v3 = g_word_8BE9CF[((uint16)(8 * v1) >> 1) + 3]; + if (v3) { + *((uint16 *)v2 + 5) = v3; + *(uint16 *)v2 |= 0x8000u; + } else { + *((uint16 *)v2 + 5) = 32; + } + *((uint16 *)v2 + 1) = 128; + *((uint16 *)v2 + 3) = 128; + *((uint16 *)v2 + 2) = 0; + *((uint16 *)v2 + 4) = 0; + v0 += 16; + ++v1; + } while ((int16)(v4 - 39) < 0); +} + +void CinematicFunction_Intro_Func149(void) { // 0x8BE812 + int16 v2; + int16 v5; + int16 v7; + int16 v8; + int16 v11; + int16 v12; + int16 v17; + OamEnt *v18; + int16 v19; + int16 v20; + int16 v22; + + if (enemy_projectile_pre_instr[1]) { + R22_ = 40; + uint16 v0 = 0xe0c; + do { + uint8 *v3 = RomPtr_RAM(v0); + if (*(int16 *)v3 < 0) { + uint8 *v1 = RomPtr_RAM(v0); + v2 = *((uint16 *)v1 + 5) - 1; + *((uint16 *)v1 + 5) = v2; + if (v2 < 0) { + *((uint16 *)v1 + 5) = 32; + *(uint16 *)v1 = *v1; + } + } else { + int v4 = (uint16)(8 * (uint8) * (uint16 *)v3) >> 1; + if (sign16((*(uint16 *)v3 & 0xFF00) - 1024)) { + *((uint16 *)v3 + 6) += g_word_8BE9CF[v4]; + v5 = *((uint16 *)v3 + 7); + } else { + *((uint16 *)v3 + 6) += g_word_8BE9CF[v4] + g_word_8BE9CF[v4]; + v5 = g_word_8BE9CF[v4 + 1] + *((uint16 *)v3 + 7); + } + *((uint16 *)v3 + 7) = g_word_8BE9CF[v4 + 1] + v5; + uint16 v23 = *((uint16 *)v3 + 6); + uint16 v6 = HIBYTE(v23); + if ((v23 & 0x8000u) != 0) + v6 |= 0xFF00u; + R18_ = v6; + LOBYTE(v7) = HIBYTE(v23); + HIBYTE(v7) = v23; + R20_ = v7 & 0xFF00; + v8 = *((uint16 *)v3 + 2); + bool v9 = __CFADD__uint16(R20_, v8); + *((uint16 *)v3 + 2) = R20_ + v8; + *((uint16 *)v3 + 1) += R18_ + v9; + uint16 v24 = *((uint16 *)v3 + 7); + uint16 v10 = HIBYTE(v24); + if ((v24 & 0x8000u) != 0) + v10 |= 0xFF00u; + R18_ = v10; + LOBYTE(v11) = HIBYTE(v24); + HIBYTE(v11) = v24; + R20_ = v11 & 0xFF00; + v12 = *((uint16 *)v3 + 4); + v9 = __CFADD__uint16(R20_, v12); + *((uint16 *)v3 + 4) = R20_ + v12; + *((uint16 *)v3 + 3) += R18_ + v9; + } + v0 += 16; + --R22_; + } while (R22_); + R22_ = 40; + uint16 v13 = oam_next_ptr; + uint16 v14 = 3596; + do { + uint8 *v15 = RomPtr_RAM(v14); + uint8 *v16 = v15; + if (*(int16 *)v15 >= 0) { + v17 = *((uint16 *)v15 + 1); + if (v15[3] + || ((v17 - 4) & 0xFF00) != 0 + || (v18 = gOamEnt(v13), *(uint16 *)&v18->xcoord = v17 - 4, v19 = *((uint16 *)v16 + 3), v16[7]) + || ((v19 - 4) & 0xFF00) != 0) { + uint8 *v21 = RomPtr_RAM(v14); + *((uint16 *)v21 + 5) = 32; + *((uint16 *)v21 + 1) = 128; + *((uint16 *)v21 + 3) = 128; + *((uint16 *)v21 + 2) = 0; + *((uint16 *)v21 + 4) = 0; + *((uint16 *)v21 + 6) = 0; + *((uint16 *)v21 + 7) = 0; + *(uint16 *)v21 = *v21; + } else { + *(uint16 *)&v18->ycoord = v19 - 4; + v20 = *((uint16 *)v16 + 5) - 1; + *((uint16 *)v16 + 5) = v20; + if (v20 <= 0) { + v22 = *(uint16 *)v16; + *((uint16 *)v16 + 5) = g_word_8BE9CF[((uint16)(8 * (uint8) * (uint16 *)v16) >> 1) + 2]; + *(uint16 *)v16 = v22 + 512; + } + if (v16[1]) { + *(uint16 *)&gOamEnt(v13)->charnum = g_word_8BE9A7[(uint16)HIBYTE(*(uint16 *)v16) >> 1]; + v13 += 4; + } + } + } + v14 += 16; + --R22_; + } while (R22_); + oam_next_ptr = v13; + } +} + +void CinematicFunction_Intro_Func150(uint16 j) { // 0x8BEF99 + int v1 = j >> 1; + cinematicbg_arr8[v1] = 128; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr9[v1] = 3584; + cinematicspr_goto_timer[v1] = 260; +} + +void CinematicFunction_Intro_Func151(uint16 k) { // 0x8BEFB2 + int v1 = k >> 1; + uint16 v2 = cinematicspr_arr7[v1]; + cinematicspr_arr7[v1] = v2 + 128; + cinematicbg_arr8[v1] += __CFADD__uint16(v2, 128); + cinematicspr_arr6[v1] = cinematicspr_arr6[v1]; + uint16 v3 = cinematicbg_arr7[v1] + 1; + cinematicbg_arr7[v1] = v3; + if (!sign16(v3 - 272)) { + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BEE9B; + } +} + +void CinematicFunction_Intro_Func152(uint16 j) { // 0x8BEFEA + cinematicbg_arr7[j >> 1] = 128; + int v1 = j >> 1; + cinematicbg_arr8[v1] = 128; + cinematicbg_arr9[v1] = 3584; +} + +void CinematicFunction_Intro_Func153(uint16 j) { // 0x8BEFFD + cinematicbg_arr7[j >> 1] = -128; + + int v1 = j >> 1; + cinematicbg_arr8[v1] = 128; + cinematicbg_arr9[v1] = 3584; +} + +void CinematicFunction_Intro_Func154(uint16 j) { // 0x8BF005 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 128; + cinematicbg_arr9[v1] = 2560; +} + +void CinematicFunction_Intro_Func155(uint16 j) { // 0x8BF018 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 128; + cinematicbg_arr9[v1] = 3072; +} + +void CinematicFunction_Intro_Func156(uint16 j) { // 0x8BF02B + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 96; + cinematicbg_arr9[v1] = 1024; +} + +void CinematicFunction_Intro_Func157(uint16 j) { // 0x8BF03E + int v1 = j >> 1; + cinematicbg_arr7[v1] = 128; + cinematicbg_arr8[v1] = 160; + cinematicbg_arr9[v1] = 512; +} + +void CinematicFunction_Intro_Func158(uint16 j) { // 0x8BF051 + int v1 = j >> 1; + cinematicbg_arr8[v1] = 160; + cinematicbg_arr9[v1] = 0; +} + +void CinematicFunction_Intro_Func159(uint16 j) { // 0x8BF05E + CinematicFunction_Intro_Func160(j, substate); + cinematicbg_arr7[j >> 1] = 156; + CinematicFunction_Intro_Func158(j); +} + +void CinematicFunction_Intro_Func161(uint16 j) { // 0x8BF06D + CinematicFunction_Intro_Func160(j, suit_pickup_light_beam_pos); + cinematicbg_arr7[j >> 1] = 164; + CinematicFunction_Intro_Func158(j); +} + +void CinematicFunction_Intro_Func162(uint16 j) { // 0x8BF07C + cinematicbg_arr7[j >> 1] = 172; + CinematicFunction_Intro_Func158(j); +} + +void CinematicFunction_Intro_Func163(uint16 j) { // 0x8BF085 + CinematicFunction_Intro_Func160(j, *(uint16 *)&suit_pickup_color_math_R); + cinematicbg_arr7[j >> 1] = 180; + CinematicFunction_Intro_Func158(j); +} + +void CinematicFunction_Intro_Func164(uint16 j) { // 0x8BF094 + CinematicFunction_Intro_Func160(j, *(uint16 *)&suit_pickup_color_math_B); + cinematicbg_arr7[j >> 1] = 188; + CinematicFunction_Intro_Func158(j); +} + +void CinematicFunction_Intro_Func160(uint16 j, uint16 a) { // 0x8BF0A3 + R18_ = 8 * a; + cinematicspr_instr_ptr[j >> 1] += 8 * a; +} + +void CinematicFunction_Intro_Func165(uint16 j) { // 0x8BF0B2 + cinematicbg_arr8[j >> 1] = -96; + CinematicFunction_F0B8(j); +} + +void CinematicFunction_F0B8(uint16 j) { // 0x8BF0B8 + int v1 = j >> 1; + if (cinematic_spawn_param) { + cinematicbg_arr7[v1] = 384; + cinematicbg_arr9[v1] = 2560; + cinematicspr_instr_ptr[v1] += 4; + } else { + cinematicbg_arr7[v1] = 128; + cinematicbg_arr9[v1] = 2560; + } +} + +void CinematicFunction_Intro_Func166(uint16 j) { // 0x8BF0E1 + cinematicbg_arr8[j >> 1] = -32; + CinematicFunction_F0B8(j); +} + +void CinematicFunction_Intro_Func167(uint16 j) { // 0x8BF0E9 + cinematicbg_arr8[j >> 1] = 288; + CinematicFunction_F0B8(j); +} + +void CinematicFunction_Intro_Func168(uint16 j) { // 0x8BF0F1 + cinematicbg_arr8[j >> 1] = 352; + CinematicFunction_F0B8(j); +} + +void CinematicFunction_Intro_Func169(uint16 j) { // 0x8BF0F9 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 320; + if (cinematic_spawn_param) + cinematicbg_arr8[v1] = 448; + else + cinematicbg_arr8[v1] = 192; + cinematicbg_arr9[v1] = 2560; +} + +void CinematicFunction_Intro_Func170(uint16 j) { // 0x8BF11E + int v1 = j >> 1; + cinematicbg_arr7[v1] = -64; + if (cinematic_spawn_param) + cinematicbg_arr8[v1] = -192; + else + cinematicbg_arr8[v1] = 64; + cinematicbg_arr9[v1] = 2560; +} + +void CinematicFunction_Intro_Func171(uint16 j) { // 0x8BF143 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 120; + cinematicbg_arr8[v1] = 136; + cinematicbg_arr9[v1] = 2560; +} + +void CinematicFunction_Intro_Func172(uint16 j) { // 0x8BF156 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 120; + cinematicbg_arr8[v1] = 152; + cinematicbg_arr9[v1] = 3072; +} + +void CinematicFunction_Intro_Func173(uint16 j) { // 0x8BF169 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 124; + cinematicbg_arr8[v1] = 108; + cinematicbg_arr9[v1] = 3072; +} + +void CinematicFunction_Intro_Func174(uint16 j) { // 0x8BF17C + int v1 = j >> 1; + cinematicbg_arr7[v1] = 121; + cinematicbg_arr8[v1] = 107; + cinematicbg_arr9[v1] = 2560; +} + +void CinematicFunction_Intro_Func175(uint16 j) { // 0x8BF18F + int v1 = j >> 1; + cinematicbg_arr7[v1] = 530; + cinematicbg_arr8[v1] = 231; + cinematicbg_arr9[v1] = 3584; + cinematicspr_goto_timer[v1] = 8; +} + +void CinematicFunction_Intro_Func176(uint16 j) { // 0x8BF1A8 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 246; + cinematicbg_arr8[v1] = 519; + cinematicbg_arr9[v1] = 3584; + cinematicspr_goto_timer[v1] = 8; +} + +void CinematicFunction_Intro_Func177(uint16 j) { // 0x8BF1C1 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 385; + cinematicbg_arr8[v1] = 366; + cinematicbg_arr9[v1] = 3584; +} + +void CinematicFunction_Intro_Func178(uint16 j) { // 0x8BF1D4 + int v1 = j >> 1; + cinematicbg_arr7[v1] = 391; + cinematicbg_arr8[v1] = 384; + cinematicbg_arr9[v1] = 3584; +} + +void CinematicFunction_Intro_Func179(uint16 k) { // 0x8BF1E7 + int v1 = k >> 1; + cinematicbg_arr8[v1] += cinematicspr_goto_timer[v1]; + uint16 v2 = cinematicbg_arr7[v1] - cinematicspr_goto_timer[v1]; + cinematicbg_arr7[v1] = v2; + if (sign16(v2 - 395)) { + cinematicbg_arr7[v1] = 394; + cinematicbg_arr8[v1] = 367; + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_nullsub_116); + SpawnPalfxObject(addr_kPalfx_E200); + } else { + cinematicspr_goto_timer[v1] += 2; + } +} + +void CinematicFunction_Intro_Func180(uint16 k) { // 0x8BF227 + int v1 = k >> 1; + cinematicbg_arr8[v1] -= cinematicspr_goto_timer[v1]; + uint16 v2 = cinematicspr_goto_timer[v1] + cinematicbg_arr7[v1]; + cinematicbg_arr7[v1] = v2; + if (sign16(v2 - 382)) { + cinematicspr_goto_timer[v1] += 2; + } else { + cinematicbg_arr7[v1] = 382; + cinematicbg_arr8[v1] = 383; + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_nullsub_116); + } +} + +uint16 CinematicSprInstr_Func181(uint16 k, uint16 j) { // 0x8BF25E + reg_TM = 3; + reg_TS = 16; + reg_CGWSEL = 2; + reg_CGADSUB = 34; + reg_BG12NBA = 100; + reg_BG2SC = 84; + cinematic_var4 = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func144); + return j; +} + +uint16 CinematicSprInstr_Func182(uint16 k, uint16 j) { // 0x8BF284 + SpawnPalfxObject(addr_kPalfx_E1C4); + palette_buffer[254] = 1; + return j; +} + +uint16 CinematicSprInstr_Func183(uint16 k, uint16 j) { // 0x8BF295 + uint16 v0 = 0; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEB5, v0); + palette_buffer[0] = 0x7FFF; + return j; +} + +void CinematicFunction_Intro_Func184(uint16 j) { // 0x8BF2A5 + if (!cinematicspr_instr_ptr[15]) { + int v2 = j >> 1; + cinematicspr_instr_timer[v2] = 1; + cinematicspr_instr_ptr[v2] = addr_off_8BEE9B; + } +} + +uint16 CinematicSprInstr_Func185(uint16 k, uint16 j) { // 0x8BF2B7 + uint16 v0; + + reg_TM = 17; + reg_TS = 2; + reg_CGWSEL = 2; + reg_CGADSUB = 17; + LOBYTE(v0) = 124; + reg_BG2SC = 124; + R18_ = 0; + SpawnCinematicSpriteObjectToR18(addr_kCinematicSpriteObjectDef_8BEEBB, 0); + R18_ = 2; + SpawnCinematicSpriteObjectToR18(addr_kCinematicSpriteObjectDef_8BEEF7, 0); + SpawnPalfxObject(addr_kPalfx_E1C8); + SpawnPalfxObject(addr_kPalfx_E1D0); + SpawnPalfxObject(addr_kPalfx_E1E8); + return j; +} + +uint16 CinematicSprInstr_Func186(uint16 k, uint16 j) { // 0x8BF2FA + reg_TM = 3; + reg_TS = 18; + reg_CGWSEL = 2; + reg_CGADSUB = 51; + reg_BG1SC = 116; + reg_BG2SC = 120; + SpawnPalfxObject(addr_kPalfx_E1CC); + R18_ = 6; + SpawnCinematicSpriteObjectToR18(addr_kCinematicSpriteObjectDef_8BEEC1, 6u); + return j; +} + +uint16 CinematicSprInstr_Func187(uint16 k, uint16 j) { // 0x8BF32B + reg_TM = 0; + reg_TS = 0; + palette_buffer[0] = 0x7FFF; + palette_buffer[128] = 0x7FFF; + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 16] = 0x7FFF; + cinematic_function = FUNC16(CinematicFunction_Intro_Func119); + cinematic_var4 = 120; + return j; +} + + +void CinematicSprPreInstr_F35A(uint16 k) { // 0x8BF35A + if (cinematic_function == (uint16)FUNC16(CinematicFunction_Intro_Func121)) { + int v1 = k >> 1; + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_Intro_Func189); + cinematicspr_arr7[v1] = 0x4000; + cinematicspr_goto_timer[v1] = 0; + } +} + +void CinematicFunction_Intro_Func189(uint16 k) { // 0x8BF375 + int v1 = k >> 1; + uint16 v2 = cinematicspr_arr7[v1]; + cinematicspr_arr7[v1] = v2 - 32; + cinematicspr_goto_timer[v1] = __CFADD__uint16(v2, -32) + cinematicspr_goto_timer[v1] - 1; + uint16 v3 = cinematicspr_arr6[v1]; + bool v4 = __CFADD__uint16(cinematicspr_arr7[v1], v3); + cinematicspr_arr6[v1] = cinematicspr_arr7[v1] + v3; + cinematicbg_arr7[v1] += cinematicspr_goto_timer[v1] + v4; + CinematicFunction_Intro_Func189b(k); +} + +void CinematicFunction_Intro_Func189b(uint16 k) { // 0x8BF39B + if (cinematic_function == FUNC16(nullsub_126)) { + int v5 = k >> 1; + cinematicspr_instr_timer[v5] = 1; + cinematicspr_instr_ptr[v5] = addr_off_8BEE9B; + } +} + +uint16 CinematicSprInstr_Func190(uint16 k, uint16 j) { // 0x8BF3B0 + uint16 v0 = 0; + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEECD, v0); + return j; +} + +void CinematicFunction_Intro_Func191(uint16 k) { // 0x8BF3B9 + if (cinematic_function == (uint16)FUNC16(CinematicFunction_Intro_Func126)) { + int v1 = k >> 1; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BEE9B; + } +} + +uint16 CinematicSprInstr_Func192(uint16 k, uint16 j) { // 0x8BF3CE + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEEFD, 0); + + int hours1 = game_time_hours / 10; + int hours2 = game_time_hours % 10; + substate = hours1; + suit_pickup_light_beam_pos = hours2; + + int min1 = game_time_minutes / 10; + int min2 = game_time_minutes % 10; + + *(uint16 *)&suit_pickup_color_math_R = min1; + *(uint16 *)&suit_pickup_color_math_B = min2; + return j; +} + +uint16 CinematicSprInstr_Func193(uint16 k, uint16 j) { // 0x8BF41B + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF03, 0); + return j; +} + +uint16 CinematicSprInstr_Func194(uint16 k, uint16 j) { // 0x8BF424 + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF09, 0); + return j; +} + +uint16 CinematicSprInstr_Func195(uint16 k, uint16 j) { // 0x8BF42D + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF0F, 0); + return j; +} + +uint16 CinematicSprInstr_Func196(uint16 k, uint16 j) { // 0x8BF436 + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF15, 0); + return j; +} + +uint16 CinematicSprInstr_Func197(uint16 k, uint16 j) { // 0x8BF43F + SpawnCinematicSpriteObject(addr_kCinematicSpriteObjectDef_8BEF1B, 0); + return j; +} + +uint16 CinematicSprInstr_Func198(uint16 k, uint16 j) { // 0x8BF448 + screen_fade_delay = 0; + screen_fade_counter = 0; + cinematic_function = FUNC16(CinematicFunction_Intro_Func125); + return j; +} + +void CinematicFunction_Intro_Func199(uint16 k) { // 0x8BF455 + if (sign16(cinematic_var6 - 176)) + cinematicspr_preinstr_func[k >> 1] = FUNC16(CinematicFunction_Intro_Func200); +} + +void CinematicFunction_Intro_Func200(uint16 k) { // 0x8BF464 + int v1 = k >> 1; + cinematicspr_arr7[v1] = cinematicspr_arr7[v1]; + ++cinematicbg_arr8[v1]; +} + +void CinematicFunction_Intro_Func201(uint16 k) { // 0x8BF478 + if (sign16(cinematic_var6 - 176)) + cinematicspr_preinstr_func[k >> 1] = FUNC16(CinematicFunction_Intro_Func202); +} + +void CinematicFunction_Intro_Func202(uint16 k) { // 0x8BF487 + int v1 = k >> 1; + cinematicspr_arr7[v1] = cinematicspr_arr7[v1]; + --cinematicbg_arr8[v1]; +} + +void CinematicFunction_Intro_Func203(uint16 k) { // 0x8BF49B + if (!sign16(cinematic_var6 - 96)) + cinematicspr_preinstr_func[k >> 1] = FUNC16(CinematicFunction_Intro_Func204); +} + +void CinematicFunction_Intro_Func204(uint16 k) { // 0x8BF4AA + int v1 = k >> 1; + cinematicspr_arr7[v1] = cinematicspr_arr7[v1]; + cinematicbg_arr8[v1] -= 2; + cinematicspr_arr6[v1] = cinematicspr_arr6[v1]; + --cinematicbg_arr7[v1]; +} + +void CinematicFunction_Intro_Func205(uint16 k) { // 0x8BF4D1 + if (!sign16(cinematic_var6 - 96)) + cinematicspr_preinstr_func[k >> 1] = FUNC16(CinematicFunction_Intro_Func206); +} + +void CinematicFunction_Intro_Func206(uint16 k) { // 0x8BF4E0 + int v1 = k >> 1; + cinematicspr_arr7[v1] = cinematicspr_arr7[v1]; + cinematicbg_arr8[v1] += 2; + cinematicspr_arr6[v1] = cinematicspr_arr6[v1]; + ++cinematicbg_arr7[v1]; +} + +void CinematicFunction_Intro_Func207(uint16 k) { // 0x8BF507 + if (cinematic_function == (uint16)FUNC16(nullsub_125)) { + int v1 = k >> 1; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BEE9B; + } +} + +uint16 CinematicSprInstr_Func208(uint16 k, uint16 j) { // 0x8BF51D + R18_ = 0; + SpawnCinematicSpriteObjectToR18(addr_kCinematicSpriteObjectDef_8BEF3F, 0); + return j; +} + +void CinematicSprPreInstr_F528(uint16 k) { // 0x8BF528 + CinematicFunction_Intro_Func210_EndingSamusFall(k); + int v1 = k >> 1; + if (sign16(cinematicbg_arr8[v1] + 80)) { + reg_OBSEL = 3; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_word_8BED95; + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_Intro_Func215); + cinematicbg_arr9[v1] = 3072; + } +} + +uint16 CinematicSprInstr_Func211(uint16 k, uint16 j) { // 0x8BF554 + R18_ = 2; + if (sign16(game_time_hours - 10)) + SpawnCinematicSpriteObjectToR18(addr_kCinematicSpriteObjectDef_8BEF7B, 2); + else + SpawnCinematicSpriteObjectToR18(addr_kCinematicSpriteObjectDef_8BEF75, 2); + R18_ = 0; + SpawnCinematicSpriteObjectToR18(addr_kCinematicSpriteObjectDef_8BEF6F, 0); + return j; +} + +void CinematicSprPreInstr_F57F(uint16 k) { // 0x8BF57F + CinematicFunction_Intro_Func210_EndingSamusFall(k); + int v1 = k >> 1; + if (sign16(cinematicbg_arr8[v1] + 80)) { + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_off_8BEE9B; + } +} + +uint16 CinematicSprInstr_Func213(uint16 k, uint16 j) { // 0x8BF597 + int v1 = k >> 1; + if (sign16(game_time_hours - 10)) + cinematicbg_arr7[v1 + 1] = 120; + else + cinematicbg_arr7[v1 + 1] = 118; + cinematicbg_arr8[v1 + 1] = 120; + return j; +} + +uint16 CinematicSprInstr_Func214(uint16 k, uint16 j) { // 0x8BF5BA + int v1 = k >> 1; + if (sign16(game_time_hours - 10)) { + cinematicbg_arr7[v1 + 1] = 121; + cinematicbg_arr8[v1 + 1] = 116; + } else { + cinematicbg_arr7[v1 + 1] = 120; + cinematicbg_arr8[v1 + 1] = 114; + } + return j; +} + +void CinematicFunction_Intro_Func215(uint16 k) { // 0x8BF5DD + CinematicFunction_Intro_Func216(); + CinematicFunction_Intro_Func210_EndingSamusFall(k); + int v1 = k >> 1; + if (!sign16(cinematicbg_arr8[v1] - 136)) { + cinematicbg_arr8[v1] = 136; + cinematicspr_instr_timer[v1] = 1; + cinematicspr_instr_ptr[v1] = addr_word_8BED9D; + cinematicspr_preinstr_func[v1] = FUNC16(CinematicFunction_nullsub_116); + } +} + +uint16 CinematicSprInstr_Func217(uint16 k, uint16 j) { // 0x8BF604 + cinematicbg_arr9[k >> 1] = 3584; + cinematic_function = FUNC16(CinematicFunction_Intro_Func139); + reg_TM = 17; + reg_TS = 16; + reg_CGWSEL = 2; + reg_CGADSUB = -127; + cinematic_var8 = -4; + cinematic_var10 = -8; + cinematic_var4 = 16; + cinematic_var14 = 32; + cinematic_var17 = 32; + CopyPalettesToFadingPalettes(); + DecomposePaletteDataForFading(); + QueueSfx1_Max15(0x22u); + return j; +} + +uint16 CinematicSprInstr_Func218(uint16 k, uint16 j) { // 0x8BF651 + samus_y_subspeed = 0; + samus_y_speed = -16; + return j; +} + +void CinematicFunction_Intro_Func210_EndingSamusFall(uint16 k) { // 0x8BF65B + uint16 v1 = (__PAIR32__(samus_y_speed, samus_y_subspeed) + 14336) >> 16; + samus_y_subspeed += 14336; + samus_y_speed = v1; + int v2 = k >> 1; + uint16 v3 = cinematicspr_arr7[v2]; + bool v4 = __CFADD__uint16(samus_y_subspeed, v3); + cinematicspr_arr7[v2] = samus_y_subspeed + v3; + cinematicbg_arr8[v2] += samus_y_speed + v4; +} + +void CinematicFunction_Intro_Func216(void) { // 0x8BF682 + if (sign16(cinematic_var14 - 16)) { + uint16 v0 = 2 * cinematic_var14; + uint16 v1 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 2048; + v1 += 2; + int v2 = v0 >> 1; + gVramWriteEntry(v1)->size = g_word_8BF6B8[v2]; + v1 += 2; + LOBYTE(gVramWriteEntry(v1++)->size) = 127; + gVramWriteEntry(v1)->size = g_word_8BF6D8[v2]; + vram_write_queue_tail = v1 + 2; + ++cinematic_var14; + } +} + +uint16 CinematicFunction_Intro_Func219(uint16 k, uint16 j) { // 0x8BF6FE + DisableTextGlowObjects_(); + uint16 v0 = 8; + do { + palette_buffer[v0 >> 1] = kPalettes_Intro4[v0 >> 1]; + v0 += 2; + } while ((int16)(v0 - 512) < 0); + reg_TM = 0; + reg_INIDISP = 0x80; + screen_fade_delay = 0; + screen_fade_counter = 0; + cinematic_var9 = 0; + cinematic_var10 = 0; + enemy_projectile_pre_instr[1] = 1; + cinematic_function = FUNC16(CinematicFunction_Intro_Func129); + cinematic_var4 = 60; + return j; +} diff --git a/src/sm_8d.c b/src/sm_8d.c new file mode 100644 index 0000000..71d7f15 --- /dev/null +++ b/src/sm_8d.c @@ -0,0 +1,361 @@ +// Enemy projectile spritemaps, palette FX objects +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" + +void EnablePaletteFx(void) { // 0x8DC4C2 + flag_for_palette_fx_objects |= 0x8000u; +} + +void DisablePaletteFx(void) { // 0x8DC4CD + flag_for_palette_fx_objects &= ~0x8000u; +} + +void ClearPaletteFXObjects(void) { // 0x8DC4D8 + for (int i = 14; i >= 0; i -= 2) + palettefx_ids[i >> 1] = 0; +} + +void CallPalfxFunc(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnnullsub_131: return; + case fnPalInit_E1BC: PalInit_E1BC(k, j); return; + case fnPalInit_F761_Norfair1: PalInit_F761_Norfair1(k, j); return; + case fnPalInit_F779_Brinstar8: PalInit_F779_Brinstar8(k, j); return; + default: Unreachable(); + } +} + +void SpawnPalfxObject(uint16 j) { // 0x8DC4E9 + PalFxDef *PalFxDef; + + uint16 v1 = 14; + while (palettefx_ids[v1 >> 1]) { + v1 -= 2; + if ((v1 & 0x8000u) != 0) + return; + } + int v2 = v1 >> 1; + palettefx_ids[v2] = j; + palettefx_color_indexes[v2] = 0; + palettefx_pre_instr[v2] = FUNC16(PalPreInstr_nullsub_129); + palettefx_instr_list_ptrs[v2] = get_PalFxDef(j)->instrs; + palettefx_instr_timers[v2] = 1; + palettefx_timers[v2] = 0; + PalFxDef = get_PalFxDef(j); + CallPalfxFunc(PalFxDef->func | 0x8D0000, -1, v1); +} + +void PalPreInstr_nullsub_129(uint16 k) { // 0x8DC526 +} + +void PaletteFxHandler(void) { // 0x8DC527 + if ((flag_for_palette_fx_objects & 0x8000u) != 0) { + for (int i = 14; i >= 0; i -= 2) { + palettefx_index = i; + if (palettefx_ids[i >> 1]) { + PalFx_ProcessOne(i); + i = palettefx_index; + } + } + } +} + +void CallPalFxPreInstr(uint32 ea, uint16 k) { + switch (ea) { + case fnPalPreInstr_nullsub_129: PalPreInstr_nullsub_129(k); return; + case fnPalPreInstr_E1BC: PalPreInstr_E1BC(k); return; + case fnPalPreInstr_CheckEnemy0Health: PalPreInstr_CheckEnemy0Health(k); return; + case fnPalPreInstr_SamusInHeat: PalPreInstr_SamusInHeat(k); return; + case fnPalPreInstr_DeletePalfxIfMinibossDead: PalPreInstr_DeletePalfxIfMinibossDead(k); return; + case fnPalPreInstr_SwitchIfYpos: PalPreInstr_SwitchIfYpos(k); return; + case fnPalPreInstr_SwitchIfYpos2: PalPreInstr_SwitchIfYpos2(k); return; + case fnPalPreInstr_F621: PalPreInstr_F621(k); return; + default: Unreachable(); + } +} + +PairU16 CallPalInstr(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnPalInstr_Finish: return PalInstr_Finish(k, j); + case fnPalInstr_ColorPlus2: return PalInstr_ColorPlus2(k, j); + case fnPalInstr_ColorPlus3: return PalInstr_ColorPlus3(k, j); + case fnPalInstr_ColorPlus4: return PalInstr_ColorPlus4(k, j); + case fnPalInstr_ColorPlus8: return PalInstr_ColorPlus8(k, j); + case fnPalInstr_ColorPlus9: return PalInstr_ColorPlus9(k, j); + case fnPalInstr_ColorPlus15: return PalInstr_ColorPlus15(k, j); + case fnPalInstr_Delete: return PalInstr_Delete(k, j); + case fnPalInstr_SetPreInstr: return PalInstr_SetPreInstr(k, j); + case fnPalInstr_ClearPreInstr: return PalInstr_ClearPreInstr(k, j); + case fnPalInstr_Goto: return PalInstr_Goto(k, j); + case fnPalInstr_GotoRel: return PalInstr_GotoRel(k, j); + case fnPalInstr_DecTimerGoto: return PalInstr_DecTimerGoto(k, j); + case fnPalInstr_DecTimerGotoRel: return PalInstr_DecTimerGotoRel(k, j); + case fnPalInstr_SetTimer: return PalInstr_SetTimer(k, j); + case fnPalInstr_SetColorIndex: return PalInstr_SetColorIndex(k, j); + case fnPalInstr_QueueMusic: return PalInstr_QueueMusic(k, j); + case fnPalInstr_QueueSfx1: return PalInstr_QueueSfx1(k, j); + case fnPalInstr_QueueSfx2: return PalInstr_QueueSfx2(k, j); + case fnPalInstr_QueueSfx3: return PalInstr_QueueSfx3(k, j); + case fnPalInstr_SetTimerIfBossBit: return PalInstr_SetTimerIfBossBit(k, j); + case fnPalInstr_SetPalfxIndex: return PalInstr_SetPalfxIndex(k, j); + default: Unreachable(); return (PairU16){0, 0}; + } +} + +void PalFx_ProcessOne(uint16 k) { // 0x8DC54A + PairU16 v7; + int16 v11; + PairU16 v12; + + CallPalFxPreInstr(palettefx_pre_instr[k >> 1] | 0x8D0000, k); + uint16 v1 = palettefx_index; + int v2 = palettefx_index >> 1; + if (palettefx_instr_timers[v2]-- == 1) { + uint16 j = palettefx_instr_list_ptrs[v2], v6; + while (1) { + uint16 *v5 = (uint16 *)RomPtr_8D(j); + v6 = *v5; + if ((*v5 & 0x8000u) == 0) + break; + R18_ = *v5; + v7 = CallPalInstr(v6 | 0x8D0000, v1, j + 2); + v1 = v7.k; + j = v7.j; + if (!v7.j) + return; + } + int v8 = v1 >> 1; + palettefx_instr_timers[v8] = v6; + uint16 v9 = palettefx_color_indexes[v8]; + uint8 *v10; + do { + while (1) { + v10 = RomPtr_8D(j); + v11 = *((uint16 *)v10 + 1); + if (v11 & 0x8000) + break; + palette_buffer[v9 >> 1] = v11; + v9 += 2; + j += 2; + } + R18_ = *((uint16 *)v10 + 1); + v12 = CallPalInstr((uint16)v11 | 0x8D0000, v9, j); + v9 = v12.k; + j = v12.j; + } while (v12.j); + } +} + +PairU16 PalInstr_Finish(uint16 k, uint16 j) { // 0x8DC595 + palettefx_instr_list_ptrs[palettefx_index >> 1] = j + 4; + return MakePairU16(0, 0); +} + +PairU16 PalInstr_ColorPlus2(uint16 k, uint16 j) { // 0x8DC599 + return MakePairU16(k + 4, j + 2); +} + +PairU16 PalInstr_ColorPlus3(uint16 k, uint16 j) { // 0x8DC5A2 + return MakePairU16(k + 6, j + 2); +} + +PairU16 PalInstr_ColorPlus4(uint16 k, uint16 j) { // 0x8DC5AB + return MakePairU16(k + 8, j + 2); +} + +PairU16 PalInstr_ColorPlus8(uint16 k, uint16 j) { // 0x8DC5B4 + return MakePairU16(k + 16, j + 2); +} + +PairU16 PalInstr_ColorPlus9(uint16 k, uint16 j) { // 0x8DC5BD + return MakePairU16(k + 18, j + 2); +} + +PairU16 PalInstr_ColorPlus15(uint16 k, uint16 j) { // 0x8DC5C6 + return MakePairU16(k + 30, j + 2); +} + +PairU16 PalInstr_Delete(uint16 k, uint16 j) { // 0x8DC5CF + palettefx_ids[k >> 1] = 0; + return MakePairU16(k, 0); +} + +PairU16 PalInstr_SetPreInstr(uint16 k, uint16 j) { // 0x8DC5D4 + palettefx_pre_instr[k >> 1] = *(uint16 *)RomPtr_8D(j); + return MakePairU16(k, j + 2); +} + +PairU16 PalInstr_ClearPreInstr(uint16 k, uint16 j) { // 0x8DC5DD + palettefx_pre_instr[k >> 1] = addr_locret_8DC5E3; + return MakePairU16(k, j); +} + +PairU16 PalInstr_Goto(uint16 k, uint16 j) { // 0x8DC61E + uint16 v2 = *(uint16 *)RomPtr_8D(j); + return MakePairU16(k, v2); +} + +PairU16 PalInstr_GotoRel(uint16 k, uint16 j) { // 0x8DC623 + int16 v2; + + R18_ = j; + LOBYTE(v2) = HIBYTE(*(uint16 *)RomPtr_8D(j - 1)); + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + else + v2 = (uint8)v2; + return MakePairU16(k, R18_ + v2); +} + +PairU16 PalInstr_DecTimerGoto(uint16 k, uint16 j) { // 0x8DC639 + PairU16 v4; + + int v2 = k >> 1; + if (palettefx_timers[v2]-- == 1) + return MakePairU16(k, j + 2); + v4 = PalInstr_Goto(k, j); + return MakePairU16(v4.k, v4.j); +} + +PairU16 PalInstr_DecTimerGotoRel(uint16 k, uint16 j) { // 0x8DC641 + PairU16 v4; + + int v2 = k >> 1; + if (palettefx_timers[v2]-- == 1) + return MakePairU16(k, j + 1); + v4 = PalInstr_GotoRel(k, j); + return MakePairU16(v4.k, v4.j); +} + +PairU16 PalInstr_SetTimer(uint16 k, uint16 j) { // 0x8DC648 + *((uint8 *)palettefx_timers + k) = *RomPtr_8D(j); + return MakePairU16(k, j + 1); +} + +PairU16 PalInstr_SetColorIndex(uint16 k, uint16 j) { // 0x8DC655 + palettefx_color_indexes[k >> 1] = *(uint16 *)RomPtr_8D(j); + return MakePairU16(k, j + 2); +} + +PairU16 PalInstr_QueueMusic(uint16 k, uint16 j) { // 0x8DC65E + uint8 *v2 = RomPtr_8D(j); + QueueMusic_Delayed8(*v2); + return MakePairU16(k, j + 1); +} + +PairU16 PalInstr_QueueSfx1(uint16 k, uint16 j) { // 0x8DC66A + uint16 *v2 = (uint16 *)RomPtr_8D(j); + QueueSfx1_Max6(*v2); + return MakePairU16(k, j + 1); +} + +PairU16 PalInstr_QueueSfx2(uint16 k, uint16 j) { // 0x8DC673 + uint16 *v2 = (uint16 *)RomPtr_8D(j); + QueueSfx2_Max6(*v2); + return MakePairU16(k, j + 1); +} + +PairU16 PalInstr_QueueSfx3(uint16 k, uint16 j) { // 0x8DC67C + uint16 *v2 = (uint16 *)RomPtr_8D(j); + QueueSfx3_Max6(*v2); + return MakePairU16(k, j + 1); +} + +void PalInit_E1BC(uint16 k, uint16 j) { // 0x8DE204 + palettefx_pre_instr[j >> 1] = FUNC16(PalPreInstr_E1BC); +} + +void PalPreInstr_E1BC(uint16 k) { // 0x8DE20B + if (cinematic_function == (uint16)FUNC16(CinematicFunction_Intro_Page2)) { + int v1 = k >> 1; + palettefx_instr_list_ptrs[v1] = addr_off_8DE192; + palettefx_instr_timers[v1] = 1; + } +} + +void PalPreInstr_CheckEnemy0Health(uint16 k) { // 0x8DE2E0 + if (!enemy_data[0].health) + palettefx_ids[k >> 1] = 0; +} + +void PalPreInstr_SamusInHeat(uint16 k) { // 0x8DE379 + if ((equipped_items & 0x21) == 0) { + uint16 v1 = (__PAIR32__(samus_periodic_damage, samus_periodic_subdamage) + 0x4000) >> 16; + samus_periodic_subdamage += 0x4000; + samus_periodic_damage = v1; + if ((nmi_frame_counter_word & 7) == 0 && samus_health > 0x46u) + QueueSfx3_Max6(0x2Du); + } + if (samus_in_heat_palfx_index != samus_in_heat_palettefx_prev_index) { + samus_in_heat_palettefx_prev_index = samus_in_heat_palfx_index; + uint16 v2 = 2 * samus_in_heat_palfx_index, v4; + int v3 = k >> 1; + palettefx_instr_timers[v3] = 1; + if ((equipped_items & 0x20) != 0) { + v4 = addr_off_8DE3E0; + } else if ((equipped_items & 1) != 0) { + v4 = addr_off_8DE400; + } else { + v4 = addr_off_8DE420; + } + R18_ = v4; + palettefx_instr_list_ptrs[v3] = *(uint16 *)&RomPtr_8D(v4)[v2]; + } +} + +void PalInit_F761_Norfair1(uint16 k, uint16 j) { // 0x8DE440 + uint16 v2; + if ((equipped_items & 0x20) != 0) { + v2 = addr_off_8DE8B6; + } else if ((equipped_items & 1) != 0) { + v2 = addr_off_8DE68A; + } else { + v2 = addr_kPalfxInstrList_E45E; + } + palettefx_instr_list_ptrs[j >> 1] = v2; +} + +PairU16 PalInstr_SetTimerIfBossBit(uint16 k, uint16 j) { // 0x8DEB2A + if (!(CheckBossBitForCurArea(1u) & 1)) { + palettefx_instr_timers[k >> 1] = 1; + return MakePairU16(k, 0); + } + return MakePairU16(k, j); +} + +void PalPreInstr_SwitchIfYpos(uint16 k) { // 0x8DEC59 + if (samus_y_pos < 0x380u) { + int v2 = k >> 1; + palettefx_instr_timers[v2] = 1; + palettefx_instr_list_ptrs[v2] = addr_word_8DEB43; + } +} + +void PalPreInstr_SwitchIfYpos2(uint16 k) { // 0x8DED84 + if (samus_y_pos < 0x380u) { + int v2 = k >> 1; + palettefx_instr_timers[v2] = 1; + palettefx_instr_list_ptrs[v2] = addr_word_8DEC76; + } +} + +void PalPreInstr_DeletePalfxIfMinibossDead(uint16 k) { // 0x8DEEC5 + if ((*(uint16 *)&boss_bits_for_area[area_index] & 2) != 0) + palettefx_ids[k >> 1] = 0; +} + +PairU16 PalInstr_SetPalfxIndex(uint16 k, uint16 j) { // 0x8DF1C6 + samus_in_heat_palfx_index = *RomPtr_8D(j); + return MakePairU16(k, j + 1); +} + +void PalPreInstr_F621(uint16 k) { // 0x8DF621 + if (*(uint16 *)((char *)&flag_for_palette_fx_objects + k)) + palettefx_ids[k >> 1] = 0; +} + +void PalInit_F779_Brinstar8(uint16 k, uint16 j) { // 0x8DF730 + if ((*(uint16 *)&boss_bits_for_area[area_index] & 2) != 0) + palettefx_ids[j >> 1] = 0; +} diff --git a/src/sm_8f.c b/src/sm_8f.c new file mode 100644 index 0000000..e7dfdf2 --- /dev/null +++ b/src/sm_8f.c @@ -0,0 +1,989 @@ +// Rooms definitions +#include "ida_types.h" +#include "variables.h" +#include "sm_rtl.h" +#include "funcs.h" + +static const SpawnHardcodedPlmArgs unk_8F9198 = { 0x3d, 0x0b, 0xbb30 }; +static const SpawnHardcodedPlmArgs unk_8F91AD = { 0x10, 0x87, 0xb964 }; +static const SpawnHardcodedPlmArgs unk_8F91B6 = { 0x0f, 0x0a, 0xb9ed }; +void RoomSetup_AfterSavingAnimals(void) { // 0x8F9194 + SpawnHardcodedPlm(&unk_8F9198); + earthquake_type = 24; + earthquake_timer = -1; +} + +void RoomSetup_AutoDestroyWallAfterEscape(void) { // 0x8F91A9 + SpawnHardcodedPlm(&unk_8F91AD); +} + +void RoomSetup_TurnWallIntoShotblocks(void) { // 0x8F91B2 + SpawnHardcodedPlm(&unk_8F91B6); +} + +void RoomSetup_ShakeDuringEscape(void) { // 0x8F91BD + earthquake_type = 6; + earthquake_timer = -1; + RoomSetup_ScrollingSkyLand(); +} + +void RoomSetup_ScrollingSkyLand(void) { // 0x8F91C9 + FxTypeFunc_20(); +} + +void RoomSetup_ScrollingSkyOcean(void) { // 0x8F91CE + RoomSetupAsm_ScrollingSkyOcean(); +} + +void RoomSetup_RunStatueUnlockAnims(void) { // 0x8F91D7 + SpawnAnimtiles(addr_kAnimtiles_TourianStatue_Kraid); + SpawnAnimtiles(addr_kAnimtiles_TourianStatue_Phantoon); + SpawnAnimtiles(addr_kAnimtiles_TourianStatue_Draygon); + SpawnAnimtiles(addr_kAnimtiles_TourianStatue_Ridley); +} + +void DoorCode_StartWreckedShipTreadmillWest(void) { // 0x8FB971 + SpawnAnimtiles(addr_kAnimtiles_WreckedShipTradmillRight); + + static const SpawnHardcodedPlmArgs unk_8FB97C = { 0x04, 0x09, 0xb64b }; + SpawnHardcodedPlm(&unk_8FB97C); +} + +void DoorCode_Scroll6_Green(void) { // 0x8FB981 + scrolls[6] = 2; +} + +void DoorCode_Scroll0_Blue(void) { // 0x8FB98C + scrolls[0] = 1; +} + +void DoorCode_Scroll13_Blue(void) { // 0x8FB997 + scrolls[19] = 1; +} + +void DoorCode_Scroll_4Blue_8Green(void) { // 0x8FB9A2 + scrolls[4] = 0; + scrolls[8] = 2; +} + +void DoorCode_Scroll_8toB_Red(void) { // 0x8FB9B3 + scrolls[8] = 0; + scrolls[9] = 0; + scrolls[10] = 0; + scrolls[11] = 0; +} + +void DoorCode_Scroll_LotsRed(void) { // 0x8FB9CA + scrolls[2] = 0; + scrolls[3] = 0; + scrolls[4] = 0; + scrolls[5] = 0; + scrolls[11] = 0; + scrolls[12] = 0; + scrolls[13] = 0; + scrolls[17] = 0; +} + +void DoorCode_Scroll_1_4_Green(void) { // 0x8FB9F1 + scrolls[1] = 2; + scrolls[4] = 2; +} + +void DoorCode_Scroll_2_Blue(void) { // 0x8FBA00 + scrolls[2] = 1; +} + +void DoorCode_Scroll_17_Blue(void) { // 0x8FBA0B + scrolls[23] = 1; +} + +void DoorCode_Scroll_4_Blue(void) { // 0x8FBA16 + scrolls[4] = 1; +} + +void DoorCode_Scroll_6_Green(void) { // 0x8FBA21 + scrolls[6] = 2; +} + +void DoorCode_Scroll_3_Green(void) { // 0x8FBA2C + scrolls[3] = 2; +} + +void DoorCode_SetScroll_0(void) { // 0x8FBD07 + scrolls[24] = 2; + scrolls[28] = 2; +} + +void DoorCode_SetScroll_1(void) { // 0x8FBD16 + scrolls[5] = 1; + scrolls[6] = 1; +} + +void DoorCode_SetScroll_2(void) { // 0x8FBD25 + scrolls[29] = 1; +} + +void DoorCode_SetScroll_3(void) { // 0x8FBD30 + scrolls[2] = 2; + scrolls[3] = 2; +} + +void DoorCode_SetScroll_4(void) { // 0x8FBD3F + scrolls[0] = 0; + scrolls[1] = 2; +} + +void DoorCode_SetScroll_5(void) { // 0x8FBD50 + scrolls[11] = 2; +} + +void DoorCode_SetScroll_6(void) { // 0x8FBD5B + scrolls[28] = 0; + scrolls[29] = 1; +} + +void DoorCode_SetScroll_7(void) { // 0x8FBD6C + scrolls[4] = 0; +} + +void DoorCode_SetScroll_8(void) { // 0x8FBD77 + scrolls[32] = 2; + scrolls[36] = 2; + scrolls[37] = 2; +} + +void DoorCode_SetScroll_9(void) { // 0x8FBD8A + scrolls[2] = 1; +} + +void DoorCode_SetScroll_10(void) { // 0x8FBD95 + scrolls[0] = 2; +} + +void DoorCode_SetScroll_11(void) { // 0x8FBDA0 + scrolls[6] = 2; + scrolls[7] = 2; +} + +void DoorCode_SetScroll_12(void) { // 0x8FBDAF + scrolls[1] = 1; + scrolls[2] = 0; +} + +void DoorCode_SetScroll_13(void) { // 0x8FBDC0 + scrolls[1] = 1; + scrolls[3] = 0; +} + +void DoorCode_SetScroll_14(void) { // 0x8FBDD1 + scrolls[0] = 0; + scrolls[4] = 1; +} + +void DoorCode_SetScroll_15(void) { // 0x8FBDE2 + scrolls[2] = 1; + scrolls[3] = 1; +} + +void DoorCode_SetScroll_16(void) { // 0x8FBDF1 + scrolls[0] = 2; + scrolls[1] = 2; +} + +void DoorCode_SetScroll_17(void) { // 0x8FBE00 + scrolls[1] = 2; +} + +void DoorCode_SetScroll_18(void) { // 0x8FBE0B + scrolls[15] = 2; + scrolls[18] = 2; +} + +void DoorCode_SetScroll_19(void) { // 0x8FBE1A + scrolls[6] = 2; +} + +void DoorCode_SetScroll_20(void) { // 0x8FBE25 + scrolls[0] = 2; + scrolls[1] = 1; +} + +void DoorCode_SetScroll_21(void) { // 0x8FBE36 + scrolls[2] = 2; +} + +void DoorCode_SetScroll_22(void) { // 0x8FBF9E + scrolls[3] = 0; + scrolls[4] = 0; + scrolls[6] = 1; + scrolls[7] = 1; + scrolls[8] = 1; +} + +void DoorCode_SetScroll_23(void) { // 0x8FBFBB + scrolls[1] = 1; + scrolls[2] = 1; + scrolls[3] = 1; + scrolls[4] = 2; + scrolls[6] = 0; +} + +void DoorCode_SetScroll_24(void) { // 0x8FBFDA + scrolls[0] = 1; + scrolls[1] = 1; +} + +void DoorCode_SetScroll_25(void) { // 0x8FBFE9 + scrolls[1] = 0; + scrolls[0] = 1; +} + +void DoorCode_SetScroll_26(void) { // 0x8FBFFA + scrolls[10] = 2; +} + +void DoorCode_SetScroll_27(void) { // 0x8FC005 + scrolls[0] = 1; + scrolls[2] = 0; +} + +void DoorCode_SetScroll_28(void) { // 0x8FC016 + scrolls[0] = 2; + scrolls[2] = 2; +} + +void DoorCode_SetScroll_29(void) { // 0x8FC025 + scrolls[6] = 1; + scrolls[7] = 1; + scrolls[8] = 0; +} + +void DoorCode_SetScroll_30(void) { // 0x8FC03A + scrolls[2] = 0; + scrolls[3] = 1; +} + +void DoorCode_SetScroll_31(void) { // 0x8FC04B + scrolls[7] = 2; +} + +void DoorCode_SetScroll_32(void) { // 0x8FC056 + scrolls[1] = 0; + scrolls[2] = 1; +} + +void DoorCode_SetScroll_33(void) { // 0x8FC067 + scrolls[3] = 0; + scrolls[0] = 1; +} + +void DoorCode_SetScroll_34(void) { // 0x8FC078 + scrolls[1] = 1; + scrolls[4] = 0; +} + +void DoorCode_SetScroll_35(void) { // 0x8FC089 + scrolls[0] = 1; + scrolls[1] = 0; + scrolls[2] = 0; + scrolls[3] = 0; +} + +void DoorCode_SetScroll_36(void) { // 0x8FC0A2 + scrolls[0] = 2; +} + +void DoorCode_SetScroll_37(void) { // 0x8FC0AD + scrolls[0] = 1; + scrolls[1] = 1; + scrolls[4] = 0; +} + +void DoorCode_SetScroll_38(void) { // 0x8FC0C2 + scrolls[0] = 1; + scrolls[3] = 0; +} + +void DoorCode_SetScroll_39(void) { // 0x8FC0D3 + scrolls[0] = 1; +} + +void DoorCode_SetScroll_40(void) { // 0x8FC0DE + scrolls[0] = 1; + scrolls[1] = 0; +} + +void DoorCode_SetScroll_41(void) { // 0x8FC0EF + scrolls[24] = 1; +} + +void DoorCode_SetScroll_42(void) { // 0x8FC0FA + scrolls[3] = 0; + scrolls[2] = 1; +} + +void DoorCode_SetScroll_43(void) { // 0x8FC10B + scrolls[14] = 0; +} + +void RoomCode_ScrollingSkyLand_(void) { // 0x8FC116 + RoomCode_ScrollingSkyLand(); +} + +void RoomCode_ScrollingSkyOcean_(void) { // 0x8FC11B + RoomMainAsm_ScrollingSkyOcean(); +} + +void RoomCode_ScrollingSkyLand_Shakes(void) { // 0x8FC120 + RoomCode_ScrollingSkyLand(); + RoomCode_GenRandomExplodes_Nonblank(); + earthquake_timer |= 0x8000u; +} + +void RoomCode_ExplodeShakes(void) { // 0x8FC124 + RoomCode_GenRandomExplodes_Nonblank(); + earthquake_timer |= 0x8000u; +} + +void RoomCode_GenRandomExplodes_Nonblank(void) { // 0x8FC131 + int16 v1; + + if (!time_is_frozen_flag && (nmi_frame_counter_word & 1) == 0) { + uint16 Random = NextRandom(); + R18_ = layer1_x_pos + (uint8)Random; + R20_ = layer1_y_pos + HIBYTE(Random); + uint8 v2 = R20_ >> 4; + uint16 prod = Mult8x8(v2, room_width_in_blocks); + v1 = R18_ >> 4; + if ((level_data[prod + v1] & 0x3FF) != 255) + RoomCode_GenRandomExplodes(); + } +} + +void RoomCode_GenRandomExplodes_4th(void) { // 0x8FC183 + if (!time_is_frozen_flag && (nmi_frame_counter_word & 3) == 0) { + uint16 Random = NextRandom(); + R18_ = layer1_x_pos + (uint8)Random; + R20_ = layer1_y_pos + HIBYTE(Random); + RoomCode_GenRandomExplodes(); + } +} + +void RoomCode_GenRandomExplodes(void) { // 0x8FC1A9 + static const uint8 kRoomCode_GenRandomExplodes_Sprite[8] = { 3, 3, 9, 12, 12, 18, 18, 21 }; + static const uint8 kRoomCode_GenRandomExplodes_Sfx[8] = { 0x24, 0, 0, 0x25, 0, 0, 0, 0 }; + + // Bugfix, X is garbage + uint16 v1 = NextRandom() & 0xF; + if (v1 < 8u) { + uint16 v2 = kRoomCode_GenRandomExplodes_Sfx[v1]; + if (v2) + QueueSfx2_Max6(v2); + } + R22_ = kRoomCode_GenRandomExplodes_Sprite[v1 & 7]; + R24_ = 0; + CreateSpriteAtPos(); +} + +void RoomCode_ScrollRightDachora(void) { // 0x8FC1E6 + if (scrolls[11] == 2 && layer1_y_pos < 0x500u && layer1_x_pos < 0x380u) + layer1_x_pos += (layer1_x_pos >= 0x380u) + 3; +} + +void RoomCode_8FC8C8(void) { // 0x8FC8C8 + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_PrePhantomRoom, 0); +} + +void RoomCode_SetupShaktoolRoomPlm(void) { // 0x8FC8D3 + static const SpawnHardcodedPlmArgs unk_8FC8D7 = { 0x00, 0x00, 0xb8eb }; + SpawnHardcodedPlm(&unk_8FC8D7); +} + +void RoomCode_SetPauseCodeForDraygon(void) { // 0x8FC8DD + mov24(&pause_hook, fnPauseHook_DraygonRoom); + mov24(&unpause_hook, fnUnpauseHook_DraygonRoom); +} + +void PauseHook_DraygonRoom(void) { // 0x8FC8F6 + irqhandler_next_handler = 4; +} + +void UnpauseHook_DraygonRoom(void) { // 0x8FC8FC + if (hdma_object_channels_bitmask[1] == 8) + irqhandler_next_handler = 12; +} + +void RoomCode_SetCollectedMap(void) { // 0x8FC90A + uint16 v0 = *(uint16 *)&map_station_byte_array[area_index] | 1; + *(uint16 *)&map_station_byte_array[area_index] = v0; + has_area_map = v0; +} + +void RoomCode_SetZebesTimebombEvent(void) { // 0x8FC91F + SetEventHappened(0xEu); + earthquake_type = 18; + earthquake_timer = -1; +} + +void RoomCode_SetLightHorizRoomShake(void) { // 0x8FC933 + earthquake_type = 18; + *(uint16 *)&room_main_asm_variables[2] = 18; + *(uint16 *)room_main_asm_variables = 0; + earthquake_timer = -1; +} + +void RoomCode_SetMediumHorizRoomShake(void) { // 0x8FC946 + earthquake_type = 21; + earthquake_timer = -1; +} + +void RoomCode_Escape4_SetMediumHorizRoomShake(void) { // 0x8FC953 + static const SpawnHardcodedPlmArgs unk_8FC957 = { 0x10, 0x10, 0xb968 }; + SpawnHardcodedPlm(&unk_8FC957); + earthquake_type = 21; + *(uint16 *)&room_main_asm_variables[2] = 21; + *(uint16 *)room_main_asm_variables = 0; + earthquake_timer = -1; +} + +void RoomCode_SetCeresDoorSolid(void) { // 0x8FC96E + static const SpawnHardcodedPlmArgs unk_8FC972 = { 0x0f, 0x26, 0xba48 }; + SpawnHardcodedPlm(&unk_8FC972); + FxTypeFunc_2C_Haze(); +} + +void RoomCode_CeresColorMathHdma(void) { // 0x8FC976 + FxTypeFunc_2C_Haze(); +} + +void RoomCode_CeresColorMathHdma_BgBase(void) { // 0x8FC97B + reg_BG12NBA = 102; + FxTypeFunc_2C_Haze(); + hdma_data_table_in_ceres = 9; +} + +void DoorCode_StartWreckedSkipTreadmill_East(void) { // 0x8FE1D8 + SpawnAnimtiles(addr_kAnimtiles_WreckedShipTradmillLeft); + static const SpawnHardcodedPlmArgs unk_8FE1E3 = { 0x04, 0x09, 0xb64f }; + SpawnHardcodedPlm(&unk_8FE1E3); +} + +void DoorCode_SetScroll_44(void) { // 0x8FE1E8 + scrolls[1] = 1; +} + +void DoorCode_SetScroll_45(void) { // 0x8FE1F3 + scrolls[0] = 2; +} + +void DoorCode_SetScroll_46(void) { // 0x8FE1FE + scrolls[3] = 0; + scrolls[4] = 1; +} + +void DoorCode_SetScroll_47(void) { // 0x8FE20F + scrolls[41] = 1; +} + +void DoorCode_SetScroll_48(void) { // 0x8FE21A + scrolls[40] = 2; + scrolls[46] = 2; +} + +void DoorCode_SetScroll_49(void) { // 0x8FE229 + scrolls[6] = 0; + scrolls[7] = 0; + scrolls[8] = 0; + scrolls[9] = 0; + scrolls[10] = 0; + scrolls[11] = 0; +} +static const SpawnHardcodedPlmArgs unk_8FE28C = { 0x01, 0x00, 0xb8f9 }; +static const SpawnHardcodedPlmArgs unk_8FE2B1 = { 0x01, 0x00, 0xb8f9 }; +void DoorCode_SetupElevatubeFromSouth(void) { // 0x8FE26C + *(uint16 *)&room_main_asm_variables[4] = -256; + *(uint16 *)&room_main_asm_variables[2] = 2496; + *(uint16 *)&room_main_asm_variables[6] = -32; + CallSomeSamusCode(0); + SpawnHardcodedPlm(&unk_8FE28C); +} + +void DoorCode_SetupElevatubeFromNorth(void) { // 0x8FE291 + *(uint16 *)&room_main_asm_variables[4] = 256; + strcpy((char *)&room_main_asm_variables[2], "@"); + strcpy((char *)&room_main_asm_variables[6], " "); + CallSomeSamusCode(0); + SpawnHardcodedPlm(&unk_8FE2B1); +} + +void RoomCode_Elevatube(void) { // 0x8FE2B6 + int16 v0; + + samus_x_pos = 128; + samus_x_subpos = 0; + R18_ = 0; + R20_ = 0; + if (*(int16 *)&room_main_asm_variables[4] < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = *(uint16 *)&room_main_asm_variables[4]; + v0 = (__PAIR32__(R20_, R18_) + *(uint32 *)room_main_asm_variables) >> 16; + *(uint16 *)room_main_asm_variables += R18_; + *(uint16 *)&room_main_asm_variables[2] = v0; + uint16 v1 = R18_; + R18_ = R20_; + R20_ = v1; + Samus_MoveDown_NoSolidColl(); + if ((uint16)(*(uint16 *)&room_main_asm_variables[6] + *(uint16 *)&room_main_asm_variables[4] + 3616) < 0x1C41u) + *(uint16 *)&room_main_asm_variables[4] += *(uint16 *)&room_main_asm_variables[6]; +} + +void DoorCode_ResetElevatubeNorthExit(void) { // 0x8FE301 + CallSomeSamusCode(1u); +} + +void DoorCode_ResetElevatubeSouthExit(void) { // 0x8FE309 + *(uint16 *)scrolls = 514; + CallSomeSamusCode(1u); +} + +void DoorCode_SetScroll_50(void) { // 0x8FE318 + scrolls[10] = 0; + scrolls[11] = 1; +} + +void UNUSED_DoorCode_SetScroll_51(void) { // 0x8FE329 + scrolls[17] = 0; + scrolls[16] = 1; +} + +void UNUSED_DoorCode_SetScroll_52(void) { // 0x8FE33A + scrolls[4] = 2; +} + +void DoorCode_SetScroll_53(void) { // 0x8FE345 + scrolls[0] = 0; + scrolls[4] = 1; +} + +void DoorCode_SetScroll_54(void) { // 0x8FE356 + scrolls[0] = 0; + scrolls[1] = 1; +} + +void DoorCode_SetScroll_55(void) { // 0x8FE367 + scrolls[9] = 0; + scrolls[10] = 1; +} + +void DoorCode_SetScroll_56(void) { // 0x8FE378 + scrolls[0] = 0; + scrolls[2] = 0; + scrolls[1] = 1; +} + +void DoorCode_SetScroll_57(void) { // 0x8FE38D + scrolls[1] = 1; +} + +void DoorCode_SetScroll_58(void) { // 0x8FE398 + scrolls[6] = 1; +} + +void DoorCode_SetScroll_59(void) { // 0x8FE3A3 + scrolls[4] = 0; +} + +void DoorCode_SetScroll_60(void) { // 0x8FE3AE + scrolls[1] = 0; +} + +void DoorCode_SetScroll_61(void) { // 0x8FE3B9 + scrolls[4] = 0; + scrolls[7] = 0; +} + +void DoorCode_SetScroll_62(void) { // 0x8FE3C8 + scrolls[2] = 0; + scrolls[1] = 1; +} + +void DoorCode_SetScroll_63(void) { // 0x8FE3D9 + scrolls[0] = 2; + scrolls[2] = 2; +} + +void DoorCode_SetScroll_64(void) { // 0x8FE4C0 + scrolls[0] = 2; + scrolls[1] = 2; +} + +void DoorCode_SetScroll_65(void) { // 0x8FE4CF + scrolls[24] = 1; + scrolls[25] = 0; +} + +void DoorCode_CeresElevatorShaft(void) { // 0x8FE4E0 + reg_BGMODE_fake = 7; + WriteReg(BGMODE, 7u); + reg_M7A = 256; + reg_M7D = 256; + reg_M7B = 0; + reg_M7C = 0; + reg_M7X = 128; + reg_M7Y = 1008; + irq_enable_mode7 = 1; + strcpy((char *)room_main_asm_variables, "\""); + strcpy((char *)&room_main_asm_variables[2], "<"); +} + +void DoorCode_CeresElevatorShaft_2(void) { // 0x8FE513 + reg_BGMODE_fake = 9; + irq_enable_mode7 = 0; +} + +void RoomCode_CeresElevatorShaft_(void) { // 0x8FE51F + RoomCode_CeresElevatorShaft(); +} + +static const uint16 kRoomCode_SpawnCeresFallingDebris_Tab[16] = { // 0x8FE525 + 0x50, 0x60, 0x70, 0x80, + 0x90, 0xa0, 0xb0, 0xc0, + 0xd0, 0xe0, 0xf0, 0x110, + 0x130, 0x150, 0x170, 0x190, +}; +void RoomCode_SpawnCeresFallingDebris(void) { + + if (ceres_status && (-- * (uint16 *)room_main_asm_variables, *(int16 *)room_main_asm_variables < 0)) { + strcpy((char *)room_main_asm_variables, "\b"); + uint16 v0 = addr_stru_869734; + if (random_number & 0x8000) + v0 = addr_stru_869742; + SpawnEnemyProjectileWithRoomGfx( + v0, + kRoomCode_SpawnCeresFallingDebris_Tab[random_number & 0xF]); + } else { + } +} + +void RoomCode_HandleCeresRidleyGetaway(void) { // 0x8FE571 + if (ceres_status & 1) + HandleCeresRidleyGetawayCutscene(); +} + +void RoomCode_ShakeScreenHorizDiag(void) { // 0x8FE57C + uint16 v0; + if (*(uint16 *)room_main_asm_variables) { + if (!-- * (uint16 *)room_main_asm_variables) { + v0 = 18; +LABEL_6: + earthquake_type = v0; + } + } else if (NextRandom() < 0x200u) { + strcpy((char *)room_main_asm_variables, "*"); + v0 = 23; + goto LABEL_6; + } + RoomCode_GenRandomExplodes_4th(); +} + +void RoomCode_ShakeScreenHorizDiagStrong(void) { // 0x8FE5A4 + int16 v0; + + if (*(uint16 *)room_main_asm_variables) { + if (!-- * (uint16 *)room_main_asm_variables) { + v0 = 21; +LABEL_6: + *(uint16 *)&room_main_asm_variables[2] = v0; + } + } else if (NextRandom() < 0x180u) { + strcpy((char *)room_main_asm_variables, "*"); + v0 = 26; + goto LABEL_6; + } + earthquake_type = *(uint16 *)&room_main_asm_variables[2]; + RoomCode_GenRandomExplodes_4th(); +} + +uint16 CallRoomDefStateSelect(uint32 ea, uint16 k) { + switch (ea) { + case fnRoomDefStateSelect_Finish: return RoomDefStateSelect_Finish(k); + case fnRoomDefStateSelect_TourianBoss01: return RoomDefStateSelect_TourianBoss01(k); + case fnRoomDefStateSelect_IsEventSet: return RoomDefStateSelect_IsEventSet(k); + case fnRoomDefStateSelect_IsBossDead: return RoomDefStateSelect_IsBossDead(k); + case fnRoomDefStateSelect_MorphBallMissiles: return RoomDefStateSelect_MorphBallMissiles(k); + case fnRoomDefStateSelect_PowerBombs: return RoomDefStateSelect_PowerBombs(k); + default: return Unreachable(); + } +} + +void HandleRoomDefStateSelect(uint16 k) { // 0x8FE5D2 + uint16 v1 = k + 11; + do { + event_pointer = get_RoomDefStateSelect_E6E5_Finish(v1)->code_ptr; + v1 = CallRoomDefStateSelect(event_pointer | 0x8F0000, v1 + 2); + } while (v1); +} + +uint16 RoomDefStateSelect_Finish(uint16 k) { // 0x8FE5E6 + roomdefroomstate_ptr = k; + return 0; +} + +uint16 RoomDefStateSelect_Door(uint16 k) { // 0x8FE5EB + uint8 *v1 = RomPtr_8F(k); + if (*(uint16 *)v1 == door_def_ptr) + return RoomDefStateSelect_Finish(*((uint16 *)v1 + 1)); + else + return k + 4; +} + +uint16 RoomDefStateSelect_TourianBoss01(uint16 k) { // 0x8FE5FF + if (!(CheckBossBitForCurArea(1u) & 1)) + return k + 2; + uint16 *v1 = (uint16 *)RomPtr_8F(k); + return RoomDefStateSelect_Finish(*v1); +} + +uint16 RoomDefStateSelect_IsEventSet(uint16 k) { // 0x8FE612 + uint8 *v1 = RomPtr_8F(k); + if (CheckEventHappened(*v1)) + return RoomDefStateSelect_Finish(*(uint16 *)(v1 + 1)); + else + return k + 3; +} + +uint16 RoomDefStateSelect_IsBossDead(uint16 k) { // 0x8FE629 + uint8 *v1 = RomPtr_8F(k); + if (CheckBossBitForCurArea(*v1) & 1) + return RoomDefStateSelect_Finish(*(uint16 *)(v1 + 1)); + else + return k + 3; +} + +uint16 RoomDefStateSelect_MorphBallMissiles(uint16 k) { // 0x8FE652 + if ((collected_items & 4) == 0 || !samus_max_missiles) + return k + 2; + uint16 *v1 = (uint16 *)RomPtr_8F(k); + return RoomDefStateSelect_Finish(*v1); +} + +uint16 RoomDefStateSelect_PowerBombs(uint16 k) { // 0x8FE669 + if (!samus_max_power_bombs) + return k + 2; + uint16 *v1 = (uint16 *)RomPtr_8F(k); + return RoomDefStateSelect_Finish(*v1); +} + +void CallRoomSetupCode(uint32 ea) { + switch (ea) { + case fnRoomSetup_AfterSavingAnimals: RoomSetup_AfterSavingAnimals(); return; + case fnRoomSetup_AutoDestroyWallAfterEscape: RoomSetup_AutoDestroyWallAfterEscape(); return; + case fnRoomSetup_TurnWallIntoShotblocks: RoomSetup_TurnWallIntoShotblocks(); return; + case fnRoomSetup_ShakeDuringEscape: RoomSetup_ShakeDuringEscape(); return; + case fnRoomSetup_ScrollingSkyLand: RoomSetup_ScrollingSkyLand(); return; + case fnRoomSetup_ScrollingSkyOcean: RoomSetup_ScrollingSkyOcean(); return; + case fnRoomSetup_RunStatueUnlockAnims: RoomSetup_RunStatueUnlockAnims(); return; + case fnRoomCode_8FC8C8: RoomCode_8FC8C8(); return; + case fnRoomCode_SetupShaktoolRoomPlm: RoomCode_SetupShaktoolRoomPlm(); return; + case fnRoomCode_SetPauseCodeForDraygon: RoomCode_SetPauseCodeForDraygon(); return; + case fnRoomCode_SetCollectedMap: RoomCode_SetCollectedMap(); return; + case fnnullsub_132: + case fnnullsub_133: + case fnnullsub_134: + case fnnullsub_135: + case fnnullsub_136: + case fnnullsub_137: + case fnnullsub_138: + case fnnullsub_139: + case fnnullsub_140: + case fnnullsub_141: + case fnnullsub_142: + case fnnullsub_143: + case fnnullsub_144: + case fnnullsub_145: + case fnnullsub_146: + case fnnullsub_147: return; + case fnRoomCode_SetZebesTimebombEvent: RoomCode_SetZebesTimebombEvent(); return; + case fnRoomCode_SetLightHorizRoomShake: RoomCode_SetLightHorizRoomShake(); return; + case fnRoomCode_SetMediumHorizRoomShake: RoomCode_SetMediumHorizRoomShake(); return; + case fnRoomCode_Escape4_SetMediumHorizRoomShake: RoomCode_Escape4_SetMediumHorizRoomShake(); return; + case fnRoomCode_SetCeresDoorSolid: RoomCode_SetCeresDoorSolid(); return; + case fnRoomCode_CeresColorMathHdma: RoomCode_CeresColorMathHdma(); return; + case fnRoomCode_CeresColorMathHdma_BgBase: RoomCode_CeresColorMathHdma_BgBase(); return; + default: Unreachable(); + } +} +void RunRoomSetupCode(void) { // 0x8FE88F + RoomDefRoomstate *RoomDefRoomstate; + + RoomDefRoomstate = get_RoomDefRoomstate(roomdefroomstate_ptr); + if (RoomDefRoomstate->room_setup_code) + CallRoomSetupCode(RoomDefRoomstate->room_setup_code | 0x8F0000); +} + +void CallDoorDefSetupCode(uint32 ea) { + switch (ea) { + case fnDoorCode_StartWreckedShipTreadmillWest: DoorCode_StartWreckedShipTreadmillWest(); return; + case fnDoorCode_Scroll6_Green: DoorCode_Scroll6_Green(); return; + case fnDoorCode_Scroll0_Blue: DoorCode_Scroll0_Blue(); return; + case fnDoorCode_Scroll13_Blue: DoorCode_Scroll13_Blue(); return; + case fnDoorCode_Scroll_4Blue_8Green: DoorCode_Scroll_4Blue_8Green(); return; + case fnDoorCode_Scroll_8toB_Red: DoorCode_Scroll_8toB_Red(); return; + case fnDoorCode_Scroll_LotsRed: DoorCode_Scroll_LotsRed(); return; + case fnDoorCode_Scroll_1_4_Green: DoorCode_Scroll_1_4_Green(); return; + case fnDoorCode_Scroll_2_Blue: DoorCode_Scroll_2_Blue(); return; + case fnDoorCode_Scroll_17_Blue: DoorCode_Scroll_17_Blue(); return; + case fnDoorCode_Scroll_4_Blue: DoorCode_Scroll_4_Blue(); return; + case fnDoorCode_Scroll_6_Green: DoorCode_Scroll_6_Green(); return; + case fnDoorCode_Scroll_3_Green: DoorCode_Scroll_3_Green(); return; + case fnDoorCode_SetScroll_0: DoorCode_SetScroll_0(); return; + case fnDoorCode_SetScroll_1: DoorCode_SetScroll_1(); return; + case fnDoorCode_SetScroll_2: DoorCode_SetScroll_2(); return; + case fnDoorCode_SetScroll_3: DoorCode_SetScroll_3(); return; + case fnDoorCode_SetScroll_4: DoorCode_SetScroll_4(); return; + case fnDoorCode_SetScroll_5: DoorCode_SetScroll_5(); return; + case fnDoorCode_SetScroll_6: DoorCode_SetScroll_6(); return; + case fnDoorCode_SetScroll_7: DoorCode_SetScroll_7(); return; + case fnDoorCode_SetScroll_8: DoorCode_SetScroll_8(); return; + case fnDoorCode_SetScroll_9: DoorCode_SetScroll_9(); return; + case fnDoorCode_SetScroll_10: DoorCode_SetScroll_10(); return; + case fnDoorCode_SetScroll_11: DoorCode_SetScroll_11(); return; + case fnDoorCode_SetScroll_12: DoorCode_SetScroll_12(); return; + case fnDoorCode_SetScroll_13: DoorCode_SetScroll_13(); return; + case fnDoorCode_SetScroll_14: DoorCode_SetScroll_14(); return; + case fnDoorCode_SetScroll_15: DoorCode_SetScroll_15(); return; + case fnDoorCode_SetScroll_16: DoorCode_SetScroll_16(); return; + case fnDoorCode_SetScroll_17: DoorCode_SetScroll_17(); return; + case fnDoorCode_SetScroll_18: DoorCode_SetScroll_18(); return; + case fnDoorCode_SetScroll_19: DoorCode_SetScroll_19(); return; + case fnDoorCode_SetScroll_20: DoorCode_SetScroll_20(); return; + case fnDoorCode_SetScroll_21: DoorCode_SetScroll_21(); return; + case fnDoorCode_SetScroll_22: DoorCode_SetScroll_22(); return; + case fnDoorCode_SetScroll_23: DoorCode_SetScroll_23(); return; + case fnDoorCode_SetScroll_24: DoorCode_SetScroll_24(); return; + case fnDoorCode_SetScroll_25: DoorCode_SetScroll_25(); return; + case fnDoorCode_SetScroll_26: DoorCode_SetScroll_26(); return; + case fnDoorCode_SetScroll_28: DoorCode_SetScroll_28(); return; + case fnDoorCode_SetScroll_29: DoorCode_SetScroll_29(); return; + case fnDoorCode_SetScroll_30: DoorCode_SetScroll_30(); return; + case fnDoorCode_SetScroll_31: DoorCode_SetScroll_31(); return; + case fnDoorCode_SetScroll_32: DoorCode_SetScroll_32(); return; + case fnDoorCode_SetScroll_33: DoorCode_SetScroll_33(); return; + case fnDoorCode_SetScroll_34: DoorCode_SetScroll_34(); return; + case fnDoorCode_SetScroll_35: DoorCode_SetScroll_35(); return; + case fnDoorCode_SetScroll_36: DoorCode_SetScroll_36(); return; + case fnDoorCode_SetScroll_37: DoorCode_SetScroll_37(); return; + case fnDoorCode_SetScroll_38: DoorCode_SetScroll_38(); return; + case fnDoorCode_SetScroll_39: DoorCode_SetScroll_39(); return; + case fnDoorCode_SetScroll_40: DoorCode_SetScroll_40(); return; + case fnDoorCode_SetScroll_41: DoorCode_SetScroll_41(); return; + case fnDoorCode_SetScroll_42: DoorCode_SetScroll_42(); return; + case fnDoorCode_SetScroll_43: DoorCode_SetScroll_43(); return; + case fnDoorCode_StartWreckedSkipTreadmill_East: DoorCode_StartWreckedSkipTreadmill_East(); return; + case fnDoorCode_SetScroll_44: DoorCode_SetScroll_44(); return; + case fnDoorCode_SetScroll_45: DoorCode_SetScroll_45(); return; + case fnDoorCode_SetScroll_46: DoorCode_SetScroll_46(); return; + case fnDoorCode_SetScroll_47: DoorCode_SetScroll_47(); return; + case fnDoorCode_SetScroll_48: DoorCode_SetScroll_48(); return; + case fnDoorCode_SetScroll_49: DoorCode_SetScroll_49(); return; + case fnDoorCode_SetupElevatubeFromSouth: DoorCode_SetupElevatubeFromSouth(); return; + case fnDoorCode_SetupElevatubeFromNorth: DoorCode_SetupElevatubeFromNorth(); return; + case fnDoorCode_ResetElevatubeNorthExit: DoorCode_ResetElevatubeNorthExit(); return; + case fnDoorCode_ResetElevatubeSouthExit: DoorCode_ResetElevatubeSouthExit(); return; + case fnDoorCode_SetScroll_50: DoorCode_SetScroll_50(); return; + case fnDoorCode_SetScroll_53: DoorCode_SetScroll_53(); return; + case fnDoorCode_SetScroll_54: DoorCode_SetScroll_54(); return; + case fnDoorCode_SetScroll_55: DoorCode_SetScroll_55(); return; + case fnDoorCode_SetScroll_56: DoorCode_SetScroll_56(); return; + case fnDoorCode_SetScroll_57: DoorCode_SetScroll_57(); return; + case fnDoorCode_SetScroll_58: DoorCode_SetScroll_58(); return; + case fnDoorCode_SetScroll_59: DoorCode_SetScroll_59(); return; + case fnDoorCode_SetScroll_61: DoorCode_SetScroll_61(); return; + case fnDoorCode_SetScroll_62: DoorCode_SetScroll_62(); return; + case fnDoorCode_SetScroll_63: DoorCode_SetScroll_63(); return; + case fnDoorCode_SetScroll_64: DoorCode_SetScroll_64(); return; + case fnDoorCode_SetScroll_65: DoorCode_SetScroll_65(); return; + case fnDoorCode_CeresElevatorShaft: DoorCode_CeresElevatorShaft(); return; + case fnDoorCode_CeresElevatorShaft_2: DoorCode_CeresElevatorShaft_2(); return; + default: Unreachable(); + } +} + +void RunDoorSetupCode(void) { // 0x8FE8A3 + DoorDef *DoorDef; + VoidP door_setup_code; + + DoorDef = get_DoorDef(door_def_ptr); + door_setup_code = DoorDef->door_setup_code; + if (door_setup_code) { + R18_ = DoorDef->door_setup_code; + CallDoorDefSetupCode(door_setup_code | 0x8F0000); + } +} + +void CallRoomCode(uint32 ea) { + switch (ea) { + case fnRoomCode_ScrollingSkyLand_: RoomCode_ScrollingSkyLand_(); return; + case fnRoomCode_ScrollingSkyOcean_: RoomCode_ScrollingSkyOcean_(); return; + case fnRoomCode_ScrollingSkyLand_Shakes: RoomCode_ScrollingSkyLand_Shakes(); return; + case fnRoomCode_ExplodeShakes: RoomCode_ExplodeShakes(); return; + case fnRoomCode_ScrollRightDachora: RoomCode_ScrollRightDachora(); return; + case fnRoomCode_Elevatube: RoomCode_Elevatube(); return; + case fnRoomCode_CeresElevatorShaft_: RoomCode_CeresElevatorShaft_(); return; + case fnnullsub_148: return; + case fnRoomCode_SpawnCeresFallingDebris: RoomCode_SpawnCeresFallingDebris(); return; + case fnRoomCode_HandleCeresRidleyGetaway: RoomCode_HandleCeresRidleyGetaway(); return; + case fnRoomCode_ShakeScreenHorizDiag: RoomCode_ShakeScreenHorizDiag(); return; + case fnRoomCode_GenRandomExplodes_4th_: RoomCode_GenRandomExplodes_4th(); return; + case fnRoomCode_ShakeScreenHorizDiagStrong: RoomCode_ShakeScreenHorizDiagStrong(); return; + case fnRoomCode_CrocomireShaking: RoomCode_CrocomireShaking(); return; + case fnRoomCode_RidleyRoomShaking: RoomCode_RidleyRoomShaking(); return; + default: Unreachable(); + } +} + +void RunRoomMainCode(void) { // 0x8FE8BD + if (room_main_code_ptr) + CallRoomCode(room_main_code_ptr | 0x8F0000); +} + +void RoomCode_CrocomireShaking(void) { // 0x8FE8CD + uint16 ai_var_D; + + if ((enemy_data[0].properties & 0x200) == 0) { + if (enemy_data[0].ai_var_A == 64) { + reg_BG1VOFS = enemy_data[1].ai_var_D + bg1_y_offset + layer1_y_pos; + } else if ((enemy_data[0].ai_var_B & 0x400) != 0) { + if (sign16(--enemy_data[1].ai_var_D + 7)) { + R18_ = 2 * (enemy_data[1].ai_var_D + 7); + ai_var_D = enemy_data[1].ai_var_D - R18_; + } else { + ai_var_D = enemy_data[1].ai_var_D; + } + R18_ = ai_var_D; + reg_BG1VOFS += ai_var_D; + reg_BG2VOFS = ai_var_D - 48; + } else if (enemy_data[0].ai_var_C == 34 && enemy_data[0].ai_var_D) { + --enemy_data[0].ai_var_D; + if ((enemy_data[0].ai_var_D & 1) != 0) + layer1_x_pos -= 4; + else + layer1_x_pos += 4; + } + } +} + +static const int16 kRoomCode_RidleyRoomShaking_X[8] = { 0, 2, 2, 2, 0, -2, -2, -2 }; +static const int16 kRoomCode_RidleyRoomShaking_Y[8] = { -2, -2, 0, 2, 2, 2, 0, -2 }; + +void RoomCode_RidleyRoomShaking(void) { // 0x8FE950 + uint16 ai_var_A = enemy_data[4].ai_var_A; + if (enemy_data[4].ai_var_A) { + --enemy_data[4].ai_var_A; + int v1 = ai_var_A - 1; + reg_BG1HOFS += kRoomCode_RidleyRoomShaking_X[v1]; + reg_BG2HOFS += kRoomCode_RidleyRoomShaking_X[v1]; + reg_BG1VOFS += kRoomCode_RidleyRoomShaking_Y[v1]; + reg_BG2VOFS += kRoomCode_RidleyRoomShaking_Y[v1]; + } +} diff --git a/src/sm_90.c b/src/sm_90.c new file mode 100644 index 0000000..c6379a9 --- /dev/null +++ b/src/sm_90.c @@ -0,0 +1,7719 @@ +// Samus + +#include "ida_types.h" +#include "variables.h" +#include "sm_rtl.h" +#include "funcs.h" + +static const uint16 kUnchargedProjectile_Sfx[12] = { 0xb, 0xd, 0xc, 0xe, 0xf, 0x12, 0x10, 0x11, 0x13, 0x16, 0x14, 0x15 }; +static const uint16 kChargedProjectile_Sfx[12] = { 0x17, 0x19, 0x18, 0x1a, 0x1b, 0x1e, 0x1c, 0x1d, 0x1f, 0x22, 0x20, 0x21 }; +static const uint16 kNonBeamProjectile_Sfx[9] = { 0, 3, 4, 0, 0, 0, 0, 0, 0 }; +static const uint8 kProjectileCooldown_Uncharged[38] = { + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 15, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; +static const uint8 kNonBeamProjectileCooldowns[9] = { 0, 0xa, 0x14, 0x28, 0, 0x10, 0, 0, 0 }; +static const uint8 kBeamAutoFireCooldowns[12] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + +void nullsub_12(void) {} + +static Func_V *const kSamusFxHandlers[8] = { + Samus_Animate_NoFx, + Samus_Animate_LavaFx, + Samus_Animate_AcidFx, + Samus_Animate_WaterFx, + nullsub_12, + nullsub_12, + nullsub_12, + nullsub_12, +}; + +void Samus_Animate(void) { // 0x908000 + Samus_GetTopBottomBoundary(); + kSamusFxHandlers[(uint8)(fx_type & 0xF) >> 1](); + if (samus_pose == kPose_4D_FaceR_Jump_NoAim_NoMove_NoGun || samus_pose == kPose_4E_FaceL_Jump_NoAim_NoMove_NoGun) { + if (samus_y_dir != 2 && samus_anim_frame == 1 && samus_anim_frame_timer == 1) + samus_anim_frame_timer = 4; + bool v1 = (--samus_anim_frame_timer & 0x8000u) != 0; + if (!samus_anim_frame_timer || v1) { + ++samus_anim_frame; + Samus_HandleAnimDelay(); + } + } else { + bool v0 = (--samus_anim_frame_timer & 0x8000u) != 0; + if (!samus_anim_frame_timer || v0) { + ++samus_anim_frame; + Samus_HandleAnimDelay(); + } + } +} + +void Samus_Animate_NoFx(void) { // 0x908078 + samus_anim_frame_buffer = samus_x_speed_divisor; + if (liquid_physics_type) { + if ((liquid_physics_type & 1) != 0) { + liquid_physics_type = 0; + QueueSfx2_Max6(0xEu); + if ((samus_suit_palette_index & 4) == 0 && (samus_movement_type == 3 || samus_movement_type == 20)) + QueueSfx1_Max6(0x30u); + Samus_SpawnWaterSplash(); + } else { + liquid_physics_type = 0; + } + } +} + +void Samus_Animate_WaterFx(void) { // 0x9080B8 + static const uint16 kSamusPhys_AnimDelayInWater = 3; + if ((fx_y_pos & 0x8000u) == 0 && sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + samus_anim_frame_buffer = kSamusPhys_AnimDelayInWater; + if (liquid_physics_type == kLiquidPhysicsType_Water) { + Samus_SpawnAirBubbles(); + } else { + liquid_physics_type = kLiquidPhysicsType_Water; + QueueSfx2_Max6(0xDu); + Samus_SpawnWaterSplash(); + } + } else { + Samus_Animate_NoFx(); + } +} + +void Samus_SpawnWaterSplash(void) { // 0x9080E6 + static const uint8 kWaterSplashTypeTable[28] = { + 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + }; + if (kWaterSplashTypeTable[samus_movement_type]) { + atmospheric_gfx_frame_and_type[0] = 256; + atmospheric_gfx_frame_and_type[1] = 256; + atmospheric_gfx_anim_timer[0] = 3; + atmospheric_gfx_anim_timer[1] = 3; + atmospheric_gfx_x_pos[0] = samus_x_pos + 4; + atmospheric_gfx_x_pos[1] = samus_x_pos - 3; + atmospheric_gfx_y_pos[0] = R18_ - 4; + atmospheric_gfx_y_pos[1] = R18_ - 4; + } else { + atmospheric_gfx_frame_and_type[0] = 768; + atmospheric_gfx_anim_timer[0] = 2; + atmospheric_gfx_x_pos[0] = samus_x_pos; + atmospheric_gfx_y_pos[0] = fx_y_pos; + } + Samus_SpawnAirBubbles(); +} + +void Samus_SpawnAirBubbles(void) { // 0x90813E + uint16 v0; + + if ((int16)(R20_ - 24 - fx_y_pos) >= 0 + && (nmi_frame_counter_word & 0x7F) == 0 + && !atmospheric_gfx_frame_and_type[2]) { + atmospheric_gfx_frame_and_type[2] = 1280; + atmospheric_gfx_anim_timer[2] = 3; + atmospheric_gfx_x_pos[2] = samus_x_pos; + atmospheric_gfx_y_pos[2] = samus_y_pos - samus_y_radius + 6; + if ((NextRandom() & 1) != 0) + v0 = 15; + else + v0 = 17; + QueueSfx2_Max6(v0); + } + if (samus_pose == kPose_00_FaceF_Powersuit + || samus_pose == kPose_9B_FaceF_VariaGravitySuit + || (equipped_items & 0x20) != 0) { + samus_anim_frame_buffer = 0; + } +} + +void Samus_Animate_LavaFx(void) { // 0x9081C0 + static const uint16 kSamusPhys_LavaDamagePerFrame = 0; + static const uint16 kSamusPhys_LavaSubdamagePerFrame = 0x8000; + + + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R18_)) { + if (speed_boost_counter) { + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + } + if ((equipped_items & 0x20) != 0) { + samus_anim_frame_buffer = 0; + liquid_physics_type = 2; + } else { + if ((game_time_frames & 7) == 0 && !sign16(samus_health - 71)) + QueueSfx3_Max3(0x2Du); + uint16 v0 = (__PAIR32__(kSamusPhys_LavaDamagePerFrame, kSamusPhys_LavaSubdamagePerFrame) + + __PAIR32__(samus_periodic_damage, samus_periodic_subdamage)) >> 16; + samus_periodic_subdamage += kSamusPhys_LavaSubdamagePerFrame; + samus_periodic_damage = v0; + Samus_Animate_SubmergedLavaAcid(); + } + } else { + Samus_Animate_NoFx(); + } +} + +void Samus_Animate_AcidFx(void) { // 0x908219 + static const uint16 kSamusPhys_AcidSubdamagePerFrame = 0x8000; + static const uint16 kSamusPhys_AcidDamagePerFrame = 1; + + + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R18_)) { + if ((game_time_frames & 7) == 0 && !sign16(samus_health - 71)) + QueueSfx3_Max3(0x2Du); + uint16 v0 = (__PAIR32__(kSamusPhys_AcidDamagePerFrame, kSamusPhys_AcidSubdamagePerFrame) + + __PAIR32__(samus_periodic_damage, samus_periodic_subdamage)) >> 16; + samus_periodic_subdamage += kSamusPhys_AcidSubdamagePerFrame; + samus_periodic_damage = v0; + Samus_Animate_SubmergedLavaAcid(); + } else { + Samus_Animate_NoFx(); + } +} + +void Samus_Animate_SubmergedLavaAcid(void) { // 0x90824C + static const uint16 kSamusPhys_AnimDelayInAcid = 2; + + samus_anim_frame_buffer = kSamusPhys_AnimDelayInAcid; + liquid_physics_type = 2; + if ((int16)(R20_ - lava_acid_y_pos) < 0 && (atmospheric_gfx_frame_and_type[0] & 0x400) == 0) { + atmospheric_gfx_frame_and_type[0] = 1024; + atmospheric_gfx_frame_and_type[1] = 1024; + atmospheric_gfx_frame_and_type[2] = 1024; + atmospheric_gfx_frame_and_type[3] = 1024; + atmospheric_gfx_anim_timer[0] = 3; + atmospheric_gfx_anim_timer[3] = 3; + atmospheric_gfx_anim_timer[1] = -32766; + atmospheric_gfx_anim_timer[2] = -32766; + atmospheric_gfx_y_pos[0] = lava_acid_y_pos; + atmospheric_gfx_y_pos[1] = lava_acid_y_pos; + atmospheric_gfx_y_pos[2] = lava_acid_y_pos; + atmospheric_gfx_y_pos[3] = lava_acid_y_pos; + atmospheric_gfx_x_pos[0] = samus_x_pos + 6; + atmospheric_gfx_x_pos[1] = samus_x_pos; + *(uint32 *)&atmospheric_gfx_x_pos[2] = __PAIR32__(samus_x_pos - (samus_x_pos >= 0xFFFAu), samus_x_pos) + - ((int)(samus_x_pos >= 0xFFFAu) | 0x60000); + if ((game_time_frames & 1) == 0) + QueueSfx2_Max6(0x10u); + } + if (samus_pose == kPose_00_FaceF_Powersuit + || samus_pose == kPose_9B_FaceF_VariaGravitySuit + || (equipped_items & 0x20) != 0) { + samus_anim_frame_buffer = 0; + } +} + +static Func_Y_Y *const kAnimDelayFuncs[16] = { // 0x9082DC + Samus_AnimDelayFunc_0to5, + Samus_AnimDelayFunc_0to5, + Samus_AnimDelayFunc_0to5, + Samus_AnimDelayFunc_0to5, + Samus_AnimDelayFunc_0to5, + Samus_AnimDelayFunc_0to5, + Samus_AnimDelayFunc_6_GotoStartIfLittleHealth, + Samus_AnimDelayFunc_7, + Samus_AnimDelayFunc_8_AutoJumpHack, + Samus_AnimDelayFunc_9_TransToPose, + UNUSED_Samus_AnimDelayFunc_10, + Samus_AnimDelayFunc_11_SelectDelaySequenceWalljump, + Samus_AnimDelayFunc_12_TransToPose, + Samus_AnimDelayFunc_13_TransToPose, + Samus_AnimDelayFunc_14_Goto, + Samus_AnimDelayFunc_15_GotoStart, +}; + +void Samus_HandleAnimDelay(void) { + int16 v2; + + byte_7E0002 = -111; + uint16 v0 = samus_anim_frame; + R0_.addr = kSamusAnimationDelayData[samus_pose]; + if ((*IndirPtr(&R0_, samus_anim_frame) & 0x80) != 0) { + uint16 v1 = Samus_HandleSpeedBoosterAnimDelay(v0); + if (v1) { + v2 = kAnimDelayFuncs[v1 & 0xF](v0); + if (v2 >= 0) + samus_anim_frame_timer = samus_anim_frame_buffer + *IndirPtr(&R0_, v2); + } + } else { + Samus_HandleNormalAnimDelay(v0); + } +} + +uint16 Samus_AnimDelayFunc_0to5(uint16 j) { // 0x908344 + return -1; +} + +uint16 Samus_AnimDelayFunc_6_GotoStartIfLittleHealth(uint16 j) { // 0x908346 + if (sign16(samus_health - 30)) { + return ++samus_anim_frame; + } else { + samus_anim_frame = 0; + return 0; + } +} + +uint16 Samus_AnimDelayFunc_7(uint16 j) { // 0x908360 + samus_movement_handler = FUNC16(Samus_HandleMovement_DrainedCrouching); + return ++samus_anim_frame; +} + +uint16 Samus_AnimDelayFunc_8_AutoJumpHack(uint16 j) { // 0x908370 + if (samus_input_handler == (uint16)FUNC16(Samus_InputHandler_E91D)) + return Samus_AnimDelayFunc_13_TransToPose(j); + if (samus_new_pose != kPose_4B_FaceR_Jumptrans + && samus_new_pose != kPose_4C_FaceL_Jumptrans + && samus_new_pose != kPose_19_FaceR_SpinJump + && samus_new_pose != kPose_1A_FaceL_SpinJump) { + samus_input_handler = FUNC16(HandleAutoJumpHack); + return Samus_AnimDelayFunc_13_TransToPose(j); + } + return -1; +} + +uint16 Samus_AnimDelayFunc_9_TransToPose(uint16 j) { // 0x90839A + uint16 v1 = j + 1; + R18_ = *(uint16 *)IndirPtr(&R0_, v1); + if ((R18_ & equipped_items) != 0) { + if (samus_y_speed || samus_y_subspeed) + samus_new_pose_transitional = *IndirPtr(&R0_, v1 + 5); + else + samus_new_pose_transitional = *IndirPtr(&R0_, v1 + 4); + } else if (samus_y_speed || samus_y_subspeed) { + samus_new_pose_transitional = *IndirPtr(&R0_, v1 + 3); + } else { + samus_new_pose_transitional = *IndirPtr(&R0_, v1 + 2); + } + samus_hurt_switch_index = 3; + return -1; +} + +uint16 UNUSED_Samus_AnimDelayFunc_10(uint16 j) { // 0x9083F6 + if (samus_y_speed || samus_y_subspeed) + samus_new_pose_transitional = *IndirPtr(&R0_, j + 2); + else + samus_new_pose_transitional = *IndirPtr(&R0_, j + 1); + samus_hurt_switch_index = 3; + return -1; +} + +uint16 Samus_AnimDelayFunc_11_SelectDelaySequenceWalljump(uint16 j) { // 0x90841D + if ((equipped_items & 0x20) == 0) { + Samus_GetTopBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R20_)) + goto LABEL_10; + } else if (sign16(fx_y_pos - R20_) && (fx_liquid_options & 4) == 0) { + goto LABEL_10; + } + } + if ((equipped_items & 8) != 0) { + QueueSfx1_Max6(0x33u); + samus_anim_frame += 21; + return samus_anim_frame; + } else { + if ((equipped_items & 0x200) == 0) { +LABEL_10: + QueueSfx1_Max6(0x31u); + return ++samus_anim_frame; + } + QueueSfx1_Max6(0x3Eu); + samus_anim_frame += 11; + return samus_anim_frame; + } +} + +uint16 Samus_AnimDelayFunc_12_TransToPose(uint16 j) { // 0x90848B + uint16 v1 = j + 1; + R18_ = *(uint16 *)IndirPtr(&R0_, v1); + if ((R18_ & equipped_items) != 0) + samus_new_pose_transitional = *IndirPtr(&R0_, v1 + 3); + else + samus_new_pose_transitional = *IndirPtr(&R0_, v1 + 2); + samus_hurt_switch_index = 3; + return -1; +} + +uint16 Samus_AnimDelayFunc_13_TransToPose(uint16 j) { // 0x9084B6 + samus_new_pose_transitional = *IndirPtr(&R0_, j + 1); + samus_hurt_switch_index = 3; + return -1; +} + +uint16 Samus_AnimDelayFunc_14_Goto(uint16 j) { // 0x9084C7 + R18_ = *IndirPtr(&R0_, j + 1); + samus_anim_frame -= R18_; + return samus_anim_frame; +} + +uint16 Samus_AnimDelayFunc_15_GotoStart(uint16 j) { // 0x9084DB + uint16 result = 0; + samus_anim_frame = 0; + return result; +} + +void Samus_HandleNormalAnimDelay(uint16 j) { // 0x9084E3 + byte_7E0002 = -111; + if (samus_has_momentum_flag && samus_movement_type == 1) { + uint16 *kDefaultAnimFramePtr = (uint16 *)RomPtr(0x91B5D1); + + if ((equipped_items & 0x2000) != 0) + R0_.addr = kSpeedBoostToAnimFramePtr[(uint16)(2 * HIBYTE(speed_boost_counter)) >> 1]; + else + R0_.addr = *kDefaultAnimFramePtr; + } + samus_anim_frame_timer = samus_anim_frame_buffer + *IndirPtr(&R0_, j); +} + + + +uint16 Samus_HandleSpeedBoosterAnimDelay(uint16 j) { // 0x90852C + uint16 *kDefaultAnimFramePtr = (uint16 *)RomPtr(0x91B5D1); + + byte_7E0002 = 0x91; + if (!samus_has_momentum_flag || (button_config_run_b & joypad1_lastkeys) == 0 || samus_movement_type != 1) + return *IndirPtr(&R0_, j); + if ((equipped_items & 0x2000) == 0) { + samus_anim_frame = 0; + R0_.addr = *kDefaultAnimFramePtr; + samus_anim_frame_timer = samus_anim_frame_buffer + *IndirPtr(&R0_, 0); + return 0; + } + if ((uint8)--speed_boost_counter) + return *IndirPtr(&R0_, j); + uint16 v2 = speed_boost_counter; + if ((speed_boost_counter & 0x400) == 0) { + v2 = speed_boost_counter + 256; + speed_boost_counter = v2; + if ((v2 & 0x400) != 0) { + // The original code forgets to preserve A here. + samus_echoes_sound_flag = 1; + QueueSfx3_Max6(3u); + //v2 = 0x103; // bug! + } + } + int v3 = HIBYTE(v2); + speed_boost_counter = kSpeedBoostToCtr[v3] | speed_boost_counter & 0xFF00; + samus_anim_frame = 0; + R0_.addr = kSpeedBoostToAnimFramePtr[v3]; + samus_anim_frame_timer = samus_anim_frame_buffer + *IndirPtr(&R0_, 0); + return 0; +} + +static Func_U8 *const kSamusIsBottomDrawnFuncs[28] = { // 0x9085E2 + SamusBottomDrawn_0_Standing, + SamusBottomDrawn_1, + SamusBottomDrawn_1, + SamusBottomDrawn_3_SpinJump, + SamusBottomDrawn_4, + SamusBottomDrawn_1, + SamusBottomDrawn_1, + SamusBottomDrawn_4, + SamusBottomDrawn_4, + SamusBottomDrawn_4, + SamusBottomDrawn_A_Knockback, + SamusBottomDrawn_1, + SamusBottomDrawn_1, + UNUSED_SamusBottomDrawn_D, + SamusBottomDrawn_1, + SamusBottomDrawn_F_Transitions, + SamusBottomDrawn_1, + SamusBottomDrawn_4, + SamusBottomDrawn_4, + SamusBottomDrawn_4, + SamusBottomDrawn_14_WallJump, + SamusBottomDrawn_1, + SamusBottomDrawn_1, + SamusBottomDrawn_1, + SamusBottomDrawn_1, + SamusBottomDrawn_19_DamageBoost, + SamusBottomDrawn_1, + SamusBottomDrawn_1B, +}; + +void Samus_Draw(void) { + PairU16 v0; + + if (samus_knockback_timer || !samus_invincibility_timer || samus_shine_timer || (nmi_frame_counter_word & 1) == 0) { + uint16 v2 = 2 * samus_pose; + samus_top_half_spritemap_index = samus_anim_frame + + kSamusPoseToBaseSpritemapIndexTop[samus_pose]; + uint16 a = samus_top_half_spritemap_index; + v0 = Samus_CalcSpritemapPos(2 * samus_pose); + DrawSamusSpritemap(a, v0.k, v0.j); + R36 = v2; + if (kSamusIsBottomDrawnFuncs[samus_movement_type]() & 1) { + samus_bottom_half_spritemap_index = samus_anim_frame + kSamusPoseToBaseSpritemapIndexBottom[R36 >> 1]; + DrawSamusSpritemap(samus_bottom_half_spritemap_index, samus_spritemap_x_pos, samus_spritemap_y_pos); + } + } + SetSamusTilesDefsForCurAnim(); +} + +uint8 SamusBottomDrawn_1(void) { // 0x908686 + return 1; +} + +uint8 SamusBottomDrawn_4(void) { // 0x908688 + samus_bottom_half_spritemap_index = 0; + return 0; +} + +uint8 SamusBottomDrawn_0_Standing(void) { // 0x90868D + OamEnt *v1; + + if (samus_pose == kPose_00_FaceF_Powersuit) { + uint16 v0 = oam_next_ptr; + v1 = gOamEnt(oam_next_ptr); + *(uint16 *)&v1->xcoord = samus_x_pos - 7 - layer1_x_pos; + *(uint16 *)&v1->ycoord = samus_y_pos - 17 - layer1_y_pos; + *(uint16 *)&v1->charnum = 14369; + oam_next_ptr = v0 + 4; + } + return 1; +} + +uint8 SamusBottomDrawn_3_SpinJump(void) { // 0x9086C6 + if (samus_pose == kPose_81_FaceR_Screwattack + || samus_pose == kPose_82_FaceL_Screwattack + || samus_pose == kPose_1B_FaceR_SpaceJump + || samus_pose == kPose_1C_FaceL_SpaceJump + || !samus_anim_frame + || !sign16(samus_anim_frame - kPose_0B_MoveR_Gun)) { + return 1; + } + samus_bottom_half_spritemap_index = 0; + return 0; +} + +uint8 SamusBottomDrawn_A_Knockback(void) { // 0x9086EE + if (samus_pose != kPose_D7_FaceR_CrystalFlashEnd && samus_pose != kPose_D8_FaceL_CrystalFlashEnd + || !sign16(samus_anim_frame - 3)) { + return 1; + } + samus_bottom_half_spritemap_index = 0; + return 0; +} + +uint8 SamusBottomDrawn_F_Transitions(void) { // 0x90870C + if (!sign16(samus_pose - kPose_F1_FaceR_CrouchTrans_AimU)) + return 1; + if (!sign16(samus_pose - 219)) { + if (sign16(samus_pose - 221)) { + if (samus_anim_frame) + goto LABEL_8; + } else if (samus_anim_frame != 2) { + goto LABEL_8; + } + return 1; + } + if (samus_pose == kPose_35_FaceR_CrouchTrans + || samus_pose == kPose_36_FaceL_CrouchTrans + || samus_pose == kPose_3B_FaceR_StandTrans + || samus_pose == kPose_3C_FaceL_StandTrans) { + return 1; + } +LABEL_8: + samus_bottom_half_spritemap_index = 0; + return 0; +} + +uint8 UNUSED_SamusBottomDrawn_D(void) { // 0x90874C + if (samus_pose != (kPose_44_FaceL_Turn_Crouch | kPose_01_FaceR_Normal | 0x20) + && samus_pose != (kPose_44_FaceL_Turn_Crouch | kPose_02_FaceL_Normal | 0x20) + || sign16(samus_anim_frame - 1)) { + return 1; + } + samus_bottom_half_spritemap_index = 0; + return 0; +} + +uint8 SamusBottomDrawn_14_WallJump(void) { // 0x908768 + if (sign16(samus_anim_frame - 3) || !sign16(samus_anim_frame - 13)) + return 1; + samus_bottom_half_spritemap_index = 0; + return 0; +} + +uint8 SamusBottomDrawn_19_DamageBoost(void) { // 0x90877C + if (sign16(samus_anim_frame - 2) || !sign16(samus_anim_frame - 9)) + return 1; + samus_bottom_half_spritemap_index = 0; + return 0; +} + +uint8 SamusBottomDrawn_1B(void) { // 0x908790 + if (sign16(samus_pose - kPose_CF_FaceR_Ranintowall_AimUR)) { + if (samus_pose != kPose_CB_FaceR_Shinespark_Vert && samus_pose != kPose_CC_FaceL_Shinespark_Vert) + return 1; + } else if (samus_pose != kPose_E8_FaceR_Drained_CrouchFalling && samus_pose != kPose_E9_FaceL_Drained_CrouchFalling + || !sign16(samus_anim_frame - 2)) { + return 1; + } + samus_bottom_half_spritemap_index = 0; + return 0; +} + +void Samus_DrawEchoes(void) { // 0x9087BD + if ((speed_echoes_index & 0x8000u) == 0) { + if ((speed_boost_counter & 0xFF00) == 1024) { + if (speed_echo_xpos[1]) + Samus_DrawEcho(2u); + if (speed_echo_xpos[0]) + Samus_DrawEcho(0); + } + return; + } + for (int i = 2; i >= 0; i -= 2) { + int v1 = i >> 1; + if (!speed_echo_xpos[v1]) + continue; + uint16 v2 = speed_echo_ypos[v1], v3; + if (v2 != samus_y_pos) { + if ((int16)(v2 - samus_y_pos) < 0) + v3 = v2 + 2; + else + v3 = v2 - 2; + speed_echo_ypos[v1] = v3; + } + if ((speed_echo_xspeed[v1] & 0x8000u) != 0) { + uint16 v5 = speed_echo_xspeed[v1] + speed_echo_xpos[v1]; + speed_echo_xpos[v1] = v5; + if ((int16)(v5 - samus_x_pos) < 0) { + speed_echo_xpos[v1] = 0; + continue; + } + } else { + uint16 v4 = speed_echo_xspeed[v1] + speed_echo_xpos[v1]; + speed_echo_xpos[v1] = v4; + if ((int16)(v4 - samus_x_pos) >= 0) { + speed_echo_xpos[v1] = 0; + continue; + } + } + Samus_DrawEcho(i); + } + if (!speed_echo_xpos[1] && !speed_echo_xpos[0]) + speed_echoes_index = 0; +} + +void Samus_DrawEcho(uint16 j) { // 0x908855 + int16 v2; + + R18_ = *(&kPoseParams[0].y_offset_to_gfx + (uint16)(8 * samus_pose)); + int v1 = j >> 1; + v2 = (__PAIR32__(speed_echo_ypos[v1] - R18_, speed_echo_ypos[v1]) - __PAIR32__(layer1_y_pos, R18_)) >> 16; + if (v2 >= 0 && sign16(v2 - 248)) { + DrawSamusSpritemap(samus_top_half_spritemap_index, speed_echo_xpos[v1] - layer1_x_pos, v2); + if (samus_bottom_half_spritemap_index) { + R18_ = *(&kPoseParams[0].y_offset_to_gfx + (uint16)(8 * samus_pose)); + DrawSamusSpritemap( + samus_bottom_half_spritemap_index, + speed_echo_xpos[j >> 1] - layer1_x_pos, + (__PAIR32__(speed_echo_ypos[j >> 1] - R18_, speed_echo_ypos[j >> 1]) - __PAIR32__(layer1_y_pos, R18_)) >> 16); + } + } +} + +void Samus_DrawShinesparkCrashEchoes(uint16 k) { // 0x9088BA + int16 v2; + + if ((nmi_frame_counter_word & 1) != 0) { + uint16 v4 = 2 * samus_pose; + uint16 a = samus_anim_frame + kSamusPoseToBaseSpritemapIndexTop[samus_pose]; + R18_ = *(&kPoseParams[0].y_offset_to_gfx + (uint16)(8 * samus_pose)); + int v1 = k >> 1; + v2 = speed_echo_ypos[v1] - R18_ - layer1_y_pos; + if (v2 >= 0) { + if (sign16(v2 - 248)) { + DrawSamusSpritemap(a, speed_echo_xpos[v1] - layer1_x_pos, v2); + R36 = v4; + if (kSamusIsBottomDrawnFuncs[samus_movement_type]() & 1) { + uint16 v5 = samus_anim_frame + kSamusPoseToBaseSpritemapIndexBottom[R36 >> 1]; + R18_ = *(&kPoseParams[0].y_offset_to_gfx + (uint16)(4 * R36)); + DrawSamusSpritemap(v5, speed_echo_xpos[k >> 1] - layer1_x_pos, speed_echo_ypos[k >> 1] - R18_ - layer1_y_pos); + } + } + } + } +} + +void Samus_DrawShinesparkCrashEchoProjectiles(void) { // 0x908953 + if ((nmi_frame_counter_word & 1) != 0) { + if (speed_echo_xspeed[3]) + Samus_DrawEcho(6u); + if (speed_echo_xspeed[2]) + Samus_DrawEcho(4u); + } +} + +void Samus_DrawStartingDeathAnim(void) { // 0x908976 + bool v0 = (--samus_anim_frame_timer & 0x8000u) != 0; + if (!samus_anim_frame_timer || v0) { + ++samus_anim_frame; + Samus_HandleAnimDelay(); + } + Samus_DrawDuringDeathAnim(); +} + +void Samus_DrawDuringDeathAnim(void) { // 0x908998 + uint16 v1 = 2 * samus_pose; + uint16 a = samus_anim_frame + kSamusPoseToBaseSpritemapIndexTop[samus_pose]; + Samus_CalcSpritemapPos(2 * samus_pose); + DrawSamusSpritemap(a, layer1_x_pos + samus_spritemap_x_pos, layer1_y_pos + samus_spritemap_y_pos); + R36 = v1; + if (kSamusIsBottomDrawnFuncs[samus_movement_type]() & 1) + DrawSamusSpritemap( + samus_anim_frame + kSamusPoseToBaseSpritemapIndexBottom[R36 >> 1], + layer1_x_pos + samus_spritemap_x_pos, + layer1_y_pos + samus_spritemap_y_pos); + SetSamusTilesDefsForCurAnim(); +} + +void Samus_DrawWhenNotAnimatingOrDying(void) { // 0x908A00 + PairU16 v0; + + uint16 v2 = 2 * samus_pose; + uint16 a = samus_anim_frame + kSamusPoseToBaseSpritemapIndexTop[samus_pose]; + v0 = Samus_CalcSpritemapPos(2 * samus_pose); + DrawSamusSpritemap(a, v0.k, v0.j); + R36 = v2; + if (kSamusIsBottomDrawnFuncs[samus_movement_type]() & 1) + DrawSamusSpritemap( + samus_anim_frame + kSamusPoseToBaseSpritemapIndexBottom[R36 >> 1], + samus_spritemap_x_pos, + samus_spritemap_y_pos); + SetSamusTilesDefsForCurAnim(); +} + +static FuncXY_V *const kAtmosphericTypeFuncs[8] = { // 0x908A4C + 0, + AtmosphericTypeFunc_1_FootstepSplash, + AtmosphericTypeFunc_1_FootstepSplash, + AtmosphericTypeFunc_3_DivingSplash, + AtmosphericTypeFunc_4_LavaSurfaceDmg, + AtmosphericTypeFunc_5_Bubbles, + AtmosphericTypeFunc_67_Dust, + AtmosphericTypeFunc_67_Dust, +}; + +void HandleAtmosphericEffects(void) { + int16 v4; + + for (int i = 6; i >= 0; i -= 2) { + int v1 = i >> 1; + uint16 v2 = atmospheric_gfx_frame_and_type[v1]; + if (!v2) + continue; + R18_ = 2 * (uint8)v2; + uint16 v3 = 2 * HIBYTE(v2); + v4 = atmospheric_gfx_anim_timer[v1] - 1; + atmospheric_gfx_anim_timer[v1] = v4; + if (v4) { + if (v4 < 0) { + if (v4 != (int16)0x8000) + continue; + atmospheric_gfx_anim_timer[v1] = *(uint16 *)RomPtr_90(R18_ + kAtmosphericGraphicAnimationTimers[v3 >> 1]); + } + } else { + atmospheric_gfx_anim_timer[v1] = *(uint16 *)RomPtr_90(R18_ + kAtmosphericGraphicAnimationTimers[v3 >> 1]); + uint16 v5 = atmospheric_gfx_frame_and_type[v1] + 1; + atmospheric_gfx_frame_and_type[v1] = v5; + if ((int16)((uint8)v5 - kAtmosphericTypeNumFrames[v3 >> 1]) >= 0) { + atmospheric_gfx_frame_and_type[v1] = 0; + continue; + } + } + kAtmosphericTypeFuncs[v3 >> 1](v3, i); + } +} + +void AtmosphericTypeFunc_1_FootstepSplash(uint16 k, uint16 j) { // 0x908AC5 + int16 v4; + OamEnt *v5; + int16 v6; + + int v2 = j >> 1; + R18_ = 2 * LOBYTE(atmospheric_gfx_frame_and_type[v2]); + uint16 v3 = oam_next_ptr; + v4 = atmospheric_gfx_x_pos[v2] - layer1_x_pos - 4; + if (v4 >= 0) { + if (sign16(atmospheric_gfx_x_pos[v2] - layer1_x_pos - 260)) { + v5 = gOamEnt(oam_next_ptr); + *(uint16 *)&v5->xcoord = v4; + v6 = atmospheric_gfx_y_pos[v2] - layer1_y_pos - 4; + if (v6 >= 0) { + if (sign16(atmospheric_gfx_y_pos[v2] - layer1_y_pos - 260)) { + *(uint16 *)&v5->ycoord = v6; + *(uint16 *)&v5->charnum = *(uint16 *)RomPtr_90(R18_ + g_off_908BFF[k >> 1]); + oam_next_ptr = v3 + 4; + } + } + } + } +} + +void AtmosphericTypeFunc_Common(uint16 j, uint16 a) { // 0x908B74 + int v1 = j >> 1; + if (((atmospheric_gfx_y_pos[v1] - layer1_y_pos) & 0xFF00) == 0) + DrawSamusSpritemap(a, atmospheric_gfx_x_pos[v1] - layer1_x_pos, atmospheric_gfx_y_pos[v1] - layer1_y_pos); +} + +void AtmosphericTypeFunc_3_DivingSplash(uint16 k, uint16 j) { // 0x908B16 + int v2 = j >> 1; + R18_ = LOBYTE(atmospheric_gfx_frame_and_type[v2]); + atmospheric_gfx_y_pos[v2] = fx_y_pos; + AtmosphericTypeFunc_Common(j, R18_ + 399); +} + +void AtmosphericTypeFunc_4_LavaSurfaceDmg(uint16 k, uint16 j) { // 0x908B2E + int v2 = j >> 1; + uint16 v3; + if ((j & 4) != 0) + v3 = atmospheric_gfx_x_pos[v2] - 1; + else + v3 = atmospheric_gfx_x_pos[v2] + 1; + atmospheric_gfx_x_pos[v2] = v3; + --atmospheric_gfx_y_pos[j >> 1]; + AtmosphericTypeFunc_1_FootstepSplash(k, j); +} + +void AtmosphericTypeFunc_67_Dust(uint16 k, uint16 j) { // 0x908B57 + --atmospheric_gfx_y_pos[j >> 1]; + AtmosphericTypeFunc_1_FootstepSplash(k, j); +} + +void AtmosphericTypeFunc_5_Bubbles(uint16 k, uint16 j) { // 0x908B64 + R18_ = LOBYTE(atmospheric_gfx_frame_and_type[j >> 1]); + AtmosphericTypeFunc_Common(j, R18_ + 390); +} + +static Func_Y_To_PairU16 *const kSamus_CalcSpritemapPos[28] = { // 0x908C1F + &Samus_CalcSpritemapPos_Standing, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Crouch, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Default, + &Samus_CalcSpritemapPos_Special, +}; + +PairU16 Samus_CalcSpritemapPos(uint16 k) { + PairU16 v1; + + if ((ceres_status & 0x8000u) == 0) { + v1 = kSamus_CalcSpritemapPos[samus_movement_type](k); + } else { + grapple_beam_tmpD82 = samus_x_pos; + grapple_beam_tmpD84 = samus_y_pos; + Samus_CalcPos_Mode7(); + v1 = kSamus_CalcSpritemapPos[samus_movement_type](k); + samus_y_pos = grapple_beam_tmpD84; + samus_x_pos = grapple_beam_tmpD82; + } + return MakePairU16(v1.k, v1.j); +} + +PairU16 Samus_CalcSpritemapPos_Default(uint16 j) { // 0x908C94 + uint16 v1 = *(&kPoseParams[0].y_offset_to_gfx + (uint16)(4 * j)); + if ((v1 & 0x80) != 0) + v1 |= 0xFF00u; + R18_ = v1; + samus_spritemap_y_pos = samus_y_pos - v1 - layer1_y_pos; + samus_spritemap_x_pos = samus_x_pos - layer1_x_pos; + return MakePairU16(samus_x_pos - layer1_x_pos, samus_y_pos - v1 - layer1_y_pos); +} + +PairU16 Samus_CalcSpritemapPos_Standing(uint16 j) { // 0x908CC3 + static const uint8 g_byte_908D28[16] = { + 3, 6, 0, 0, + 3, 6, 0, 0, + 3, 3, 6, 0, + 3, 3, 6, 0, + }; + + int16 v1; + PairU16 v3; + + v1 = j >> 1; + if (!(j >> 1) || v1 == kPose_9B_FaceF_VariaGravitySuit) { + if (!sign16(samus_anim_frame - 2)) { + samus_spritemap_y_pos = samus_y_pos - 1 - layer1_y_pos; + samus_spritemap_x_pos = samus_x_pos - layer1_x_pos; + return MakePairU16(samus_x_pos - layer1_x_pos, samus_y_pos - 1 - layer1_y_pos); + } + } else if (!sign16(v1 - kPose_A4_FaceR_LandJump) && sign16(v1 - kPose_A8_FaceR_Grappling)) { + R18_ = *(uint16 *)&g_byte_908D28[(uint16)(samus_anim_frame + 4 * (v1 - 164))]; + samus_spritemap_y_pos = samus_y_pos - R18_ - layer1_y_pos; + samus_spritemap_x_pos = samus_x_pos - layer1_x_pos; + return MakePairU16(samus_x_pos - layer1_x_pos, samus_y_pos - R18_ - layer1_y_pos); + } + v3 = Samus_CalcSpritemapPos_Default(j); + return MakePairU16(v3.k, v3.j); +} + +PairU16 Samus_CalcSpritemapPos_Crouch(uint16 j) { // 0x908D3C + static const int8 byte_908D80[24] = { + -8, 0, -8, 0, + -4, -2, -4, -2, + 0, 0, 0, 0, + -4, 0, -4, 0, + 5, 4, 5, 4, + 0, 0, 0, 0, + }; + + int16 v1; + + v1 = j >> 1; + if (sign16((j >> 1) - kPose_35_FaceR_CrouchTrans) || !sign16(v1 - kPose_41_FaceL_Morphball_Ground)) { + return Samus_CalcSpritemapPos_Default(j); + } else { + uint16 v4 = byte_908D80[(uint16)(samus_anim_frame + 2 * (v1 - 53))]; + if ((v4 & 0x80) != 0) + v4 |= 0xFF00u; + R18_ = v4; + samus_spritemap_y_pos = v4 + samus_y_pos - layer1_y_pos; + samus_spritemap_x_pos = samus_x_pos - layer1_x_pos; + return MakePairU16(samus_x_pos - layer1_x_pos, v4 + samus_y_pos - layer1_y_pos); + } +} + +PairU16 Samus_CalcSpritemapPos_Special(uint16 j) { // 0x908D98 + static const int8 byte_908DEF[32] = { + 7, 5, -8, -8, -8, -8, -8, -5, + 4, 4, 4, 4, 0, 0, 4, -3, + -5, 0, 0, 4, -3, -5, -3, 4, + 0, 0, 4, 0, 0, 4, 0, 0, + }; + int16 v1; + uint16 v2; + + v1 = j >> 1; + if (j >> 1 == kPose_E8_FaceR_Drained_CrouchFalling || v1 == kPose_E9_FaceL_Drained_CrouchFalling) { + v2 = byte_908DEF[samus_anim_frame]; + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + } else { + if (v1 != kPose_EA_FaceR_Drained_Stand && v1 != kPose_EB_FaceL_Drained_Stand || (int16)(samus_anim_frame - 5) < 0) { + return Samus_CalcSpritemapPos_Default(j); + } + v2 = -3; + } + R18_ = v2; + samus_spritemap_y_pos = v2 + samus_y_pos - layer1_y_pos; + samus_spritemap_x_pos = samus_x_pos - layer1_x_pos; + return MakePairU16(samus_x_pos - layer1_x_pos, v2 + samus_y_pos - layer1_y_pos); +} + +static Func_V *const kLiquidPhysicsType[8] = { // 0x908E0F + LiquidPhysicsType_0, + LiquidPhysicsType_24_LavaAcid, + LiquidPhysicsType_24_LavaAcid, + LiquidPhysicsType_6_Water, + LiquidPhysicsType_0, + LiquidPhysicsType_0, + LiquidPhysicsType_0, + LiquidPhysicsType_0, +}; + +void SetLiquidPhysicsType(void) { + Samus_GetTopBottomBoundary(); + kLiquidPhysicsType[(uint8)(fx_type & 0xF) >> 1](); +} + +void LiquidPhysicsType_0(void) { // 0x908E36 + liquid_physics_type = 0; +} + +void LiquidPhysicsType_24_LavaAcid(void) { // 0x908E3A + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R18_)) + liquid_physics_type = kLiquidPhysicsType_LavaAcid; + else + LiquidPhysicsType_0(); +} + +void LiquidPhysicsType_6_Water(void) { // 0x908E4A + if ((fx_y_pos & 0x8000u) == 0 && sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) + liquid_physics_type = kLiquidPhysicsType_Water; + else + LiquidPhysicsType_0(); +} + +void Samus_HandleMovement_X(void) { // 0x908E64 + Samus_HandleExtraRunspeedX(); + Samus_CalcBaseSpeed_X(Samus_DetermineSpeedTableEntryPtr_X()); + Samus_MoveX(); +} + +void Samus_MoveX(void) { // 0x908EA9 + if (!samus_x_accel_mode || samus_x_accel_mode == 2) { + if (samus_pose_x_dir != 4) { +LABEL_6: + Samus_CalcDisplacementMoveRight(); + goto LABEL_8; + } + } else if (samus_pose_x_dir != 8) { + goto LABEL_6; + } + Samus_CalcDisplacementMoveLeft(); +LABEL_8: + if ((R18_ & 0x8000u) != 0) + Samus_MoveLeft(); + else + Samus_MoveRight(); +} + +void Samus_BombJumpRisingXMovement_(void) { + if (knockback_dir) { + Samus_CalcBaseSpeed_X(Samus_DetermineSpeedTableEntryPtr_X()); + if (!knockback_x_dir) + goto LABEL_6; +LABEL_5: + Samus_CalcDisplacementMoveRight(); + goto LABEL_7; + } + Samus_CalcBaseSpeed_X(addr_stru_909F25); + if ((uint8)bomb_jump_dir != 1) + goto LABEL_5; +LABEL_6: + Samus_CalcDisplacementMoveLeft(); +LABEL_7: + if ((R18_ & 0x8000u) != 0) + Samus_MoveLeft(); + else + Samus_MoveRight(); +} + +void Samus_BombJumpRisingYMovement_(void) { + if (samus_y_dir == 1) { + if ((samus_y_speed & 0x8000u) != 0) { + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 2; + if ((uint8)bomb_jump_dir != 2) + samus_x_accel_mode = 2; + } else if (sign16(samus_y_speed - 1)) { + if (samus_input_handler != (uint16)FUNC16(Samus_InputHandler_E91D)) + samus_input_handler = FUNC16(Samus_InputHandler_E913); + } + } +} + +void Samus_BombJumpFallingXMovement_(void) { + Samus_CalcBaseSpeed_X(Samus_DetermineSpeedTableEntryPtr_X()); + if (samus_var62 == 1) + Samus_CalcDisplacementMoveLeft(); + else + Samus_CalcDisplacementMoveRight(); + if ((R18_ & 0x8000u) != 0) + Samus_MoveLeft(); + else + Samus_MoveRight(); +} + +void Samus_BombJumpFallingYMovement_(void) { + if (sign16(samus_y_speed - 5)) { + uint16 v0 = (__PAIR32__(samus_y_accel, samus_y_subaccel) + __PAIR32__(samus_y_speed, samus_y_subspeed)) >> 16; + samus_y_subspeed += samus_y_subaccel; + samus_y_speed = v0; + } + R20_ = samus_y_subspeed; + R18_ = samus_y_speed; + Samus_MoveDown(); +} + +void Samus_JumpingMovement(void) { // 0x908FB3 + Samus_HandleExtraRunspeedX(); + if (samus_pose == kPose_4B_FaceR_Jumptrans + || samus_pose == kPose_4C_FaceL_Jumptrans + || !sign16(samus_pose - kPose_55_FaceR_Jumptrans_AimU) && sign16(samus_pose - kPose_5B)) { + samus_x_accel_mode = 0; + Samus_Move_NoBaseSpeed_X(); + Samus_MoveExtraY(); + return; + } + if (samus_y_dir == 1 && ((button_config_jump_a & joypad1_lastkeys) == 0 || (samus_y_speed & 0x8000u) != 0)) { + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 2; + } + Samus_CalcBaseSpeed_NoDecel_X(Samus_DetermineSpeedTableEntryPtr_X()); + if (samus_movement_type == 20) { + if (!samus_x_accel_mode) + samus_x_accel_mode = 2; + goto LABEL_17; + } + if (samus_x_accel_mode || (joypad1_lastkeys & 0x100) != 0 || (joypad1_lastkeys & 0x200) != 0) { +LABEL_17: + Samus_MoveX(); + goto LABEL_18; + } + R18_ = 0; + R20_ = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_collision_flag = 0; +LABEL_18: + Samus_MoveY_WithSpeedCalc(); +} + +void Samus_SpinJumpMovement(void) { // 0x909040 + static const uint16 g_word_909E9F = 8; + + Samus_HandleExtraRunspeedX(); + if (samus_y_dir == 1 && ((button_config_jump_a & joypad1_lastkeys) == 0 || (samus_y_speed & 0x8000u) != 0)) { + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 2; + } + if (Samus_CalcBaseSpeed_NoDecel_X(Samus_DetermineSpeedTableEntryPtr_X()) & 1 || samus_x_accel_mode == 1) + goto LABEL_12; + if (samus_pose_x_dir == 4) { + if ((joypad1_lastkeys & kButton_Left) != 0) + goto LABEL_12; +LABEL_11: + R18_ = 0; + R20_ = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_collision_flag = 0; + samus_x_accel_mode = 0; + goto LABEL_14; + } + if ((joypad1_lastkeys & kButton_Right) == 0) + goto LABEL_11; +LABEL_12: + if (!samus_x_accel_mode) + samus_x_accel_mode = 2; +LABEL_14: + Samus_MoveX(); + R18_ = g_word_909E9F; + R20_ = 0; + if (!(Samus_WallJumpCheck() & 1)) + Samus_MoveY_WithSpeedCalc(); +} + +void Samus_CheckStartFalling(void) { // 0x9090C4 + if (samus_y_dir == 1 && (samus_y_speed & 0x8000u) != 0) { + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 2; + } +} + +void Samus_MoveY_WithSpeedCalc(void) { // 0x9090E2 + int16 v3; + + R20_ = samus_y_subspeed; + R18_ = samus_y_speed; + if (samus_y_dir == 2) { + if (samus_y_speed != 5) { + uint16 v1 = (__PAIR32__(samus_y_accel, samus_y_subaccel) + __PAIR32__(samus_y_speed, samus_y_subspeed)) >> 16; + samus_y_subspeed += samus_y_subaccel; + samus_y_speed = v1; + } + } else { + uint16 v0 = (__PAIR32__(samus_y_speed, samus_y_subspeed) - __PAIR32__(samus_y_accel, samus_y_subaccel)) >> 16; + samus_y_subspeed -= samus_y_subaccel; + samus_y_speed = v0; + } + if (samus_y_dir != 2) { + R18_ = ~R18_; + bool v2 = R20_ == 0; + R20_ = -R20_; + if (v2) + ++R18_; + } + v3 = (__PAIR32__(R18_, R20_) + __PAIR32__(extra_samus_y_displacement, extra_samus_y_subdisplacement)) >> 16; + R20_ += extra_samus_y_subdisplacement; + R18_ = v3; + if (v3 < 0) + Samus_MoveUp(); + else + Samus_MoveDown(); +} + +void Samus_FallingMovement(void) { // 0x909168 + Samus_HandleExtraRunspeedX(); + Samus_CalcBaseSpeed_NoDecel_X(Samus_DetermineSpeedTableEntryPtr_X()); + if (samus_x_accel_mode || (joypad1_lastkeys & kButton_Right) != 0 || (joypad1_lastkeys & kButton_Left) != 0) { + Samus_MoveX(); + } else { + R18_ = 0; + R20_ = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_collision_flag = 0; + } + Samus_CheckStartFalling(); + Samus_MoveY_WithSpeedCalc(); +} + +void Samus_MorphedFallingMovement(void) { // 0x90919F + Samus_CalcBaseSpeed_NoDecel_X(Samus_DetermineSpeedTableEntryPtr_X()); + if (!samus_x_accel_mode && (joypad1_lastkeys & kButton_Right) == 0 && (joypad1_lastkeys & kButton_Left) == 0) { + R18_ = 0; + R20_ = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_collision_flag = 0; + } + Samus_MoveX(); + Samus_CheckStartFalling(); + Samus_MoveY_WithSpeedCalc(); +} + +void Samus_MorphedBouncingMovement(void) { // 0x9091D1 + Samus_CalcBaseSpeed_NoDecel_X(Samus_DetermineSpeedTableEntryPtr_X()); + if (!samus_x_accel_mode && (joypad1_lastkeys & kButton_Right) == 0 && (joypad1_lastkeys & kButton_Left) == 0) { + R18_ = 0; + R20_ = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_collision_flag = 0; + } + Samus_MoveX(); + if (!knockback_dir) { + if (extra_samus_y_displacement || extra_samus_y_subdisplacement) { + samus_y_dir = 2; + samus_y_subspeed = 0; + samus_y_speed = 0; + R20_ = extra_samus_y_subdisplacement; + R18_ = extra_samus_y_displacement; + if ((extra_samus_y_displacement & 0x8000u) != 0) { + Samus_MoveUp(); + } else { + ++R18_; + Samus_MoveDown(); + } + } else { + Samus_CheckStartFalling(); + Samus_MoveY_WithSpeedCalc(); + } + } +} + +void Samus_Move_NoSpeedCalc_Y(void) { // 0x90923F + if (!extra_samus_y_displacement && !extra_samus_y_subdisplacement) { + if (samus_pos_adjusted_by_slope_flag) { + R20_ = 0; + R18_ = 1; + } else { + R20_ = samus_total_x_subspeed; + R18_ = samus_total_x_speed + 1; + } + goto LABEL_8; + } + R20_ = extra_samus_y_subdisplacement; + R18_ = extra_samus_y_displacement; + if ((extra_samus_y_displacement & 0x8000u) == 0) { + ++R18_; +LABEL_8: + Samus_MoveDown(); + return; + } + Samus_MoveUp(); +} + +void Samus_MoveExtraY(void) { // 0x909288 + if (extra_samus_y_displacement || extra_samus_y_subdisplacement) { + R20_ = extra_samus_y_subdisplacement; + R18_ = extra_samus_y_displacement; + if ((extra_samus_y_displacement & 0x8000u) != 0) { + Samus_MoveUp(); + } else { + ++R18_; + Samus_MoveDown(); + } + } +} + +uint8 Samus_CheckAndMoveY(void) { // 0x9092B8 + if (!samus_y_dir) + return 0; + Samus_CheckStartFalling(); + Samus_MoveY_WithSpeedCalc(); + return 1; +} + +uint8 Samus_MoveY_Simple_(void) { // 0x9092C7 + if (!samus_y_dir) + return 0; + Samus_CheckStartFalling(); + Samus_MoveY_WithSpeedCalc(); + return 1; +} + +void UNUSED_sub_9092D6(void) { // 0x9092D6 + samus_y_pos += R18_; + samus_prev_y_pos = samus_y_pos; +} + +void Samus_Move_NoBaseSpeed_X(void) { // 0x909348 + R18_ = 0; + R20_ = 0; + Samus_MoveX(); +} + +void Samus_MoveLeft(void) { // 0x909350 + R18_ = ~R18_; + bool v0 = R20_ == 0; + R20_ = -R20_; + if (v0) + ++R18_; + samus_collision_flag = Samus_CheckSolidEnemyColl(); + if (samus_collision_flag) { + Samus_ClearXSpeedIfColl(); + Samus_MoveLeft_NoColl(); + Samus_AlignYPosSlope(); + } else { + R18_ = ~R18_; + v0 = R20_ == 0; + R20_ = -R20_; + if (v0) + ++R18_; + Samus_MoveRight_NoSolidColl(); + projectile_init_speed_samus_moved_left_fract = R20_; + projectile_init_speed_samus_moved_left = R18_; + if ((samus_collision_direction & 1) != 0) + samus_collision_flag = 0; + Samus_ClearXSpeedIfColl(); + Samus_AlignYPosSlope(); + } +} + +void Samus_MoveRight(void) { // 0x9093B1 + samus_collision_flag = Samus_CheckSolidEnemyColl(); + if (samus_collision_flag) { + Samus_ClearXSpeedIfColl(); + Samus_MoveRight_NoColl(); + Samus_AlignYPosSlope(); + } else { + Samus_MoveRight_NoSolidColl(); + projectile_init_speed_samus_moved_right_fract = R20_; + projectile_init_speed_samus_moved_right = R18_; + if ((samus_collision_direction & 1) == 0) + samus_collision_flag = 0; + Samus_ClearXSpeedIfColl(); + Samus_AlignYPosSlope(); + } +} + +void Samus_MoveUp(void) { // 0x9093EC + samus_collision_direction = 2; + R18_ = ~R18_; + bool v0 = R20_ == 0; + R20_ = -R20_; + if (v0) + ++R18_; + samus_collision_flag = Samus_CheckSolidEnemyColl(); + if (samus_collision_flag) { + Samus_MoveUp_SetPoseCalcInput(); + Samus_MoveUp_NoColl(); + } else { + R18_ = ~R18_; + v0 = R20_ == 0; + R20_ = -R20_; + if (v0) + ++R18_; + Samus_MoveDown_NoSolidColl(); + projectile_init_speed_samus_moved_up_fract = R20_; + projectile_init_speed_samus_moved_up = R18_; + Samus_MoveUp_SetPoseCalcInput(); + } +} + +void Samus_MoveDown(void) { // 0x909440 + samus_collision_direction = 3; + samus_collision_flag = Samus_CheckSolidEnemyColl(); + if (samus_collision_flag) { + Samus_MoveDown_SetPoseCalcInput(); + Samus_MoveDown_NoColl(); + } else { + Samus_MoveDown_NoSolidColl(); + projectile_init_speed_samus_moved_down_fract = R20_; + projectile_init_speed_samus_moved_down = R18_; + Samus_MoveDown_SetPoseCalcInput(); + } +} + +void Samus_MoveHandler_ReleaseFromGrapple(void) { // 0x90946E + if (samus_y_dir == 1 && (samus_y_speed & 0x8000u) != 0) { + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 2; + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + } + samus_x_accel_mode = 2; + Samus_CalcBaseSpeed_X(Samus_DetermineGrappleSwingSpeed_X()); + if (samus_x_accel_mode || (joypad1_lastkeys & kButton_Right) != 0 || (joypad1_lastkeys & kButton_Left) != 0) { + Samus_MoveX(); + } else { + R18_ = 0; + R20_ = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_collision_flag = 0; + } + Samus_MoveY_WithSpeedCalc(); + if (input_to_pose_calc) + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); +} + +void Samus_HandleMovement_DrainedCrouching(void) { // 0x9094CB + Samus_MoveY_WithSpeedCalc(); + if (samus_collision_flag) { + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + samus_anim_frame_timer = 8; + samus_anim_frame = 7; + samus_y_subspeed = 0; + samus_y_speed = 0; + } +} + +void CallScrollingFinishedHook(uint32 ea) { + switch (ea) { + case fnSamus_ScrollFinishedHook_SporeSpawnFight: Samus_ScrollFinishedHook_SporeSpawnFight(); return; + default: Unreachable(); + } +} + +void MainScrollingRoutine(void) { // 0x9094EC + if (slow_grabble_scrolling_flag) { + if ((samus_x_pos & 0x8000u) != 0) + goto LABEL_14; + uint16 v0; + v0 = samus_x_pos - layer1_x_pos; + if (samus_x_pos < layer1_x_pos) + goto LABEL_7; + if (v0 >= 0xA0u) { + layer1_x_pos += 3; + goto LABEL_8; + } + if (v0 < 0x60u) + LABEL_7: + layer1_x_pos -= 3; +LABEL_8: + if ((samus_y_pos & 0x8000u) == 0) { + uint16 v1 = samus_y_pos - layer1_y_pos; + if (samus_y_pos >= layer1_y_pos) { + if (v1 >= 0x90u) { + layer1_y_pos += 3; + goto LABEL_14; + } + if (v1 >= 0x70u) + goto LABEL_14; + } + layer1_y_pos -= 3; + } +LABEL_14: + HandleAutoscrolling_X(); + HandleAutoscrolling_Y(); + goto LABEL_16; + } + Samus_CalcDistanceMoved_X(); + Samus_HandleScroll_X(); + Samus_CalcDistanceMoved_Y(); + Samus_HandleScroll_Y(); +LABEL_16: + if (scrolling_finished_hook) + CallScrollingFinishedHook(scrolling_finished_hook | 0x900000); + samus_prev_x_pos = samus_x_pos; + samus_prev_x_subpos = samus_x_subpos; + samus_prev_y_pos = samus_y_pos; + samus_prev_y_subpos = samus_y_subpos; +} + +void Samus_ScrollFinishedHook_SporeSpawnFight(void) { // 0x909589 + if (layer1_y_pos <= 0x1D0u) + layer1_y_pos = 464; +} + +void Samus_HandleScroll_X(void) { // 0x9095A0 + static const uint16 kSamus_HandleScroll_X_FaceLeft[4] = { 0xa0, 0x50, 0x20, 0xe0 }; + static const uint16 kSamus_HandleScroll_X_FaceRight[4] = { 0x60, 0x40, 0x20, 0xe0 }; + + + if (samus_prev_x_pos == samus_x_pos) { + HandleAutoscrolling_X(); + return; + } + R18_ = layer1_x_pos; + if (knockback_dir || samus_movement_type == 16 || samus_x_accel_mode == 1) { + if (samus_pose_x_dir == 4) { +LABEL_9: + ideal_layer1_xpos = samus_x_pos - kSamus_HandleScroll_X_FaceRight[camera_distance_index >> 1]; + goto LABEL_11; + } + } else if (samus_pose_x_dir != 4) { + goto LABEL_9; + } + ideal_layer1_xpos = samus_x_pos - kSamus_HandleScroll_X_FaceLeft[camera_distance_index >> 1]; +LABEL_11: + if (ideal_layer1_xpos != layer1_x_pos) { + if ((int16)(ideal_layer1_xpos - layer1_x_pos) < 0) { + uint16 v1 = (__PAIR32__(layer1_x_pos, layer1_x_subpos) - __PAIR32__(absolute_moved_last_frame_x, absolute_moved_last_frame_x_fract)) >> 16; + layer1_x_subpos -= absolute_moved_last_frame_x_fract; + layer1_x_pos = v1; + HandleScrollingWhenTriggeringScrollLeft(); + } else { + uint16 v0 = (__PAIR32__(absolute_moved_last_frame_x, absolute_moved_last_frame_x_fract) + __PAIR32__(layer1_x_pos, layer1_x_subpos)) >> 16; + layer1_x_subpos += absolute_moved_last_frame_x_fract; + layer1_x_pos = v0; + HandleScrollingWhenTriggeringScrollRight(); + } + } +} + +void Samus_HandleScroll_Y(void) { // 0x90964F + if (samus_prev_y_pos == samus_y_pos) { + HandleAutoscrolling_Y(); + } else { + R18_ = layer1_y_pos; + if (samus_y_dir == 1) + ideal_layer1_ypos = samus_y_pos - down_scroller; + else + ideal_layer1_ypos = samus_y_pos - up_scroller; + if (ideal_layer1_ypos != layer1_y_pos) { + if ((int16)(ideal_layer1_ypos - layer1_y_pos) < 0) { + uint16 v1 = (__PAIR32__(layer1_y_pos, layer1_y_subpos) + - __PAIR32__(absolute_moved_last_frame_y, absolute_moved_last_frame_y_fract)) >> 16; + layer1_y_subpos -= absolute_moved_last_frame_y_fract; + layer1_y_pos = v1; + HandleScrollingWhenTriggeringScrollUp(); + } else { + uint16 v0 = (__PAIR32__(absolute_moved_last_frame_y, absolute_moved_last_frame_y_fract) + + __PAIR32__(layer1_y_pos, layer1_y_subpos)) >> 16; + layer1_y_subpos += absolute_moved_last_frame_y_fract; + layer1_y_pos = v0; + HandleScrollingWhenTriggeringScrollDown(); + } + } + } +} + +static const uint16 g_word_909EAD = 1; + +void Samus_CalcDistanceMoved_X(void) { // 0x9096C0 + if ((int16)(samus_x_pos - samus_prev_x_pos) >= 0) { + absolute_moved_last_frame_x_fract = samus_x_subpos - samus_prev_x_subpos; + absolute_moved_last_frame_x = g_word_909EAD + + ((__PAIR32__(samus_x_pos, samus_x_subpos) + - __PAIR32__(samus_prev_x_pos, samus_prev_x_subpos)) >> 16); + } else { + absolute_moved_last_frame_x_fract = samus_prev_x_subpos - samus_x_subpos; + absolute_moved_last_frame_x = g_word_909EAD + + ((__PAIR32__(samus_prev_x_pos, samus_prev_x_subpos) + - __PAIR32__(samus_x_pos, samus_x_subpos)) >> 16); + } +} + +void Samus_CalcDistanceMoved_Y(void) { // 0x9096FF + if ((int16)(samus_y_pos - samus_prev_y_pos) >= 0) { + absolute_moved_last_frame_y_fract = samus_y_subpos - samus_prev_y_subpos; + absolute_moved_last_frame_y = g_word_909EAD + + ((__PAIR32__(samus_y_pos, samus_y_subpos) + - __PAIR32__(samus_prev_y_pos, samus_prev_y_subpos)) >> 16); + } else { + absolute_moved_last_frame_y_fract = samus_prev_y_subpos - samus_y_subpos; + absolute_moved_last_frame_y = g_word_909EAD + + ((__PAIR32__(samus_prev_y_pos, samus_prev_y_subpos) + - __PAIR32__(samus_y_pos, samus_y_subpos)) >> 16); + } +} + +static const uint16 kSamus_HandleExtraRunspeedX_Tab0[3] = { 0, 0, 0 }; +static const uint16 kSamus_HandleExtraRunspeedX_Tab1[3] = { 0x1000, 0x400, 0x400 }; +static const uint16 kSamus_HandleExtraRunspeedX_Tab2[3] = { 7, 4, 4 }; +static const uint16 kSamus_HandleExtraRunspeedX_Tab3[3] = { 0, 0, 0 }; +static const uint16 kSamus_HandleExtraRunspeedX_Tab4[3] = { 2, 1, 0 }; +static const uint16 kSamus_HandleExtraRunspeedX_Tab5[3] = { 0, 0, 0 }; + +void Samus_HandleExtraRunspeedX(void) { // 0x90973E + if ((equipped_items & 0x20) == 0) { + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R18_)) { +LABEL_24: + if (!samus_has_momentum_flag) { + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + } + goto LABEL_26; + } + } else if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + goto LABEL_24; + } + } + if (samus_movement_type != 1 || (button_config_run_b & joypad1_lastkeys) == 0) + goto LABEL_24; + if ((equipped_items & 0x2000) != 0) { + if (!samus_has_momentum_flag) { + samus_has_momentum_flag = 1; + special_samus_palette_timer = 1; + special_samus_palette_frame = 0; + speed_boost_counter = kSpeedBoostToCtr[0]; + } + if ((int16)(samus_x_extra_run_speed - kSamus_HandleExtraRunspeedX_Tab2[0]) >= 0 + && (int16)(samus_x_extra_run_subspeed - kSamus_HandleExtraRunspeedX_Tab3[0]) >= 0) { + samus_x_extra_run_speed = kSamus_HandleExtraRunspeedX_Tab2[0]; + samus_x_extra_run_subspeed = kSamus_HandleExtraRunspeedX_Tab3[0]; + goto LABEL_26; + } + } else { + if (!samus_has_momentum_flag) { + samus_has_momentum_flag = 1; + speed_boost_counter = 0; + } + if ((int16)(samus_x_extra_run_speed - kSamus_HandleExtraRunspeedX_Tab4[0]) >= 0 + && (int16)(samus_x_extra_run_subspeed - kSamus_HandleExtraRunspeedX_Tab5[0]) >= 0) { + samus_x_extra_run_speed = kSamus_HandleExtraRunspeedX_Tab4[0]; + samus_x_extra_run_subspeed = kSamus_HandleExtraRunspeedX_Tab5[0]; + goto LABEL_26; + } + } + bool v0; + v0 = __CFADD__uint16(kSamus_HandleExtraRunspeedX_Tab1[0], samus_x_extra_run_subspeed); + samus_x_extra_run_subspeed += kSamus_HandleExtraRunspeedX_Tab1[0]; + samus_x_extra_run_speed += kSamus_HandleExtraRunspeedX_Tab0[0] + v0; +LABEL_26: + if ((speed_boost_counter & 0xFF00) == 1024) + samus_contact_damage_index = 1; +} + +void Samus_MoveRight_NoColl(void) { // 0x909826 + bool v0 = __CFADD__uint16(R20_, samus_x_subpos); + samus_x_subpos += R20_; + samus_x_pos += R18_ + v0; + projectile_init_speed_samus_moved_right_fract = R20_; + projectile_init_speed_samus_moved_right = R18_; +} + +void Samus_MoveLeft_NoColl(void) { // 0x909842 + uint16 v0 = (__PAIR32__(samus_x_pos, samus_x_subpos) - __PAIR32__(R18_, R20_)) >> 16; + samus_x_subpos -= R20_; + samus_x_pos = v0; + R18_ = ~R18_; + bool v1 = R20_ == 0; + R20_ = -R20_; + if (v1) + ++R18_; + projectile_init_speed_samus_moved_left_fract = R20_; + projectile_init_speed_samus_moved_left = R18_; +} + +void Samus_MoveDown_NoColl(void) { // 0x909871 + bool v0 = __CFADD__uint16(R20_, samus_y_subpos); + samus_y_subpos += R20_; + samus_y_pos += R18_ + v0; + projectile_init_speed_samus_moved_down_fract = R20_; + projectile_init_speed_samus_moved_down = R18_; +} + +void Samus_MoveUp_NoColl(void) { // 0x90988D + uint16 v0 = (__PAIR32__(samus_y_pos, samus_y_subpos) - __PAIR32__(R18_, R20_)) >> 16; + samus_y_subpos -= R20_; + samus_y_pos = v0; + R18_ = ~R18_; + bool v1 = R20_ == 0; + R20_ = -R20_; + if (v1) + ++R18_; + projectile_init_speed_samus_moved_up_fract = R20_; + projectile_init_speed_samus_moved_up = R18_; +} + +void Samus_InitJump(void) { // 0x9098BC + static const uint16 kSamus_InitJump_Speed_Y[3] = { 4, 1, 2 }; + static const uint16 kSamus_InitJump_Subspeed_Y[3] = { 0xe000, 0xc000, 0xc000 }; + static const uint16 kSamus_InitJump_Tab2[3] = { 6, 2, 3 }; + static const uint16 kSamus_InitJump_Tab3[3] = { 0, 0x8000, 0x8000 }; + uint16 v0; + + if ((equipped_items & 0x20) != 0) + goto LABEL_7; + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) == 0) { + if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + v0 = 2; + goto LABEL_11; + } +LABEL_7: + v0 = 0; + goto LABEL_11; + } + if ((lava_acid_y_pos & 0x8000u) != 0 || !sign16(lava_acid_y_pos - R18_)) + goto LABEL_7; + v0 = 4; +LABEL_11:; + int v1 = v0 >> 1; + if ((equipped_items & 0x100) != 0) { + samus_y_subspeed = kSamus_InitJump_Tab3[v1]; + samus_y_speed = kSamus_InitJump_Tab2[v1]; + } else { + samus_y_subspeed = kSamus_InitJump_Subspeed_Y[v1]; + samus_y_speed = kSamus_InitJump_Speed_Y[v1]; + } + if ((equipped_items & 0x2000) != 0) { + R18_ = samus_x_extra_run_speed >> 1; + samus_y_subspeed += samus_x_extra_run_subspeed; + samus_y_speed += samus_x_extra_run_speed >> 1; + } + grapple_walljump_timer = 0; + reached_ceres_elevator_fade_timer = 0; + samus_y_dir = 1; +} + +void Samus_InitWallJump(void) { // 0x909949 + static const uint16 kSamus_InitWallJump_0[3] = { 4, 0, 2 }; + static const uint16 kSamus_InitWallJump_1[3] = { 0xa000, 0x4000, 0xa000 }; + static const uint16 kSamus_InitWallJump_2[3] = { 5, 0, 3 }; + static const uint16 kSamus_InitWallJump_3[3] = { 0x8000, 0x8000, 0x8000 }; + uint16 v0; + + if ((equipped_items & 0x20) != 0) + goto LABEL_7; + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) == 0) { + if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + v0 = 2; + goto LABEL_11; + } +LABEL_7: + v0 = 0; + goto LABEL_11; + } + if ((lava_acid_y_pos & 0x8000u) != 0 || !sign16(lava_acid_y_pos - R18_)) + goto LABEL_7; + v0 = 4; +LABEL_11:; + int v1 = v0 >> 1; + if ((equipped_items & 0x100) != 0) { + samus_y_subspeed = kSamus_InitWallJump_3[v1]; + samus_y_speed = kSamus_InitWallJump_2[v1]; + } else { + samus_y_subspeed = kSamus_InitWallJump_1[v1]; + samus_y_speed = kSamus_InitWallJump_0[v1]; + } + if ((equipped_items & 0x2000) != 0) { + R18_ = samus_x_extra_run_speed >> 1; + samus_y_subspeed += samus_x_extra_run_subspeed; + samus_y_speed += samus_x_extra_run_speed >> 1; + } + grapple_walljump_timer = 0; + reached_ceres_elevator_fade_timer = 0; + samus_y_dir = 1; +} + +static const uint16 kSamus_SetSpeedForKnockback_Y_Speed[3] = { 5, 2, 2 }; +static const uint16 kSamus_SetSpeedForKnockback_Y_Subspeed[3] = { 0, 0, 0 }; + +void Samus_SetSpeedForKnockback_Y(void) { // 0x9099D6 + uint16 v0; + + if ((equipped_items & 0x20) == 0) { + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R18_)) { + v0 = 4; + goto LABEL_11; + } + } else if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + v0 = 2; + goto LABEL_11; + } + } + v0 = 0; +LABEL_11:; + int v1 = v0 >> 1; + samus_y_subspeed = kSamus_SetSpeedForKnockback_Y_Subspeed[v1]; + samus_y_speed = kSamus_SetSpeedForKnockback_Y_Speed[v1]; + grapple_walljump_timer = 0; + reached_ceres_elevator_fade_timer = 0; + samus_y_dir = 1; +} + +void Samus_InitBombJump(void) { // 0x909A2C + static const uint16 kSamus_InitBombJump_Speed[3] = { 2, 0, 0 }; + static const uint16 kSamus_InitBombJump_Subspeed[3] = { 0xc000, 0x1000, 0x1000 }; + uint16 v0; + + if ((equipped_items & 0x20) == 0) { + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R18_)) { + v0 = 4; + goto LABEL_11; + } + } else if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + v0 = 2; + goto LABEL_11; + } + } + v0 = 0; +LABEL_11:; + int v1 = v0 >> 1; + samus_y_subspeed = kSamus_InitBombJump_Subspeed[v1]; + samus_y_speed = kSamus_InitBombJump_Speed[v1]; + grapple_walljump_timer = 0; + reached_ceres_elevator_fade_timer = 0; + samus_y_dir = 1; +} + +void Samus_CalcBaseSpeed_X(uint16 k) { // 0x909A7E + SamusSpeedTableEntry *v1; + SamusSpeedTableEntry *v4; + SamusSpeedTableEntry *v5; + SamusSpeedTableEntry *sste; + SamusSpeedTableEntry *v7; + int16 v8; + + if (samus_x_accel_mode) { + if (samus_x_decel_mult) { + sste = get_SamusSpeedTableEntry(k); + R20_ = Mult8x8(samus_x_decel_mult, HIBYTE(sste->decel_sub)); + R18_ = Mult8x8(samus_x_decel_mult, sste->decel) >> 8; + } else { + v7 = get_SamusSpeedTableEntry(k); + R20_ = v7->decel_sub; + R18_ = v7->decel; + } + v8 = (__PAIR32__(samus_x_base_speed, samus_x_base_subspeed) - __PAIR32__(R18_, R20_)) >> 16; + samus_x_base_subspeed -= R20_; + samus_x_base_speed = v8; + if (v8 < 0) { + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_x_accel_mode = 0; + } + } else { + v1 = get_SamusSpeedTableEntry(k); + bool v2 = __CFADD__uint16(v1->accel_sub, samus_x_base_subspeed); + samus_x_base_subspeed += v1->accel_sub; + uint16 v3 = v1->accel + v2 + samus_x_base_speed; + samus_x_base_speed = v3; + if ((int16)(v3 - v1->max_speed) >= 0) { + if (v3 != v1->max_speed + || (v5 = get_SamusSpeedTableEntry(k), (int16)(samus_x_base_subspeed - v5->max_speed_sub) >= 0) + && samus_x_base_subspeed != v5->max_speed_sub) { + v4 = get_SamusSpeedTableEntry(k); + samus_x_base_speed = v4->max_speed; + samus_x_base_subspeed = v4->max_speed_sub; + } + } + } + R18_ = samus_x_base_speed; + R20_ = samus_x_base_subspeed; +} + +uint8 Samus_CalcBaseSpeed_NoDecel_X(uint16 k) { // 0x909B1F + SamusSpeedTableEntry *v1; + SamusSpeedTableEntry *v4; + SamusSpeedTableEntry *v5; + SamusSpeedTableEntry *sste; + SamusSpeedTableEntry *v7; + int16 v8; + + if ((samus_x_accel_mode & 1) != 0) { + if (samus_x_decel_mult) { + sste = get_SamusSpeedTableEntry(k); + R20_ = Mult8x8(samus_x_decel_mult, HIBYTE(sste->decel_sub)); + R18_ = Mult8x8(samus_x_decel_mult, sste->decel) >> 8; + } else { + v7 = get_SamusSpeedTableEntry(k); + R20_ = v7->decel_sub; + R18_ = v7->decel; + } + v8 = (__PAIR32__(samus_x_base_speed, samus_x_base_subspeed) - __PAIR32__(R18_, R20_)) >> 16; + samus_x_base_subspeed -= R20_; + samus_x_base_speed = v8; + if (v8 < 0) { + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_x_accel_mode = 0; + } + } else { + v1 = get_SamusSpeedTableEntry(k); + bool v2 = __CFADD__uint16(v1->accel_sub, samus_x_base_subspeed); + samus_x_base_subspeed += v1->accel_sub; + uint16 v3 = v1->accel + v2 + samus_x_base_speed; + samus_x_base_speed = v3; + if ((int16)(v3 - v1->max_speed) >= 0) { + if (v3 != v1->max_speed + || (v5 = get_SamusSpeedTableEntry(k), (int16)(samus_x_base_subspeed - v5->max_speed_sub) >= 0) + && samus_x_base_subspeed != v5->max_speed_sub) { + v4 = get_SamusSpeedTableEntry(k); + samus_x_base_speed = v4->max_speed; + samus_x_base_subspeed = v4->max_speed_sub; + R18_ = samus_x_base_speed; + R20_ = samus_x_base_subspeed; + return 1; + } + } + } + R18_ = samus_x_base_speed; + R20_ = samus_x_base_subspeed; + return 0; +} + +uint16 Samus_DetermineSpeedTableEntryPtr_X(void) { // 0x909BD1 + if ((equipped_items & 0x20) == 0) { + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R18_)) + samus_x_speed_table_pointer = addr_kSamusSpeedTable_LavaAcid_X; + } else if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + samus_x_speed_table_pointer = addr_kSamusSpeedTable_Water_X; + } + } + R20_ = samus_movement_type; + return samus_x_speed_table_pointer + 12 * samus_movement_type; +} + +uint16 Samus_DetermineGrappleSwingSpeed_X(void) { // 0x909C21 + if ((equipped_items & 0x20) != 0) + return addr_stru_909F31; + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) == 0) { + if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) + return addr_stru_909F3D; + return addr_stru_909F31; + } + if ((lava_acid_y_pos & 0x8000u) != 0 || !sign16(lava_acid_y_pos - R18_)) + return addr_stru_909F31; + return addr_kSamusSpeedTable_Normal_X; +} + +void Samus_DetermineAccel_Y(void) { // 0x909C5B + static const uint16 g_word_909EA1 = 0x1c00; + static const uint16 g_word_909EA3 = 0x800; + static const uint16 g_word_909EA5 = 0x900; + static const uint16 g_word_909EA7 = 0; + static const uint16 g_word_909EA9 = 0; + static const uint16 g_word_909EAB = 0; + static const uint16 g_word_909EAD = 1; + + if ((equipped_items & 0x20) != 0) + goto LABEL_7; + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) == 0) { + if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + samus_y_subaccel = g_word_909EA3; + samus_y_accel = g_word_909EA9; + return; + } +LABEL_7: + samus_y_subaccel = g_word_909EA1; + samus_y_accel = g_word_909EA7; + return; + } + if ((lava_acid_y_pos & 0x8000u) != 0 || !sign16(lava_acid_y_pos - R18_)) + goto LABEL_7; + samus_y_subaccel = g_word_909EA5; + samus_y_accel = g_word_909EAB; +} + +uint8 Samus_GrappleWallJumpCheck(void) { // 0x909CAC + enemy_index_to_shake = -1; + if (samus_pose_x_dir != 4) { + if (samus_pose_x_dir != 8) + return 0; + samus_collision_direction = 1; + if (!Samus_CheckSolidEnemyColl()) + return WallJumpBlockCollDetect() & 1 && (button_config_jump_a & joypad1_newkeys) != 0; + if ((button_config_jump_a & joypad1_newkeys) == 0) + return 0; + goto LABEL_17; + } + samus_collision_direction = 0; + if (!Samus_CheckSolidEnemyColl()) { + R18_ = ~R18_; + bool v0 = R20_ == 0; + R20_ = -R20_; + if (v0) + ++R18_; + return WallJumpBlockCollDetect() & 1 && (button_config_jump_a & joypad1_newkeys) != 0; + } + if ((button_config_jump_a & joypad1_newkeys) != 0) { +LABEL_17: + enemy_index_to_shake = R22_; + return 1; + } + return 0; +} + +uint8 Samus_WallJumpCheck(void) { // 0x909D35 + if (samus_last_different_pose_movement_type != 3 && samus_last_different_pose_movement_type != 20) + return 0; + if (samus_pose == kPose_81_FaceR_Screwattack || samus_pose == kPose_82_FaceL_Screwattack) { + if (!sign16(samus_anim_frame - 27)) + goto LABEL_22; + goto LABEL_8; + } + if (sign16(samus_anim_frame - 11)) { +LABEL_8: + if ((joypad1_lastkeys & kButton_Left) == 0) { + if ((joypad1_lastkeys & kButton_Right) == 0) + return 0; + samus_collision_direction = 0; + if (!Samus_CheckSolidEnemyColl()) { + R18_ = ~R18_; + bool v1 = R20_ == 0; + R20_ = -R20_; + if (v1) + ++R18_; + if (!(WallJumpBlockCollDetect() & 1)) + return 0; + } + goto LABEL_18; + } + samus_collision_direction = 1; + if (Samus_CheckSolidEnemyColl() || WallJumpBlockCollDetect() & 1) { +LABEL_18: + if (samus_pose == kPose_81_FaceR_Screwattack || samus_pose == kPose_82_FaceL_Screwattack) { + samus_anim_frame_timer = 1; + samus_anim_frame = 26; + } else { + samus_anim_frame_timer = 1; + samus_anim_frame = 10; + } + } + return 0; + } +LABEL_22: + enemy_index_to_shake = -1; + if ((joypad1_lastkeys & kButton_Left) != 0) { + samus_collision_direction = 1; + if (!Samus_CheckSolidEnemyColl()) { + if (!(WallJumpBlockCollDetect() & 1) || (button_config_jump_a & joypad1_newkeys) == 0) + return 0; + goto LABEL_40; + } + if ((button_config_jump_a & joypad1_newkeys) == 0) + return 0; +LABEL_38: + if (sign16(R18_ - 8)) { + input_to_pose_calc = 5; + enemy_index_to_shake = R22_; + return 1; + } + return 0; + } + if ((joypad1_lastkeys & kButton_Right) == 0) + return 0; + samus_collision_direction = 0; + if (Samus_CheckSolidEnemyColl()) { + if ((button_config_jump_a & joypad1_newkeys) == 0) + return 0; + goto LABEL_38; + } + R18_ = ~R18_; + bool v1; + v1 = R20_ == 0; + R20_ = -R20_; + if (v1) + ++R18_; + if (!(WallJumpBlockCollDetect() & 1) || (button_config_jump_a & joypad1_newkeys) == 0) + return 0; +LABEL_40: + if (sign16(R18_ - 8)) { + input_to_pose_calc = 5; + return 1; + } + return 0; +} + +void Samus_Movement_07_Unused(void) { // 0x90A32D + input_to_pose_calc = 0; +} + +static HandlerFunc *const kSamusMovementHandlers[28] = { // 0x90A337 + &Samus_Movement_00_Standing, + &Samus_Movement_01_Running, + &Samus_Movement_02_NormalJumping, + &Samus_Movement_03_SpinJumping, + &Samus_Movement_04_MorphBallOnGround, + &Samus_Movement_05_Crouching, + &Samus_Movement_06_Falling, + &Samus_Movement_07_Unused, + &Samus_Movement_08_MorphBallFalling, + &Samus_Movement_09_Unused, + &Samus_Movement_0A_KnockbackOrCrystalFlashEnding, + &Samus_Movement_0B_Unused, + &Samus_Movement_0C_Unused, + &Samus_Movement_0D_Unused, + &Samus_Movement_0E_TurningAroundOnGround, + &Samus_Movement_0F_CrouchingEtcTransition, + &Samus_Movement_10_Moonwalking, + &Samus_Movement_11_SpringBallOnGround, + &Samus_Movement_12_SpringBallInAir, + &Samus_Movement_13_SpringBallFalling, + &Samus_Movement_14_WallJumping, + &Samus_Movement_15_RanIntoWall, + &Samus_Movement_16_Grappling, + &Samus_Movement_17_TurningAroundJumping, + &Samus_Movement_18_TurningAroundFalling, + &Samus_Movement_19_DamageBoost, + &Samus_Movement_1A_GrabbedByDraygon, + &Samus_Movement_1B_ShinesparkEtc, +}; + +void Samus_MovementHandler_Normal(void) { + if (!time_is_frozen_flag) { + kSamusMovementHandlers[samus_movement_type](); + Samus_UpdateSpeedEchoPos(); + } +} + +void Samus_Movement_00_Standing(void) { // 0x90A383 + if (samus_pose && samus_pose != kPose_9B_FaceF_VariaGravitySuit) { + if ((samus_pose == kPose_01_FaceR_Normal || samus_pose == kPose_02_FaceL_Normal) + && (button_config_shoot_x & joypad1_lastkeys) != 0) { + samus_anim_frame_timer = 16; + samus_anim_frame = 0; + } + Samus_Move_NoBaseSpeed_X(); + Samus_Move_NoSpeedCalc_Y(); + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_x_accel_mode = 0; + } else { + if (elevator_status) { + samus_collision_direction = 2; + R18_ = 1; + R20_ = 0; + Samus_MoveDown_NoSolidColl(); + } + input_to_pose_calc = 0; + } +} + +void Samus_Movement_01_Running(void) { // 0x90A3E5 + static const uint8 kSamusFootstepFrame[10] = { 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }; + Samus_HandleMovement_X(); + Samus_Move_NoSpeedCalc_Y(); + if (samus_anim_frame_timer == 1) { + if (kSamusFootstepFrame[samus_anim_frame]) { + Samus_FootstepGraphics(); + if (!cinematic_function && !boss_id && !samus_shine_timer && (speed_boost_counter & 0x400) == 0) + QueueSfx3_Max6(6u); + } + } +} + +void Samus_Movement_02_NormalJumping(void) { // 0x90A42E + Samus_JumpingMovement(); +} + +void Samus_Movement_03_SpinJumping(void) { // 0x90A436 + static const uint16 kSamusPhys_JumpMinYVelAir = 0x280; + static const uint16 kSamusPhys_JumpMaxYVelAir = 0x500; + static const uint16 kSamusPhys_JumpMinYVelWater = 0x80; + static const uint16 kSamusPhys_JumpMaxYVelWater = 0x500; + static const uint8 kSamusFramesForUnderwaterSfx[13] = { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 }; + if ((samus_suit_palette_index & 4) == 0) { + Samus_GetTopBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R20_)) + goto LABEL_8; + } else if (sign16(fx_y_pos - R20_) && (fx_liquid_options & 4) == 0) { +LABEL_8: + R18_ = 1; + goto LABEL_10; + } + } + R18_ = 0; +LABEL_10: + if (R18_) + goto LABEL_26; + if ((equipped_items & 0x200) != 0) { + if (samus_y_dir != 2) + goto LABEL_24; + if (liquid_physics_type) { + if ((int16)(*(uint16 *)((char *)&samus_y_subspeed + 1) - kSamusPhys_JumpMinYVelWater) < 0 + || (int16)(*(uint16 *)((char *)&samus_y_subspeed + 1) - kSamusPhys_JumpMaxYVelWater) >= 0) { + goto LABEL_24; + } + } else if ((int16)(*(uint16 *)((char *)&samus_y_subspeed + 1) - kSamusPhys_JumpMinYVelAir) < 0 + || (int16)(*(uint16 *)((char *)&samus_y_subspeed + 1) - kSamusPhys_JumpMaxYVelAir) >= 0) { + goto LABEL_24; + } + UNUSED_word_7E0DFA = UNUSED_word_7E0DFA & 0xFF00 | 1; + if ((button_config_jump_a & joypad1_newkeys) != 0) + Samus_InitJump(); +LABEL_24: + if (samus_pose == kPose_81_FaceR_Screwattack || samus_pose == kPose_82_FaceL_Screwattack) + goto LABEL_33; + goto LABEL_26; + } + if (samus_pose == kPose_81_FaceR_Screwattack || samus_pose == kPose_82_FaceL_Screwattack) { +LABEL_33: + samus_contact_damage_index = 3; + goto LABEL_34; + } +LABEL_26: + if (R18_ && samus_anim_frame_timer == 1 && kSamusFramesForUnderwaterSfx[samus_anim_frame]) + QueueSfx1_Max6(0x2Fu); + if (!sign16(flare_counter - 60) && !R18_) + samus_contact_damage_index = 4; +LABEL_34: + Samus_SpinJumpMovement(); +} + +void Samus_Movement_04_MorphBallOnGround(void) { // 0x90A521 + if (!samus_x_accel_mode) { + if (samus_pose_x_dir == 4) { + if (samus_pose == kPose_41_FaceL_Morphball_Ground) + goto LABEL_6; + } else if (samus_pose == kPose_1D_FaceR_Morphball_Ground) { +LABEL_6: + Samus_Move_NoBaseSpeed_X(); + if (!(Samus_CheckAndMoveY() & 1)) { + Samus_Move_NoSpeedCalc_Y(); + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_x_accel_mode = 0; + } + return; + } + } + Samus_HandleMovement_X(); + if (!(Samus_CheckAndMoveY() & 1)) + Samus_Move_NoSpeedCalc_Y(); +} + +void Samus_Movement_05_Crouching(void) { // 0x90A573 + Samus_Move_NoBaseSpeed_X(); + Samus_Move_NoSpeedCalc_Y(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_x_accel_mode = 0; +} + +void Samus_Movement_06_Falling(void) { // 0x90A58D + Samus_FallingMovement(); + if ((samus_pose == kPose_29_FaceR_Fall + || samus_pose == kPose_2A_FaceL_Fall + || samus_pose == kPose_67_FaceR_Fall_Gun + || samus_pose == kPose_68_FaceL_Fall_Gun) + && !sign16(samus_y_speed - 5)) { + if (sign16(samus_anim_frame - 5)) { + samus_anim_frame_timer = 8; + samus_anim_frame = 5; + } + } +} + +void Samus_Movement_08_MorphBallFalling(void) { // 0x90A5CA + if ((joypad1_lastkeys & (kButton_Left | kButton_Right)) == 0 && !samus_x_accel_mode) { + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_x_accel_mode = 0; + } + if (used_for_ball_bounce_on_landing) + Samus_MorphedBouncingMovement(); + else + Samus_MorphedFallingMovement(); +} + +void Samus_Movement_09_Unused(void) { // 0x90A5FB + ; +} + +void Samus_Movement_0A_KnockbackOrCrystalFlashEnding(void) { // 0x90A5FC + input_to_pose_calc = 0; + Samus_Move_NoSpeedCalc_Y(); +} + +void Samus_Movement_0B_Unused(void) { // 0x90A607 + input_to_pose_calc = 0; +} + +void Samus_Movement_0C_Unused(void) { // 0x90A60F + input_to_pose_calc = 0; +} + +void Samus_Movement_0D_Unused(void) { // 0x90A617 + ; +} + +void nullsub_13(void) {} + +static HandlerFunc *const kSamusCrouchingEtcFuncs[12] = { // 0x90A61C + nullsub_13, + nullsub_13, + nullsub_13, + nullsub_13, + SamusCrouchingEtcFunc, + SamusCrouchingEtcFunc, + nullsub_13, + nullsub_13, + nullsub_13, + nullsub_13, + SamusCrouchingEtcFunc, + SamusCrouchingEtcFunc, +}; + +void Samus_Movement_0F_CrouchingEtcTransition(void) { + if (sign16(samus_pose - kPose_F1_FaceR_CrouchTrans_AimU)) { + if (!sign16(samus_pose - kPose_DB)) + goto LABEL_6; + kSamusCrouchingEtcFuncs[samus_pose - 53](); + } + Samus_Move_NoBaseSpeed_X(); + if (!(Samus_MoveY_Simple_() & 1)) + Samus_Move_NoSpeedCalc_Y(); +LABEL_6: + if (input_to_pose_calc == 1025) { + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 0; + used_for_ball_bounce_on_landing = 0; + } + input_to_pose_calc = 0; +} + +void SamusCrouchingEtcFunc(void) { // 0x90A672 + enable_horiz_slope_coll = 3; + UNUSEDword_7E0AA4 = 0; +} + +void Samus_Movement_0E_TurningAroundOnGround(void) { // 0x90A67C + Samus_HandleMovement_X(); + Samus_Move_NoSpeedCalc_Y(); + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + input_to_pose_calc = 0; +} + +void Samus_Movement_10_Moonwalking(void) { // 0x90A694 + Samus_HandleMovement_X(); + Samus_Move_NoSpeedCalc_Y(); +} + +void Samus_Movement_11_SpringBallOnGround(void) { // 0x90A69F + if (!samus_x_accel_mode) { + if (samus_pose_x_dir == 4) { + if (samus_pose == kPose_7A_FaceL_Springball_Ground) + goto LABEL_6; + } else if (samus_pose == kPose_79_FaceR_Springball_Ground) { +LABEL_6: + Samus_Move_NoBaseSpeed_X(); + if (!(Samus_CheckAndMoveY() & 1)) { + Samus_Move_NoSpeedCalc_Y(); + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_x_accel_mode = 0; + } + return; + } + } + Samus_HandleMovement_X(); + if (!(Samus_CheckAndMoveY() & 1)) + Samus_Move_NoSpeedCalc_Y(); +} + +void Samus_Movement_12_SpringBallInAir(void) { // 0x90A6F1 + if (used_for_ball_bounce_on_landing) + Samus_MorphedBouncingMovement(); + else + Samus_JumpingMovement(); +} + +void Samus_Movement_13_SpringBallFalling(void) { // 0x90A703 + if ((joypad1_lastkeys & (kButton_Left | kButton_Right)) == 0 && !samus_x_accel_mode) { + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_x_accel_mode = 0; + } + if (used_for_ball_bounce_on_landing) + Samus_MorphedBouncingMovement(); + else + Samus_MorphedFallingMovement(); +} + +void Samus_Movement_14_WallJumping(void) { // 0x90A734 + if (sign16(samus_anim_frame - 23)) { + if (!sign16(samus_anim_frame - 3) && !sign16(flare_counter - 60)) + samus_contact_damage_index = 4; + } else { + samus_contact_damage_index = 3; + } + Samus_JumpingMovement(); +} + +void Samus_Movement_15_RanIntoWall(void) { // 0x90A75F + Samus_Move_NoBaseSpeed_X(); + Samus_Move_NoSpeedCalc_Y(); + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_x_accel_mode = 0; +} + +void Samus_Movement_16_Grappling(void) { // 0x90A780 + if (input_to_pose_calc != 5) + input_to_pose_calc = 0; +} + +void Samus_Movement_17_TurningAroundJumping(void) { // 0x90A790 + Samus_HandleMovement_X(); + if (!(Samus_CheckAndMoveY() & 1)) + Samus_Move_NoSpeedCalc_Y(); + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + input_to_pose_calc = 0; +} + +void Samus_Movement_18_TurningAroundFalling(void) { // 0x90A7AD + Samus_HandleMovement_X(); + if (!(Samus_CheckAndMoveY() & 1)) + Samus_Move_NoSpeedCalc_Y(); + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + input_to_pose_calc = 0; +} + +void Samus_Movement_19_DamageBoost(void) { // 0x90A7CA + Samus_JumpingMovement(); +} + +void Samus_Movement_1A_GrabbedByDraygon(void) { // 0x90A7D2 + input_to_pose_calc = 0; +} + +void Samus_Movement_1B_ShinesparkEtc(void) { // 0x90A7DA + input_to_pose_calc = 0; +} + +void DisableMinimapAndMarkBossRoomAsExplored(void) { // 0x90A7E2 + debug_disable_minimap = 1; + uint16 v0 = 0; + do { + int v1 = v0 >> 1; + hud_tilemap[v1 + 26] = 11295; + hud_tilemap[v1 + 58] = 11295; + hud_tilemap[v1 + 90] = 11295; + v0 += 2; + } while ((int16)(v0 - 10) < 0); + uint16 v2 = 5; + while (boss_id != g_stru_90A83A[v2].boss_id_) { + if ((--v2 & 0x8000u) != 0) + return; + } + for (int i = g_stru_90A83A[v2].ptrs; ; i += 4) { + uint16 *v4 = (uint16 *)RomPtr_90(i); + if ((*v4 & 0x8000u) != 0) + break; + R18_ = *v4; + R24_ = v4[1]; + MarkMapTileAsExplored(); + } +} + +static const uint8 kShr0x80[8] = { 0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1 }; +static const uint16 kShr0xFc00[8] = { 0xfc00, 0x7e00, 0x3f00, 0x1f80, 0xfc0, 0x7e0, 0x3f0, 0x1f8 }; + +void MarkMapTileAsExplored(void) { // 0x90A8A6 + uint8 v0 = (uint16)(R18_ & 0xFF00) >> 8; + R34 = (room_x_coordinate_on_map + v0) & 0x20; + R18_ = ((uint8)room_x_coordinate_on_map + v0) & 0x1F; + R20_ = (uint8)((room_x_coordinate_on_map + v0) & 0x1F) >> 3; + R22_ = room_y_coordinate_on_map + (uint8)((uint16)(R24_ & 0xFF00) >> 8) + 1; + map_tiles_explored[(uint16)(R20_ + 4 * (R34 + R22_))] |= kShr0x80[((uint8)room_x_coordinate_on_map + v0) & 7]; +} + +void InitializeMiniMapBroken(void) { // 0x90A8EF + R18_ = room_x_coordinate_on_map + (uint8)((uint16)(samus_x_pos & 0xFF00) >> 8); + R20_ = R18_ >> 3; + R22_ = room_y_coordinate_on_map + (uint8)((uint16)(samus_y_pos & 0xFF00) >> 8) + 1; + UpdateMinimapInside(); +} + + +#define kPauseMenuMapData ((uint16*)RomPtr(0x829717)) +void UpdateMinimap(void) { // 0x90A91B + int16 v4; + uint16 v5; + int16 v10; + int16 v11; + + if (!debug_disable_minimap + && (uint16)(samus_x_pos >> 4) < room_width_in_blocks + && (uint16)(samus_y_pos >> 4) < room_height_in_blocks) { + R46 = 0; + uint8 v0 = (uint16)(samus_x_pos & 0xFF00) >> 8; + R34 = (room_x_coordinate_on_map + v0) & 0x20; + R18_ = ((uint8)room_x_coordinate_on_map + v0) & 0x1F; + uint16 v1 = ((uint8)room_x_coordinate_on_map + v0) & 7; + R20_ = (uint8)((room_x_coordinate_on_map + v0) & 0x1F) >> 3; + R22_ = room_y_coordinate_on_map + (uint8)((uint16)(samus_y_pos & 0xFF00) >> 8) + 1; + uint16 v2 = R20_ + 4 * (R34 + R22_); + map_tiles_explored[v2] |= kShr0x80[((uint8)room_x_coordinate_on_map + v0) & 7]; + R32 = v1; + g_word_7E001E = v2; + uint16 v3 = v2 - 4; + v4 = v1 - 2; + if ((int16)(v1 - 2) < 0) { + v4 &= 7u; + --v3; + ++R46; + } + R50 = v3; + bg3_tilemap_offset = 2 * v4; + LOBYTE(v5) = HIBYTE(*(uint16 *)&map_tiles_explored[v3]); + HIBYTE(v5) = *(uint16 *)&map_tiles_explored[v3]; + int v6 = bg3_tilemap_offset >> 1; + R24_ = kShr0xFc00[v6] & v5; + LOBYTE(v5) = HIBYTE(*(uint16 *)&map_tiles_explored[v3 + 4]); + HIBYTE(v5) = *(uint16 *)&map_tiles_explored[v3 + 4]; + R26_ = kShr0xFc00[v6] & v5; + LOBYTE(v5) = HIBYTE(*(uint16 *)&map_tiles_explored[v3 + 8]); + HIBYTE(v5) = *(uint16 *)&map_tiles_explored[v3 + 8]; + R28_ = kShr0xFc00[v6] & v5; + *(uint16 *)((char *)&R10_ + 1) = 130; + *(uint16 *)((char *)&R8_ + 1) = kPauseMenuMapData[area_index]; + *(uint16 *)((char *)&R14_ + 1) = *(uint16 *)((char *)&R8_ + 1); + *(uint16 *)((char *)&R8_ + 1) += v3; + uint8 *v7 = IndirPtr((char *)&R8_ + 1, 0); + LOBYTE(v5) = HIBYTE(*(uint16 *)v7); + HIBYTE(v5) = *(uint16 *)v7; + R38 = v5; + *(uint16 *)((char *)&R8_ + 1) += 4; + uint8 *v8 = IndirPtr((char *)&R8_ + 1, 0); + LOBYTE(v5) = HIBYTE(*(uint16 *)v8); + HIBYTE(v5) = *(uint16 *)v8; + R40 = v5; + *(uint16 *)((char *)&R8_ + 1) += 4; + uint8 *v9 = IndirPtr((char *)&R8_ + 1, 0); + LOBYTE(v5) = HIBYTE(*(uint16 *)v9); + HIBYTE(v5) = *(uint16 *)v9; + R42 = v5; + if ((R50 & 3) == 3) { + v10 = R46 ? bg3_tilemap_offset >> 1 : R32; + if (!sign16(v10 - 6)) { + if (R34) + LOBYTE(R48) = R50 - 124; + else + LOBYTE(R48) = R50 + 125; + AdjustMapBitsForMapPageSpill(); + } + } + v11 = bg3_tilemap_offset >> 1; + for (int i = bg3_tilemap_offset >> 1 == 0; !i; i = v11 == 0) { + R24_ *= 2; + R38 *= 2; + R26_ *= 2; + R40 *= 2; + R28_ *= 2; + R42 *= 2; + --v11; + } + UpdateMinimapInside(); + } +} + +#define kPauseMenuMapTilemaps ((LongPtr*)RomPtr(0x82964a)) +void UpdateMinimapInside(void) { // 0x90AA43 + uint16 v0; + int16 v1; + int16 v5; + int16 v7; + int16 v8; + + LOBYTE(v0) = (uint16)(R34 + R22_) >> 8; + HIBYTE(v0) = R34 + R22_; + remaining_enemy_spritemap_entries = R18_ + (v0 >> 3); + if (R34 && sign16((remaining_enemy_spritemap_entries & 0x1F) - 2)) + v1 = remaining_enemy_spritemap_entries - 1026; + else + v1 = remaining_enemy_spritemap_entries - 34; + uint16 v2 = 2 * v1; + *(uint16 *)&byte_7E0002 = *(uint16 *)((char *)kPauseMenuMapTilemaps + 2 + (uint16)(3 * area_index)); + R3_.bank = *(uint16 *)&byte_7E0002; + R8_ = *(uint16 *)&byte_7E0002; + R0_.addr = *(uint16 *)((char *)kPauseMenuMapTilemaps + (uint16)(3 * area_index)); + R3_.addr = R0_.addr + 64; + R6_ = R0_.addr + 128; + R18_ = 5; + uint16 v3 = 0; + do { + bool v4 = R38 >> 15; + R38 *= 2; + if (!v4 || (v5 = *(uint16 *)IndirPtr(&R0_, v2), !has_area_map)) + v5 = 31; + int v6 = v3 >> 1; + hud_tilemap[v6 + 26] = v5 & 0xC3FF | 0x2C00; + v4 = R24_ >> 15; + R24_ *= 2; + if (v4) + hud_tilemap[v6 + 26] = *(uint16 *)IndirPtr(&R0_, v2) & 0xC3FF | 0x2800; + v4 = R40 >> 15; + R40 *= 2; + if (!v4 || (v7 = *(uint16 *)IndirPtr(&R3_, v2), !has_area_map)) + v7 = 31; + hud_tilemap[v6 + 58] = v7 & 0xC3FF | 0x2C00; + v4 = R26_ >> 15; + R26_ *= 2; + if (v4) { + hud_tilemap[v6 + 58] = *(uint16 *)IndirPtr(&R3_, v2) & 0xC3FF | 0x2800; + if (R18_ == 3 && (hud_tilemap[v6 + 58] & 0x1FF) == 40) + MarkMapTileAboveSamusAsExplored(); + } + v4 = R42 >> 15; + R42 *= 2; + if (!v4 || (v8 = *(uint16 *)IndirPtr(&R6_, v2), !has_area_map)) + v8 = 31; + hud_tilemap[v6 + 90] = v8 & 0xC3FF | 0x2C00; + v4 = R28_ >> 15; + R28_ *= 2; + if (v4) + hud_tilemap[v6 + 90] = *(uint16 *)IndirPtr(&R6_, v2) & 0xC3FF | 0x2800; + v3 += 2; + v2 += 2; + if ((v2 & 0x3F) == 0) + v2 += 1984; + --R18_; + } while (R18_); + if ((nmi_frame_counter_byte & 8) == 0) + hud_tilemap[60] |= 0x1C00u; +} + +void MarkMapTileAboveSamusAsExplored(void) { // 0x90AB5F + *((uint8 *)&music_data_index + g_word_7E001E) |= kShr0x80[R32]; +} + +void AdjustMapBitsForMapPageSpill(void) { // 0x90AB75 + uint16 v0 = (uint8)R48; + *(uint16 *)((char *)&R8_ + 1) = *(uint16 *)((char *)&R14_ + 1) + (uint8)R48; + LOBYTE(R44) = map_tiles_explored[(uint8)R48]; + HIBYTE(R44) = *IndirPtr((char *)&R8_ + 1, 0); + if ((uint8)R34 == 32) { + uint16 v1 = R44; + HIBYTE(R38) = HIBYTE(v1); + HIBYTE(R24_) = v1; + } else { + uint16 v2 = R44; + LOBYTE(R38) = HIBYTE(v2); + LOBYTE(R24_) = v2; + } + LOBYTE(R44) = map_tiles_explored[v0 + 4]; + *(uint16 *)((char *)&R8_ + 1) += 4; + HIBYTE(R44) = *IndirPtr((char *)&R8_ + 1, 0); + if ((uint8)R34 == 32) { + uint16 v3 = R44; + HIBYTE(R40) = HIBYTE(v3); + HIBYTE(R26_) = v3; + } else { + uint16 v4 = R44; + LOBYTE(R40) = HIBYTE(v4); + LOBYTE(R26_) = v4; + } + LOBYTE(R44) = map_tiles_explored[v0 + 8]; + *(uint16 *)((char *)&R8_ + 1) += 4; + HIBYTE(R44) = *IndirPtr((char *)&R8_ + 1, 0); + if ((uint8)R34 == 32) { + uint16 v5 = R44; + HIBYTE(R42) = HIBYTE(v5); + HIBYTE(R28_) = v5; + } else { + uint16 v6 = R44; + LOBYTE(R42) = HIBYTE(v6); + LOBYTE(R28_) = v6; + } +} + +void Samus_HandleCooldown(void) { // 0x90AC1C + if (time_is_frozen_flag) { + cooldown_timer = 32; + } else if (cooldown_timer) { + if ((cooldown_timer & 0x8000u) != 0 || (--cooldown_timer, (cooldown_timer & 0x8000u) != 0)) + cooldown_timer = 0; + } +} + +uint8 Samus_CanFireBeam(void) { // 0x90AC39 + if (!sign16(projectile_counter - 5) || (uint8)cooldown_timer) + return 0; + cooldown_timer = 1; + ++projectile_counter; + return 1; +} + +uint8 Samus_CanFireSuperMissile(void) { // 0x90AC5A + if (hud_item_index != 2) { + if (!sign16(projectile_counter - 5)) + return 0; +LABEL_3: + if (!(uint8)cooldown_timer) { + cooldown_timer = 1; + ++projectile_counter; + return 1; + } + return 0; + } + if (sign16(projectile_counter - 4)) + goto LABEL_3; + return 0; +} + +#define kBeamTilePtrs ((uint16*)RomPtr(0x90c3b1)) +#define kBeamPalettePtrs ((uint16*)RomPtr(0x90c3c9)) + +void UpdateBeamTilesAndPalette(void) { // 0x90AC8D + uint16 v0 = 2 * (equipped_beams & 0xFFF); + uint16 v1 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 256; + v1 += 2; + gVramWriteEntry(v1)->size = kBeamTilePtrs[v0 >> 1]; + v1 += 2; + LOBYTE(gVramWriteEntry(v1++)->size) = -102; + gVramWriteEntry(v1)->size = addr_unk_606300; + vram_write_queue_tail = v1 + 2; + WriteBeamPalette_Y(v0); +} + +void WriteBeamPalette_A(uint16 a) { // 0x90ACC2 + WriteBeamPalette_Y(2 * (a & 0xFFF)); +} + +void WriteBeamPalette_Y(uint16 j) { // 0x90ACCD + *(VoidP *)((char *)&R0_.addr + 1) = -28672; + R0_.addr = kBeamPalettePtrs[j >> 1]; + uint16 v1 = 0; + uint16 v2 = 0; + do { + palette_buffer[(v2 >> 1) + 224] = *(uint16 *)IndirPtr(&R0_, v1); + v2 += 2; + v1 += 2; + } while ((int16)(v1 - 32) < 0); +} + +void LoadProjectilePalette(uint16 a) { // 0x90ACF0 + LoadProjectilePalette_(a); +} + +void LoadProjectilePalette_(uint16 a) { // 0x90ACFC + *(VoidP *)((char *)&R0_.addr + 1) = -28672; + R0_.addr = kBeamPalettePtrs[a & 0xFFF]; + uint16 v1 = 0; + uint16 v2 = 0; + do { + palette_buffer[(v2 >> 1) + 224] = *(uint16 *)IndirPtr(&R0_, v1); + v2 += 2; + v1 += 2; + } while ((int16)(v1 - 32) < 0); +} + +void ResetProjectileData(void) { // 0x90AD22 + uint16 v0 = 0; + do { + int v1 = v0 >> 1; + projectile_timers[v1] = 0; + projectile_x_pos[v1] = 0; + projectile_y_pos[v1] = 0; + projectile_dir[v1] = 0; + projectile_bomb_x_speed[v1] = 0; + projectile_bomb_y_speed[v1] = 0; + projectile_x_radius[v1] = 0; + projectile_y_radius[v1] = 0; + projectile_type[v1] = 0; + projectile_damage[v1] = 0; + projectile_bomb_instruction_ptr[v1] = 0; + projectile_bomb_instruction_timers[v1] = 0; + projectile_variables[v1] = 0; + projectile_spritemap_pointers[v1] = 0; + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_Empty); + v0 += 2; + } while ((int16)(v0 - 20) < 0); + bomb_counter = 0; + cooldown_timer = 0; + projectile_counter = 0; + power_bomb_flag = 0; + if (hud_auto_cancel_flag) { + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + } + speed_echo_xpos[0] = 0; + speed_echo_xpos[1] = 0; + speed_echo_xpos[2] = 0; + speed_echo_xpos[3] = 0; + speed_echo_ypos[0] = 0; + speed_echo_ypos[1] = 0; + speed_echo_ypos[2] = 0; + speed_echo_ypos[3] = 0; + speed_echo_xspeed[0] = 0; + speed_echo_xspeed[1] = 0; + speed_echo_xspeed[2] = 0; + speed_echo_xspeed[3] = 0; + speed_echoes_index = 0; + if (samus_special_super_palette_flags) { + samus_special_super_palette_flags = 0; + Samus_LoadSuitTargetPalette(); + } + if (hyper_beam_flag) + SpawnPalfxObject(addr_stru_8DE1F0); +} + +void ClearProjectile(uint16 k) { // 0x90ADB7 + int v1 = k >> 1; + projectile_x_pos[v1] = 0; + projectile_y_pos[v1] = 0; + projectile_bomb_x_subpos[v1] = 0; + projectile_bomb_y_subpos[v1] = 0; + projectile_dir[v1] = 0; + projectile_bomb_x_speed[v1] = 0; + projectile_bomb_y_speed[v1] = 0; + projectile_x_radius[v1] = 0; + projectile_y_radius[v1] = 0; + projectile_type[v1] = 0; + projectile_damage[v1] = 0; + projectile_bomb_instruction_ptr[v1] = 0; + projectile_bomb_instruction_timers[v1] = 0; + projectile_variables[v1] = 0; + projectile_spritemap_pointers[v1] = 0; + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_Empty); + if ((int16)(k - 10) >= 0) { + if ((--bomb_counter & 0x8000u) != 0) + bomb_counter = 0; + } else if ((--projectile_counter & 0x8000u) != 0) { + projectile_counter = 0; + } +} + +static Func_Y_V *const kKillProjectileFuncs[10] = { // 0x90AE06 + KillProjectileFunc_0, + KillProjectileFunc_1, + KillProjectileFunc_2, + KillProjectileFunc_3, + KillProjectileFunc_4, + KillProjectileFunc_4, + KillProjectileFunc_6, + KillProjectileFunc_7, + KillProjectileFunc_8, + KillProjectileFunc_0, +}; + +void KillProjectile(uint16 k) { + + int v1 = k >> 1; + if ((projectile_type[v1] & 0xF00) != 0) { + if (!sign16((HIBYTE(projectile_type[v1]) & 0xF) - 3)) { + ClearProjectile(k); + return; + } + } else { + kKillProjectileFuncs[projectile_dir[v1] & 0xF](k); + } + KillProjectileInner(k); + projectile_bomb_pre_instructions[k >> 1] = FUNC16(ProjPreInstr_Empty); +} + +void KillProjectileFunc_0(uint16 j) { // 0x90AE4E + projectile_y_pos[j >> 1] -= projectile_y_radius[j >> 1]; +} + +void KillProjectileFunc_1(uint16 j) { // 0x90AE59 + int v1 = j >> 1; + projectile_x_pos[v1] += projectile_x_radius[v1]; + projectile_y_pos[v1] -= projectile_y_radius[v1]; +} + +void KillProjectileFunc_2(uint16 j) { // 0x90AE6E + projectile_x_pos[j >> 1] += projectile_x_radius[j >> 1]; +} + +void KillProjectileFunc_3(uint16 j) { // 0x90AE79 + int v1 = j >> 1; + projectile_x_pos[v1] += projectile_x_radius[v1]; + projectile_y_pos[v1] += projectile_y_radius[v1]; +} + +void KillProjectileFunc_4(uint16 j) { // 0x90AE8E + projectile_y_pos[j >> 1] += projectile_y_radius[j >> 1]; +} + +void KillProjectileFunc_6(uint16 j) { // 0x90AE99 + int v1 = j >> 1; + projectile_x_pos[v1] -= projectile_x_radius[v1]; + projectile_y_pos[v1] += projectile_y_radius[v1]; +} + +void KillProjectileFunc_7(uint16 j) { // 0x90AEAE + projectile_x_pos[j >> 1] -= projectile_x_radius[j >> 1]; +} + +void KillProjectileFunc_8(uint16 j) { // 0x90AEB9 + int v1 = j >> 1; + projectile_x_pos[v1] -= projectile_x_radius[v1]; + projectile_y_pos[v1] -= projectile_y_radius[v1]; +} + +void CallProjPreInstr(uint32 ea, uint16 k) { + switch (ea) { + case fnProjPreInstr_Empty: return; + case fnProjPreInstr_Beam_NoWaveBeam: ProjPreInstr_Beam_NoWaveBeam(k); return; + case fnProjPreInstr_Dir0459: ProjPreInstr_Dir0459(k); return; + case fnProjPreInstr_Dir1368: ProjPreInstr_Dir1368(k); return; + case fnProjPreInstr_Dir27: ProjPreInstr_Dir27(k); return; + case fnProjPreInstr_Missile: ProjPreInstr_Missile(k); return; + case fnProjPreInstr_Missile_Func0459: ProjPreInstr_Missile_Func0459(k); return; + case fnProjPreInstr_Missile_Func1368: ProjPreInstr_Missile_Func1368(k); return; + case fnProjPreInstr_Missile_Func27: ProjPreInstr_Missile_Func27(k); return; + case fnProjPreInstr_SuperMissile: ProjPreInstr_SuperMissile(k); return; + case fnProjPreInstr_SuperMissile_Func0459: ProjPreInstr_SuperMissile_Func0459(k); return; + case fnProjPreInstr_SuperMissile_Func1368: ProjPreInstr_SuperMissile_Func1368(k); return; + case fnProjPreInstr_SuperMissile_Func27: ProjPreInstr_SuperMissile_Func27(k); return; + case fnProjPreInstr_Func1: ProjPreInstr_Func1(k); return; + case fnProjPreInstr_Bomb: ProjPreInstr_Bomb(k); return; + case fnProjPreInstr_PowerBomb: ProjPreInstr_PowerBomb(k); return; + case fnProjPreInstr_WavePlasmaEtc: ProjPreInstr_WavePlasmaEtc(k); return; + case fnProjPreInstr_BeamOrIceWave: ProjPreInstr_BeamOrIceWave(k); return; + case fnProjPreInstr_Wave_Shared: ProjPreInstr_Wave_Shared(k); return; + case fnProjPreInstr_WavePlasmaEtc_0459: ProjPreInstr_WavePlasmaEtc_0459(k); return; + case fnProjPreInstr_WavePlasmaEtc_1368: ProjPreInstr_WavePlasmaEtc_1368(k); return; + case fnProjPreInstr_WavePlasmaEtc_27: ProjPreInstr_WavePlasmaEtc_27(k); return; + case fnProjPreInstr_HyperBeam: ProjPreInstr_HyperBeam(k); return; + case fnProjPreInstr_IceSba: ProjPreInstr_IceSba(k); return; + case fnProjPreInstr_IceSba2: ProjPreInstr_IceSba2(k); return; + case fnProjPreInstr_SpeedEcho: ProjPreInstr_SpeedEcho(k); return; + case fnProjPreInstr_PlasmaSba: ProjPreInstr_PlasmaSba(k); return; + case fnProjPreInstr_PlasmaSbaFunc_0: ProjPreInstr_PlasmaSbaFunc_0(k); return; + case fnProjPreInstr_PlasmaSbaFunc_1: ProjPreInstr_PlasmaSbaFunc_1(k); return; + case fnProjPreInstr_PlasmaSbaFunc_2: ProjPreInstr_PlasmaSbaFunc_2(k); return; + case fnProjPreInstr_SpreadBomb: ProjPreInstr_SpreadBomb(k); return; + case fnProjPreInstr_WaveSba: ProjPreInstr_WaveSba(k); return; + case fnProjPreInstr_SpazerSba: ProjPreInstr_SpazerSba(k); return; + case fnProjPreInstr_SpazerSba_FuncA_0: ProjPreInstr_SpazerSba_FuncA_0(k); return; + case fnProjPreInstr_SpazerSba_FuncA_1: ProjPreInstr_SpazerSba_FuncA_1(k); return; + case fnProjPreInstr_SpazerSba_FuncA_2: ProjPreInstr_SpazerSba_FuncA_2(k); return; + case fnProjPreInstr_SpazerSba_FuncA_3: ProjPreInstr_SpazerSba_FuncA_3(k); return; + case fnProjPreInstr_SpazerSba_FuncB_0: ProjPreInstr_SpazerSba_FuncB_0(k); return; + case fnProjPreInstr_SpazerSba_FuncB_1: ProjPreInstr_SpazerSba_FuncB_1(k); return; + case fnProjPreInstr_SpazerSba_FuncB_2: ProjPreInstr_SpazerSba_FuncB_2(k); return; + case fnProjPreInstr_EndOfSpazerSba: ProjPreInstr_EndOfSpazerSba(k); return; + case fnProjPreInstr_UnknownProj8027: ProjPreInstr_UnknownProj8027(k); return; + default: Unreachable(); + } +} + +void HandleProjectile(void) { // 0x90AECE + projectile_index = 18; + for (int i = 18; i >= 0; projectile_index = i) { + int v1 = i >> 1; + if (projectile_bomb_instruction_ptr[v1]) { + CallProjPreInstr(projectile_bomb_pre_instructions[v1] | 0x900000, i); + RunProjectileInstructions(); + i = projectile_index; + } + i -= 2; + } + temp_collision_DD2 = 0; +} + +static const int16 kDirToVelMult16_X[10] = { 0, 16, 16, 16, 0, 0, -16, -16, -16, 0 }; +static const int16 kDirToVelMult16_Y[10] = { -16, -16, 0, 16, 16, 16, 16, 0, -16, -16 }; + +static Func_Y_V *const kProjPreInstr_Beam_Funcs[10] = { // 0x90AEF3 + ProjPreInstr_Dir0459, + ProjPreInstr_Dir1368, + ProjPreInstr_Dir27, + ProjPreInstr_Dir1368, + ProjPreInstr_Dir0459, + ProjPreInstr_Dir0459, + ProjPreInstr_Dir1368, + ProjPreInstr_Dir27, + ProjPreInstr_Dir1368, + ProjPreInstr_Dir0459, +}; + +void ProjPreInstr_Beam_NoWaveBeam(uint16 k) { + + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) { + ClearProjectile(k); + } else { + if (projectile_timers[v1]-- == 1) { + projectile_timers[v1] = 4; + SpawnProjectileTrail(k); + k = projectile_index; + } + int v3 = k >> 1; + uint16 v4 = 2 * (projectile_dir[v3] & 0xF); + int v5 = v4 >> 1; + projectile_bomb_x_speed[v3] += kDirToVelMult16_X[v5]; + projectile_bomb_y_speed[v3] += kDirToVelMult16_Y[v5]; + kProjPreInstr_Beam_Funcs[v5](v4); + DeleteProjectileIfFarOffScreen(); + } +} + +void ProjPreInstr_Dir0459(uint16 k) { // 0x90AF4A + BlockCollNoWaveBeamVert(projectile_index); +} + +void ProjPreInstr_Dir1368(uint16 k) { // 0x90AF52 + uint16 v1 = projectile_index; + if (!(BlockCollNoWaveBeamHoriz(projectile_index) & 1)) + BlockCollNoWaveBeamVert(v1); +} + +void ProjPreInstr_Dir27(uint16 k) { // 0x90AF60 + BlockCollNoWaveBeamHoriz(projectile_index); +} + +static Func_Y_V *const kProjPreInstr_Missile_Funcs[10] = { // 0x90AF68 + ProjPreInstr_Missile_Func0459, + ProjPreInstr_Missile_Func1368, + ProjPreInstr_Missile_Func27, + ProjPreInstr_Missile_Func1368, + ProjPreInstr_Missile_Func0459, + ProjPreInstr_Missile_Func0459, + ProjPreInstr_Missile_Func1368, + ProjPreInstr_Missile_Func27, + ProjPreInstr_Missile_Func1368, + ProjPreInstr_Missile_Func0459, +}; + +void ProjPreInstr_Missile(uint16 k) { + + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) { + ClearProjectile(k); + } else { + if (projectile_timers[v1]-- == 1) { + projectile_timers[v1] = 4; + SpawnProjectileTrail(k); + k = projectile_index; + } + int v3 = k >> 1; + uint16 v4 = 2 * (projectile_dir[v3] & 0xF); + int v5 = v4 >> 1; + projectile_bomb_x_speed[v3] += kDirToVelMult16_X[v5]; + projectile_bomb_y_speed[v3] += kDirToVelMult16_Y[v5]; + Missile_Func1(k); + kProjPreInstr_Missile_Funcs[v4 >> 1](v4); + DeleteProjectileIfFarOffScreen(); + } +} + +void ProjPreInstr_Missile_Func0459(uint16 k) { // 0x90AFC7 + BlockCollMissileVert(projectile_index); +} + +void ProjPreInstr_Missile_Func1368(uint16 k) { // 0x90AFCF + uint16 v1 = projectile_index; + if (!(BlockCollMissileHoriz(projectile_index) & 1)) + BlockCollMissileVert(v1); +} + +void ProjPreInstr_Missile_Func27(uint16 k) { // 0x90AFDD + BlockCollMissileHoriz(projectile_index); +} + +static Func_Y_V *const kProjPreInstr_SuperMissile_Funcs[10] = { // 0x90AFE5 + ProjPreInstr_SuperMissile_Func0459, + ProjPreInstr_SuperMissile_Func1368, + ProjPreInstr_SuperMissile_Func27, + ProjPreInstr_SuperMissile_Func1368, + ProjPreInstr_SuperMissile_Func0459, + ProjPreInstr_SuperMissile_Func0459, + ProjPreInstr_SuperMissile_Func1368, + ProjPreInstr_SuperMissile_Func27, + ProjPreInstr_SuperMissile_Func1368, + ProjPreInstr_SuperMissile_Func0459, +}; + +void ProjPreInstr_SuperMissile(uint16 k) { + int16 v3; + + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) { + ClearProjectile(k); +LABEL_7: + for (int i = 8; i >= 0; i -= 2) { + if ((projectile_type[i >> 1] & 0xFFF) == 512) + ClearProjectile(i); + } + return; + } + if (projectile_timers[v1]-- == 1) { + projectile_timers[v1] = 2; + SpawnProjectileTrail(k); + k = projectile_index; + } + v3 = projectile_dir[k >> 1] & 0xF; + Missile_Func1(k); + kProjPreInstr_SuperMissile_Funcs[v3](v3); + if (DeleteProjectileIfFarOffScreen() & 1) + goto LABEL_7; +} + +void ProjPreInstr_SuperMissile_Func0459(uint16 k) { // 0x90B047 + BlockCollMissileVert(projectile_index); + SuperMissileBlockCollDetect_Y(); +} + +void ProjPreInstr_SuperMissile_Func1368(uint16 k) { // 0x90B052 + uint16 v1 = projectile_index; + if (BlockCollMissileHoriz(projectile_index) & 1) { + SuperMissileBlockCollDetect_X(); + } else { + SuperMissileBlockCollDetect_X(); + BlockCollMissileVert(v1); + SuperMissileBlockCollDetect_Y(); + } +} + +void ProjPreInstr_SuperMissile_Func27(uint16 k) { // 0x90B06A + BlockCollMissileHoriz(projectile_index); + SuperMissileBlockCollDetect_X(); +} + +void ProjPreInstr_Func1(uint16 k) { // 0x90B075 + if ((projectile_dir[k >> 1] & 0xF0) != 0) { + ClearProjectile(k); + for (int i = 8; i >= 0; i -= 2) { + if ((projectile_type[i >> 1] & 0xFFF) == 512) + ClearProjectile(i); + } + } +} + +void ProjPreInstr_Bomb(uint16 k) { // 0x90B099 + if ((projectile_dir[k >> 1] & 0xF0) != 0) { + ClearProjectile(k); + } else { + Bomb_Func2(); + BombOrPowerBomb_Func1(k); + } +} + +void ProjPreInstr_PowerBomb(uint16 k) { // 0x90B0AE + if ((projectile_dir[k >> 1] & 0xF0) != 0) { + ClearProjectile(k); + } else { + PowerBomb_Func3(); + BombOrPowerBomb_Func1(k); + } +} + +void ProjPreInstr_WavePlasmaEtc(uint16 k) { // 0x90B0C3 + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) { + ClearProjectile(k); + } else if (projectile_timers[v1]-- == 1) { + projectile_timers[v1] = 4; + SpawnProjectileTrail(k); + ProjPreInstr_Wave_Shared(projectile_index); + } else { + ProjPreInstr_Wave_Shared(k); + } +} + +void ProjPreInstr_BeamOrIceWave(uint16 k) { // 0x90B0E4 + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) { + ClearProjectile(k); + } else if (projectile_timers[v1]-- == 1) { + projectile_timers[v1] = 3; + SpawnProjectileTrail(k); + ProjPreInstr_Wave_Shared(projectile_index); + } else { + ProjPreInstr_Wave_Shared(k); + } +} + +static Func_Y_V *const kProjPreInstr_WavePlasmaEtcFuncs[10] = { // 0x90B103 + ProjPreInstr_WavePlasmaEtc_0459, + ProjPreInstr_WavePlasmaEtc_1368, + ProjPreInstr_WavePlasmaEtc_27, + ProjPreInstr_WavePlasmaEtc_1368, + ProjPreInstr_WavePlasmaEtc_0459, + ProjPreInstr_WavePlasmaEtc_0459, + ProjPreInstr_WavePlasmaEtc_1368, + ProjPreInstr_WavePlasmaEtc_27, + ProjPreInstr_WavePlasmaEtc_1368, + ProjPreInstr_WavePlasmaEtc_0459, +}; + +void ProjPreInstr_Wave_Shared(uint16 k) { + + int v1 = k >> 1; + uint16 v2 = 2 * (projectile_dir[v1] & 0xF); + int v3 = v2 >> 1; + projectile_bomb_x_speed[v1] += kDirToVelMult16_X[v3]; + projectile_bomb_y_speed[v1] += kDirToVelMult16_Y[v3]; + kProjPreInstr_WavePlasmaEtcFuncs[v3](v2); + DeleteProjectileIfFarOffScreen(); +} + +void ProjPreInstr_WavePlasmaEtc_0459(uint16 k) { // 0x90B13B + BlockCollWaveBeamVert(projectile_index); +} + +void ProjPreInstr_WavePlasmaEtc_1368(uint16 k) { // 0x90B143 + uint16 v1 = projectile_index; + if (!(BlockCollWaveBeamHoriz(projectile_index) & 1)) + BlockCollWaveBeamVert(v1); +} + +void ProjPreInstr_WavePlasmaEtc_27(uint16 k) { // 0x90B151 + BlockCollWaveBeamHoriz(projectile_index); +} + +void ProjPreInstr_HyperBeam(uint16 k) { // 0x90B159 + if ((projectile_dir[k >> 1] & 0xF0) != 0) + ClearProjectile(k); + else + ProjPreInstr_Wave_Shared(k); +} + +uint8 DeleteProjectileIfFarOffScreen(void) { // 0x90B16A + int16 v0; + int16 v2; + + v0 = projectile_x_pos[projectile_index >> 1] - layer1_x_pos; + if (!sign16(v0 + 64)) { + if (sign16(v0 - 320)) { + v2 = projectile_y_pos[projectile_index >> 1] - layer1_y_pos; + if (!sign16(v2 + 64)) { + if (sign16(v2 - 320)) + return 0; + } + } + } + ClearProjectile(projectile_index); + return 1; +} + +static const uint16 kInitializeProjectileSpeed_XY_Diag[24] = { // 0x90B197 + 0x400, 0x2ab, + 0x400, 0x2ab, + 0x400, 0x2ab, + 0x400, 0x2ab, + 0x400, 0x2ab, + 0x400, 0x2ab, + 0x400, 0x2ab, + 0x400, 0x2ab, + 0x400, 0x2ab, + 0x400, 0x2ab, + 0x400, 0x2ab, + 0x400, 0x2ab, +}; + +void SetInitialProjectileSpeed(void) { + int16 v2; + + int v0 = R20_ >> 1; + uint16 v1 = 4 * (projectile_type[v0] & 0xF); + v2 = 2 * (projectile_dir[v0] & 0xF); + if (!v2 || v2 == 4 || v2 == 8 || v2 == 10 || v2 == 14 || v2 == 18) { + R22_ = kInitializeProjectileSpeed_XY_Diag[v1 >> 1]; + } else { + if (v2 != 2 && v2 != 6 && v2 != 12 && v2 != 16) { + Unreachable(); + while (1) + ; + } + R22_ = kInitializeProjectileSpeed_XY_Diag[(v1 >> 1) + 1]; + } + R18_ = R20_; + InitializeProjectileSpeed(R20_); +} + +void InitializeProjectileSpeedOfType(void) { // 0x90B1DD + R22_ = 0; + R18_ = R20_; + InitializeProjectileSpeed(R20_); +} + +void InitializeProjectileSpeed(uint16 k) { // 0x90B1F3 + int16 v2; + + int v1 = k >> 1; + projectile_bomb_x_subpos[v1] = 0; + projectile_bomb_y_subpos[v1] = 0; + v2 = 2 * (projectile_dir[v1] & 0xF); + switch (v2) { + case 0: + case 18: { + uint16 v3 = R18_; + if ((uint8)projectile_init_speed_samus_moved_up) + R18_ = (*(uint16 *)((char *)&projectile_init_speed_samus_moved_right_fract + 1) >> 2) | 0xC000; + else + R18_ = 0; + int v4 = v3 >> 1; + projectile_bomb_y_speed[v4] = R18_ - R22_; + projectile_bomb_x_speed[v4] = 0; + break; + } + case 2: { + uint16 v5 = R18_; + if ((uint8)projectile_init_speed_samus_moved_up) + R18_ = (*(uint16 *)((char *)&projectile_init_speed_samus_moved_right_fract + 1) >> 2) | 0xC000; + else + R18_ = 0; + int v6 = v5 >> 1; + projectile_bomb_y_speed[v6] = R18_ - R22_; + projectile_bomb_x_speed[v6] = *(uint16 *)((char *)&projectile_init_speed_samus_moved_left_fract + 1) + R22_; + break; + } + case 4: { + int v7 = R18_ >> 1; + projectile_bomb_y_speed[v7] = 0; + projectile_bomb_x_speed[v7] = *(uint16 *)((char *)&projectile_init_speed_samus_moved_left_fract + 1) + R22_; + break; + } + case 6: { + int v8 = R18_ >> 1; + projectile_bomb_y_speed[v8] = *(uint16 *)((char *)&projectile_init_speed_samus_moved_up_fract + 1) + R22_; + projectile_bomb_x_speed[v8] = *(uint16 *)((char *)&projectile_init_speed_samus_moved_left_fract + 1) + R22_; + break; + } + case 8: + case 10: { + int v9 = R18_ >> 1; + projectile_bomb_y_speed[v9] = *(uint16 *)((char *)&projectile_init_speed_samus_moved_up_fract + 1) + R22_; + projectile_bomb_x_speed[v9] = 0; + break; + } + case 12: { + int v10 = R18_ >> 1; + projectile_bomb_y_speed[v10] = *(uint16 *)((char *)&projectile_init_speed_samus_moved_up_fract + 1) + R22_; + projectile_bomb_x_speed[v10] = *(uint16 *)((char *)&absolute_moved_last_frame_y_fract + 1) - R22_; + break; + } + case 14: { + int v11 = R18_ >> 1; + projectile_bomb_y_speed[v11] = 0; + projectile_bomb_x_speed[v11] = *(uint16 *)((char *)&absolute_moved_last_frame_y_fract + 1) - R22_; + break; + } + case 16: { + uint16 v12 = R18_; + if ((uint8)projectile_init_speed_samus_moved_up) + R18_ = (*(uint16 *)((char *)&projectile_init_speed_samus_moved_right_fract + 1) >> 2) | 0xC000; + else + R18_ = 0; + int v13 = v12 >> 1; + projectile_bomb_y_speed[v13] = R18_ - R22_; + projectile_bomb_x_speed[v13] = *(uint16 *)((char *)&absolute_moved_last_frame_y_fract + 1) - R22_; + break; + } + default: + Unreachable(); + while (1) + ; + } +} + +void Missile_Func1(uint16 k) { // 0x90B2F6 + static const uint16 word_90C301 = 0x100; + uint16 v3; + + int v1 = k >> 1; + if ((projectile_variables[v1] & 0xFF00) != 0) { + R18_ = 4 * (projectile_dir[v1] & 0xF); + if ((projectile_type[v1] & 0x200) != 0) + v3 = R18_ - 0x3CD5; + else + v3 = R18_ - 0x3CFD; + uint8 *v4 = RomPtr_90(v3); + projectile_bomb_x_speed[v1] += *(uint16 *)v4; + projectile_bomb_y_speed[v1] += *((uint16 *)v4 + 1); + } else { + uint16 v2 = word_90C301 + projectile_variables[v1]; + projectile_variables[v1] = v2; + if ((v2 & 0xFF00) != 0) { + R22_ = projectile_variables[v1]; + R18_ = k; + InitializeProjectileSpeed(k); + if ((projectile_type[v1] & 0x200) != 0) + Missile_Func2(); + } + } +} + +void SuperMissileBlockCollDetect_Y(void) { // 0x90B366 + int16 v1; + int16 v2; + char v3; // t0 + + int v0 = projectile_index >> 1; + if ((projectile_type[v0] & 0xF00) == 512 || (projectile_type[v0] & 0xF00) == 2048) { + uint8 v5 = projectile_variables[v0]; + if (*((uint8 *)projectile_variables + projectile_index + 1)) { + v1 = abs16(projectile_bomb_y_speed[v0]) & 0xFF00; + if (sign16(v1 - 2816)) { + int v4 = projectile_index >> 1; + if ((projectile_type[v4] & 0xF00) != 2048) { + projectile_y_pos[v5 >> 1] = projectile_y_pos[v4]; + return; + } + } else { + v3 = v1; + LOBYTE(v2) = HIBYTE(v1); + HIBYTE(v2) = v3; + R18_ = v2 - 10; + if ((projectile_bomb_y_speed[v0] & 0x8000u) == 0) { + uint16 v6 = projectile_index; + projectile_y_pos[v5 >> 1] = projectile_y_pos[v0] - R18_; + projectile_index = v5; + BlockCollMissileVert(v5); + projectile_index = v6; + if ((projectile_type[v6 >> 1] & 0xF00) == 2048) + ClearProjectile(v5); + return; + } + uint16 v7 = projectile_index; + projectile_y_pos[v5 >> 1] = R18_ + projectile_y_pos[projectile_index >> 1]; + projectile_index = v5; + BlockCollMissileVert(v5); + projectile_index = v7; + if ((projectile_type[v7 >> 1] & 0xF00) != 2048) + return; + } + ClearProjectile(v5); + } + } +} + +void Projectile_Func4(uint16 k) { // 0x90B4A6 + int v1 = k >> 1; + if (*((uint8 *)projectile_variables + k + 1)) { + if ((projectile_type[v1] & 0xF00) == 2048) + ClearProjectile((uint8)projectile_variables[v1]); + } +} + +void SuperMissileBlockCollDetect_X(void) { // 0x90B406 + int16 v1; + int16 v2; + char v3; // t0 + + int v0 = projectile_index >> 1; + if ((projectile_type[v0] & 0xF00) == 512 || (projectile_type[v0] & 0xF00) == 2048) { + uint8 v5 = projectile_variables[v0]; + if (*((uint8 *)projectile_variables + projectile_index + 1)) { + v1 = abs16(projectile_bomb_x_speed[v0]) & 0xFF00; + if (sign16(v1 - 2816)) { + int v4 = projectile_index >> 1; + if ((projectile_type[v4] & 0xF00) != 2048) { + projectile_x_pos[v5 >> 1] = projectile_x_pos[v4]; + return; + } + } else { + v3 = v1; + LOBYTE(v2) = HIBYTE(v1); + HIBYTE(v2) = v3; + R18_ = v2 - 10; + if ((projectile_bomb_x_speed[v0] & 0x8000u) == 0) { + uint16 v6 = projectile_index; + projectile_x_pos[v5 >> 1] = projectile_x_pos[v0] - R18_; + projectile_index = v5; + BlockCollMissileHoriz(v5); + projectile_index = v6; + if ((projectile_type[v6 >> 1] & 0xF00) == 2048) + ClearProjectile(v5); + return; + } + uint16 v7 = projectile_index; + projectile_x_pos[v5 >> 1] = R18_ + projectile_x_pos[projectile_index >> 1]; + projectile_index = v5; + BlockCollMissileHoriz(v5); + projectile_index = v7; + if ((projectile_type[v7 >> 1] & 0xF00) != 2048) + return; + } + ClearProjectile(v5); + } + } +} + +void ProjInstr_MoveLeftProjectileTrailDown(uint16 j) { // 0x90B525 + ++projectiletrail_left_y_pos[j >> 1]; +} + +void ProjInstr_MoveRightProjectileTrailDown(uint16 j) { // 0x90B587 + ++projectiletrail_right_y_pos[j >> 1]; +} + +void ProjInstr_MoveLeftProjectileTrailUp(uint16 j) { // 0x90B5B3 + --projectiletrail_left_y_pos[j >> 1]; +} + +void SpawnProjectileTrail(uint16 k) { // 0x90B657 +#define off_90B5BB ((uint16*)RomPtr(0x90b5bb)) +#define off_90B609 ((uint16*)RomPtr(0x90b609)) + int16 v2; + + uint16 v1 = projectile_type[k >> 1]; + if ((v1 & 0xF00) != 0) { + uint16 v3 = HIBYTE(v1) & 0xF; + if (v3 >= 3u) + return; + v2 = v3 + 31; + } else { + v2 = projectile_type[k >> 1] & 0x3F; + } + uint16 v4 = 34; + while (projectiletrail_left_instr_timer[v4 >> 1]) { + v4 -= 2; + if ((v4 & 0x8000u) != 0) + return; + } + int v5 = v4 >> 1; + projectiletrail_left_instr_timer[v5] = 1; + projectiletrail_right_instr_timer[v5] = 1; + int v6 = v2; + projectiletrail_left_instr_list_ptr[v5] = off_90B5BB[v6]; + projectiletrail_right_instr_list_ptr[v5] = off_90B609[v6]; + ProjectileTrail_Func5(projectile_index, v4); +} + +void CallProjInstr(uint32 ea, uint16 j) { + switch (ea) { + case fnProjInstr_MoveLeftProjectileTrailDown: ProjInstr_MoveLeftProjectileTrailDown(j); return; // 0x90b525 + case fnProjInstr_MoveRightProjectileTrailDown: ProjInstr_MoveRightProjectileTrailDown(j); return; // 0x90b587 + case fnProjInstr_MoveLeftProjectileTrailUp: ProjInstr_MoveLeftProjectileTrailUp(j); return; // 0x90b5b3 + default: Unreachable(); + } +} + +void HandleProjectileTrails(void) { // 0x90B6A9 + int i; + int16 v10; + OamEnt *v11; + int16 v12; + uint16 j; + int16 v22; + OamEnt *v23; + int16 v24; + uint16 k; + int16 v28; + OamEnt *v29; + int16 v30; + int16 v33; + OamEnt *v34; + int16 v35; + uint16 v6, v18; + int v7; + + if (!time_is_frozen_flag) { + uint16 v0 = 34; + while (1) { + uint16 v2; + int v1; + v1 = v0 >> 1; + v2 = projectiletrail_left_instr_timer[v1]; + if (v2) { + uint16 v3 = v2 - 1; + projectiletrail_left_instr_timer[v1] = v3; + if (v3) + goto LABEL_10; + for (i = projectiletrail_left_instr_list_ptr[v1]; ; i += 2) { + uint16 *v5 = (uint16 *)RomPtr_90(i); + v6 = *v5; + if ((*v5 & 0x8000u) == 0) + break; + R18_ = *v5; + CallProjInstr(v6 | 0x900000, v0); + } + v7 = v0 >> 1; + projectiletrail_left_instr_timer[v7] = v6; + if (v6) + break; + } +LABEL_14:; + int v13 = v0 >> 1; + uint16 v14 = projectiletrail_right_instr_timer[v13]; + if (v14) { + uint16 v15 = v14 - 1; + projectiletrail_right_instr_timer[v13] = v15; + if (v15) + goto LABEL_21; + for (j = projectiletrail_right_instr_list_ptr[v13]; ; j += 2) { + uint16 *v17 = (uint16 *)RomPtr_90(j); + v18 = *v17; + if ((*v17 & 0x8000u) == 0) + break; + R18_ = *v17; + CallProjInstr(v18 | 0x900000, v0); + } + int v19; + v19 = v0 >> 1; + projectiletrail_right_instr_timer[v19] = v18; + if (v18) { + projectiletrail_right_tile_and_attribs[v19] = *((uint16 *)RomPtr_90(j) + 1); + projectiletrail_right_instr_list_ptr[v19] = j + 4; +LABEL_21:; + uint16 v20 = oam_next_ptr; + if ((int16)(oam_next_ptr - 512) < 0) { + int v21 = v0 >> 1; + v22 = projectiletrail_right_x_pos[v21] - layer1_x_pos; + if ((v22 & 0xFF00) == 0) { + v23 = gOamEnt(oam_next_ptr); + *(uint16 *)&v23->xcoord = v22; + v24 = projectiletrail_right_y_pos[v21] - layer1_y_pos; + if ((v24 & 0xFF00) == 0) { + *(uint16 *)&v23->ycoord = v24; + *(uint16 *)&v23->charnum = projectiletrail_right_tile_and_attribs[v21]; + oam_next_ptr = v20 + 4; + } + } + } + } + } + v0 -= 2; + if ((v0 & 0x8000u) != 0) + return; + } + projectiletrail_left_tile_and_attribs[v7] = *((uint16 *)RomPtr_90(i) + 1); + projectiletrail_left_instr_list_ptr[v7] = i + 4; +LABEL_10:; + uint16 v8 = oam_next_ptr; + if ((int16)(oam_next_ptr - 512) < 0) { + int v9 = v0 >> 1; + v10 = projectiletrail_left_x_pos[v9] - layer1_x_pos; + if ((v10 & 0xFF00) == 0) { + v11 = gOamEnt(oam_next_ptr); + *(uint16 *)&v11->xcoord = v10; + v12 = projectiletrail_left_y_pos[v9] - layer1_y_pos; + if ((v12 & 0xFF00) == 0) { + *(uint16 *)&v11->ycoord = v12; + *(uint16 *)&v11->charnum = projectiletrail_left_tile_and_attribs[v9]; + oam_next_ptr = v8 + 4; + } + } + } + goto LABEL_14; + } + for (k = 34; (k & 0x8000u) == 0; k -= 2) { + uint16 v26 = oam_next_ptr; + if ((int16)(oam_next_ptr - 512) < 0) { + int v27 = k >> 1; + if (projectiletrail_left_instr_timer[v27]) { + v28 = projectiletrail_left_x_pos[v27] - layer1_x_pos; + if ((v28 & 0xFF00) == 0) { + v29 = gOamEnt(oam_next_ptr); + *(uint16 *)&v29->xcoord = v28; + v30 = projectiletrail_left_y_pos[v27] - layer1_y_pos; + if ((v30 & 0xFF00) == 0) { + *(uint16 *)&v29->ycoord = v30; + *(uint16 *)&v29->charnum = projectiletrail_left_tile_and_attribs[v27]; + oam_next_ptr = v26 + 4; + } + } + } + } + uint16 v31 = oam_next_ptr; + if ((int16)(oam_next_ptr - 512) < 0) { + int v32 = k >> 1; + if (projectiletrail_right_instr_timer[v32]) { + v33 = projectiletrail_right_x_pos[v32] - layer1_x_pos; + if ((v33 & 0xFF00) == 0) { + v34 = gOamEnt(oam_next_ptr); + *(uint16 *)&v34->xcoord = v33; + v35 = projectiletrail_right_y_pos[v32] - layer1_y_pos; + if ((v35 & 0xFF00) == 0) { + *(uint16 *)&v34->ycoord = v35; + *(uint16 *)&v34->charnum = projectiletrail_right_tile_and_attribs[v32]; + oam_next_ptr = v31 + 4; + } + } + } + } + } +} + +void HudSelectionHandler_NothingOrPowerBombs(void) { // 0x90B80D + prev_beam_charge_counter = flare_counter; + if (hyper_beam_flag || (equipped_beams & 0x1000) == 0) { + if ((button_config_shoot_x & joypad1_lastkeys) != 0) + FireUnchargedBeam(); + return; + } + if (new_projectile_direction_changed_pose) { + if (sign16(flare_counter - 60)) { +LABEL_14: + flare_counter = 0; + ClearFlareAnimationState(); + FireUnchargedBeam(); + return; + } +LABEL_15: + flare_counter = 0; + ClearFlareAnimationState(); + FireChargedBeam(); + return; + } + if ((button_config_shoot_x & joypad1_lastkeys) == 0) { + if (!flare_counter) + return; + if (sign16(flare_counter - 60)) + goto LABEL_14; + goto LABEL_15; + } + if (sign16(flare_counter - 120)) { + if (++flare_counter == 1) { + ClearFlareAnimationState(); + FireUnchargedBeam(); + } + } else if (FireSba() & 1) { + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + } +} + +static const uint16 kProjectileBombPreInstr[12] = { // 0x90B887 + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_BeamOrIceWave, + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_BeamOrIceWave, + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_WavePlasmaEtc, + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_WavePlasmaEtc, + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_WavePlasmaEtc, + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_WavePlasmaEtc, +}; + +void FireUnchargedBeam(void) { + char v3; + + if (hyper_beam_flag) { + FireHyperBeam(); + return; + } + if (Samus_CanFireBeam() & 1) { + uint16 v0 = 0; + while (projectile_damage[v0 >> 1]) { + v0 += 2; + if ((int16)(v0 - 10) >= 0) { + v0 -= 2; + break; + } + } + R20_ = v0; + if (!(InitProjectilePositionDirection() & 1)) { + projectile_invincibility_timer = 10; + uint16 v1 = R20_; + int v2 = R20_ >> 1; + projectile_timers[v2] = 4; + v3 = equipped_beams; + projectile_type[v2] = equipped_beams | 0x8000; + QueueSfx1_Max15(kUnchargedProjectile_Sfx[v3 & 0xF]); + play_resume_charging_beam_sfx = 0; + InitializeProjectile(v1); + if ((equipped_beams & 0x1000) != 0 + || (button_config_shoot_x & joypad1_newkeys) != 0 + || (button_config_shoot_x & joypad1_newinput_samusfilter) != 0) { + uint16 v6; + v6 = projectile_type[v2]; + cooldown_timer = kProjectileCooldown_Uncharged[v6 & 0x3F]; + if ((v6 & 1) == 0) + goto LABEL_17; + } else { + uint16 v5; + v5 = projectile_type[v2]; + cooldown_timer = kBeamAutoFireCooldowns[v5 & 0x3F]; + if ((v5 & 1) == 0) { +LABEL_17: + projectile_bomb_x_speed[v2] = 0; + projectile_bomb_y_speed[v2] = 0; + projectile_index = v1; + CheckBeamCollByDir(v1); + v1 = projectile_index; + if ((projectile_type[projectile_index >> 1] & 0xF00) != 0) + return; + goto LABEL_20; + } + } + int v4; + v4 = v1 >> 1; + projectile_bomb_x_speed[v4] = 0; + projectile_bomb_y_speed[v4] = 0; + projectile_index = v1; + WaveBeam_CheckColl(v1); +LABEL_20: + R20_ = v1; + projectile_bomb_pre_instructions[v1 >> 1] = kProjectileBombPreInstr[projectile_type[v1 >> 1] & 0xF]; + SetInitialProjectileSpeed(); + return; + } + } + if (!sign16(prev_beam_charge_counter - 16)) { + play_resume_charging_beam_sfx = 0; + QueueSfx1_Max15(2u); + } +} + +static const uint16 kFireChargedBeam_Funcs[12] = { // 0x90B986 + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_WavePlasmaEtc, + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_WavePlasmaEtc, + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_WavePlasmaEtc, + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_WavePlasmaEtc, + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_WavePlasmaEtc, + (uint16)fnProjPreInstr_Beam_NoWaveBeam, + (uint16)fnProjPreInstr_WavePlasmaEtc, +}; + +void FireChargedBeam(void) { + + if (Samus_CanFireBeam() & 1) { + uint16 v0 = 0; + while (projectile_damage[v0 >> 1]) { + v0 += 2; + if ((int16)(v0 - 10) >= 0) { + v0 -= 2; + break; + } + } + R20_ = v0; + if (!(InitProjectilePositionDirection() & 1)) { + projectile_invincibility_timer = 10; + uint16 v1 = R20_; + int v2 = R20_ >> 1; + projectile_timers[v2] = 4; + uint16 v3 = equipped_beams & 0x100F | 0x8010; + projectile_type[v2] = v3; + QueueSfx1_Max15(kChargedProjectile_Sfx[v3 & 0xF]); + play_resume_charging_beam_sfx = 0; + InitializeProjectile(v1); + uint16 v5 = projectile_type[v2]; + cooldown_timer = kProjectileCooldown_Uncharged[v5 & 0x3F]; + if ((v5 & 1) != 0) { + int v4 = v1 >> 1; + projectile_bomb_x_speed[v4] = 0; + projectile_bomb_y_speed[v4] = 0; + projectile_index = v1; + WaveBeam_CheckColl(v1); + } else { + projectile_bomb_x_speed[v2] = 0; + projectile_bomb_y_speed[v2] = 0; + projectile_index = v1; + CheckBeamCollByDir(v1); + v1 = projectile_index; + if ((projectile_type[projectile_index >> 1] & 0xF00) != 0) { +LABEL_14: + charged_shot_glow_timer = 4; + return; + } + } + R20_ = v1; + projectile_bomb_pre_instructions[v1 >> 1] = kFireChargedBeam_Funcs[(uint16)(2 + * (projectile_type[v1 >> 1] & 0xF)) >> 1]; + SetInitialProjectileSpeed(); + goto LABEL_14; + } + } + if (!sign16(prev_beam_charge_counter - 16)) { + play_resume_charging_beam_sfx = 0; + QueueSfx1_Max15(2u); + } +} + +static const int16 kProjectileOriginOffsets3_X[10] = { 2, 13, 11, 13, 2, -5, -14, -11, -19, -2 }; +static const int16 kProjectileOriginOffsets3_Y[10] = { -8, -13, 1, 4, 13, 13, 4, 1, -19, -8 }; +static const int16 kProjectileOriginOffsets4_X[10] = { 2, 15, 15, 13, 2, -5, -13, -13, -15, -2 }; +static const int16 kProjectileOriginOffsets4_Y[10] = { -8, -16, -2, 1, 13, 13, 1, -2, -16, -8 }; + +uint8 InitProjectilePositionDirection(void) { // 0x90BA56 + uint16 v0 = samus_pose; + uint16 direction_shots_fired; + + if (new_projectile_direction_changed_pose) { + direction_shots_fired = (uint8)new_projectile_direction_changed_pose; + new_projectile_direction_changed_pose = 0; + } else { + direction_shots_fired = kPoseParams[v0].direction_shots_fired; + if ((direction_shots_fired & 0xF0) != 0) { + if (direction_shots_fired != 16 + || (LOBYTE(direction_shots_fired) = *(&kPoseParams[0].direction_shots_fired + + (uint16)(8 * samus_last_different_pose)), + (direction_shots_fired & 0xF0) != 0)) { + --projectile_counter; + return 1; + } + direction_shots_fired = (uint8)direction_shots_fired; + v0 = samus_pose; + } + } + int v2 = R20_ >> 1; + projectile_dir[v2] = direction_shots_fired; + R22_ = kPoseParams[v0].y_offset_to_gfx; + uint16 v3 = 2 * (projectile_dir[v2] & 0xF); + if (samus_pose == kPose_75_FaceL_Moonwalk_AimUL + || samus_pose == kPose_76_FaceR_Moonwalk_AimUR + || samus_movement_type == 1) { + int v6 = v3 >> 1; + projectile_x_pos[v2] = samus_x_pos + kProjectileOriginOffsets4_X[v6]; + projectile_y_pos[v2] = samus_y_pos + kProjectileOriginOffsets4_Y[v6] - R22_; + return 0; + } else { + int v4 = v3 >> 1; + projectile_x_pos[v2] = samus_x_pos + kProjectileOriginOffsets3_X[v4]; + projectile_y_pos[v2] = samus_y_pos + kProjectileOriginOffsets3_Y[v4] - R22_; + return 0; + } +} + +void HandleChargingBeamGfxAudio(void) { // 0x90BAFC +#define kFlareAnimDelays ((uint16*)RomPtr(0x90c481)) + int16 v1; + int16 v4; + uint16 v9; + + if (hyper_beam_flag) { + if (flare_counter) { + for (int i = 4; i >= 0; i -= 2) { + bool v7 = *(uint16 *)((char *)&flare_animation_timer + i) == 1; + bool v8 = (-- * (uint16 *)((char *)&flare_animation_timer + i) & 0x8000u) != 0; + if (v7 || v8) { + v7 = (*(uint16 *)((char *)&flare_animation_frame + i))-- == 1; + if (v7) { + if (i == 4) + flare_counter = 0; + } else { + *(uint16 *)((char *)&flare_animation_timer + i) = 3; + } + } + DrawFlareAnimationComponent(i); + } + } + } else if ((int16)flare_counter > 0) { + if (flare_counter == 1) { + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 3; + flare_slow_sparks_anim_timer = 5; + flare_fast_sparks_anim_timer = 4; + } + if (!sign16(flare_counter - 15)) { + if (flare_counter == 16) + QueueSfx1_Max9(8u); + uint16 v0 = 0; + do { + byte_7E0002 = -112; + v1 = *(uint16 *)((char *)&flare_animation_timer + v0) - 1; + *(uint16 *)((char *)&flare_animation_timer + v0) = v1; + if (v1 < 0) { + uint16 v2 = *(uint16 *)((char *)&flare_animation_frame + v0) + 1; + *(uint16 *)((char *)&flare_animation_frame + v0) = v2; + uint16 v3 = v2; + R0_.addr = kFlareAnimDelays[v0 >> 1]; + v4 = *IndirPtr(&R0_, v2); + if (v4 == 255) { + *(uint16 *)((char *)&flare_animation_frame + v0) = 0; + v3 = 0; + } else if (v4 == 254) { + R18_ = *IndirPtr(&R0_, v3 + 1); + uint16 v5 = *(uint16 *)((char *)&flare_animation_frame + v0) - R18_; + *(uint16 *)((char *)&flare_animation_frame + v0) = v5; + v3 = v5; + } + *(uint16 *)((char *)&flare_animation_timer + v0) = *IndirPtr(&R0_, v3); + } + v9 = v0; + DrawFlareAnimationComponent(v0); + if (sign16(flare_counter - 30)) + break; + v0 += 2; + } while ((int16)(v9 - 4) < 0); + } + } +} + +static const int16 kProjectileOriginOffsets_X[13] = { 2, 18, 15, 17, 3, -4, -17, -15, -18, -2, -4, -4, -4 }; +static const int16 kProjectileOriginOffsets_Y[13] = { -28, -19, 1, 6, 17, 17, 6, 1, -20, -28, -20, -2, 8 }; +static const int16 kProjectileOriginOffsets2_X[10] = { 2, 19, 20, 18, 3, -4, -18, -20, -19, -2 }; +static const int16 kProjectileOriginOffsets2_Y[10] = { -32, -22, -3, 6, 25, 25, 6, -3, -20, -32 }; + + +void DrawFlareAnimationComponent(uint16 k) { // 0x90BBE1 + static const uint16 word_93A225[3] = { 0, 0x1e, 0x24 }; + static const uint16 word_93A22B[3] = { 0, 0x2a, 0x30 }; + int16 v2; + uint16 v1; + + byte_7E0002 = -109; + R18_ = *((uint8 *)&flare_animation_frame + k); + if (samus_pose_x_dir == 4) + v1 = word_93A22B[k >> 1]; + else + v1 = word_93A225[k >> 1]; + R22_ = R18_ + v1; + R24_ = *(&kPoseParams[0].y_offset_to_gfx + (uint16)(8 * samus_pose)); + v2 = *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)); + if (v2 != 255 && v2 != 16) { + uint16 v3 = 2 * (v2 & 0xF); + if ((ceres_status & 0x8000u) != 0) { + grapple_beam_tmpD82 = samus_x_pos; + grapple_beam_tmpD84 = samus_y_pos; + Samus_CalcPos_Mode7(); + } + int v4 = v3 >> 1; + uint16 v5; + if (samus_movement_type == 1) { + R20_ = samus_x_pos + kProjectileOriginOffsets2_X[v4] - layer1_x_pos; + v5 = (__PAIR32__( + samus_y_pos + kProjectileOriginOffsets2_Y[v4] - R24_, + samus_y_pos + kProjectileOriginOffsets2_Y[v4]) + - __PAIR32__(layer1_y_pos, R24_)) >> 16; + } else { + R20_ = samus_x_pos + kProjectileOriginOffsets_X[v4] - layer1_x_pos; + v5 = (__PAIR32__( + samus_y_pos + kProjectileOriginOffsets_Y[v4] - R24_, + samus_y_pos + kProjectileOriginOffsets_Y[v4]) + - __PAIR32__(layer1_y_pos, R24_)) >> 16; + } + R18_ = v5; + if ((v5 & 0xFF00) != 0) + ; + else + DrawBeamGrappleSpritemap(R22_); + if ((ceres_status & 0x8000u) != 0) { + samus_y_pos = grapple_beam_tmpD84; + samus_x_pos = grapple_beam_tmpD82; + } + } +} + +void ClearFlareAnimationState(void) { // 0x90BCBE + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 0; + flare_slow_sparks_anim_timer = 0; + flare_fast_sparks_anim_timer = 0; +} + +void FireHyperBeam(void) { // 0x90BCD1 + if (Samus_CanFireBeam() & 1) { + uint16 v0 = 0; + while (projectile_damage[v0 >> 1]) { + v0 += 2; + if ((int16)(v0 - 10) >= 0) { + v0 -= 2; + break; + } + } + R20_ = v0; + if (!(InitProjectilePositionDirection() & 1)) { + projectile_invincibility_timer = 10; + uint16 k = R20_; + projectile_type[R20_ >> 1] = -28648; + QueueSfx1_Max15(kChargedProjectile_Sfx[8]); + play_resume_charging_beam_sfx = 0; + InitializeProjectile(k); + int v1 = k >> 1; + projectile_bomb_x_speed[v1] = 0; + projectile_bomb_y_speed[v1] = 0; + projectile_index = k; + WaveBeam_CheckColl(k); + uint16 v2 = projectile_index; + int v3 = projectile_index >> 1; + projectile_damage[v3] = 1000; + projectile_bomb_pre_instructions[v3] = FUNC16(ProjPreInstr_HyperBeam); + R20_ = v2; + SetInitialProjectileSpeed(); + cooldown_timer = 21; + charged_shot_glow_timer = -32748; + flare_animation_frame = 29; + flare_slow_sparks_anim_frame = 5; + flare_fast_sparks_anim_frame = 5; + flare_animation_timer = 3; + flare_slow_sparks_anim_timer = 3; + flare_fast_sparks_anim_timer = 3; + flare_counter = 0x8000; + } + } +} + +static Func_V *const kCheckBeamCollByDir[10] = { // 0x90BD64 + CheckBeamCollByDir_0459, + CheckBeamCollByDir_1368, + CheckBeamCollByDir_2, + CheckBeamCollByDir_1368, + CheckBeamCollByDir_0459, + CheckBeamCollByDir_0459, + CheckBeamCollByDir_1368, + CheckBeamCollByDir_7, + CheckBeamCollByDir_1368, + CheckBeamCollByDir_0459, +}; + +void CheckBeamCollByDir(uint16 k) { + kCheckBeamCollByDir[projectile_dir[k >> 1] & 0xF](); +} + +void CheckBeamCollByDir_0459(void) { // 0x90BD86 + BlockCollNoWaveBeamVert(projectile_index); +} + +void CheckBeamCollByDir_1368(void) { // 0x90BD8E + uint16 v0 = projectile_index; + if (!(BlockCollNoWaveBeamHoriz(projectile_index) & 1)) + BlockCollNoWaveBeamVert(v0); +} + +void CheckBeamCollByDir_2(void) { // 0x90BD9C + BlockCollNoWaveBeamHoriz(projectile_index); +} + +void CheckBeamCollByDir_7(void) { // 0x90BDA4 + uint16 v0 = projectile_index; + projectile_bomb_x_speed[projectile_index >> 1] = -1; + BlockCollNoWaveBeamHoriz(v0); +} + +static Func_V *const kWaveBeam_CheckColl_Funcs[10] = { // 0x90BDB2 + WaveBeam_CheckColl_0459, + WaveBeam_CheckColl_1368, + WaveBeam_CheckColl_2, + WaveBeam_CheckColl_1368, + WaveBeam_CheckColl_0459, + WaveBeam_CheckColl_0459, + WaveBeam_CheckColl_1368, + WaveBeam_CheckColl_7, + WaveBeam_CheckColl_1368, + WaveBeam_CheckColl_0459, +}; +void WaveBeam_CheckColl(uint16 k) { + kWaveBeam_CheckColl_Funcs[projectile_dir[k >> 1] & 0xF](); +} + +void WaveBeam_CheckColl_0459(void) { // 0x90BDD4 + BlockCollWaveBeamVert(projectile_index); +} + +void WaveBeam_CheckColl_1368(void) { // 0x90BDDC + uint16 v0 = projectile_index; + if (!(BlockCollWaveBeamHoriz(projectile_index) & 1)) + BlockCollWaveBeamVert(v0); +} + +void WaveBeam_CheckColl_2(void) { // 0x90BDEA + BlockCollWaveBeamHoriz(projectile_index); +} + +void WaveBeam_CheckColl_7(void) { // 0x90BDF2 + uint16 v0 = projectile_index; + projectile_bomb_x_speed[projectile_index >> 1] = -1; + BlockCollWaveBeamHoriz(v0); +} + +void ProjectileReflection(void) { // 0x90BE00 + uint16 v0 = R20_; + int v1 = R20_ >> 1; + uint16 v2 = projectile_type[v1]; + if ((v2 & 0x100) != 0) { + InitializeProjectile(R20_); + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_Missile); + projectile_variables[v1] = 240; + } else if ((v2 & 0x200) != 0) { + uint16 k = R20_; + ClearProjectile(LOBYTE(projectile_variables[v1])); + InitializeProjectile(k); + int v3 = k >> 1; + projectile_bomb_pre_instructions[v3] = FUNC16(ProjPreInstr_SuperMissile); + projectile_variables[v3] = 240; + } else { + SetInitialProjectileSpeed(); + InitializeProjectile(v0); + projectile_bomb_pre_instructions[v1] = kFireChargedBeam_Funcs[projectile_type[v1] & 0xF]; + } +} + +void HudSelectionHandler_MissilesOrSuperMissiles(void) { // 0x90BE62 + uint16 v2; + char v6; + + if ((button_config_shoot_x & joypad1_newkeys) == 0 && (button_config_shoot_x & joypad1_newinput_samusfilter) == 0 + || !(Samus_CanFireSuperMissile() & 1)) { + return; + } + if (hud_item_index != 2) { + if (samus_missiles) + goto LABEL_10; +LABEL_5: + --projectile_counter; + return; + } + if (!samus_super_missiles) + goto LABEL_5; +LABEL_10:; + uint16 v0 = 0; + while (projectile_damage[v0 >> 1]) { + v0 += 2; + if ((int16)(v0 - 10) >= 0) + goto LABEL_5; + } + R20_ = v0; + if (!(InitProjectilePositionDirection() & 1)) { + projectile_invincibility_timer = 20; + if (hud_item_index == 2) + --samus_super_missiles; + else + --samus_missiles; + int v1 = R20_ >> 1; + projectile_timers[v1] = 4; + uint16 v3 = hud_item_index; + LOBYTE(v2) = HIBYTE(v3); + v6 = v3; + HIBYTE(v2) = hud_item_index; + R18_ = v2; + projectile_type[v1] |= v2 | 0x8000; + uint16 v4 = 2 * (v6 & 0xF); + if (!cinematic_function) + QueueSfx1_Max6(kNonBeamProjectile_Sfx[v4 >> 1]); + InitializeProjectileSpeedOfType(); + InitializeProjectile(R20_); + uint16 v7 = projectile_type[v1]; + if ((v7 & 0x200) != 0) + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_SuperMissile); + else + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_Missile); + cooldown_timer = kNonBeamProjectileCooldowns[HIBYTE(v7) & 0xF]; + if (samus_auto_cancel_hud_item_index) { + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + return; + } + if (hud_item_index == 2) { + if (samus_super_missiles) + return; + } else if (samus_missiles) { + return; + } + hud_item_index = 0; + } +} + +void Missile_Func2(void) { // 0x90BF46 + uint16 v0 = 0; + while (projectile_damage[v0 >> 1]) { + v0 += 2; + if ((int16)(v0 - 10) >= 0) + return; + } + R20_ = v0; + int v1 = v0 >> 1; + projectile_type[v1] |= 0x8200u; + int v2 = projectile_index >> 1; + projectile_x_pos[v1] = projectile_x_pos[v2]; + projectile_y_pos[v1] = projectile_y_pos[v2]; + projectile_dir[v1] = projectile_dir[v2]; + InitProjectilePositionDirection(); + InitializeInstrForSuperMissile(v0); + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_Func1); + R18_ = v0; + projectile_variables[projectile_index >> 1] = v0 + (projectile_variables[projectile_index >> 1] & 0xFF00); + ++projectile_counter; +} + +void HudSelectionHandler_MorphBall(void) { // 0x90BF9D + uint16 v3; + char v6; + + if ((button_config_shoot_x & joypad1_lastkeys) != 0) { + if (hud_item_index == 3) { + if ((power_bomb_flag & 0x8000u) == 0) { + if (HudSelectionHandler_MorphBall_Helper2() & 1) { + if (samus_power_bombs) { + if ((--samus_power_bombs & 0x8000u) == 0) { + power_bomb_flag = -1; + uint16 v2 = 10; + while (projectile_type[v2 >> 1]) { + v2 += 2; + if ((int16)(v2 - 20) >= 0) { + v2 -= 2; + break; + } + } + R20_ = v2; + LOBYTE(v3) = HIBYTE(hud_item_index); + HIBYTE(v3) = hud_item_index; + R18_ = v3; + int v4 = v2 >> 1; + uint16 v5 = v3 | projectile_type[v4]; + projectile_type[v4] = v5; + v6 = HIBYTE(v5); + projectile_dir[v4] = 0; + projectile_x_pos[v4] = samus_x_pos; + projectile_y_pos[v4] = samus_y_pos; + projectile_variables[v4] = 60; + InitializeInstrForMissile(v2); + projectile_bomb_pre_instructions[v4] = FUNC16(ProjPreInstr_PowerBomb); + cooldown_timer = kNonBeamProjectileCooldowns[v6 & 0xF]; + if (samus_auto_cancel_hud_item_index) { + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + } else if (hud_item_index == 3 && !samus_power_bombs) { + hud_item_index = 0; + } + } + } + } + } + } else if (HudSelectionHandler_MorphBall_Helper() & 1) { + uint16 v0 = 10; + while (projectile_type[v0 >> 1]) { + v0 += 2; + if ((int16)(v0 - 20) >= 0) { + v0 -= 2; + break; + } + } + R20_ = v0; + int v1 = v0 >> 1; + projectile_type[v1] = 1280; + projectile_dir[v1] = 0; + projectile_x_pos[v1] = samus_x_pos; + projectile_y_pos[v1] = samus_y_pos; + projectile_variables[v1] = 60; + InitializeInstrForMissile(v0); + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_Bomb); + cooldown_timer = kNonBeamProjectileCooldowns[5]; + } + } else if (flare_counter) { + QueueSfx1_Max9(2u); + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + } +} + +uint8 HudSelectionHandler_MorphBall_Helper(void) { // 0x90C0AB + if ((equipped_items & 0x1000) != 0) { + if (sign16(flare_counter - 60) || bomb_counter) + return HudSelectionHandler_MorphBall_Helper2(); + if ((joypad1_lastkeys & kButton_Down) != 0 && sign16((bomb_spread_charge_timeout_counter & 0xC0) - 192)) { + ++bomb_spread_charge_timeout_counter; + } else { + BombSpread(); + Samus_LoadSuitPalette(); + QueueSfx1_Max9(2u); + } + } + return 0; +} + +uint8 HudSelectionHandler_MorphBall_Helper2(void) { // 0x90C0E7 + if ((button_config_shoot_x & joypad1_newkeys) == 0 + || bomb_counter && (!sign16(bomb_counter - 5) || (uint8)cooldown_timer)) { + if (flare_counter) { + QueueSfx1_Max9(2u); + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + } + return 0; + } else { + ++cooldown_timer; + ++bomb_counter; + return 1; + } +} + +void Bomb_Func2(void) { // 0x90C128 + uint16 v0 = projectile_index; + int v1 = projectile_index >> 1; + uint16 v2 = projectile_variables[v1]; + if (v2) { + uint16 v3 = v2 - 1; + projectile_variables[v1] = v3; + if (v3) { + if (v3 == 15) + projectile_bomb_instruction_ptr[v1] += 28; + } else { + QueueSfx2_Max6(8u); + InitializeBombExplosion(v0); + } + } +} + +void PowerBomb_Func3(void) { // 0x90C157 + uint16 v0 = projectile_index; + int v1 = projectile_index >> 1; + uint16 v2 = projectile_variables[v1]; + if (v2) { + uint16 v3 = v2 - 1; + projectile_variables[v1] = v3; + if (v3) { + if (v3 == 15) + projectile_bomb_instruction_ptr[v1] += 28; + } else { + power_bomb_explosion_x_pos = projectile_x_pos[v1]; + power_bomb_explosion_y_pos = projectile_y_pos[v1]; + EnableHdmaObjects(); + SpawnPowerBombExplosion(); + projectile_variables[v0 >> 1] = -1; + } + } else if (!power_bomb_flag) { + ClearProjectile(projectile_index); + } +} + +static Func_U8 *const kRunSwitchedToHudHandler[6] = { // 0x90C4B5 + SwitchToHudHandler_Nothing, + SwitchToHudHandler_Missiles, + SwitchToHudHandler_SuperMissiles, + SwitchToHudHandler_PowerBombs, + SwitchToHudHandler_Grapple, + SwitchToHudHandler_Xray, +}; +void HandleSwitchingHudSelection(void) { + uint16 v0; + R18_ = hud_item_index; + if ((button_config_itemcancel_y & joypad1_newkeys) != 0) { + samus_auto_cancel_hud_item_index = 0; +LABEL_5: + v0 = 0; + goto LABEL_6; + } + R22_ = (button_config_itemcancel_y & joypad1_lastkeys) != 0; + if ((button_config_itemswitch & joypad1_newkeys) == 0) + goto LABEL_13; + v0 = hud_item_index + 1; + if (!sign16(hud_item_index - 5)) + goto LABEL_5; +LABEL_6: + hud_item_index = v0; + while (kRunSwitchedToHudHandler[v0]() & 1) { + v0 = hud_item_index + 1; + hud_item_index = v0; + if (!sign16(v0 - 6)) { + v0 = 0; + hud_item_index = 0; + } + } + if (R22_) + samus_auto_cancel_hud_item_index = hud_item_index; + else + samus_auto_cancel_hud_item_index = 0; +LABEL_13: + if (hud_item_index == R18_) { + uint16 v1 = hud_item_changed_this_frame + 1; + if (!sign16(hud_item_changed_this_frame - 2)) + v1 = 2; + hud_item_changed_this_frame = v1; + } else { + hud_item_changed_this_frame = 1; + } +} + +uint8 SwitchToHudHandler_Nothing(void) { // 0x90C545 + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + return 0; +} + +uint8 SwitchToHudHandler_Missiles(void) { // 0x90C551 + if (!samus_missiles) + return 1; + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + return 0; +} + +uint8 SwitchToHudHandler_SuperMissiles(void) { // 0x90C564 + if (!samus_super_missiles) + return 1; + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + return 0; +} + +uint8 SwitchToHudHandler_PowerBombs(void) { // 0x90C577 + if (!samus_power_bombs) + return 1; + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + return 0; +} + +uint8 SwitchToHudHandler_Grapple(void) { // 0x90C58A + if ((equipped_items & 0x4000) == 0) + return 1; + if (grapple_beam_function == (uint16)FUNC16(GrappleBeamFunc_Inactive)) { + Samus_LoadSuitPalette(); + flare_counter = 0; + ClearFlareAnimationState(); + grapple_beam_function = FUNC16(GrappleBeamFunc_Inactive); + } + return 0; +} + +uint8 SwitchToHudHandler_Xray(void) { // 0x90C5AE + if ((equipped_items & 0x8000u) == 0) + return 1; + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + return 0; +} + +void HandleArmCannonOpenState(void) { // 0x90C5C4 + if (flag_arm_cannon_opening_or_closing || UpdateArmCannonIsOpenFlag() & 1) + AdvanceArmCannonFrame(); + arm_cannon_drawing_mode = RomPtr_90(kPlayerPoseToPtr[samus_pose])[1]; +} + +uint8 UpdateArmCannonIsOpenFlag(void) { // 0x90C5EB + static const int8 kFlagShouldArmCannonBeOpen[6] = { 0, 1, 1, 0, 1, 0 }; + if (sign16(hud_item_changed_this_frame - 2)) + return 0; + R18_ = kFlagShouldArmCannonBeOpen[hud_item_index]; + if (flag_arm_cannon_open_or_opening == R18_) + return 0; + if (R18_) + arm_cannon_frame = 0; + else + arm_cannon_frame = 4; + *(uint16 *)&flag_arm_cannon_open_or_opening = R18_ | 0x100; + return 1; +} + +void AdvanceArmCannonFrame(void) { // 0x90C627 + if (flag_arm_cannon_open_or_opening) { + if (sign16(arm_cannon_frame - 2)) { + ++arm_cannon_frame; + return; + } + arm_cannon_frame = 3; + } else { + if (arm_cannon_frame != 1 && (int16)(arm_cannon_frame - 1) >= 0) { + --arm_cannon_frame; + return; + } + arm_cannon_frame = 0; + } + *(uint16 *)&flag_arm_cannon_open_or_opening = flag_arm_cannon_open_or_opening; +} + +void Samus_ArmCannon_Draw(void) { // 0x90C663 + static const uint16 kDrawArmCannon_Char[10] = { 0x281f, 0x281f, 0x281f, 0x681f, 0xa81f, 0xe81f, 0x281f, 0x681f, 0x681f, 0x681f }; + int16 v2; + int16 v8; + OamEnt *v9; + int16 v10; + int16 v12; + uint16 v3; + + if (arm_cannon_frame && (!samus_invincibility_timer || (nmi_frame_counter_word & 1) == 0)) { + uint16 v0 = kPlayerPoseToPtr[samus_pose]; + uint8 *v1 = RomPtr_90(v0); + v2 = *v1; + if ((v2 & 0x80) != 0) { + if (samus_anim_frame) + v3 = 2 * (v1[2] & 0x7F); + else + v3 = 2 * (*v1 & 0x7F); + R22_ = v0 + 4; + } else { + v3 = 2 * v2; + R22_ = v0 + 2; + } + R24_ = kDrawArmCannon_Char[v3 >> 1]; + uint8 *v4 = RomPtr_90(R22_ + 2 * samus_anim_frame); + uint16 v5 = *v4; + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + R18_ = v5; + uint16 v6 = v4[1]; + if ((v6 & 0x80) != 0) + v6 |= 0xFF00u; + R20_ = v6; + R22_ = *(&kPoseParams[0].y_offset_to_gfx + (uint16)(8 * samus_pose)); + uint16 v7 = oam_next_ptr; + v8 = R18_ + samus_x_pos - layer1_x_pos; + if (v8 >= 0) { + if (sign16(v8 - 256)) { + v9 = gOamEnt(oam_next_ptr); + *(uint16 *)&v9->xcoord = v8; + v10 = (__PAIR32__(R20_ + samus_y_pos - R22_, R20_ + samus_y_pos) - __PAIR32__(layer1_y_pos, R22_)) >> 16; + if (v10 >= 0) { + if (sign16(v10 - 256)) { + *(uint16 *)&v9->ycoord = v10; + *(uint16 *)&v9->charnum = R24_; + oam_next_ptr = v7 + 4; + } + } + } + } + uint8 *v11 = RomPtr_90(kPlayerPoseToPtr[samus_pose]); + v12 = *v11; + if ((v12 & 0x80) != 0) { + if (samus_anim_frame) + v12 = *RomPtr_90(kPlayerPoseToPtr[samus_pose] + 2) & 0x7F; + else + v12 = *v11 & 0x7F; + } + R22_ = kDrawArmCannon_Tab2[v12]; + uint16 v13 = R22_ + 2 * arm_cannon_frame; + uint16 v14 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 32; + v14 += 2; + uint16 v15 = *(uint16 *)RomPtr_90(v13); + gVramWriteEntry(v14)->size = v15; + v14 += 2; + LOBYTE(gVramWriteEntry(v14++)->size) = -102; + gVramWriteEntry(v14)->size = addr_unk_6061F0; + vram_write_queue_tail = v14 + 2; + } +} + +void Projectile_SinLookup(uint16 j, uint16 a) { // 0x90CC39 + int16 v3; + uint16 v2, v4; + + R24_ = a; + R26_ = j; + if (sign16(j - 128)) + v2 = Projectile_SinLookup_Inner(2 * j); + else + v2 = -Projectile_SinLookup_Inner(2 * (uint8)(j + 0x80)); + R20_ = v2; + v3 = (uint8)(R26_ - 64); + if (sign16(v3 - 128)) + v4 = Projectile_SinLookup_Inner(2 * v3); + else + v4 = -Projectile_SinLookup_Inner(2 * (uint8)(v3 + 0x80)); + R22_ = v4; +} + + +uint16 Projectile_SinLookup_Inner(uint16 k) { // 0x90CC8A + uint16 prod = Mult8x8(*((uint8 *)&kSinCosTable8bit_Sext[64] + k), R24_); + R18_ = prod >> 8; + prod = Mult8x8(*((uint8 *)&kSinCosTable8bit_Sext[64] + k + 1), R24_); + return R18_ + prod; +} + +static const uint16 kCostOfSbaInPowerBombs[12] = { // 0x90CCC0 + 0, 1, 1, 0, 1, 0, 0, 0, + 1, 0, 0, 0, +}; + +static Func_V_A *const kFireSbaFuncs[12] = { + FireSba_ClearCarry, + FireSba_FireWave, + FireSba_FireIce, + FireSba_ClearCarry, + FireSba_FireSpazer, + FireSba_ClearCarry, + FireSba_ClearCarry, + FireSba_ClearCarry, + FireSba_FirePlasma, + FireSba_ClearCarry, + FireSba_ClearCarry, + FireSba_ClearCarry, +}; + +uint8 FireSba(void) { + int16 v2; + + if (hud_item_index != 3) + return 0; + uint16 v1 = 2 * (equipped_beams & 0xF); + v2 = samus_power_bombs - kCostOfSbaInPowerBombs[v1 >> 1]; + if (v2 < 0) + v2 = 0; + samus_power_bombs = v2; + uint8 rv = kFireSbaFuncs[v1 >> 1](); + if (!samus_power_bombs) { + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + } + return rv; +} + +uint8 FireSba_ClearCarry(void) { // 0x90CD18 + return 0; +} + +uint8 FireSba_FireWave(void) { // 0x90CD1A + static const int16 kFireSba_FireWave_X[4] = { 128, 128, -128, -128 }; + static const int16 kFireSba_FireWave_Y[4] = { 128, -128, -128, 128 }; + + for (int i = 6; i >= 0; i -= 2) { + int v1 = i >> 1; + projectile_timers[v1] = 4; + projectile_type[v1] = equipped_beams & 0x100F | 0x8010; + projectile_dir[v1] = 0; + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_WaveSba); + projectile_bomb_y_speed[v1] = 600; + projectile_bomb_x_speed[v1] = 0; + projectile_variables[v1] = 0; + projectile_bomb_x_subpos[v1] = 0; + projectile_bomb_y_subpos[v1] = 0; + projectile_x_pos[v1] = kFireSba_FireWave_X[v1] + samus_x_pos; + projectile_y_pos[v1] = kFireSba_FireWave_Y[v1] + samus_y_pos; + InitializeSbaProjectile(i); + } + projectile_counter = 4; + cooldown_timer = kProjectileCooldown_Uncharged[projectile_type[0] & 0x3F]; + used_for_sba_attacksB60 = 4; + QueueSfx1_Max6(0x28u); + return 1; +} + +uint8 FireSba_FireIce(void) { // 0x90CD9B + static const uint16 kIcePlasmaSbaProjectileOriginAngles[8] = { 0, 0x40, 0x80, 0xc0, 0x20, 0x60, 0xa0, 0xe0 }; + + if (projectile_bomb_pre_instructions[0] == (uint16)FUNC16(ProjPreInstr_IceSba2) + || projectile_bomb_pre_instructions[0] == (uint16)FUNC16(ProjPreInstr_IceSba)) { + return 0; + } + for (int i = 6; i >= 0; i -= 2) { + int v2 = i >> 1; + projectile_timers[v2] = 4; + projectile_type[v2] = equipped_beams & 0x100F | 0x8010; + projectile_dir[v2] = 0; + projectile_bomb_pre_instructions[v2] = FUNC16(ProjPreInstr_IceSba); + projectile_variables[v2] = kIcePlasmaSbaProjectileOriginAngles[v2]; + projectile_bomb_y_speed[v2] = 600; + InitializeProjectile(i); + } + projectile_counter = 4; + cooldown_timer = kProjectileCooldown_Uncharged[projectile_type[0] & 0x3F]; + if (samus_pose_x_dir == 4) + used_for_sba_attacksB60 = -4; + else + used_for_sba_attacksB60 = 4; + QueueSfx1_Max6(0x23u); + return 1; +} + +uint8 FireSba_FireSpazer(void) { // 0x90CE14 + static const int16 kFireSpazer_Timer[4] = { 0, 0, 4, 4 }; + static const int16 kFireSpazer_Yspeed[4] = { 4, -4, 4, -4 }; + + for (int i = 6; i >= 0; i -= 2) { + int v1 = i >> 1; + projectile_timers[v1] = kFireSpazer_Timer[v1]; + projectile_dir[v1] = 5; + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_SpazerSba); + projectile_bomb_x_speed[v1] = 40; + projectile_bomb_y_speed[v1] = kFireSpazer_Yspeed[v1]; + projectile_variables[v1] = 0; + projectile_unk_A[v1] = 0; + projectile_bomb_x_subpos[v1] = 0; + projectile_bomb_y_subpos[v1] = 0; + if ((int16)(i - 4) >= 0) { + projectile_type[i >> 1] = -32732; + InitializeShinesparkEchoOrSpazerSba(i); + } else { + projectile_type[i >> 1] = equipped_beams & 0x100F | 0x8010; + InitializeSbaProjectile(i); + } + } + projectile_counter = 4; + cooldown_timer = kProjectileCooldown_Uncharged[projectile_type[0] & 0x3F]; + used_for_sba_attacksB60 = 0; + QueueSfx1_Max6(0x25u); + return 1; +} + +uint8 FireSba_FirePlasma(void) { // 0x90CE98 + static const uint16 kIcePlasmaSbaProjectileOriginAngles[8] = { 0, 0x40, 0x80, 0xc0, 0x20, 0x60, 0xa0, 0xe0 }; + + + if (projectile_bomb_pre_instructions[0] == (uint16)FUNC16(ProjPreInstr_PlasmaSba)) + return 0; + for (int i = 6; i >= 0; i -= 2) { + int v2 = i >> 1; + projectile_type[v2] = equipped_beams & 0x100F | 0x8010; + projectile_dir[v2] = 0; + projectile_bomb_pre_instructions[v2] = FUNC16(ProjPreInstr_PlasmaSba); + projectile_variables[v2] = kIcePlasmaSbaProjectileOriginAngles[v2]; + projectile_bomb_x_speed[v2] = 40; + projectile_bomb_y_speed[v2] = 0; + InitializeSbaProjectile(i); + } + projectile_counter = 4; + cooldown_timer = kProjectileCooldown_Uncharged[projectile_type[0] & 0x3F]; + if (samus_pose_x_dir == 4) + used_for_sba_attacksB60 = -4; + else + used_for_sba_attacksB60 = 4; + QueueSfx1_Max6(0x27u); + return 1; +} + +void ProjPreInstr_IceSba(uint16 k) { // 0x90CF09 + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) { + QueueSfx1_Max6(0x24u); + ClearProjectile(k); + } else { + bool v2 = projectile_timers[v1]-- == 1; + if (v2) { + projectile_timers[v1] = 4; + SpawnProjectileTrail(k); + k = projectile_index; + } + int v3 = k >> 1; + Projectile_SinLookup(projectile_variables[v3], 0x20u); + projectile_x_pos[v3] = R20_ + samus_x_pos; + projectile_y_pos[v3] = R22_ + samus_y_pos; + projectile_variables[v3] = (uint8)(used_for_sba_attacksB60 + projectile_variables[v3]); + v2 = projectile_bomb_y_speed[v3]-- == 1; + if (v2) { + projectile_bomb_pre_instructions[v3] = FUNC16(ProjPreInstr_IceSba2); + projectile_bomb_x_speed[v3] = 40; + QueueSfx1_Max6(0x24u); + } + cooldown_timer = 2; + flare_counter = 0; + } +} + +void ProjPreInstr_IceSba2(uint16 k) { // 0x90CF7A + int16 v4; + int16 v5; + int16 v6; + int16 v7; + + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) + goto LABEL_9; + if (projectile_timers[v1]-- == 1) { + projectile_timers[v1] = 4; + SpawnProjectileTrail(k); + k = projectile_index; + } + int v3; + v3 = k >> 1; + Projectile_SinLookup(projectile_variables[v3], projectile_bomb_x_speed[v3]); + v4 = R20_ + samus_x_pos; + projectile_x_pos[v3] = R20_ + samus_x_pos; + v5 = v4 - layer1_x_pos; + if (sign16(v5 + 32) + || !sign16(v5 - 288) + || (v6 = R22_ + samus_y_pos, projectile_y_pos[v3] = R22_ + samus_y_pos, v7 = v6 - layer1_y_pos, sign16(v7 - 16)) + || !sign16(v7 - 256)) { +LABEL_9: + ClearProjectile(k); + } else { + projectile_variables[v3] = (uint8)(used_for_sba_attacksB60 + projectile_variables[v3]); + projectile_bomb_x_speed[v3] = (uint8)(projectile_bomb_x_speed[v3] + 8); + cooldown_timer = 2; + flare_counter = 0; + } +} + +void Projectile_Func7_Shinespark(void) { // 0x90CFFA + samus_movement_handler = FUNC16(Samus_MoveHandlerShinesparkWindup); + samus_y_dir = 1; + speed_boost_counter = 1024; + samus_y_subspeed = 0; + samus_y_speed = 0; + knockback_dir = 0; + samus_x_extra_run_speed = 8; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + substate = 7; + suit_pickup_light_beam_pos = 0; + cooldown_timer = 0; + timer_for_shinesparks_startstop = 30; + samus_shine_timer = 60; + timer_for_shine_timer = 6; + special_samus_palette_frame = 0; + bomb_jump_dir = 0; + if (flare_counter) { + if (!sign16(flare_counter - 16)) + QueueSfx1_Max9(2u); + flare_counter = 0; + ClearFlareAnimationState(); + } +} + +void Samus_MoveHandlerShinesparkWindup(void) { // 0x90D068 + bool v0 = (--timer_for_shinesparks_startstop & 0x8000u) != 0; + if (!timer_for_shinesparks_startstop || v0) { + if (samus_pose_x_dir == 4) + samus_new_pose_interrupted = 204; + else + samus_new_pose_interrupted = 203; + samus_movement_handler = FUNC16(Samus_MoveHandlerVerticalShinespark); + samus_input_handler = FUNC16(nullsub_152); + speed_echoes_index = 0; + speed_echo_xspeed[0] = 0; + speed_echo_xspeed[1] = 0; + speed_echo_xpos[0] = 0; + speed_echo_xpos[1] = 0; + QueueSfx3_Max9(0xFu); + } +} + +void Samus_MoveHandlerVerticalShinespark(void) { // 0x90D0AB + samus_contact_damage_index = 2; + samus_hurt_flash_counter = 8; + Samus_UpdateSpeedEchoPos(); + Samus_ShinesparkMove_Y(); + Samus_EndSuperJump(); + if (!sign16(samus_health - 30) && (--samus_health & 0x8000u) != 0) + samus_health = 0; +} + +void Samus_MoveHandler_Shinespark_Diag(void) { // 0x90D0D7 + samus_contact_damage_index = 2; + samus_hurt_flash_counter = 8; + Samus_UpdateSpeedEchoPos(); + Samus_ShinesparkMove_X(); + Samus_ShinesparkMove_Y(); + Samus_EndSuperJump(); + if (!sign16(samus_health - 30) && (--samus_health & 0x8000u) != 0) + samus_health = 0; +} + +void Samus_MoveHandler_Shinespark_Horiz(void) { // 0x90D106 + samus_contact_damage_index = 2; + samus_hurt_flash_counter = 8; + Samus_UpdateSpeedEchoPos(); + Samus_ShinesparkMove_X(); + Samus_EndSuperJump(); + if (!sign16(samus_health - 30) && (--samus_health & 0x8000u) != 0) + samus_health = 0; +} + +void Samus_ShinesparkMove_X(void) { // 0x90D132 + int16 v4; + + samus_shine_timer = 15; + uint16 v0 = (__PAIR32__(samus_y_accel, samus_y_subaccel) + __PAIR32__(samus_x_extra_run_speed, samus_x_extra_run_subspeed)) >> 16; + samus_x_extra_run_subspeed += samus_y_subaccel; + samus_x_extra_run_speed = v0; + if (!sign16(v0 - 15)) { + samus_x_extra_run_speed = 15; + samus_x_extra_run_subspeed = 0; + } + R18_ = 0; + R20_ = 0; + if (samus_pose_x_dir == 4) { + Samus_CalcDisplacementMoveLeft(); + R18_ = ~R18_; + bool v2 = R20_ == 0; + R20_ = -R20_; + if (v2) + ++R18_; + if (!sign16(R18_ - 15)) + R18_ = 15; + uint16 v3 = Samus_CheckSolidEnemyColl(); + if (v3) { + samus_collision_flag = v3; + goto LABEL_18; + } + R18_ = ~R18_; + v2 = R20_ == 0; + R20_ = -R20_; + if (v2) + ++R18_; + } else { + Samus_CalcDisplacementMoveRight(); + if (!sign16(R18_ - 15)) + R18_ = 15; + uint16 v1 = Samus_CheckSolidEnemyColl(); + if (v1) { + samus_collision_flag = v1; + goto LABEL_18; + } + } + Samus_MoveRight_NoSolidColl(); + Samus_AlignYPosSlope(); +LABEL_18: + v4 = samus_x_pos - samus_prev_x_pos; + if ((int16)(samus_x_pos - samus_prev_x_pos) < 0) { + if (sign16(v4 + 15)) + samus_prev_x_pos = samus_x_pos + 15; + } else if (!sign16(v4 - 16)) { + samus_prev_x_pos = samus_x_pos - 15; + } +} + +void Samus_ShinesparkMove_Y(void) { // 0x90D1FF + int16 v3; + + samus_shine_timer = 15; + uint16 v0 = (__PAIR32__(samus_y_accel, samus_y_subaccel) + __PAIR32__(substate, suit_pickup_light_beam_pos)) >> 16; + suit_pickup_light_beam_pos += samus_y_subaccel; + substate = v0; + bool v1 = __CFADD__uint16(suit_pickup_light_beam_pos, samus_y_subspeed); + samus_y_subspeed += suit_pickup_light_beam_pos; + R20_ = samus_y_subspeed; + samus_y_speed += v0 + v1; + R18_ = samus_y_speed; + if (!sign16(samus_y_speed - 14)) + R18_ = 14; + R18_ = ~R18_; + bool v2 = R20_ == 0; + R20_ = -R20_; + if (v2) + ++R18_; + v3 = (__PAIR32__(R18_, R20_) + __PAIR32__(extra_samus_y_displacement, extra_samus_y_subdisplacement)) >> 16; + R20_ += extra_samus_y_subdisplacement; + samus_collision_direction = 2; + R18_ = ~v3; + v2 = R20_ == 0; + R20_ = -R20_; + if (v2) + ++R18_; + if (!sign16(R18_ - 15)) + R18_ = 15; + uint16 v4 = Samus_CheckSolidEnemyColl(); + if (v4) { + samus_collision_flag = v4; + } else { + R18_ = ~R18_; + v2 = R20_ == 0; + R20_ = -R20_; + if (v2) + ++R18_; + Samus_MoveDown_NoSolidColl(); + } + if (sign16(samus_y_pos - samus_prev_y_pos + 14)) + samus_prev_y_pos = samus_y_pos + 14; +} + +uint8 Samus_EndSuperJump(void) { // 0x90D2BA + if (!sign16(samus_health - 30) && !samus_collision_flag) + return 0; + if (samus_pose_x_dir == 4) { + speed_echo_xspeed[0] = 32; + speed_echo_xspeed[1] = 160; + speed_echo_xpos[2] = 4; + } else { + speed_echo_xspeed[0] = 224; + speed_echo_xspeed[1] = 96; + speed_echo_xpos[2] = -4; + } + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + speed_boost_counter = 0; + UNUSED_word_7E0B1A = 0; + samus_y_dir = 0; + samus_movement_handler = FUNC16(Samus_MoveHandler_ShinesparkCrash); + samus_draw_handler = FUNC16(Samus_DrawHandler_EndOfShinespark); + speed_echoes_index = 0; + speed_echo_xpos[0] = samus_x_pos; + speed_echo_xpos[1] = samus_x_pos; + speed_echo_ypos[0] = samus_y_pos; + speed_echo_ypos[1] = samus_y_pos; + speed_echo_xspeed[2] = 0; + samus_hurt_flash_counter = 0; + QueueSfx1_Max6(0x35u); + QueueSfx3_Max6(0x10u); + return 1; +} + +static Func_V *const kSamus_MoveHandler_ShinesparkCrash[3] = { // 0x90D346 + Samus_MoveHandler_ShinesparkCrash_0, + Samus_MoveHandler_ShinesparkCrash_1, + Samus_MoveHandler_ShinesparkCrash_2, +}; + +void Samus_MoveHandler_ShinesparkCrash(void) { + + samus_shine_timer = 15; + kSamus_MoveHandler_ShinesparkCrash[(uint16)(2 * HIBYTE(speed_echoes_index)) >> 1](); + for (int i = 2; i >= 0; i -= 2) { + int v1 = i >> 1; + Projectile_SinLookup(speed_echo_xspeed[v1], (uint8)speed_echoes_index); + speed_echo_xpos[v1] = R20_ + samus_x_pos; + speed_echo_ypos[v1] = R22_ + samus_y_pos; + } +} + +void Samus_MoveHandler_ShinesparkCrash_0(void) { // 0x90D383 + uint16 v0 = speed_echoes_index + 4; + if (!sign16(speed_echoes_index - 12)) + v0 |= 0x100u; + speed_echoes_index = v0; +} + +void Samus_MoveHandler_ShinesparkCrash_1(void) { // 0x90D396 + speed_echo_xspeed[0] = (uint8)(LOBYTE(speed_echo_xpos[2]) + LOBYTE(speed_echo_xspeed[0])); + speed_echo_xspeed[1] = (uint8)(LOBYTE(speed_echo_xpos[2]) + LOBYTE(speed_echo_xspeed[1])); + speed_echo_ypos[2] += 4; + if (!sign16(speed_echo_ypos[2] - 128)) + speed_echoes_index = (uint8)speed_echoes_index | 0x200; +} + +void Samus_MoveHandler_ShinesparkCrash_2(void) { // 0x90D3CC + speed_echoes_index -= 4; + if (!(uint8)speed_echoes_index) { + samus_movement_handler = FUNC16(Samus_MoveHandler_ShinesparkCrashEchoCircle); + timer_for_shinesparks_startstop = 30; + speed_echoes_index = 0; + speed_echo_xspeed[0] = 0; + speed_echo_xspeed[1] = 0; + } +} + +void Samus_MoveHandler_ShinesparkCrashEchoCircle(void) { // 0x90D3F3 + samus_shine_timer = 15; + bool v0 = (--timer_for_shinesparks_startstop & 0x8000u) != 0; + if (!timer_for_shinesparks_startstop || v0) { + samus_movement_handler = FUNC16(Samus_MoveHandler_ShinesparkCrashFinish); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + } +} + +void Samus_MoveHandler_ShinesparkCrashFinish(void) { // 0x90D40D + static const uint8 kShinesparkCrashFinish_Tab0[12] = { 0, 0x80, 0, 0x80, 0x40, 0xc0, 0x40, 0xc0, 0xe0, 0x60, 0x20, 0xa0 }; + speed_echoes_index = 0; + if (sign16(projectile_counter - 5)) { + if (sign16(projectile_counter - 4)) { + ++projectile_counter; + speed_echo_xspeed[2] = 64; + speed_echo_xpos[2] = samus_x_pos; + speed_echo_ypos[2] = samus_y_pos; + projectile_type[3] = addr_loc_908029; + InitializeShinesparkEchoOrSpazerSba(6u); + projectile_bomb_pre_instructions[3] = FUNC16(ProjPreInstr_SpeedEcho); + projectile_variables[3] = kShinesparkCrashFinish_Tab0[(uint16)(2 * (samus_pose - 201))]; + projectile_bomb_x_speed[3] = 0; + } + ++projectile_counter; + speed_echo_xspeed[3] = 64; + speed_echo_xpos[3] = samus_x_pos; + speed_echo_ypos[3] = samus_y_pos; + projectile_type[4] = addr_loc_908029; + InitializeShinesparkEchoOrSpazerSba(8u); + projectile_bomb_pre_instructions[4] = FUNC16(ProjPreInstr_SpeedEcho); + projectile_variables[4] = kShinesparkCrashFinish_Tab0[(uint16)(2 * (samus_pose - 201)) + 1]; + projectile_bomb_x_speed[4] = 0; + } + cooldown_timer = 0; + samus_shine_timer = 1; + if (samus_pose_x_dir == 4) + samus_new_pose_transitional = 2; + else + samus_new_pose_transitional = 1; + samus_hurt_switch_index = 2; + substate = 0; + suit_pickup_light_beam_pos = 0; +} + +void ProjPreInstr_SpeedEcho(uint16 k) { // 0x90D4D2 + int16 v3; + uint16 v4; + int16 v5; + + int v1 = k >> 1; + projectile_bomb_x_speed[v1] += 8; + Projectile_SinLookup(projectile_variables[v1], LOBYTE(projectile_bomb_x_speed[v1])); + uint16 v2 = R20_ + samus_x_pos; + *(uint16 *)((char *)&speed_echoes_index + k) = R20_ + samus_x_pos; + projectile_x_pos[v1] = v2; + v3 = v2 - layer1_x_pos; + if (v3 < 0 + || !sign16(v3 - 256) + || (v4 = R22_ + samus_y_pos, + speed_echo_xpos[v1 + 3] = R22_ + samus_y_pos, + projectile_y_pos[v1] = v4, + v5 = v4 - layer1_y_pos, + v5 < 0) + || !sign16(v5 - 256)) { + speed_echo_ypos[v1 + 3] = 0; + *(uint16 *)((char *)&speed_echoes_index + k) = 0; + speed_echo_xpos[v1 + 3] = 0; + ClearProjectile(k); + } +} + +void Grapple_Func1(void) { // 0x90D525 + bool v0; // sf + + if ((button_config_shoot_x & joypad1_lastkeys) != 0 + && (v0 = (int16)(grapple_walljump_timer - 1) < 0, --grapple_walljump_timer, grapple_walljump_timer) + && !v0) { + if ((grapple_beam_length_delta & 0x8000u) == 0) { + grapple_beam_length += grapple_beam_length_delta; + if (!sign16(grapple_beam_length - 96)) + grapple_beam_length_delta = -16; + } + Projectile_SinLookup(HIBYTE(*(uint16 *)&grapple_beam_end_subangle), grapple_beam_length); + grapple_beam_end_x_pos = R20_ + x_pos_of_start_of_grapple_beam; + grapple_beam_end_y_pos = R22_ + y_pos_of_start_of_grapple_beam; + *(uint16 *)&grapple_beam_end_subangle += 2048; + GrappleBeamFunc_BF1B(); + } else { + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + } +} + +uint8 Hdmaobj_CrystalFlash(void) { // 0x90D5A2 + SamusPose v1; + + if (sign16(game_state - 40)) { + R18_ = button_config_shoot_x | 0x430; + if (joypad1_lastkeys != (button_config_shoot_x | 0x430)) + return 1; + } + if (samus_y_speed + || samus_y_subspeed + || !sign16(samus_health - 51) + || samus_reserve_health + || sign16(samus_missiles - 10) + || sign16(samus_super_missiles - 10) + || sign16(samus_power_bombs - 10)) { + return 1; + } + v1 = samus_pose_x_dir == 4 ? kPose_D4_FaceL_CrystalFlash : kPose_D3_FaceR_CrystalFlash; + samus_pose = v1; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + if (samus_movement_type != 27) + return 1; + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + samus_movement_handler = FUNC16(SamusMoveHandler_CrystalFlashStart); + if (samus_input_handler != (uint16)FUNC16(Samus_InputHandler_E91D)) + samus_input_handler = FUNC16(nullsub_152); + timer_for_shinesparks_startstop = 9; + which_item_to_pickup = 0; + substate = 10; + suit_pickup_light_beam_pos = 0; + *(uint16 *)&suit_pickup_color_math_R = 0; + timer_for_shine_timer = 7; + special_samus_palette_frame = 0; + samus_shine_timer = 1; + *(uint16 *)&suit_pickup_color_math_B = 1; + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + knockback_dir = 0; + return 0; +} + +void SamusMoveHandler_CrystalFlashStart(void) { // 0x90D678 + samus_y_pos -= 2; + if ((--timer_for_shinesparks_startstop & 0x8000u) != 0) { + samus_anim_frame_timer = 3; + samus_anim_frame = 6; + *(uint16 *)&suit_pickup_color_math_R = samus_y_pos; + samus_movement_handler = FUNC16(SamusMoveHandler_CrystalFlashMain); + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + QueueSfx3_Max15(1u); + power_bomb_flag = 0; + power_bomb_explosion_x_pos = samus_x_pos; + power_bomb_explosion_y_pos = samus_y_pos; + EnableHdmaObjects(); + SpawnCrystalFlashHdmaObjs(); + } +} + +static Func_V *const kSamusMoveHandler_CrystalFlashMainFuncs[3] = { // 0x90D6CE + SamusMoveHandler_CrystalFlashMain_0, + SamusMoveHandler_CrystalFlashMain_1, + SamusMoveHandler_CrystalFlashMain_2, +}; + +void SamusMoveHandler_CrystalFlashMain(void) { + kSamusMoveHandler_CrystalFlashMainFuncs[which_item_to_pickup](); + samus_invincibility_timer = 0; + samus_knockback_timer = 0; +} + +void SamusMoveHandler_CrystalFlashMain_0(void) { // 0x90D6E3 + if ((nmi_frame_counter_word & 7) == 0) { + --samus_missiles; + Samus_RestoreHealth(0x32u); + bool v0 = (int16)(substate - 1) < 0; + if (!--substate || v0) { + substate = 10; + ++which_item_to_pickup; + } + } +} + +void SamusMoveHandler_CrystalFlashMain_1(void) { // 0x90D706 + if ((nmi_frame_counter_word & 7) == 0) { + --samus_super_missiles; + Samus_RestoreHealth(0x32u); + bool v0 = (int16)(substate - 1) < 0; + if (!--substate || v0) { + substate = 10; + ++which_item_to_pickup; + } + } +} + +void SamusMoveHandler_CrystalFlashMain_2(void) { // 0x90D729 + if ((nmi_frame_counter_word & 7) == 0) { + --samus_power_bombs; + Samus_RestoreHealth(0x32u); + bool v0 = (int16)(substate - 1) < 0; + if (!--substate || v0) { + samus_movement_handler = FUNC16(kSamusMoveHandler_CrystalFlashFinish); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + samus_anim_frame_timer = 3; + samus_anim_frame = 12; + } + } +} + +void kSamusMoveHandler_CrystalFlashFinish(void) { // 0x90D75B + if (samus_y_pos != *(uint16 *)&suit_pickup_color_math_R) + ++samus_y_pos; + if (!samus_movement_type) { + power_bomb_flag = 0; + samus_shine_timer = -1; + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + if (samus_input_handler != (uint16)FUNC16(Samus_InputHandler_E91D)) { + samus_input_handler = FUNC16(Samus_InputHandler_E913); + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + } + } +} + +void ProjPreInstr_PlasmaSba(uint16 k) { // 0x90D793 + int16 v3; + + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) { + ClearProjectile(k); + } else { + cooldown_timer = 2; + flare_counter = 0; + Projectile_SinLookup(projectile_variables[v1], projectile_bomb_x_speed[v1]); + projectile_x_pos[v1] = R20_ + samus_x_pos; + projectile_y_pos[v1] = R22_ + samus_y_pos; + projectile_variables[v1] = (uint8)(used_for_sba_attacksB60 + projectile_variables[v1]); + v3 = 2 * projectile_bomb_y_speed[v1]; + if (v3) { + if (v3 == 2) { + ProjPreInstr_PlasmaSbaFunc_1(k); + } else { + if (v3 != 4) { + Unreachable(); + while (1) + ; + } + ProjPreInstr_PlasmaSbaFunc_2(k); + } + } else { + ProjPreInstr_PlasmaSbaFunc_0(k); + } + } +} + +void ProjPreInstr_PlasmaSbaFunc_0(uint16 j) { // 0x90D7E1 + int v1 = j >> 1; + uint16 v2 = (uint8)(projectile_bomb_x_speed[v1] + 4); + projectile_bomb_x_speed[v1] = v2; + if (!sign16(v2 - 192)) + projectile_bomb_y_speed[v1] = 1; +} + +void ProjPreInstr_PlasmaSbaFunc_1(uint16 j) { // 0x90D7FA + int v1 = j >> 1; + uint16 v2 = (uint8)(projectile_bomb_x_speed[v1] - 4); + projectile_bomb_x_speed[v1] = v2; + if (sign16(v2 - 45)) + projectile_bomb_y_speed[v1] = 2; +} + +void ProjPreInstr_PlasmaSbaFunc_2(uint16 j) { // 0x90D813 + int v1 = j >> 1; + if (sign16(projectile_x_pos[v1] - layer1_x_pos + 32) + || !sign16(projectile_x_pos[v1] - layer1_x_pos - 288) + || sign16(projectile_y_pos[v1] - layer1_y_pos - 16) + || !sign16(projectile_y_pos[v1] - layer1_y_pos - 256)) { + ClearProjectile(j); + } else { + projectile_bomb_x_speed[v1] = (uint8)(projectile_bomb_x_speed[v1] + 4); + } +} + +static const uint16 kBombSpread_Tab0[5] = { 0x78, 0x6e, 0x64, 0x6e, 0x78 }; +static const uint16 kBombSpread_Tab1[5] = { 0x8100, 0x8080, 0, 0x80, 0x100 }; +static const uint16 kBombSpread_Tab2[5] = { 0, 1, 2, 1, 0 }; +static const uint16 kBombSpread_Tab3[5] = { 0, 0, 0x8000, 0, 0 }; + +void ProjPreInstr_SpreadBomb(uint16 k) { // 0x90D8F7 + int16 v13; + int16 v17; + uint16 v9; + + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) { + ClearProjectile(k); + return; + } + Bomb_Func2(); + if (projectile_variables[v1]) { + uint16 v2 = projectile_timers[v1]; + bool v3 = __CFADD__uint16(samus_y_subaccel, v2); + projectile_timers[v1] = samus_y_subaccel + v2; + projectile_bomb_y_speed[v1] += samus_y_accel + v3; + uint16 v4 = projectile_bomb_y_subpos[v1]; + v3 = __CFADD__uint16(projectile_timers[v1], v4); + projectile_bomb_y_subpos[v1] = projectile_timers[v1] + v4; + projectile_y_pos[v1] += projectile_bomb_y_speed[v1] + v3; + if (BlockCollSpreadBomb(k) & 1) { + uint16 v5 = projectile_index - 10; + int v6 = projectile_index >> 1; + uint16 v7 = projectile_bomb_y_subpos[v6]; + v3 = v7 < projectile_timers[v6]; + projectile_bomb_y_subpos[v6] = v7 - projectile_timers[v6]; + projectile_y_pos[v6] -= v3 + projectile_bomb_y_speed[v6]; + if ((projectile_bomb_y_speed[v6] & 0x8000u) != 0) { + projectile_bomb_y_speed[v6] = 0; + projectile_y_radius[v6] = 0; + } else { + projectile_timers[v6] = kBombSpread_Tab3[v5 >> 1]; + projectile_bomb_y_speed[v6] = projectile_unk_A[v6]; + } + return; + } + k = projectile_index; + int v8 = projectile_index >> 1; + LOBYTE(v9) = HIBYTE(projectile_bomb_x_speed[v8]); + HIBYTE(v9) = projectile_bomb_x_speed[v8]; + R20_ = v9 & 0xFF00; + v9 = (uint8)v9; + R18_ = v9; + if ((v9 & 0x80) != 0) { + R18_ = v9 & 0x7F; + uint16 v11 = projectile_bomb_x_subpos[v8]; + v3 = v11 < R20_; + projectile_bomb_x_subpos[v8] = v11 - R20_; + projectile_x_pos[v8] -= v3 + R18_; + } else { + uint16 v10 = projectile_bomb_x_subpos[v8]; + v3 = __CFADD__uint16(R20_, v10); + projectile_bomb_x_subpos[v8] = R20_ + v10; + projectile_x_pos[v8] += R18_ + v3; + } + } + if (BlockCollSpreadBomb(k) & 1) { + int v12 = projectile_index >> 1; + v17 = projectile_bomb_x_speed[v12]; + LOBYTE(v13) = HIBYTE(v17); + HIBYTE(v13) = v17; + R20_ = v13 & 0xFF00; + R18_ = HIBYTE(v17) & 0x7F; + uint16 v15; + if (v17 >= 0) { + projectile_bomb_x_speed[v12] = v17 | 0x8000; + uint16 v16 = projectile_bomb_x_subpos[v12]; + bool v3 = v16 < R20_; + projectile_bomb_x_subpos[v12] = v16 - R20_; + v15 = projectile_x_pos[v12] - (v3 + R18_); + } else { + projectile_bomb_x_speed[v12] = v17 & 0x7FFF; + uint16 v14 = projectile_bomb_x_subpos[v12]; + bool v3 = __CFADD__uint16(R20_, v14); + projectile_bomb_x_subpos[v12] = R20_ + v14; + v15 = R18_ + v3 + projectile_x_pos[v12]; + } + projectile_x_pos[v12] = v15; + } +} + +void ProjPreInstr_WaveSba(uint16 k) { // 0x90DA08 + int v1 = k >> 1; + bool v2, v3; + if ((projectile_dir[v1] & 0xF0) != 0 + || (v2 = projectile_bomb_y_speed[v1] == 1, + v3 = (int16)(projectile_bomb_y_speed[v1] - 1) < 0, + --projectile_bomb_y_speed[v1], + v2) + || v3) { + QueueSfx1_Max6(0x29u); + ClearProjectile(k); + return; + } + R34 = projectile_bomb_x_speed[v1]; + R36 = projectile_variables[v1]; + v2 = projectile_timers[v1]-- == 1; + if (v2) { + projectile_timers[v1] = 4; + SpawnProjectileTrail(k); + k = projectile_index; + } + int v4 = k >> 1; + if ((int16)(samus_x_pos - projectile_x_pos[v4]) < 0) { + if (!sign16(projectile_bomb_x_speed[v4] + 2047)) + projectile_bomb_x_speed[v4] -= 64; + } else if (sign16(projectile_bomb_x_speed[v4] - 2048)) { + projectile_bomb_x_speed[v4] += 64; + } + uint16 v5; + LOBYTE(v5) = HIBYTE(projectile_bomb_x_speed[v4]); + HIBYTE(v5) = projectile_bomb_x_speed[v4]; + R20_ = v5 & 0xFF00; + v5 = (uint8)v5; + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + R18_ = v5; + uint16 v6 = projectile_bomb_x_subpos[v4]; + bool v7 = __CFADD__uint16(R20_, v6); + projectile_bomb_x_subpos[v4] = R20_ + v6; + projectile_x_pos[v4] += R18_ + v7; + if ((int16)(samus_y_pos - projectile_y_pos[v4]) < 0) { + if (!sign16(projectile_variables[v4] + 2047)) + projectile_variables[v4] -= 64; + } else if (sign16(projectile_variables[v4] - 2048)) { + projectile_variables[v4] += 64; + } + uint16 v8; + LOBYTE(v8) = HIBYTE(projectile_variables[v4]); + HIBYTE(v8) = projectile_variables[v4]; + R20_ = v8 & 0xFF00; + v8 = (uint8)v8; + if ((v8 & 0x80) != 0) + v8 |= 0xFF00u; + R18_ = v8; + uint16 v9 = projectile_bomb_y_subpos[v4]; + v7 = __CFADD__uint16(R20_, v9); + projectile_bomb_y_subpos[v4] = R20_ + v9; + projectile_y_pos[v4] += R18_ + v7; + if (k == 6) { + if ((projectile_bomb_x_speed[3] & 0x8000u) != 0) { + if ((R34 & 0x8000u) == 0) + LABEL_26: + QueueSfx1_Max6(0x28u); + } else if ((R34 & 0x8000u) != 0) { + goto LABEL_26; + } + } + cooldown_timer = 2; + flare_counter = 0; +} + + +void BombSpread(void) { // 0x90D849 + if (bomb_functions[0] != (uint16)FUNC16(ProjPreInstr_SpreadBomb)) { + uint16 v0 = 10; + do { + int v1 = v0 >> 1; + projectile_type[v1] = -31488; + projectile_dir[v1] = 0; + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_SpreadBomb); + InitializeInstrForMissile(v0); + projectile_x_pos[v1] = samus_x_pos; + projectile_bomb_x_subpos[v1] = 0; + projectile_y_pos[v1] = samus_y_pos; + projectile_bomb_y_subpos[v1] = 0; + int v2 = (uint16)(v0 - 10) >> 1; + projectile_bomb_x_speed[v1] = kBombSpread_Tab1[v2]; + projectile_timers[v1] = kBombSpread_Tab3[v2]; + uint16 v3 = -(int16)(kBombSpread_Tab2[v2] + ((bomb_spread_charge_timeout_counter >> 6) & 3)); + projectile_bomb_y_speed[v1] = v3; + projectile_unk_A[v1] = v3; + projectile_variables[v1] = kBombSpread_Tab0[v2]; + v0 += 2; + } while ((int16)(v0 - 20) < 0); + bomb_counter = 5; + cooldown_timer = kNonBeamProjectileCooldowns[HIBYTE(projectile_type[5]) & 0xF]; + bomb_spread_charge_timeout_counter = 0; + flare_counter = 0; + } +} + +static Func_Y_V *const kProjPreInstr_SpazerSba_FuncsB[3] = { // 0x90DB06 + ProjPreInstr_SpazerSba_FuncB_0, + ProjPreInstr_SpazerSba_FuncB_1, + ProjPreInstr_SpazerSba_FuncB_2, +}; +static Func_Y_V *const kProjPreInstr_SpazerSba_FuncsA[4] = { + ProjPreInstr_SpazerSba_FuncA_0, + ProjPreInstr_SpazerSba_FuncA_1, + ProjPreInstr_SpazerSba_FuncA_2, + ProjPreInstr_SpazerSba_FuncA_3, +}; + +void ProjPreInstr_SpazerSba(uint16 k) { + + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) { + kProjPreInstr_SpazerSba_FuncsA[v1](k); + } else { + int v2 = k >> 1; + if (projectile_timers[v2]-- == 1) { + projectile_timers[v2] = 4; + SpawnProjectileTrail(k); + k = projectile_index; + } + int v4 = k >> 1; + Projectile_SinLookup(projectile_variables[v4], projectile_bomb_x_speed[v4]); + projectile_x_pos[v4] = R20_ + samus_x_pos; + kProjPreInstr_SpazerSba_FuncsB[projectile_unk_A[v4] >> 1](k); + cooldown_timer = 2; + flare_counter = 0; + } +} + +void ProjPreInstr_SpazerSba_FuncA_0(uint16 k) { // 0x90DB57 + ClearProjectile(k); + ClearProjectile(4u); +} + +void ProjPreInstr_SpazerSba_FuncA_1(uint16 k) { // 0x90DB66 + ClearProjectile(k); + ClearProjectile(6u); +} + +void ProjPreInstr_SpazerSba_FuncA_2(uint16 k) { // 0x90DB75 + ClearProjectile(k); + ClearProjectile(0); +} + +void ProjPreInstr_SpazerSba_FuncA_3(uint16 k) { // 0x90DB84 + ClearProjectile(k); + ClearProjectile(2u); +} + +void ProjPreInstr_SpazerSba_FuncB_0(uint16 j) { // 0x90DB93 + static const int16 kProjPreInstr_SpazerSba_Yspeed[4] = { 2, -2, 2, -2 }; + + int v1 = j >> 1; + projectile_y_pos[v1] = R22_ + samus_y_pos; + uint16 v2 = (uint8)(LOBYTE(projectile_bomb_y_speed[v1]) + LOBYTE(projectile_variables[v1])); + projectile_variables[v1] = v2; + if (v2 == 128) { + projectile_bomb_x_speed[v1] = 160; + projectile_bomb_y_speed[v1] = kProjPreInstr_SpazerSba_Yspeed[v1]; + projectile_dir[v1] = 0; + projectile_unk_A[v1] = 2; + } +} + +void ProjPreInstr_SpazerSba_FuncB_1(uint16 j) { // 0x90DBCF + static const int16 kSpazerProjectileYSpeed[4] = { -2, 2, -2, 2 }; + + uint16 v1 = R22_ + samus_y_pos - 114; + int v2 = j >> 1; + projectile_y_pos[v2] = v1; + if (sign16(v1 - layer1_y_pos - 16)) { + FireEndOfSpazerSba(j); + } else { + projectile_variables[v2] = (uint8)(LOBYTE(projectile_bomb_y_speed[v2]) + LOBYTE(projectile_variables[v2])); + uint16 v3 = projectile_bomb_x_speed[v2] - 5; + projectile_bomb_x_speed[v2] = v3; + if (!v3) { + projectile_bomb_y_speed[v2] = kSpazerProjectileYSpeed[v2]; + projectile_variables[v2] = (uint8)(projectile_variables[v2] + 0x80); + projectile_unk_A[v2] = 4; + if (!j) + QueueSfx1_Max6(0x26u); + } + } +} + +void ProjPreInstr_SpazerSba_FuncB_2(uint16 j) { // 0x90DC30 + int v2; + uint16 v3; + + uint16 v1 = R22_ + samus_y_pos - 114; + projectile_y_pos[j >> 1] = v1; + if (sign16(v1 - layer1_y_pos - 16) + || (v2 = j >> 1, + projectile_variables[v2] = (uint8)(LOBYTE(projectile_bomb_y_speed[v2]) + + LOBYTE(projectile_variables[v2])), + v3 = projectile_bomb_x_speed[v2] + 5, + projectile_bomb_x_speed[v2] = v3, + !sign16(v3 - 96))) { + FireEndOfSpazerSba(j); + } +} + +void FireEndOfSpazerSba(uint16 j) { // 0x90DC67 + static const int16 kFireEndOfSpazerSba[4] = { 16, 16, -16, -16 }; + + int v1 = j >> 1; + projectile_x_pos[v1] += kFireEndOfSpazerSba[v1]; + projectile_dir[v1] = 5; + projectile_timers[v1] = 4; + projectile_bomb_pre_instructions[v1] = FUNC16(ProjPreInstr_EndOfSpazerSba); + if ((int16)(j - 4) < 0) { + projectile_type[j >> 1] = -32732; + InitializeShinesparkEchoOrSpazerSba(j); + } +} + +void ProjPreInstr_EndOfSpazerSba(uint16 k) { // 0x90DC9C + int v1 = k >> 1; + if ((projectile_dir[v1] & 0xF0) != 0) + goto LABEL_2; + if (projectile_timers[v1]-- == 1) { + projectile_timers[v1] = 4; + SpawnProjectileTrail(k); + k = projectile_index; + } + int v3; + v3 = k >> 1; + uint16 v4; + v4 = projectile_y_pos[v3] + 8; + projectile_y_pos[v3] = v4; + if (!sign16(v4 - layer1_y_pos - 248)) { +LABEL_2: + ClearProjectile(k); + } else { + cooldown_timer = 2; + flare_counter = 0; + } +} + +static Func_V *kHandleHudSpecificBehaviorAndProjs[28] = { // 0x90DCDD + HudSelectionHandler_Normal, + HudSelectionHandler_Normal, + HudSelectionHandler_Normal, + HudSelectionHandler_JumpEtc, + HudSelectionHandler_MorphBall, + HudSelectionHandler_Normal, + HudSelectionHandler_Normal, + HudSelectionHandler_MorphBall, + HudSelectionHandler_MorphBall, + HudSelectionHandler_MorphBall, + HudSelectionHandler_JumpEtc, + HudSelectionHandler_Grappling, + HudSelectionHandler_Grappling, + HudSelectionHandler_JumpEtc, + HudSelectionHandler_TurningAround, + HudSelectionHandler_CrouchEtcTrans, + HudSelectionHandler_Normal, + HudSelectionHandler_MorphBall, + HudSelectionHandler_MorphBall, + HudSelectionHandler_MorphBall, + HudSelectionHandler_JumpEtc, + HudSelectionHandler_Normal, + HudSelectionHandler_Grappling, + HudSelectionHandler_TurningAround, + HudSelectionHandler_TurningAround, + HudSelectionHandler_JumpEtc, + HudSelectionHandler_GrabbedByDraygon, + HudSelectionHandler_JumpEtc, +}; + +void Samus_HandleHudSpecificBehaviorAndProjs(void) { + if (samus_pose == kPose_00_FaceF_Powersuit + || samus_pose == kPose_9B_FaceF_VariaGravitySuit + || (Samus_HandleCooldown(), + HandleSwitchingHudSelection(), + kHandleHudSpecificBehaviorAndProjs[samus_movement_type](), + !time_is_frozen_flag)) { + HandleProjectile(); + } +} + +void HudSelectionHandler_Normal(void) { // 0x90DD3D + static Func_V *const kHudSelectionHandler_Normal[7] = { + HudSelectionHandler_NothingOrPowerBombs, + HudSelectionHandler_MissilesOrSuperMissiles, + HudSelectionHandler_MissilesOrSuperMissiles, + HudSelectionHandler_NothingOrPowerBombs, + HudSelectionHandler_Grappling, + HudSelectionHandler_Xray, + HudSelectionHandler_TurningAround, + }; + uint16 v0; + if (grapple_beam_function == (uint16)FUNC16(GrappleBeamFunc_Inactive)) { + if (time_is_frozen_flag) + v0 = 10; + else + v0 = 2 * hud_item_index; + } else { + v0 = 8; + } + kHudSelectionHandler_Normal[v0 >> 1](); +} + +void HudSelectionHandler_Grappling(void) { // 0x90DD6F + GrappleBeamHandler(); +} + +void HudSelectionHandler_TurningAround(void) { // 0x90DD74 + if (new_projectile_direction_changed_pose) { + HudSelectionHandler_Normal(); + } else if (grapple_beam_function != (uint16)FUNC16(GrappleBeamFunc_Inactive)) { + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + } +} + +void HudSelectionHandler_CrouchEtcTrans(void) { // 0x90DD8C + static const uint8 byte_90DDAA[12] = { 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 }; + if (!sign16(samus_pose - kPose_F1_FaceR_CrouchTrans_AimU)) + goto LABEL_4; + if (!sign16(samus_pose - kPose_DB)) + return; + if (byte_90DDAA[(uint16)(samus_pose - 53)]) { + if (grapple_beam_function != (uint16)FUNC16(GrappleBeamFunc_Inactive)) { + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + HudSelectionHandler_Normal(); + } + } else { +LABEL_4: + HudSelectionHandler_Normal(); + } +} + +void HudSelectionHandler_JumpEtc(void) { // 0x90DDB6 + if (grapple_beam_function != (uint16)FUNC16(GrappleBeamFunc_Inactive)) { + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + HudSelectionHandler_Normal(); + } +} + +void HudSelectionHandler_Xray(void) { // 0x90DDC8 + if ((button_config_run_b & joypad1_lastkeys) != 0) + XrayRunHandler(); + else + HudSelectionHandler_NothingOrPowerBombs(); +} + +void HudSelectionHandler_GrabbedByDraygon(void) { // 0x90DDD8 + if (samus_pose == (kPose_DB | kPose_04_FaceL_AimU)) + HudSelectionHandler_MorphBall(); + else + HudSelectionHandler_Normal(); +} + +static Func_U8 *const kSamusHitInterrupts[28] = { // 0x90DDE9 + Samus_HitInterrupt_Stand, + Samus_HitInterrupt_Stand, + Samus_HitInterrupt_Stand, + Samus_HitInterrupt_Stand, + Samus_HitInterrupt_Ball, + Samus_HitInterrupt_Stand, + Samus_HitInterrupt_Falling, + Samus_HitInterrupt_Unused, + Samus_HitInterrupt_Ball, + Samus_HitInterrupt_Ball, + Samus_HitInterrupt_KnockbackGrapple, + Samus_HitInterrupt_Turning, + Samus_HitInterrupt_Turning, + Samus_HitInterrupt_Stand, + Samus_HitInterrupt_Turning, + Samus_HitInterrupt_Turning, + Samus_HitInterrupt_Stand, + Samus_HitInterrupt_Ball, + Samus_HitInterrupt_Ball, + Samus_HitInterrupt_Ball, + Samus_HitInterrupt_Stand, + Samus_HitInterrupt_Stand, + Samus_HitInterrupt_KnockbackGrapple, + Samus_HitInterrupt_Turning, + Samus_HitInterrupt_Turning, + Samus_HitInterrupt_Turning, + Samus_HitInterrupt_Turning, + Samus_HitInterrupt_Shinespark, +}; + +void Samus_HitInterruption(void) { + if (samus_knockback_timer) { + if (sign16(debug_invincibility - 7)) { + if (!time_is_frozen_flag && !knockback_dir) { + if (kSamusHitInterrupts[samus_movement_type]() & 1) + samus_special_transgfx_index = 1; + } + } else { + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + } + } else if (knockback_dir) { + if (samus_movement_type == kPose_0A_MoveL_NoAim) { + if (!sign16(flare_counter - 16)) + QueueSfx1_Max6(0x41u); + if (samus_pose_x_dir == 4) + samus_new_pose_transitional = kPose_2A_FaceL_Fall; + else + samus_new_pose_transitional = kPose_29_FaceR_Fall; + } else { + if (samus_hurt_switch_index == 3) { + samus_hurt_switch_index = 8; + return; + } + samus_new_pose_transitional = samus_pose; + } + samus_hurt_switch_index = 1; + } else if (bomb_jump_dir) { + SetupBombJump(); + } +} + +uint8 Samus_HitInterrupt_Shinespark(void) { // 0x90DEBA + if (samus_pose == kPose_E8_FaceR_Drained_CrouchFalling || samus_pose == kPose_E9_FaceL_Drained_CrouchFalling) { + samus_anim_frame_timer = 17; + samus_anim_frame = 26; + } + samus_special_transgfx_index = 0; + knockback_dir = 0; + return 0; +} + +uint8 Samus_HitInterrupt_KnockbackGrapple(void) { // 0x90DEDD + samus_special_transgfx_index = 0; + return 0; +} + +uint8 Samus_HitInterrupt_Turning(void) { // 0x90DEE2 + samus_special_transgfx_index = 0; + knockback_dir = 0; + return 0; +} + +uint8 Samus_HitInterrupt_Falling(void) { // 0x90DEEA + if (frame_handler_gamma != (uint16)FUNC16(Samus_Func9)) + return Samus_HitInterrupt_Stand(); + samus_special_transgfx_index = 0; + knockback_dir = 0; + return 0; +} + +uint8 Samus_HitInterrupt_Stand(void) { // 0x90DEFA + if (samus_pose_x_dir == 4) + samus_new_pose_interrupted = 84; + else + samus_new_pose_interrupted = 83; + return 1; +} + +uint8 Samus_HitInterrupt_Ball(void) { // 0x90DF15 + samus_new_pose_interrupted = samus_pose; + return 1; +} + +uint8 Samus_HitInterrupt_Unused(void) { // 0x90DF1D + if (samus_pose_x_dir == 4) + samus_new_pose_interrupted = 52; + else + samus_new_pose_interrupted = 51; + return 1; +} + +static Func_V *const kSamus_MoveHandler_Knockback[6] = { // 0x90DF38 + Samus_MoveHandler_Knockback_0, + Samus_MoveHandler_Knockback_Up, + Samus_MoveHandler_Knockback_Up, + Samus_MoveHandler_Knockback_3, + Samus_MoveHandler_Knockback_Down, + Samus_MoveHandler_Knockback_Down, +}; + +void Samus_MoveHandler_Knockback(void) { + kSamus_MoveHandler_Knockback[knockback_dir](); + input_to_pose_calc = 0; +} + +void Samus_MoveHandler_Knockback_0(void) { // 0x90DF50 + InvalidInterrupt_Crash(); +} + +void Samus_MoveHandler_Knockback_Up(void) { // 0x90DF53 + Samus_BombJumpRisingXMovement_(); + Samus_MoveY_WithSpeedCalc(); + Samus_ClearMoveVars(); +} + +void Samus_MoveHandler_Knockback_3(void) { // 0x90DF5D + Samus_MoveY_WithSpeedCalc(); + Samus_ClearMoveVars(); +} + +void Samus_MoveHandler_Knockback_Down(void) { // 0x90DF64 + Samus_BombJumpRisingXMovement_(); + Samus_Move_NoSpeedCalc_Y(); + Samus_ClearMoveVars(); +} + +void Samus_ClearMoveVars(void) { // 0x90DF6E + if (samus_collision_flag) { + samus_x_accel_mode = 0; + samus_collides_with_solid_enemy = 0; + samus_is_falling_flag = 0; + UNUSED_word_7E0B1A = 0; + UNUSED_word_7E0B2A = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 0; + UNUSED_word_7E0B38 = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + Samus_AlignBottomWithPrevPose(); + } +} + +static Func_U8 *const kSetupBombJump[28] = { // 0x90DF99 + SetupBombJump_StandCrouch, + SetupBombJump_1, + SetupBombJump_2, + SetupBombJump_2, + SetupBombJump_4, + SetupBombJump_StandCrouch, + SetupBombJump_1, + SetupBombJump_4, + SetupBombJump_4, + SetupBombJump_4, + SetupBombJump_4, + SetupBombJump_1, + SetupBombJump_1, + SetupBombJump_1, + SetupBombJump_2, + SetupBombJump_2, + SetupBombJump_1, + SetupBombJump_4, + SetupBombJump_4, + SetupBombJump_4, + SetupBombJump_1, + SetupBombJump_1, + SetupBombJump_1, + SetupBombJump_2, + SetupBombJump_2, + SetupBombJump_2, + SetupBombJump_1A, + SetupBombJump_1A, +}; +void SetupBombJump(void) { + if (!HIBYTE(bomb_jump_dir)) { + if (kSetupBombJump[samus_movement_type]() & 1) + samus_special_transgfx_index = 3; + } +} + +uint8 SetupBombJump_StandCrouch(void) { // 0x90DFED + if (!time_is_frozen_flag) + return SetupBombJump_1(); + bomb_jump_dir = 0; + return 0; +} + +uint8 SetupBombJump_1(void) { // 0x90DFF7 + if (samus_pose_x_dir == 4) + samus_new_pose_interrupted = kPose_52_FaceL_Jump_NoAim_MoveF; + else + samus_new_pose_interrupted = kPose_51_FaceR_Jump_NoAim_MoveF; + return 1; +} + +uint8 SetupBombJump_4(void) { // 0x90E012 + samus_new_pose_interrupted = samus_pose; + return 1; +} + +uint8 SetupBombJump_2(void) { // 0x90E01A + samus_input_handler = FUNC16(Samus_InputHandler_E913); + return SetupBombJump_1A(); +} + +uint8 SetupBombJump_1A(void) { // 0x90E020 + bomb_jump_dir = 0; + return 0; +} + +void Samus_MoveHandler_BombJumpStart(void) { // 0x90E025 + Samus_InitBombJump(); + samus_movement_handler = FUNC16(Samus_MoveHandler_BombJumpMain); + input_to_pose_calc = 0; +} + +static Func_V *const kSamus_MoveHandler_BombJumpMain[4] = { // 0x90E032 + Samus_MoveHandler_Knockback_0, + Samus_HorizontalBombJump, + Samus_VerticalBombJump, + Samus_HorizontalBombJump, +}; + +void Samus_MoveHandler_BombJumpMain(void) { + if (bomb_jump_dir) + kSamus_MoveHandler_BombJumpMain[(uint16)(2 * (uint8)bomb_jump_dir) >> 1](); + else + Samus_MoveHandler_BombJumpFunc1(); +} + +void Samus_HorizontalBombJump(void) { // 0x90E04C + Samus_BombJumpRisingXMovement_(); + Samus_BombJumpRisingYMovement_(); + if (samus_y_dir == 2 || (Samus_MoveY_WithSpeedCalc(), samus_collision_flag)) + Samus_MoveHandler_BombJumpFunc1(); +} + +void Samus_VerticalBombJump(void) { // 0x90E066 + Samus_BombJumpRisingYMovement_(); + if (samus_y_dir == 2 || (Samus_MoveY_WithSpeedCalc(), samus_collision_flag)) + Samus_MoveHandler_BombJumpFunc1(); +} + +void Samus_MoveHandler_BombJumpFunc1(void) { // 0x90E07D + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + if (samus_input_handler != (uint16)FUNC16(Samus_InputHandler_E91D)) + samus_input_handler = FUNC16(Samus_InputHandler_E913); + bomb_jump_dir = 0; +} + +void CallFrameHandlerGamma(uint32 ea) { + switch (ea) { + case fnSamus_Func1: Samus_Func1(); return; + case fnSamus_Func2: Samus_Func2(); return; + case fnSamus_Func3: Samus_Func3(); return; + case fnDrawTimer_: DrawTimer_(); return; + case fnSamus_PushOutOfRidleysWay: Samus_PushOutOfRidleysWay(); return; + case fnSamus_Func4: Samus_Func4(); return; + case fnSamus_GrabbedByDraygonFrameHandler: Samus_GrabbedByDraygonFrameHandler(); return; + case fnnullsub_151: return; + case fnSamus_Func7: Samus_Func7(); return; + case fnSamus_Func9: Samus_Func9(); return; + case fnnullsub_152: return; + default: Unreachable(); + } +} +void RunFrameHandlerGamma(void) { // 0x90E097 + CallFrameHandlerGamma(frame_handler_gamma | 0x900000); +} + +void Samus_Func1(void) { // 0x90E09B + if (samus_pose == kPose_E9_FaceL_Drained_CrouchFalling + && !sign16(samus_anim_frame - 8) + && (joypad1_newkeys & kButton_Up) != 0) { + samus_anim_frame_timer = 1; + samus_anim_frame = 13; + frame_handler_gamma = FUNC16(nullsub_152); + } +} + +void Samus_Func2(void) { // 0x90E0C5 + if (!sign16(samus_anim_frame - 8) && sign16(samus_anim_frame - 12) && (joypad1_newkeys & kButton_Up) != 0) { + samus_anim_frame_timer = 1; + samus_anim_frame = 18; + } +} + +void Samus_Func3(void) { // 0x90E0E6 + if (ProcessTimer() & 1) { + game_state = kGameState_35_TimeUp; + for (int i = 510; i >= 0; i -= 2) + target_palettes[i >> 1] = 0x7FFF; + frame_handler_gamma = FUNC16(DrawTimer_); + DisablePaletteFx(); + } + if (timer_status) + DrawTimer(); +} + +void DrawTimer_(void) { // 0x90E114 + DrawTimer(); +} + +void Samus_SetPushedOutOfCeresRidley(void) { // 0x90E119 + samus_movement_handler = FUNC16(nullsub_152); + frame_handler_gamma = FUNC16(Samus_PushOutOfRidleysWay); +} + +void Samus_PushOutOfRidleysWay(void) { // 0x90E12E + if (samus_pose_x_dir == 4) + samus_pose = kPose_54_FaceL_Knockback; + else + samus_pose = kPose_53_FaceR_Knockback; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + R18_ = 21 - samus_y_radius; + samus_y_pos -= 21 - samus_y_radius; + if (sign16(samus_x_pos - layer1_x_pos - 128)) + samus_var62 = 1; + else + samus_var62 = 2; + samus_y_speed = 5; + samus_y_subspeed = 0; + bomb_jump_dir = 0; + frame_handler_gamma = FUNC16(Samus_Func4); + samus_new_pose = -1; + samus_new_pose_interrupted = -1; + samus_new_pose_transitional = -1; + samus_momentum_routine_index = 0; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; + ProcessTimer(); + if (timer_status) + DrawTimer(); +} + +void Samus_Func4(void) { // 0x90E1C8 + static Func_V *const off_90E1F7[3] = { + 0, + Samus_Func5, + Samus_Func6, + }; + + if (samus_new_pose == kPose_4F_FaceL_Dmgboost || samus_new_pose == kPose_50_FaceR_Dmgboost) { + samus_new_pose = -1; + samus_momentum_routine_index = 0; + } + off_90E1F7[samus_var62](); + input_to_pose_calc = 0; + ProcessTimer(); + if (timer_status) + DrawTimer(); +} + +void Samus_Func5(void) { // 0x90E1FD + Samus_BombJumpFallingXMovement_(); + if (samus_collision_flag) { + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + frame_handler_gamma = FUNC16(Samus_Func3); + samus_var62 = 0; + Samus_ClearMoveVars(); + } else { + Samus_BombJumpFallingYMovement_(); + } +} +void Samus_Func6(void) { // 0x90E21C + Samus_BombJumpFallingXMovement_(); + if (samus_collision_flag) { + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + frame_handler_gamma = FUNC16(Samus_Func3); + samus_var62 = 0; + Samus_ClearMoveVars(); + } else { + Samus_BombJumpFallingYMovement_(); + } +} +void Samus_GrabbedByDraygonFrameHandler(void) { // 0x90E2A1 + if (grapple_beam_function == (uint16)FUNC16(GrappleBeamFunc_ConnectedLockedInPlace)) { + samus_new_pose = -1; + samus_momentum_routine_index = 0; + } + if ((joypad1_newkeys & (kButton_Up | kButton_Down | kButton_Left | kButton_Right)) != 0 + && (joypad1_newkeys & (kButton_Up | kButton_Down | kButton_Left | kButton_Right)) != suit_pickup_light_beam_pos) { + suit_pickup_light_beam_pos = joypad1_newkeys & (kButton_Up | kButton_Down | kButton_Left | kButton_Right); + if ((int16)(++substate - 60) >= 0) + Samus_ReleaseFromDraygon(); + } +} + +void Samus_SetGrabbedByDraygonPose(uint16 a) { // 0x90E23B + if ((a & 1) != 0) + samus_pose = kPose_EC_FaceR_Draygon_NoMove_NoAim; + else + samus_pose = kPose_BA_FaceL_Draygon_NoMove_NoAim; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + frame_handler_gamma = FUNC16(Samus_GrabbedByDraygonFrameHandler); + samus_movement_handler = FUNC16(nullsub_152); + substate = 0; + suit_pickup_light_beam_pos = 0; + *(uint16 *)&suit_pickup_color_math_R = 0; + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + samus_new_pose = -1; + samus_new_pose_interrupted = -1; + samus_new_pose_transitional = -1; + samus_momentum_routine_index = 0; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; +} + +void Samus_ReleaseFromDraygon_(void) { // 0x90E2D4 + Samus_ReleaseFromDraygon(); +} + +void Samus_ReleaseFromDraygon(void) { // 0x90E2DE + if (samus_pose_x_dir == 4) + samus_pose = kPose_02_FaceL_Normal; + else + samus_pose = kPose_01_FaceR_Normal; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + frame_handler_gamma = FUNC16(nullsub_152); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_new_pose = -1; + samus_new_pose_interrupted = -1; + samus_new_pose_transitional = -1; + samus_momentum_routine_index = 0; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; + samus_y_speed = 0; + samus_y_subspeed = 0; + samus_y_dir = 0; + used_for_ball_bounce_on_landing = 0; + samus_x_accel_mode = 0; + samus_grapple_flags = samus_grapple_flags & 0xFFFD | 2; +} + +void Samus_Func7(void) { // 0x90E3A3 + Samus_BombJumpFallingXMovement_(); + if (samus_collision_flag || (Samus_BombJumpFallingYMovement_(), samus_collision_flag)) { + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + frame_handler_gamma = FUNC16(nullsub_152); + samus_var62 = 0; + Samus_ClearMoveVars(); + samus_new_pose_interrupted = 65; + samus_special_transgfx_index = 0; + } +} + +void Samus_Func8(void) { // 0x90E400 + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + frame_handler_gamma = FUNC16(nullsub_152); +} + +void Samus_Func9(void) { // 0x90E41B + unsigned int v0; // kr00_4 + + if (sign16(samus_y_speed - 5)) { + v0 = __PAIR32__(samus_y_accel, samus_y_subaccel) + __PAIR32__(samus_y_speed, samus_y_subspeed); + samus_y_speed = HIWORD(v0); + samus_y_subspeed = v0; + } + if ((samus_pose == kPose_29_FaceR_Fall + || samus_pose == kPose_2A_FaceL_Fall + || samus_pose == kPose_67_FaceR_Fall_Gun + || samus_pose == kPose_68_FaceL_Fall_Gun) + && !sign16(samus_y_speed - 5)) { + samus_anim_frame_timer = 16; + samus_anim_frame = 4; + } +} + +void Samus_CalcDisplacementMoveLeft(void) { // 0x90E464 + int16 v1; + + Samus_CalcSpeed_X(); + samus_collision_direction = 0; + R18_ = ~R18_; + bool v0 = R20_ == 0; + R20_ = -R20_; + if (v0) + ++R18_; + v1 = (__PAIR32__(R18_, R20_) + __PAIR32__(extra_samus_x_displacement, extra_samus_x_subdisplacement)) >> 16; + R20_ += extra_samus_x_subdisplacement; + R18_ = v1; + if (v1 < 0) { + if (sign16(v1 + 15)) + R18_ = -15; + } else if (!sign16(v1 - 16)) { + R18_ = 15; + } +} + +void Samus_CalcDisplacementMoveRight(void) { // 0x90E4AD + int16 v0; + + Samus_CalcSpeed_X(); + samus_collision_direction = 1; + v0 = (__PAIR32__(R18_, R20_) + __PAIR32__(extra_samus_x_displacement, extra_samus_x_subdisplacement)) >> 16; + R20_ += extra_samus_x_subdisplacement; + R18_ = v0; + if (v0 < 0) { + if (sign16(v0 + 15)) + R18_ = -15; + } else if (!sign16(v0 - 16)) { + R18_ = 15; + } +} + +void Samus_CalcSpeed_X(void) { // 0x90E4E6 + int16 v1; + uint16 v3; + char v4; // t1 + uint16 v5; + char v6; // tt + uint16 v7; + char v8; // t1 + uint16 v9; + char v10; // tt + + uint16 v0 = samus_x_speed_divisor; + if (!sign16(samus_x_speed_divisor - 5)) + v0 = 4; + v1 = 2 * v0; + if (v1) { + switch (v1) { + case 2: { + bool v2 = __CFADD__uint16(samus_x_extra_run_subspeed, R20_); + R20_ += samus_x_extra_run_subspeed; + LOBYTE(v3) = (uint16)(samus_x_extra_run_speed + v2 + R18_) >> 8; + HIBYTE(v3) = samus_x_extra_run_speed + v2 + R18_; + v3 >>= 1; + v4 = v3; + LOBYTE(v3) = HIBYTE(v3); + HIBYTE(v3) = v4; + R18_ = (uint8)v3; + samus_total_x_speed = (uint8)v3; + R22_ = v3 & 0xFF00; + R20_ = (v3 & 0xFF00) + (R20_ >> 1); + samus_total_x_subspeed = R20_; + break; + } + case 4: { + bool v2 = __CFADD__uint16(samus_x_extra_run_subspeed, R20_); + R20_ += samus_x_extra_run_subspeed; + LOBYTE(v5) = (uint16)(samus_x_extra_run_speed + v2 + R18_) >> 8; + HIBYTE(v5) = samus_x_extra_run_speed + v2 + R18_; + v5 >>= 2; + v6 = v5; + LOBYTE(v5) = HIBYTE(v5); + HIBYTE(v5) = v6; + R18_ = (uint8)v5; + samus_total_x_speed = (uint8)v5; + R22_ = v5 & 0xFF00; + R20_ = (v5 & 0xFF00) + (R20_ >> 2); + samus_total_x_subspeed = R20_; + break; + } + case 6: { + bool v2 = __CFADD__uint16(samus_x_extra_run_subspeed, R20_); + R20_ += samus_x_extra_run_subspeed; + LOBYTE(v7) = (uint16)(samus_x_extra_run_speed + v2 + R18_) >> 8; + HIBYTE(v7) = samus_x_extra_run_speed + v2 + R18_; + v7 >>= 3; + v8 = v7; + LOBYTE(v7) = HIBYTE(v7); + HIBYTE(v7) = v8; + R18_ = (uint8)v7; + samus_total_x_speed = (uint8)v7; + R22_ = v7 & 0xFF00; + R20_ = (v7 & 0xFF00) + (R20_ >> 3); + samus_total_x_subspeed = R20_; + break; + } + case 8: { + bool v2 = __CFADD__uint16(samus_x_extra_run_subspeed, R20_); + R20_ += samus_x_extra_run_subspeed; + LOBYTE(v9) = (uint16)(samus_x_extra_run_speed + v2 + R18_) >> 8; + HIBYTE(v9) = samus_x_extra_run_speed + v2 + R18_; + v9 >>= 4; + v10 = v9; + LOBYTE(v9) = HIBYTE(v9); + HIBYTE(v9) = v10; + R18_ = (uint8)v9; + samus_total_x_speed = (uint8)v9; + R22_ = v9 & 0xFF00; + R20_ = (v9 & 0xFF00) + (R20_ >> 4); + samus_total_x_subspeed = R20_; + break; + } + default: + Unreachable(); + while (1) + ; + } + } else { + bool v2 = __CFADD__uint16(samus_x_extra_run_subspeed, R20_); + R20_ += samus_x_extra_run_subspeed; + samus_total_x_subspeed = R20_; + R18_ += samus_x_extra_run_speed + v2; + samus_total_x_speed = R18_; + } +} + +void Samus_ClearXSpeedIfColl(void) { // 0x90E5CE + if (samus_collision_flag) { + if (samus_collision_direction) + samus_collides_with_solid_enemy = 8; + else + samus_collides_with_solid_enemy = 4; + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_x_accel_mode = 0; + } else { + input_to_pose_calc = 0; + samus_collides_with_solid_enemy = 0; + } +} + +void Samus_MoveUp_SetPoseCalcInput(void) { // 0x90E606 + if (samus_collision_flag) + input_to_pose_calc = 4; + else + input_to_pose_calc = 0; +} + +static const uint8 kSamus_MoveDown_SetPoseCalcInput_Tab0[28] = { // 0x90E61B + 0, 0, 4, 4, 1, 0, 4, 2, + 4, 4, 0, 0, 0, 0, 4, 4, + 0, 3, 4, 4, 4, 0, 4, 4, + 4, 4, 4, 4, +}; +static const uint8 kSamus_MoveDown_SetPoseCalcInput_Tab1[28] = { + 4, 4, 0, 0, 4, 4, 0, 4, + 1, 2, 0, 4, 4, 0, 4, 4, + 4, 4, 3, 3, 0, 4, 4, 4, + 4, 0, 4, 4, +}; +void Samus_MoveDown_SetPoseCalcInput(void) { + if (samus_collision_flag) { + input_to_pose_calc = 1; + HIBYTE(input_to_pose_calc) = kSamus_MoveDown_SetPoseCalcInput_Tab1[samus_movement_type]; + } else if ((uint8)input_to_pose_calc != 5) { + input_to_pose_calc = 2; + HIBYTE(input_to_pose_calc) = kSamus_MoveDown_SetPoseCalcInput_Tab0[samus_movement_type]; + } +} + +void CallFrameHandlerAlfa(uint32 ea) { + switch (ea) { + case fnSamus_FrameHandlerAlfa_Func11: Samus_FrameHandlerAlfa_Func11(); return; + case fnSamus_FrameHandlerAlfa_Func12: Samus_FrameHandlerAlfa_Func12(); return; + case fnSamus_FrameHandlerAlfa_Func13: Samus_FrameHandlerAlfa_Func13(); return; + case fnEmptyFunction: return; + default: Unreachable(); + } +} +void HandleControllerInputForGamePhysics(void) { // 0x90E692 + CallFrameHandlerAlfa(frame_handler_alfa | 0x900000); +} + +void Samus_FrameHandlerAlfa_Func11(void) { // 0x90E695 + samus_new_pose = -1; + samus_new_pose_interrupted = -1; + samus_new_pose_transitional = -1; + samus_momentum_routine_index = 0; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; + Samus_SetRadius(); + Samus_CallInputHandler(); + Samus_UpdateSuitPaletteIndex(); + Samus_DetermineAccel_Y(); + BlockInsideDetection(); + Samus_HandleHudSpecificBehaviorAndProjs(); + Samus_Func10(); +} + +void Samus_FrameHandlerAlfa_Func12(void) { // 0x90E6C9 + samus_new_pose = -1; + samus_new_pose_interrupted = -1; + samus_new_pose_transitional = -1; + samus_momentum_routine_index = 0; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; + controller1_input_for_demo = joypad1_lastkeys; + controller1_new_input_for_demo = joypad1_newkeys; + demo_backup_prev_controller_input = joypad1_input_samusfilter; + demo_backup_prev_controller_input_new = joypad1_newinput_samusfilter; + Samus_SetRadius(); + Samus_UpdateSuitPaletteIndex(); + Samus_CallInputHandler(); + Samus_DetermineAccel_Y(); + BlockInsideDetection(); + Samus_HandleHudSpecificBehaviorAndProjs(); + Samus_Func10(); +} + +void Samus_FrameHandlerAlfa_Func13(void) { // 0x90E713 + HandleProjectile(); + Samus_Func10(); +} + +void CallFrameHandlerBeta(uint32 ea) { + switch (ea) { + case fnSamus_FrameHandlerBeta_Func17: Samus_FrameHandlerBeta_Func17(); return; + case fnHandleDemoRecorder_3: HandleDemoRecorder_3(); return; + case fnSamus_FrameHandlerBeta_Func14: Samus_FrameHandlerBeta_Func14(); return; + case fnSamus_Func15: Samus_Func15(); return; + case fnSamus_Func16: Samus_Func16(); return; + case fnSamus_Func18: Samus_Func18(); return; + case fnEmptyFunction: return; + case fnj_HandleDemoRecorder_2: return; + case fnj_HandleDemoRecorder_2_0: return; + case fnSetContactDamageIndexAndUpdateMinimap: SetContactDamageIndexAndUpdateMinimap(); return; + case fnSamus_Func19: Samus_Func19(); return; + case fnSamus_LowHealthCheck: Samus_LowHealthCheck(); return; + default: Unreachable(); + } +} + +void HandleSamusMovementAndPause(void) { // 0x90E722 + CallFrameHandlerBeta(frame_handler_beta | 0x900000); +} + +void Samus_FrameHandlerBeta_Func17(void) { // 0x90E725 + samus_contact_damage_index = 0; + RunSamusMovementHandler(); + UpdateMinimap(); + RunFrameHandlerGamma(); + Samus_Animate(); + Samus_HitInterruption(); + Samus_HandleTransFromBlockColl(); + Samus_HandleTransitions(); + Samus_HandlePalette(); + Samus_HandlePeriodicDamage(); + Samus_PauseCheck(); + Samus_LowHealthCheck_(); +} + +void HandleDemoRecorder_1(void) { // 0x90E786 + if ((joypad2_new_keys & 0x8000u) == 0) { + if (!debug_flag && (joypad2_new_keys & 0x80) != 0) { + DisableEnemyProjectiles(); + time_is_frozen_flag = 1; + frame_handler_alfa = FUNC16(EmptyFunction); + frame_handler_beta = FUNC16(HandleDemoRecorder_3); + } + } else if (debug_flag) { + samus_draw_handler = FUNC16(nullsub_152); + debug_flag = 0; + } else { + debug_flag = 1; + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + } +} + +void HandleDemoRecorder_3(void) { // 0x90E7D2 + if ((joypad2_new_keys & 0x80) != 0) { + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func11); + frame_handler_beta = FUNC16(Samus_FrameHandlerBeta_Func17); + EnableEnemyProjectiles(); + time_is_frozen_flag = 0; + } +} + +void Samus_FrameHandlerBeta_Func14(void) { // 0x90E7F5 + samus_contact_damage_index = 0; + RunSamusMovementHandler(); + UpdateMinimap(); + Samus_Animate(); + Samus_HitInterruption(); + Samus_HandleTransFromBlockColl(); + Samus_HandleTransitions(); + Samus_HandlePalette(); + joypad1_lastkeys = controller1_input_for_demo; + joypad1_newkeys = controller1_new_input_for_demo; + joypad1_input_samusfilter = demo_backup_prev_controller_input; + joypad1_newinput_samusfilter = demo_backup_prev_controller_input_new; +} + +void Samus_Func15(void) { // 0x90E833 + samus_contact_damage_index = 0; + RunSamusMovementHandler(); + Samus_Animate(); + Samus_HitInterruption(); + Samus_HandleTransFromBlockColl(); + Samus_HandleTransitions(); + Samus_HandlePalette(); + joypad1_lastkeys = controller1_input_for_demo; + joypad1_newkeys = controller1_new_input_for_demo; + joypad1_input_samusfilter = demo_backup_prev_controller_input; + joypad1_newinput_samusfilter = demo_backup_prev_controller_input_new; +} + +void Samus_Func16(void) { // 0x90E86A + Samus_SetRadius(); + UpdateMinimap(); + Samus_Animate(); + elevator_status = 0; + samus_prev_y_pos = samus_y_pos; + if (PlaySamusFanfare() & 1) { + if (sign16(debug_invincibility - 7) || (joypad2_last & 0x8000u) == 0) + debug_invincibility = 0; + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func11); + frame_handler_beta = FUNC16(Samus_FrameHandlerBeta_Func17); + } +} + +void Samus_Func18(void) { // 0x90E8AA + Samus_FrameHandlerBeta_Func17(); + if (frame_handler_gamma == (uint16)FUNC16(DrawTimer_) && game_state != kGameState_35_TimeUp) + game_state = kGameState_35_TimeUp; +} + +void SetContactDamageIndexAndUpdateMinimap(void) { // 0x90E8DC + samus_contact_damage_index = 0; + UpdateMinimap(); +} + +void Samus_Func19(void) { // 0x90E8EC + samus_contact_damage_index = 0; + RunSamusMovementHandler(); + UpdateMinimap(); + Samus_Animate(); +} + +void Samus_LowHealthCheck(void) { // 0x90E902 + Samus_LowHealthCheck_(); +} + +void CallSamusInputHandler(uint32 ea) { + switch (ea) { + case fnnullsub_152: return; + case fnSamus_InputHandler_E913: Samus_InputHandler_E913(); return; + case fnSamus_Func20_: Samus_Func20_(); return; + case fnSamus_InputHandler_E91D: Samus_InputHandler_E91D(); return; + case fnHandleAutoJumpHack: HandleAutoJumpHack(); return; + default: Unreachable(); + } +} + +void Samus_CallInputHandler(void) { // 0x90E90F + CallSamusInputHandler(samus_input_handler | 0x900000); +} + +void Samus_InputHandler_E913(void) { // 0x90E913 + Samus_InputHandler(); +} + +void Samus_Func20_(void) { // 0x90E918 + Samus_Func20(); +} + +void Samus_InputHandler_E91D(void) { // 0x90E91D + DemoObjectInputHandler(); + Samus_InputHandler(); +} + +void HandleAutoJumpHack(void) { // 0x90E926 + uint16 v0 = joypad1_newkeys; + if (autojump_timer && sign16(autojump_timer - 9)) { + joypad1_newkeys |= button_config_jump_a; + autojump_timer = 0; + } + Samus_InputHandler(); + joypad1_newkeys = v0; + samus_input_handler = FUNC16(Samus_InputHandler_E913); +} + +void CallSamusMovementHandler(uint32 ea) { + switch (ea) { + case fnSamus_MoveHandler_ReleaseFromGrapple: Samus_MoveHandler_ReleaseFromGrapple(); return; + case fnSamus_HandleMovement_DrainedCrouching: Samus_HandleMovement_DrainedCrouching(); return; + case fnSamus_MovementHandler_Normal: Samus_MovementHandler_Normal(); return; + case fnSamus_MoveHandlerShinesparkWindup: Samus_MoveHandlerShinesparkWindup(); return; + case fnSamus_MoveHandlerVerticalShinespark: Samus_MoveHandlerVerticalShinespark(); return; + case fnSamus_MoveHandler_Shinespark_Diag: Samus_MoveHandler_Shinespark_Diag(); return; + case fnSamus_MoveHandler_Shinespark_Horiz: Samus_MoveHandler_Shinespark_Horiz(); return; + case fnSamus_MoveHandler_ShinesparkCrash: Samus_MoveHandler_ShinesparkCrash(); return; + case fnSamus_MoveHandler_ShinesparkCrash_0: Samus_MoveHandler_ShinesparkCrash_0(); return; + case fnSamus_MoveHandler_ShinesparkCrash_1: Samus_MoveHandler_ShinesparkCrash_1(); return; + case fnSamus_MoveHandler_ShinesparkCrash_2: Samus_MoveHandler_ShinesparkCrash_2(); return; + case fnSamus_MoveHandler_ShinesparkCrashEchoCircle: Samus_MoveHandler_ShinesparkCrashEchoCircle(); return; + case fnSamus_MoveHandler_ShinesparkCrashFinish: Samus_MoveHandler_ShinesparkCrashFinish(); return; + case fnSamusMoveHandler_CrystalFlashStart: SamusMoveHandler_CrystalFlashStart(); return; + case fnSamusMoveHandler_CrystalFlashMain: SamusMoveHandler_CrystalFlashMain(); return; + case fnkSamusMoveHandler_CrystalFlashFinish: kSamusMoveHandler_CrystalFlashFinish(); return; + case fnSamus_MoveHandler_Knockback: Samus_MoveHandler_Knockback(); return; + case fnSamus_MoveHandler_Knockback_0: Samus_MoveHandler_Knockback_0(); return; + case fnSamus_MoveHandler_Knockback_Up: Samus_MoveHandler_Knockback_Up(); return; + case fnSamus_MoveHandler_Knockback_3: Samus_MoveHandler_Knockback_3(); return; + case fnSamus_MoveHandler_Knockback_Down: Samus_MoveHandler_Knockback_Down(); return; + case fnSamus_MoveHandler_BombJumpStart: Samus_MoveHandler_BombJumpStart(); return; + case fnSamus_MoveHandler_BombJumpMain: Samus_MoveHandler_BombJumpMain(); return; + case fnSamus_MoveHandler_BombJumpFunc1: Samus_MoveHandler_BombJumpFunc1(); return; + case fnnullsub_152: return; + case fnSamusMovementType_Xray: SamusMovementType_Xray(); return; + case fnSamus_Func25_ShineSpark: Samus_Func25_ShineSpark(); return; + case fnSamus_MoveHandler_F072: Samus_MoveHandler_F072(); return; + default: Unreachable(); + } +} + +void RunSamusMovementHandler(void) { // 0x90E94B + CallSamusMovementHandler(samus_movement_handler | 0x900000); +} + +void SamusMovementType_Xray(void) { // 0x90E94F + uint16 v0; + if (samus_movement_type != kMovementType_0E_TurningAroundOnGround) { + samus_anim_frame_timer = 15; + if (samus_pose_x_dir == 4) { + if (sign16(xray_angle - 153)) { + v0 = 4; + } else if (sign16(xray_angle - 178)) { + v0 = 3; + } else if (sign16(xray_angle - 203)) { + v0 = 2; + } else { + v0 = sign16(xray_angle - 228) != 0; + } + } else if (sign16(xray_angle - 25)) { + v0 = 0; + } else if (sign16(xray_angle - 50)) { + v0 = 1; + } else if (sign16(xray_angle - 75)) { + v0 = 2; + } else if (sign16(xray_angle - 100)) { + v0 = 3; + } else { + v0 = 4; + } + samus_anim_frame = v0; + } +} + +void Samus_HandlePeriodicDamage(void) { // 0x90E9CE + int16 v0; + int16 v1; + int16 v2; + + if (time_is_frozen_flag) + goto LABEL_10; + if ((equipped_items & 0x20) != 0) { + uint16 v4 = *(uint16 *)((char *)&samus_periodic_subdamage + 1) >> 2; + LOBYTE(v1) = (uint16)(*(uint16 *)((char *)&samus_periodic_subdamage + 1) >> 2) >> 8; + HIBYTE(v1) = *(uint16 *)((char *)&samus_periodic_subdamage + 1) >> 2; + samus_periodic_subdamage = v1 & 0xFF00; + samus_periodic_damage = HIBYTE(v4); + } else if ((equipped_items & 1) != 0) { + uint16 v3 = *(uint16 *)((char *)&samus_periodic_subdamage + 1) >> 1; + LOBYTE(v0) = (uint16)(*(uint16 *)((char *)&samus_periodic_subdamage + 1) >> 1) >> 8; + HIBYTE(v0) = *(uint16 *)((char *)&samus_periodic_subdamage + 1) >> 1; + samus_periodic_subdamage = v0 & 0xFF00; + samus_periodic_damage = HIBYTE(v3); + } + if ((samus_periodic_damage & 0x8000u) != 0) { + InvalidInterrupt_Crash(); + return; + } + v2 = (__PAIR32__(samus_health, samus_subunit_health) - __PAIR32__(samus_periodic_damage, samus_periodic_subdamage)) >> 16; + samus_subunit_health -= samus_periodic_subdamage; + samus_health = v2; + if (v2 >= 0) { +LABEL_10: + samus_periodic_subdamage = 0; + samus_periodic_damage = 0; + } else { + samus_subunit_health = 0; + samus_health = 0; + samus_periodic_subdamage = 0; + samus_periodic_damage = 0; + } +} + +void Samus_PauseCheck(void) { // 0x90EA45 + if (!power_bomb_flag + && !time_is_frozen_flag + && !door_transition_flag_enemies + && area_index != 6 + && game_state == kGameState_8_MainGameplay + && (joypad1_newkeys & kButton_Start) != 0) { + screen_fade_delay = 1; + screen_fade_counter = 1; + game_state = kGameState_12_Pausing; + } +} + +void Samus_LowHealthCheck_(void) { // 0x90EA7F + if (sign16(samus_health - 31)) { + if (!samus_health_warning) { + QueueSfx3_Max6(2u); + samus_health_warning = 1; + } + } else if (samus_health_warning) { + samus_health_warning = 0; + QueueSfx3_Max6(1u); + } +} + +void Samus_LowHealthCheck_0(void) { // 0x90EAAB + Samus_LowHealthCheck_(); +} + +void Samus_JumpCheck(void) { // 0x90EAB3 + if ((button_config_jump_a & joypad1_lastkeys) != 0 && (button_config_jump_a & joypad1_input_samusfilter) != 0) + ++autojump_timer; + else + autojump_timer = 0; + joypad1_input_samusfilter = joypad1_lastkeys; + joypad1_newinput_samusfilter = joypad1_newkeys; + if ((int16)(samus_health - samus_prev_health_for_flash) >= 0) + goto LABEL_10; + if (!samus_hurt_flash_counter) + samus_hurt_flash_counter = 1; + if (sign16(debug_invincibility - 7)) + LABEL_10: + samus_prev_health_for_flash = samus_health; + else + samus_health = samus_prev_health_for_flash; +} + +void Samus_Func10(void) { // 0x90EB02 + int16 v0; + + projectile_init_speed_samus_moved_left = 0; + projectile_init_speed_samus_moved_left_fract = 0; + projectile_init_speed_samus_moved_right = 0; + projectile_init_speed_samus_moved_right_fract = 0; + projectile_init_speed_samus_moved_up = 0; + projectile_init_speed_samus_moved_up_fract = 0; + projectile_init_speed_samus_moved_down = 0; + projectile_init_speed_samus_moved_down_fract = 0; + samus_anim_frame_skip = 0; + new_projectile_direction_changed_pose = 0; + LOBYTE(v0) = HIBYTE(UNUSED_word_7E0DFA); + HIBYTE(v0) = UNUSED_word_7E0DFA; + UNUSED_word_7E0DFA = v0 & 0xFF00; + WORD(g_ram[0xa10]) = *(uint16 *)&samus_pose_x_dir; +} + +void DrawSamusAndProjectiles(void) { // 0x90EB35 + SamusDrawSprites(); + DrawPlayerExplosions2(); + Samus_JumpCheck(); + Samus_ShootCheck(); +} + +void CallSamusDrawHandler(uint32 ea) { + switch (ea) { + case fnSamusDrawHandler_Default: SamusDrawHandler_Default(); return; + case fnsub_90EB86: sub_90EB86(); return; + case fnnullsub_152: + case fnnullsub_156: return; + case fnSamus_DrawHandler_EndOfShinespark: Samus_DrawHandler_EndOfShinespark(); return; + case fnSamusDisplayHandler_UsingElevator: SamusDisplayHandler_UsingElevator(); return; + case fnSamusDisplayHandler_SamusReceivedFatal: SamusDisplayHandler_SamusReceivedFatal(); return; + default: Unreachable(); + } +} + +void SamusDrawSprites(void) { // 0x90EB4B + HandleArmCannonOpenState(); + CallSamusDrawHandler(samus_draw_handler | 0x900000); +} + +void SamusDrawHandler_Default(void) { // 0x90EB52 + HandleChargingBeamGfxAudio(); + sub_90EB55(); +} + +void sub_90EB55(void) { // 0x90EB55 + if ((arm_cannon_drawing_mode & 0xF) != 0) { + if ((arm_cannon_drawing_mode & 0xF) == 2) { + HandleAtmosphericEffects(); + Samus_Draw(); + Samus_ArmCannon_Draw(); + } else { + HandleAtmosphericEffects(); + Samus_ArmCannon_Draw(); + Samus_Draw(); + } + Samus_DrawEchoes(); + } else { + HandleAtmosphericEffects(); + Samus_Draw(); + Samus_DrawEchoes(); + } +} + +void sub_90EB86(void) { // 0x90EB86 + if (!sign16(grapple_beam_function + 0x37AA)) { + sub_90EB55(); + return; + } + if (grapple_beam_function == (uint16)FUNC16(GrappleBeamFunc_Firing) + || grapple_beam_function == (uint16)FUNC16(UNUSED_sub_9BC759)) { + GrappleBeamFunc_BF1B(); + } + HandleGrappleBeamFlare(); + if ((arm_cannon_drawing_mode & 0xF) != 0) { + if ((arm_cannon_drawing_mode & 0xF) == 2) { + HandleAtmosphericEffects(); + Samus_Draw(); + Samus_ArmCannon_Draw(); + UpdateGrappleBeamTilesAndIncrFlameCtr(); + if (!grapple_beam_length) + return; + } else { + HandleAtmosphericEffects(); + Samus_ArmCannon_Draw(); + Samus_Draw(); + UpdateGrappleBeamTilesAndIncrFlameCtr(); + if (!grapple_beam_length) + return; + } + } else { + HandleAtmosphericEffects(); + Samus_Draw(); + UpdateGrappleBeamTilesAndIncrFlameCtr(); + if (!grapple_beam_length) + return; + } + HandleGrappleBeamGfx(); +} + +void Samus_DrawHandler_EndOfShinespark(void) { // 0x90EBF3 + Samus_Draw(); + for (int i = 2; i >= 0; i -= 2) + Samus_DrawShinesparkCrashEchoes(i); +} + +void Samus_DrawManyEchoes(void) { // 0x90EC03 + SamusDrawHandler_Default(); + for (int i = 2; i >= 0; i -= 2) + Samus_DrawEchoes(); +} + +void SamusDisplayHandler_UsingElevator(void) { // 0x90EC14 + if ((nmi_frame_counter_word & 1) == 0) + SamusDisplayHandler_SamusReceivedFatal(); +} + +void SamusDisplayHandler_SamusReceivedFatal(void) { // 0x90EC1D + Samus_DrawWhenNotAnimatingOrDying(); +} + +void Samus_SetRadius(void) { // 0x90EC22 + samus_y_radius = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)); + samus_x_radius = 5; +} + +void Samus_GetBottomBoundary(void) { // 0x90EC3E + R18_ = samus_y_pos + *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)) - 1; +} + +void Samus_GetTopBottomBoundary(void) { // 0x90EC58 + int16 v0; + + v0 = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)); + R18_ = samus_y_pos + v0 - 1; + R20_ = samus_y_pos - v0; +} + +void Samus_AlignBottomWithPrevPose(void) { // 0x90EC7E + R18_ = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)); + R18_ = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_prev_pose)) - R18_; + samus_y_pos += R18_; + samus_prev_y_pos += R18_; +} + +void Samus_UpdateSuitPaletteIndex(void) { // 0x90ECB6 + if ((equipped_items & 0x20) != 0) { + samus_suit_palette_index = 4; + } else if ((equipped_items & 1) != 0) { + samus_suit_palette_index = 2; + } else { + samus_suit_palette_index = 0; + } +} + +void MoveSamusWithControlPad(void) { // 0x90ECD5 + if ((joypad1_lastkeys & 0x800) != 0) { + R18_ = -4; + R20_ = 0; + Samus_MoveUp(); + } + if ((joypad1_lastkeys & 0x400) != 0) { + R18_ = 4; + R20_ = 0; + Samus_MoveDown(); + } + if ((joypad1_lastkeys & 0x200) != 0) { + R18_ = -4; + R20_ = 0; + Samus_MoveLeft(); + } + if ((joypad1_lastkeys & 0x100) != 0) { + R18_ = 4; + R20_ = 0; + Samus_MoveRight(); + } +} + +static const uint8 byte_90ED50[28] = { // 0x90ED26 + 0, 0, 0, 0, 1, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +void SwappedAmmoRoutine(void) { + if (byte_90ED50[samus_movement_type]) { + samus_missiles = samus_x_pos >> 4; + samus_max_missiles = samus_x_pos >> 4; + samus_super_missiles = samus_y_pos >> 4; + samus_max_super_missiles = samus_y_pos >> 4; + } +} + +void UNUSEDsub_90ED6C(void) { // 0x90ED6C + samus_missiles = game_time_hours; + samus_max_missiles = game_time_hours; + samus_super_missiles = game_time_minutes; + samus_max_super_missiles = game_time_minutes; + samus_power_bombs = game_time_seconds; + samus_max_power_bombs = game_time_seconds; +} + +static Func_V *const kSamus_FootstepGraphics[8] = { // 0x90ED88 + Samus_FootstepGraphics_Crateria, + Samus_FootstepGraphics_1, + Samus_FootstepGraphics_1, + Samus_FootstepGraphics_1, + Samus_FootstepGraphics_Maridia, + Samus_FootstepGraphics_1, + Samus_FootstepGraphics_1, + Samus_FootstepGraphics_1, +}; +void Samus_FootstepGraphics(void) { + kSamus_FootstepGraphics[area_index](); +} + +static const uint8 byte_90EDC9[16] = { // 0x90EDA1 + 1, 0, 0, 0, 0, 2, 0, 4, + 0, 4, 4, 4, 4, 0, 4, 0, +}; +void Samus_FootstepGraphics_Crateria(void) { + if (cinematic_function || (int16)(room_index - 16) >= 0) + goto LABEL_11; + if ((byte_90EDC9[room_index] & 1) == 0) { + if ((byte_90EDC9[room_index] & 2) != 0) { + if (!sign16(samus_y_pos - 944)) + goto LABEL_12; + } else if ((byte_90EDC9[room_index] & 4) != 0) { + goto LABEL_12; + } +LABEL_11: + Samus_FootstepGraphics_1(); + return; + } + if (fx_type != 10) + goto LABEL_11; +LABEL_12: + Samus_FootstepGraphics_Maridia(); +} + +void Samus_FootstepGraphics_Maridia(void) { // 0x90EDEC + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R18_)) + return; + } else if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + return; + } + if (samus_pose_x_dir == 4) { + atmospheric_gfx_x_pos[0] = samus_x_pos - 12; + atmospheric_gfx_x_pos[1] = samus_x_pos + 8; + } else { + atmospheric_gfx_x_pos[0] = samus_x_pos + 12; + atmospheric_gfx_x_pos[1] = samus_x_pos - 8; + } + atmospheric_gfx_y_pos[0] = samus_y_pos + 16; + atmospheric_gfx_y_pos[1] = samus_y_pos + 16; + atmospheric_gfx_frame_and_type[0] = 256; + atmospheric_gfx_frame_and_type[1] = 256; + atmospheric_gfx_anim_timer[0] = -32766; + atmospheric_gfx_anim_timer[1] = 3; +} + +void Samus_FootstepGraphics_1(void) { // 0x90EE64 + if ((speed_boost_counter & 0xFF00) == 1024) { + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R18_)) + return; + } else if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + return; + } + if (samus_pose_x_dir == 4) { + atmospheric_gfx_x_pos[0] = samus_x_pos - 12; + atmospheric_gfx_x_pos[1] = samus_x_pos + 8; + } else { + atmospheric_gfx_x_pos[0] = samus_x_pos + 12; + atmospheric_gfx_x_pos[1] = samus_x_pos - 8; + } + atmospheric_gfx_y_pos[0] = samus_y_pos + 16; + atmospheric_gfx_y_pos[1] = samus_y_pos + 16; + atmospheric_gfx_frame_and_type[0] = 1792; + atmospheric_gfx_frame_and_type[1] = 1792; + atmospheric_gfx_anim_timer[0] = -32766; + atmospheric_gfx_anim_timer[1] = 3; + } +} + +void Samus_UpdateSpeedEchoPos(void) { // 0x90EEE7 + if ((speed_boost_counter & 0xFF00) == 1024 && (speed_echoes_index & 0x8000u) == 0 && (game_time_frames & 3) == 0) { + uint16 v0 = speed_echoes_index; + int v1 = speed_echoes_index >> 1; + speed_echo_xpos[v1] = samus_x_pos; + speed_echo_ypos[v1] = samus_y_pos; + uint16 v2 = v0 + 2; + if ((int16)(v2 - 4) >= 0) + v2 = 0; + speed_echoes_index = v2; + } +} + +void Samus_PostGrappleCollisionDetect(void) { // 0x90EF22 + PostGrappleCollisionDetect_X(); + PostGrappleCollisionDetect_Y(); + if (!distance_to_eject_samus_down || !distance_to_eject_samus_up) { + if (distance_to_eject_samus_up) { + samus_y_pos -= distance_to_eject_samus_up; + if (!sign16(samus_y_radius - 16)) { + PostGrappleCollisionDetect_Y(); + samus_y_pos -= distance_to_eject_samus_up; + } + } + } +} + + +void ProjPreInstr_UnknownProj8027(uint16 k) { // 0x90EFD3 + static const int16 kProjPreInstr_UnknownProj8027_X[4] = { -4, -4, 4, 4 }; + static const int16 kProjPreInstr_UnknownProj8027_Y[4] = { 4, -4, -4, 4 }; + static const int16 kProjPreInstr_UnknownProj8027_X2[4] = { 0x80, 0x80, -0x80, -0x80 }; + static const int16 kProjPreInstr_UnknownProj8027_Y2[4] = { -0x80, 0x80, 0x80, -0x80 }; + + int v1 = k >> 1; + projectile_x_pos[v1] += kProjPreInstr_UnknownProj8027_X[v1]; + uint16 v2 = kProjPreInstr_UnknownProj8027_Y[v1] + projectile_y_pos[v1]; + projectile_y_pos[v1] = v2; + if (v2 == samus_y_pos) { + if (projectile_variables[v1] == 1) { + if (k == 6) + samus_movement_handler = FUNC16(Samus_Func25_ShineSpark); + ClearProjectile(k); + } else { + int v3 = k >> 1; + ++projectile_variables[v3]; + samus_shine_timer = 180; + timer_for_shine_timer = 1; + special_samus_palette_frame = 0; + projectile_x_pos[v3] = kProjPreInstr_UnknownProj8027_X2[v3] + samus_x_pos; + projectile_y_pos[v3] = kProjPreInstr_UnknownProj8027_Y2[v3] + samus_y_pos; + } + } +} + +void Samus_Func25_ShineSpark(void) { // 0x90F04B + if (!samus_shine_timer) { + special_samus_palette_frame = 6; + special_samus_palette_timer = 1; + demo_timer_counter = 1; + timer_for_shine_timer = 10; + samus_shine_timer = 120; + samus_movement_handler = FUNC16(Samus_MoveHandler_F072); + } +} + +void Samus_MoveHandler_F072(void) { // 0x90F072 + if (!samus_shine_timer) { + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func11); + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + } +} + +static Func_U8 *const kSamusCodeHandlers[32] = { // 0x90F084 + SamusCode_00_LockSamus, + SamusCode_01_UnlockSamus, + SamusCode_02_ReachCeresElevator, + SamusCode_03, + SamusCode_04, + SamusCode_05_SetupDrained, + SamusCode_06_LockToStation, + SamusCode_07_SetupForElevator, + SamusCode_08_SetupForCeresStart, + SamusCode_08_SetupForZebesStart, + SamusCode_0A_ClearDrawHandler, + SamusCode_0B_DrawHandlerDefault, + SamusCode_0C_UnlockFromMapStation, + SamusCode_0D_IsGrappleActive, + SamusCode_0E, + SamusCode_0F_EnableTimerHandling, + SamusCode_10, + SamusCode_11_SetupForDeath, + SamusCode_12_SetSuperPaletteFlag1, + SamusCode_12_SetSuperPaletteFlag0, + SamusCode_14, + SamusCode_15_CalledBySuitAcquision, + SamusCode_16, + SamusCode_17_DisableRainbowSamusAndStandUp, + SamusCode_18, + SamusCode_17_FreezeDrainedSamus, + SamusCode_1A, + SamusCode_1B_CheckedLockSamus, + SamusCode_1C, + SamusCode_1D_ClearSoundInDoor, + SamusCode_1E, + SamusCode_1F, +}; + +uint16 CallSomeSamusCode(uint16 a) { + uint16 code = kSamusCodeHandlers[a & 0x1F](); + if (!(code & 1)) + return code >> 1; + samus_new_pose = -1; + samus_new_pose_interrupted = -1; + samus_new_pose_transitional = -1; + samus_momentum_routine_index = 0; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; + return -1; +} + +void Samus_UpdatePreviousPose(void) { // 0x90F0EE + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; +} + +uint8 ClearCarry(void) { // 0x90F107 + return 0; +} + +uint8 SamusCode_00_LockSamus(void) { // 0x90F109 + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func13); + frame_handler_beta = FUNC16(SetContactDamageIndexAndUpdateMinimap); + return 1; +} + +uint8 SamusCode_01_UnlockSamus(void) { // 0x90F117 + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func11); + frame_handler_beta = FUNC16(Samus_FrameHandlerBeta_Func17); + return 1; +} + +uint8 SamusCode_02_ReachCeresElevator(void) { // 0x90F125 + if (samus_pose_x_dir == 4) + samus_pose = kPose_02_FaceL_Normal; + else + samus_pose = kPose_01_FaceR_Normal; + samus_anim_frame_skip = 0; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + reached_ceres_elevator_fade_timer = 60; + return SamusCode_00_LockSamus(); +} + +uint8 SamusCode_03(void) { // 0x90F152 + if (grapple_beam_function != (uint16)FUNC16(GrappleBeamFunc_Inactive)) { + grapple_beam_function = FUNC16(GrappleBeam_Func2); + return 0; + } + if (samus_movement_type != kMovementType_03_SpinJumping && samus_movement_type != kMovementType_14_WallJumping) + return 0; + if (samus_pose_x_dir == kMovementType_04_MorphBallOnGround) + samus_pose = kPose_02_FaceL_Normal; + else + samus_pose = kPose_01_FaceR_Normal; + samus_anim_frame_skip = 0; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + Samus_UpdatePreviousPose(); + return 1; +} + +uint8 SamusCode_04_06_Common(void) { // 0x90F19E + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + return 0; +} + +uint8 SamusCode_04(void) { // 0x90F19B + samus_charge_palette_index = 0; + return SamusCode_04_06_Common(); +} + +uint8 SamusCode_06_LockToStation(void) { // 0x90F1AA + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func13); + frame_handler_beta = FUNC16(j_HandleDemoRecorder_2); + if (!sign16(flare_counter - 15)) + QueueSfx1_Max15(2u); + return SamusCode_04_06_Common(); +} + +uint8 SamusCode_07_SetupForElevator(void) { // 0x90F1C8 + MakeSamusFaceForward(); + frame_handler_beta = FUNC16(Samus_Func19); + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + samus_draw_handler = FUNC16(SamusDisplayHandler_UsingElevator); + samus_input_handler = FUNC16(Samus_InputHandler_E913); + bomb_jump_dir = 0; + return 1; +} + +uint8 SamusCode_08_SetupForCeresStart(void) { // 0x90F1E9 + uint16 v1; + uint16 v2; + + frame_handler_alfa = FUNC16(EmptyFunction); + frame_handler_beta = FUNC16(SetContactDamageIndexAndUpdateMinimap); + samus_pose = kPose_00_FaceF_Powersuit; + samus_anim_frame_skip = 0; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + Samus_LoadSuitPalette(); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + samus_prev_pose = samus_pose; + samus_last_different_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + samus_y_pos = 0; + uint16 v0 = v1 = v2 = 0; + SpawnEnemyProjectileWithGfx(0, 0, addr_kEproj_CeresElevatorPad); + SpawnEnemyProjectileWithGfx(0, 0, addr_kEproj_CeresElevatorPlatform); + debug_disable_minimap = 0; + PlayRoomMusicTrackAfterAFrames(0x20); + return 1; +} + +uint8 SamusCode_08_SetupForZebesStart(void) { // 0x90F23C + if ((equipped_items & 0x20) != 0) { + SpawnPalfxObject(addr_stru_8DE1FC); + samus_pose = kPose_9B_FaceF_VariaGravitySuit; + } else if ((equipped_items & 1) != 0) { + SpawnPalfxObject(addr_stru_8DE1F8); + samus_pose = kPose_9B_FaceF_VariaGravitySuit; + } else { + SpawnPalfxObject(addr_stru_8DE1F4); + samus_pose = kPose_00_FaceF_Powersuit; + } + Samus_LoadSuitPalette(); + SamusFunc_F433(); + samus_anim_frame_timer = 3; + samus_anim_frame = 2; + substate = 0; + return 1; +} + +uint8 SamusCode_0A_ClearDrawHandler(void) { // 0x90F28D + samus_draw_handler = FUNC16(nullsub_152); + return 0; +} + +uint8 SamusCode_0B_DrawHandlerDefault(void) { // 0x90F295 + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + return SamusCode_01_UnlockSamus(); +} + +uint8 SamusCode_0C_UnlockFromMapStation(void) { // 0x90F29E + SamusFunc_E633(); + if (frame_handler_beta == (uint16)FUNC16(j_HandleDemoRecorder_2)) { + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func11); + frame_handler_beta = FUNC16(Samus_FrameHandlerBeta_Func17); + } + return 1; +} + +uint8 SamusCode_0D_IsGrappleActive(void) { // 0x90F2B8 + return (grapple_beam_function != FUNC16(GrappleBeamFunc_Inactive)) ? 2 : 0; +} + +uint8 SamusCode_0D_IsGrappleActive_A(void) { + return grapple_beam_function != FUNC16(GrappleBeamFunc_Inactive); +} + + +uint8 SamusCode_0E(void) { // 0x90F2CA + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func11); + frame_handler_beta = FUNC16(Samus_Func18); + return 1; +} + +uint8 SamusCode_0F_EnableTimerHandling(void) { // 0x90F2D8 + frame_handler_gamma = FUNC16(Samus_Func3); + return 0; +} + +uint8 SamusCode_10(void) { // 0x90F2E0 + if (frame_handler_beta != (uint16)FUNC16(j_HandleDemoRecorder_2_0)) { + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func11); + frame_handler_beta = FUNC16(Samus_FrameHandlerBeta_Func17); + } + return 1; +} + +uint8 SamusCode_11_15_Common(void) { // 0x90F2FC + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func13); + frame_handler_beta = FUNC16(EmptyFunction); + samus_draw_handler = FUNC16(SamusDisplayHandler_SamusReceivedFatal); + return 1; +} +uint8 SamusCode_11_SetupForDeath(void) { // 0x90F2F8 + DisablePaletteFx(); + return SamusCode_11_15_Common(); +} + + +uint8 SamusCode_15_CalledBySuitAcquision(void) { // 0x90F310 + Samus_UpdatePreviousPose(); + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + return SamusCode_11_15_Common(); +} + +uint8 SamusCode_12_SetSuperPaletteFlag1(void) { // 0x90F320 + samus_special_super_palette_flags = 1; + return 0; +} + +uint8 SamusCode_12_SetSuperPaletteFlag0(void) { // 0x90F328 + samus_special_super_palette_flags = 0; + Samus_LoadSuitPalette(); + return 0; +} + +uint8 SamusCode_14(void) { // 0x90F331 + if (sign16(samus_health - 31)) + QueueSfx3_Max6(2u); + if (!SamusCode_0D_IsGrappleActive_A()) { + if (samus_pose_x_dir == 3) { + if (samus_pose == kPose_81_FaceR_Screwattack || samus_pose == kPose_82_FaceL_Screwattack) { + QueueSfx1_Max6(0x33u); + return 0; + } else if (samus_pose == kPose_1B_FaceR_SpaceJump || samus_pose == kPose_1C_FaceL_SpaceJump) { + QueueSfx1_Max6(0x3Eu); + return 0; + } else { + QueueSfx1_Max6(0x31u); + return 0; + } + } else { + return 0; + } + } else { + QueueSfx1_Max6(6u); + return 0; + } +} + +uint8 SamusCode_05_SetupDrained(void) { // 0x90F38E + frame_handler_gamma = FUNC16(Samus_Func1); + return Samus_SetupForBeingDrained(); +} + +uint8 Samus_SetupForBeingDrained(void) { // 0x90F394 + samus_pose = kPose_54_FaceL_Knockback; + samus_anim_frame_skip = 0; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + Samus_UpdatePreviousPose(); + flare_counter = 0; + ClearFlareAnimationState(); + Samus_LoadSuitPalette(); + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func13); + frame_handler_beta = FUNC16(j_HandleDemoRecorder_2_0); + return 1; +} + +uint8 SamusCode_18(void) { // 0x90F3C0 + frame_handler_gamma = FUNC16(Samus_Func2); + return Samus_SetupForBeingDrained(); +} + +uint8 SamusCode_16(void) { // 0x90F3C9 + samus_special_super_palette_flags = 0x8000; + special_samus_palette_frame = 1; + special_samus_palette_timer = 1; + samus_charge_palette_index = 0; + return 0; +} + +uint8 SamusCode_17_DisableRainbowSamusAndStandUp(void) { // 0x90F3DD + samus_special_super_palette_flags = 0; + special_samus_palette_frame = 0; + special_samus_palette_timer = 0; + samus_charge_palette_index = 0; + Samus_LoadSuitPalette(); + samus_anim_frame_timer = 1; + samus_anim_frame = 13; + return 0; +} + +uint8 SamusCode_17_FreezeDrainedSamus(void) { // 0x90F3FB + samus_anim_frame_timer = 1; + samus_anim_frame = 28; + return 1; +} + +uint8 SamusCode_1A(void) { // 0x90F409 + frame_handler_beta = FUNC16(Samus_LowHealthCheck); + return 0; +} + +uint8 SamusCode_1B_CheckedLockSamus(void) { // 0x90F411 + if (frame_handler_beta == (uint16)FUNC16(j_HandleDemoRecorder_2_0)) + return 1; + else + return SamusCode_00_LockSamus(); +} + +uint8 SamusCode_1C(void) { // 0x90F41E + if (samus_movement_type == kMovementType_14_WallJumping) { + if (sign16(samus_anim_frame - 23)) { + if (sign16(samus_anim_frame - 13)) { +LABEL_11: + QueueSfx1_Max9(0x31u); + return 0; + } + goto LABEL_12; + } + } else { + if (samus_movement_type != kMovementType_03_SpinJumping) + return 0; + if (samus_pose != kPose_81_FaceR_Screwattack && samus_pose != kPose_82_FaceL_Screwattack) { + if (samus_pose != kPose_1B_FaceR_SpaceJump && samus_pose != kPose_1C_FaceL_SpaceJump) + goto LABEL_11; +LABEL_12: + QueueSfx1_Max9(0x3Eu); + return 0; + } + } + QueueSfx1_Max9(0x33u); + return 0; +} + +uint8 SamusCode_1D_ClearSoundInDoor(void) { // 0x90F471 + if (samus_movement_type == 3 || samus_movement_type == 20) { + QueueSfx1_Max15(0x32u); + return 0; + } else { + if ((button_config_shoot_x & joypad1_lastkeys) == 0) { + if (sign16(flare_counter - 16)) + QueueSfx1_Max15(2u); + } + return 0; + } +} + +uint8 SamusCode_1E(void) { // 0x90F4A2 + if (game_state == 8) { + if (samus_movement_type == 3 || samus_movement_type == 20) { + SamusCode_1C(); + return 0; + } + if (!sign16(flare_counter - 16)) + QueueSfx1_Max9(0x41u); + } + return 0; +} + +uint8 SamusCode_1F(void) { // 0x90F4D0 + if (grapple_beam_function != (uint16)addr_loc_90C4F0) { + grapple_beam_unkD1E = 0; + grapple_beam_unkD20 = 0; + grapple_beam_direction = 0; + grapple_beam_unkD36 = 0; + grapple_walljump_timer = 0; + slow_grabble_scrolling_flag = 0; + grapple_varCF6 = 0; + grapple_beam_flags = 0; + LoadProjectilePalette(equipped_beams); + grapple_beam_function = -15120; + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + } + return 0; +} + +uint8 Samus_Func26(void) { // 0x90F507 + if (samus_movement_type != kMovementType_03_SpinJumping + && samus_movement_type != kMovementType_14_WallJumping + && (button_config_shoot_x & joypad1_lastkeys) != 0 + && !sign16(flare_counter - 16)) { + QueueSfx1_Max9(0x41u); + } + return 0; +} + +void Samus_ShootCheck(void) { // 0x90F576 + if ((play_resume_charging_beam_sfx & 0x8000u) != 0) + goto LABEL_15; + if (play_resume_charging_beam_sfx) { + if ((button_config_shoot_x & joypad1_lastkeys) != 0) + QueueSfx1_Max9(0x41u); + play_resume_charging_beam_sfx = 0; + } + if (samus_echoes_sound_flag && (speed_boost_counter & 0x400) == 0) { + samus_echoes_sound_flag = 0; + QueueSfx3_Max15(0x25u); + } + if ((samus_prev_movement_type == 3 || samus_prev_movement_type == 20) + && samus_movement_type != kMovementType_03_SpinJumping + && samus_movement_type != kMovementType_14_WallJumping) { + QueueSfx1_Max15(0x32u); + if (!sign16(flare_counter - 16) && (button_config_shoot_x & joypad1_lastkeys) != 0) + LABEL_15: + play_resume_charging_beam_sfx = 1; + } + if (enable_debug) { + if (samus_pose == kPose_00_FaceF_Powersuit || samus_pose == kPose_9B_FaceF_VariaGravitySuit) { + if ((joypad2_last & 0x30) == 48 && (joypad2_new_keys & 0x80) != 0) + debug_invincibility = 7; + } else { + if (!sign16(debug_invincibility - 7)) + return; + debug_invincibility = 0; + } + } + if (CheckEventHappened(0xEu) & 1 + && frame_handler_gamma == (uint16)FUNC16(DrawTimer_) + && game_state != kGameState_35_TimeUp) { + game_state = kGameState_35_TimeUp; + } +} diff --git a/src/sm_91.c b/src/sm_91.c new file mode 100644 index 0000000..ac87168 --- /dev/null +++ b/src/sm_91.c @@ -0,0 +1,5303 @@ +// Aran +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "sm_rtl.h" + +static Func_V *const kSamusInputHandlers[28] = { + Samus_Input_00_Standing, + Samus_Input_01_Running, + Samus_Input_02_NormalJumping, + Samus_Input_03_SpinJumping, + Samus_Input_04_MorphBallOnGround, + Samus_Input_05_Crouching, + Samus_Input_06_Falling, + Samus_Input_07_Unused, + Samus_Input_08_MorphBallFalling, + Samus_Input_09_Unused, + Samus_Input_0A_KnockbackOrCrystalFlashEnding, + Samus_Input_0B_Unused, + Samus_Input_0C_Unused, + Samus_Input_0D_Unused, + Samus_Input_0E_TurningAroundOnGround, + Samus_Input_0F_CrouchingEtcTransition, + Samus_Input_10_Moonwalking, + Samus_Input_11_SpringBallOnGround, + Samus_Input_12_SpringBallInAir, + Samus_Input_13_SpringBallFalling, + Samus_Input_14_WallJumping, + Samus_Input_15_RanIntoWall, + Samus_Input_16_Grappling, + Samus_Input_17_TurningAroundJumping, + Samus_Input_18_TurningAroundFalling, + Samus_Input_19_DamageBoost, + Samus_Input_1A_GrabbedByDraygon, + Samus_Input_1B_ShinesparkEtc, +}; +void Samus_InputHandler(void) { // 0x918000 + kSamusInputHandlers[samus_movement_type](); +} + +void Samus_Input_00_Standing(void) { // 0x91804D + if (samus_pose && samus_pose != kPose_9B_FaceF_VariaGravitySuit || !elevator_status) + Samus_LookupTransitionTable(); +} + +void Samus_Input_01_Running(void) { // 0x918066 + Samus_LookupTransitionTable(); +} + +void Samus_Input_02_NormalJumping(void) { // 0x91806E + Samus_LookupTransitionTable(); +} + +void Samus_Input_03_SpinJumping(void) { // 0x918076 + Samus_LookupTransitionTable(); +} + +void Samus_Input_04_MorphBallOnGround(void) { // 0x91807E + Samus_LookupTransitionTable(); +} + +void Samus_Input_07_Unused(void) { // 0x918086 + ; +} + +void Samus_Input_05_Crouching(void) { // 0x918087 + if (time_is_frozen_flag) { + Samus_Func20(); + } else { + Samus_LookupTransitionTable(); + if (!samus_movement_type) { + samus_y_pos -= 5; + samus_prev_y_pos -= 5; + } + } +} + +void Samus_Input_06_Falling(void) { // 0x9180B6 + Samus_LookupTransitionTable(); +} + +void Samus_Input_08_MorphBallFalling(void) { // 0x91810A + Samus_LookupTransitionTable(); +} + +void Samus_Input_09_Unused(void) { // 0x918112 + ; +} + +void Samus_Input_0A_KnockbackOrCrystalFlashEnding(void) { // 0x918113 + Samus_LookupTransitionTable(); + if (samus_movement_type != kMovementType_0A_KnockbackOrCrystalFlashEnding) { + Samus_InitJump(); + samus_knockback_timer = 0; + } +} + +void Samus_Input_0B_Unused(void) { // 0x91812D + ; +} + +void Samus_Input_0C_Unused(void) { // 0x918132 + Samus_LookupTransitionTable(); +} + +void Samus_Input_0D_Unused(void) { // 0x91813A + Samus_LookupTransitionTable(); +} + +void Samus_Input_0E_TurningAroundOnGround(void) { // 0x918142 + Samus_LookupTransitionTable(); +} + +void Samus_Input_0F_CrouchingEtcTransition(void) { // 0x918146 + ; +} + +void Samus_Input_10_Moonwalking(void) { // 0x918147 + Samus_LookupTransitionTable(); +} + +void Samus_Input_11_SpringBallOnGround(void) { // 0x91814F + Samus_LookupTransitionTable(); +} + +void Samus_Input_12_SpringBallInAir(void) { // 0x918157 + Samus_LookupTransitionTable(); +} + +void Samus_Input_13_SpringBallFalling(void) { // 0x91815F + Samus_LookupTransitionTable(); +} + +void Samus_Input_14_WallJumping(void) { // 0x918167 + Samus_LookupTransitionTable(); +} + +void Samus_Input_15_RanIntoWall(void) { // 0x91816F + if (time_is_frozen_flag) + Samus_Func20(); + else + Samus_LookupTransitionTable(); +} + +void Samus_Input_16_Grappling(void) { // 0x918181 + Samus_LookupTransitionTable(); +} + +void Samus_Input_17_TurningAroundJumping(void) { // 0x918189 + Samus_LookupTransitionTable(); +} + +void Samus_Input_18_TurningAroundFalling(void) { // 0x91818D + Samus_LookupTransitionTable(); +} + +void Samus_Input_19_DamageBoost(void) { // 0x918191 + Samus_LookupTransitionTable(); +} + +void Samus_Input_1A_GrabbedByDraygon(void) { // 0x918199 + Samus_LookupTransitionTable(); +} + +void Samus_Input_1B_ShinesparkEtc(void) { // 0x9181A1 + Samus_LookupTransitionTable(); +} + +void Samus_LookupTransitionTable(void) { // 0x9181A9 + PoseEntry *pe; + int16 v2; + PoseEntry *v5; + PoseEntry *v6; + + if (joypad1_lastkeys) { + TranslateCustomControllerBindingsToDefault(); + uint16 v0 = kPoseTransitionTable[samus_pose]; + pe = get_PoseEntry(v0); + v2 = pe->new_input + 1; + if (pe->new_input != 0xFFFF) { + while (1) { + uint16 v3 = v2 - 1; + if (!v3 || (R18_ & v3) == 0) { + uint16 cur_input = get_PoseEntry(v0)->cur_input; + if (!cur_input || (R20_ & cur_input) == 0) + break; + } + v0 += 6; + v5 = get_PoseEntry(v0); + v2 = v5->new_input + 1; + if (v5->new_input == 0xFFFF) + goto LABEL_8; + } + v6 = get_PoseEntry(v0); + if (v6->new_pose != samus_pose) { + samus_new_pose = v6->new_pose; + bomb_jump_dir = 0; + } + } + } else { +LABEL_8: + UNUSED_word_7E0A18 = 0; + Samus_Pose_CancelGrapple(); + } +} + +void TranslateCustomControllerBindingsToDefault(void) { // 0x9181F4 + R18_ = joypad1_newkeys & (kButton_Up | kButton_Down | kButton_Left | kButton_Right); + R20_ = joypad1_lastkeys & (kButton_Up | kButton_Down | kButton_Left | kButton_Right); + uint16 v0 = joypad1_newkeys; + if ((button_config_shoot_x & joypad1_newkeys) != 0) { + R18_ |= kButton_X; + v0 = joypad1_newkeys; + } + if ((button_config_jump_a & v0) != 0) { + R18_ |= kButton_A; + v0 = joypad1_newkeys; + } + if ((button_config_run_b & v0) != 0) { + R18_ |= kButton_B; + v0 = joypad1_newkeys; + } + if ((button_config_itemcancel_y & v0) != 0) { + R18_ |= kButton_Y; + v0 = joypad1_newkeys; + } + if ((button_config_aim_up_R & v0) != 0) { + if ((button_config_aim_up_R & (kButton_L | kButton_R)) != 0) + R18_ |= kButton_R; + v0 = joypad1_newkeys; + } + if ((button_config_aim_down_L & v0) != 0 && (button_config_aim_down_L & (kButton_L | kButton_R)) != 0) + R18_ |= kButton_L; + R18_ = ~R18_; + uint16 v1 = joypad1_lastkeys; + if ((button_config_shoot_x & joypad1_lastkeys) != 0) { + R20_ |= kButton_X; + v1 = joypad1_lastkeys; + } + if ((button_config_jump_a & v1) != 0) { + R20_ |= kButton_A; + v1 = joypad1_lastkeys; + } + if ((button_config_run_b & v1) != 0) { + R20_ |= kButton_B; + v1 = joypad1_lastkeys; + } + if ((button_config_itemcancel_y & v1) != 0) { + R20_ |= kButton_Y; + v1 = joypad1_lastkeys; + } + if ((button_config_aim_up_R & v1) != 0) { + if ((button_config_aim_up_R & (kButton_L | kButton_R)) != 0) + R20_ |= kButton_R; + v1 = joypad1_lastkeys; + } + if ((button_config_aim_down_L & v1) != 0 && (button_config_aim_down_L & (kButton_L | kButton_R)) != 0) + R20_ |= kButton_L; + R20_ = ~R20_; +} + +void Samus_Pose_CancelGrapple(void) { // 0x9182D9 + if (Samus_Pose_Func2() & 1 || *(&kPoseParams[0].new_pose_unless_buttons + (uint16)(8 * samus_pose)) == 255) + samus_new_pose = samus_pose; + else + samus_new_pose = *(&kPoseParams[0].new_pose_unless_buttons + (uint16)(8 * samus_pose)); +} + +static const uint8 kSamus_Pose_Func2_Tab[28] = { // 0x918304 + 2, 1, 1, 0, 6, 2, 8, 2, 1, 6, 2, 2, 2, 6, 2, 2, + 2, 6, 6, 6, 6, 2, 6, 2, 2, 2, 2, 2, +}; + +uint8 Samus_Pose_Func2(void) { + + uint16 v0 = kSamus_Pose_Func2_Tab[samus_movement_type]; + if (v0 != 1) + goto LABEL_2; + if (!samus_x_base_speed && !samus_x_base_subspeed) { + v0 = 2; +LABEL_2: + samus_momentum_routine_index = v0; + return 0; + } + samus_momentum_routine_index = 1; + return 1; +} + +void EnableDemoInput(void) { // 0x91834E + samus_input_handler = FUNC16(Samus_InputHandler_E91D); + demo_enable |= 0x8000u; +} + +void DisableDemoInput(void) { // 0x91835F + samus_input_handler = FUNC16(Samus_InputHandler_E913); + demo_enable &= ~0x8000u; +} + +void ResetDemoData(void) { // 0x918370 + demo_input_pre_instr = 0; + demo_input_instr_timer = 0; + demo_input_instr_ptr = 0; + demo_timer_counter = 0; + xray_angle = 0; + demo_input = 0; + demo_input_new = 0; + demo_input_prev = 0; + demo_input_prev_new = 0; + demo_enable = 0; +} + +void LoadDemoInputObject(uint16 a, uint16 j) { // 0x918395 + DemoInputObject *dio; + xray_angle = a; + dio = get_DemoInputObject(j); + demo_input_pre_instr = dio->pre_instr; + demo_input_instr_ptr = dio->instr_ptr; + demo_input_instr_timer = 1; + demo_timer_counter = 0; + // Call(dio->ptr | 0x910000); +} + +void DemoObjectInputHandler(void) { // 0x9183C0 + if ((demo_enable & 0x8000u) != 0) { + if (demo_input_instr_ptr) { + ProcessDemoInputObject(); + joypad1_input_samusfilter = demo_input_prev; + joypad1_newinput_samusfilter = demo_input_prev_new; + joypad1_lastkeys = demo_input; + demo_input_prev = demo_input; + joypad1_newkeys = demo_input_new; + demo_input_prev_new = demo_input_new; + } + } +} + +void CallDemoPreInstr(uint32 ea) { + switch (ea) { + case fnDemoPreInstr_nullsub_162: return; + case fnDemoPreInstr_864F: DemoPreInstr_864F(); return; + case fnDemoPreInstr_866A: DemoPreInstr_866A(); return; + case fnDemoPreInstr_CheckLeaveDemo: DemoPreInstr_CheckLeaveDemo(); return; + case fnDemoPreInstr_8AB0: DemoPreInstr_8AB0(); return; + default: Unreachable(); + } +} + +uint16 CallDemoInstr(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnDemoInstr_Finish: return DemoInstr_Finish(k, j); + case fnDemoInstr_SetPreInstr: return DemoInstr_SetPreInstr(k, j); + case fnDemoInstr_ClearPreInstr: return DemoInstr_ClearPreInstr(k, j); + case fnDemoInstr_Goto: return DemoInstr_Goto(k, j); + case fnDemoInstr_DecTimerAndGoto: return DemoInstr_DecTimerAndGoto(k, j); + case fnDemoInstr_SetTimer: return DemoInstr_SetTimer(k, j); + case fnDemoInstr_Func2: return DemoInstr_Func2(k, j); + case fnDemoInstr_Disable: return DemoInstr_Disable(k, j); + case fnDemoInstr_Func3: return DemoInstr_Func3(k, j); + default: return Unreachable(); + } +} + +void ProcessDemoInputObject(void) { // 0x9183F2 + CallDemoPreInstr(demo_input_pre_instr | 0x910000); + if (!--demo_input_instr_timer) { + uint16 v0 = demo_input_instr_ptr; + uint16 *v1; + while (1) { + v1 = (uint16 *)RomPtr_91(v0); + uint16 v2 = *v1; + if ((*v1 & 0x8000u) == 0) + break; + R18_ = *v1; + v0 = CallDemoInstr(v2 | 0x910000, 0, v0 + 2); + if (!v0) + return; + } + demo_input_instr_timer = *v1; + uint8 *v3 = RomPtr_91(v0); + demo_input = *((uint16 *)v3 + 1); + demo_input_new = *((uint16 *)v3 + 2); + demo_input_instr_ptr = v0 + 6; + } +} + +uint16 DemoInstr_Finish(uint16 k, uint16 j) { // 0x918427 + demo_input_instr_ptr = 0; + demo_input = 0; + demo_input_new = 0; + return 0; +} + +uint16 DemoInstr_SetPreInstr(uint16 k, uint16 j) { // 0x918434 + demo_input_pre_instr = *(uint16 *)RomPtr_91(j); + return j + 2; +} + +uint16 DemoInstr_ClearPreInstr(uint16 k, uint16 j) { // 0x91843F + demo_input_pre_instr = 0x8447; + return j; +} + +uint16 DemoInstr_Goto(uint16 k, uint16 j) { // 0x918448 + return *(uint16 *)RomPtr_91(j); +} + +uint16 DemoInstr_DecTimerAndGoto(uint16 k, uint16 j) { // 0x91844F + if (--demo_timer_counter) + return DemoInstr_Goto(k, j); + else + return j + 2; +} + +uint16 DemoInstr_SetTimer(uint16 k, uint16 j) { // 0x918459 + demo_timer_counter = *(uint16 *)RomPtr_91(j); + return j + 2; +} + +uint16 DemoInstr_Func2(uint16 k, uint16 j) { // 0x9185FC + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func11); + frame_handler_beta = FUNC16(Samus_FrameHandlerBeta_Func17); + DisableDemoInput(); + return j; +} + +void DemoPreInstr_864F(void) { // 0x91864F + if (sign16(samus_x_pos - 178)) { + demo_input_pre_instr = FUNC16(DemoPreInstr_866A); + demo_input_instr_ptr = 0x8623; + demo_input_instr_timer = 1; + } +} + +void DemoPreInstr_866A(void) { // 0x91866A + if (!enemy_projectile_x_pos[0]) { + demo_input_pre_instr = FUNC16(DemoPreInstr_nullsub_162); + demo_input_instr_ptr = addr_off_91864B; + demo_input_instr_timer = 1; + } +} + +uint16 DemoInstr_Disable(uint16 k, uint16 j) { // 0x918682 + frame_handler_alfa = FUNC16(EmptyFunction); + frame_handler_beta = FUNC16(EmptyFunction); + DisableDemoInput(); + return j; +} + +void UNUSED_DemoInstr_Func4(void) { // 0x9186FE + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func13); + samus_pose = kPose_02_FaceL_Normal; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + DisableDemoInput(); + samus_input_handler = FUNC16(nullsub_152); +} + +uint16 DemoInstr_Func3(uint16 k, uint16 j) { // 0x918739 + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func13); + samus_pose = kPose_02_FaceL_Normal; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + DisableDemoInput(); + samus_input_handler = FUNC16(nullsub_152); + return j; +} + +static Func_V *const kDemoSetFuncPtrs_0[6] = { // 0x918790 + DemoSetFunc_0, + DemoSetFunc_1, + DemoSetFunc_1, + DemoSetFunc_2, + DemoSetFunc_1, + DemoSetFunc_3, +}; +static Func_V *const kDemoSetFuncPtrs_1[6] = { + DemoSetFunc_2, + DemoSetFunc_2, + DemoSetFunc_1, + DemoSetFunc_2, + DemoSetFunc_1, + DemoSetFunc_4, +}; +static Func_V *const kDemoSetFuncPtrs_2[6] = { + DemoSetFunc_2, + DemoSetFunc_5, + DemoSetFunc_1, + DemoSetFunc_1, + DemoSetFunc_1, + DemoSetFunc_1, +}; +static Func_V *const kDemoSetFuncPtrs_3[5] = { + DemoSetFunc_6, + DemoSetFunc_2, + DemoSetFunc_2, + DemoSetFunc_1, + DemoSetFunc_7, +}; + +static Func_V *const *const kDemoSetFuncPtrs[4] = { + kDemoSetFuncPtrs_0, + kDemoSetFuncPtrs_1, + kDemoSetFuncPtrs_2, + kDemoSetFuncPtrs_3, +}; + +void LoadDemoData(void) { + DemoSetDef *DemoSetDef; + + R18_ = 16 * demo_scene; + uint16 v0 = 16 * demo_scene + kDemoSetDefPtrs[demo_set]; + DemoSetDef = get_DemoSetDef(v0); + collected_items = DemoSetDef->items; + equipped_items = collected_items; + samus_max_missiles = DemoSetDef->missiles; + samus_missiles = samus_max_missiles; + samus_max_super_missiles = DemoSetDef->super_missiles; + samus_super_missiles = samus_max_super_missiles; + samus_max_power_bombs = DemoSetDef->power_bombs; + samus_power_bombs = samus_max_power_bombs; + samus_max_health = DemoSetDef->health; + samus_health = samus_max_health; + collected_beams = DemoSetDef->beams; + equipped_beams = DemoSetDef->equipped_beams_; + samus_reserve_health = 0; + ResetDemoData(); + EnableDemoInput(); + uint16 demo_obj = get_DemoSetDef(v0)->demo_obj; + LoadDemoInputObject(demo_obj, demo_obj); + R18_ = 2 * demo_scene; + kDemoSetFuncPtrs[demo_set][demo_scene](); + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func12); + frame_handler_beta = FUNC16(Samus_FrameHandlerBeta_Func14); + samus_momentum_routine_index = 0; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; + Samus_LoadSuitPalette(); + UpdateBeamTilesAndPalette(); + button_config_up = kButton_Up; + button_config_down = kButton_Down; + button_config_left = kButton_Left; + button_config_right = kButton_Right; + button_config_shoot_x = kButton_X; + button_config_jump_a = kButton_A; + button_config_run_b = kButton_B; + button_config_itemcancel_y = kButton_Y; + button_config_itemswitch = kButton_Select; + button_config_aim_up_R = kButton_R; + button_config_aim_down_L = kButton_L; + UNUSED_word_7E09E8 = 1; + debug_flag = 1; + moonwalk_flag = 0; + UNUSED_word_7E0DF8 = 0; + UNUSED_word_7E0DFA = 0; + UNUSED_word_7E0DFC = 0; +} + +void DemoSetFunc_0(void) { // 0x918A33 + MakeSamusFaceForward(); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); +} + +void DemoSetFunc_3(void) { // 0x918A3E + DemoSetFunc_Common(0x1Fu); +} + +void DemoSetFunc_7(void) { // 0x918A43 + samus_health = 20; + DemoSetFunc_2(); +} + +void DemoSetFunc_2(void) { // 0x918A49 + DemoSetFunc_Common(2u); +} + +void DemoSetFunc_4(void) { // 0x918A4E + DemoSetFunc_Common(0x2Au); +} + +void DemoSetFunc_1(void) { // 0x918A53 + DemoSetFunc_Common(1u); +} + +void DemoSetFunc_Common(uint16 a) { // 0x918A56 + samus_pose = a; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); +} + +void DemoSetFunc_5(void) { // 0x918A68 + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + Projectile_Func7_Shinespark(); + samus_pose = kPose_CD_FaceR_Shinespark_Diag; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); +} + +void DemoSetFunc_6(void) { // 0x918A81 + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + Projectile_Func7_Shinespark(); + samus_pose = kPose_CA_FaceL_Shinespark_Horiz; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); +} + +void DemoPreInstr_CheckLeaveDemo(void) { // 0x918A9B + if (game_state == kGameState_44_TransitionFromDemo) { + demo_input_instr_ptr = addr_kDemoInstrs_LeaveDemo; + demo_input_instr_timer = 1; + } +} + +void DemoPreInstr_8AB0(void) { // 0x918AB0 + if (samus_movement_type != kMovementType_1A_GrabbedByDraygon) { + demo_input_pre_instr = FUNC16(DemoPreInstr_CheckLeaveDemo); + demo_input_instr_ptr = addr_stru_919346; + demo_input_instr_timer = 1; + } +} + + +static Func_V *const kXrayHdmaFuncs[5] = { // 0x91BE11 + XrayHdmaFunc_BeamAimedR, + XrayHdmaFunc_BeamAimedU, + XrayHdmaFunc_BeamAimedD, + XrayHdmaFunc_BeamAimedL, + XrayHdmaFunc_BeamHoriz, +}; + +void CalculateXrayHdmaTable_OriginOffScreen(uint16 k, uint16 j) { + int16 v2; + uint16 v3; + + LOBYTE(v2) = HIBYTE(k); + HIBYTE(v2) = k; + R22_ = v2 & 0xFF00; + R24_ = j; + R26_ = R18_ - R20_; + R26_ += (R26_ & 0x8000u) != 0 ? 0x100 : 0; + R28_ = R20_ + R18_; + if (!sign16(R20_ + R18_ - 257)) + R28_ = R20_ + R18_ - 256; + if (!R20_ && (R18_ == 64 || R18_ == 192)) { + v3 = 8; + } else { + if (sign16(R26_ - 128)) { + if (sign16(R26_ - 64)) { + if (!sign16(R28_ - 64)) { + v3 = 0; + goto LABEL_16; + } + goto LABEL_13; + } + } else { + if (!sign16(R26_ - 192)) { +LABEL_13: + v3 = 2; + goto LABEL_16; + } + if (!sign16(R28_ - 192)) { + v3 = 6; + goto LABEL_16; + } + } + v3 = 4; + } +LABEL_16:; + uint16 v4 = R26_; + if (!sign16(R26_ - 128)) + v4 = R26_ - 128; + g_word_7E001E = kTanTable[v4]; + uint16 v5 = R28_; + if (!sign16(R28_ - 128)) + v5 = R28_ - 128; + R32 = kTanTable[v5]; + kXrayHdmaFuncs[v3 >> 1](); +} + +void XrayHdmaFunc_BeamAimedR(void) { // 0x91BEC2 + int16 v0; + int16 v2; + + v0 = 2 * (R24_ - 1); + R34 = R22_; + R36 = R22_; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + v0 -= 2; + if (v0 < 0) { + R18_ = 0; + goto LABEL_10; + } + } + IndirWriteWord(&R0_, v0, HIBYTE(R34) | 0xFF00); + R18_ = v0 + 2; + v2 = v0 - 2; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + IndirWriteWord(&R0_, v2, HIBYTE(R34) | 0xFF00); + v2 -= 2; + if (v2 < 0) + goto LABEL_10; + } + do { + IndirWriteWord(&R0_, v2, 0xFFu); + v2 -= 2; + } while (v2 >= 0); +LABEL_10:; + uint16 v3 = 2 * R24_; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + v3 += 2; + if ((int16)(v3 - 460) >= 0) { + R20_ = v3; + goto LABEL_19; + } + } + IndirWriteWord(&R0_, v3, HIBYTE(R36) | 0xFF00); + R20_ = v3 - 2; + uint16 v4; + v4 = v3 - 2 + 4; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + IndirWriteWord(&R0_, v4, HIBYTE(R36) | 0xFF00); + v4 += 2; + if ((int16)(v4 - 460) >= 0) + goto LABEL_19; + } + do { + IndirWriteWord(&R0_, v4, 0xFFu); + v4 += 2; + } while ((int16)(v4 - 460) < 0); +LABEL_19:; + uint16 v5 = R18_; + do { + do { + IndirWriteWord(&R0_, v5, 0xFF00u); + v5 += 2; + } while ((int16)(v5 - R20_) < 0); + } while (v5 == R20_); +} + +void XrayHdmaFunc_BeamAimedL(void) { // 0x91BF72 + int16 v0; + int16 v2; + + v0 = 2 * (R24_ - 1); + R34 = R22_; + R36 = R22_; + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + v0 -= 2; + if (v0 < 0) { + R18_ = 0; + goto LABEL_10; + } + } + IndirWriteWord(&R0_, v0, R36 & 0xFF00); + R18_ = v0 + 2; + v2 = v0 - 2; + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + IndirWriteWord(&R0_, v2, R36 & 0xFF00); + v2 -= 2; + if (v2 < 0) + goto LABEL_10; + } + do { + IndirWriteWord(&R0_, v2, 0xFFu); + v2 -= 2; + } while (v2 >= 0); +LABEL_10:; + uint16 v3 = 2 * R24_; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + v3 += 2; + if ((int16)(v3 - 460) >= 0) { + R20_ = v3; + goto LABEL_19; + } + } + IndirWriteWord(&R0_, v3, R34 & 0xFF00); + R20_ = v3 - 2; + uint16 v4; + v4 = v3 - 2 + 4; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + IndirWriteWord(&R0_, v4, R34 & 0xFF00); + v4 += 2; + if ((int16)(v4 - 460) >= 0) + goto LABEL_19; + } + do { + IndirWriteWord(&R0_, v4, 0xFFu); + v4 += 2; + } while ((int16)(v4 - 460) < 0); +LABEL_19:; + uint16 v5 = R18_; + do { + do { + IndirWriteWord(&R0_, v5, 0xFF00u); + v5 += 2; + } while ((int16)(v5 - R20_) < 0); + } while (v5 == R20_); +} + +static Func_Y_V *const off_91C063[3] = { // 0x91C022 + XrayHdmaFunc_BeamAimedUUR, + XrayHdmaFunc_BeamAimedUU, + XrayHdmaFunc_BeamAimedUUL, +}; + +void XrayHdmaFunc_BeamAimedU(void) { + uint16 v0; + R34 = R22_; + R36 = R22_; + if (sign16(R26_ - 192)) { + v0 = 0; + } else if (sign16(R28_ - 192)) { + v0 = 2; + } else { + v0 = 4; + } + R26_ = 2 * R24_; + off_91C063[v0 >> 1](2 * (R24_ - 1)); + uint16 v1 = R18_; + do { + IndirWriteWord(&R0_, v1, 0xFFu); + v1 += 2; + } while ((int16)(v1 - 460) < 0); +} + +void XrayHdmaFunc_BeamAimedUUR(uint16 v0) { // 0x91C069 + int16 v2; + int16 v3; + int16 v4; + int16 v6; + + v6 = v0; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + v0 -= 2; + if (v0 < 0) { + R18_ = 0; + goto LABEL_12; + } + } + IndirWriteByte(&R0_, v0, HIBYTE(R34)); + v2 = v0 - 2; + if (v2 >= 0) { + R18_ = v2 + 4; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + IndirWriteByte(&R0_, v2, HIBYTE(R34)); + v2 -= 2; + if (v2 < 0) + goto LABEL_12; + } + do { + IndirWriteByte(&R0_, v2, 0xFFu); + v2 -= 2; + } while (v2 >= 0); + } else { + R18_ = 2; + } +LABEL_12: + v3 = v6 + 1; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + v3 -= 2; + if (v3 < 0) { + R20_ = 1; + goto LABEL_23; + } + } + IndirWriteByte(&R0_, v3, HIBYTE(R36)); + v4 = v3 - 2; + if (v4 >= 0) { + R20_ = v4 + 4; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + IndirWriteByte(&R0_, v4, HIBYTE(R36)); + v4 -= 2; + if (v4 < 0) + goto LABEL_23; + } + do { + IndirWriteByte(&R0_, v4, 0xFFu); + v4 -= 2; + } while (v4 >= 0); + } else { + R20_ = 3; + } +LABEL_23:; + uint16 v5 = R18_; + do { + IndirWriteByte(&R0_, v5, 0); + v5 += 2; + } while ((int16)(v5 - R20_) < 0); + R18_ = R20_ - 1; +} + +void XrayHdmaFunc_BeamAimedUU(uint16 j) { // 0x91C123 + int16 v2; + int16 v3; + int16 v4; + + uint16 v5 = j; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + j -= 2; + if ((j & 0x8000u) != 0) { + R18_ = 0; + goto LABEL_12; + } + } + IndirWriteByte(&R0_, j, HIBYTE(R34)); + v2 = j - 2; + if (v2 >= 0) { + R18_ = v2 + 4; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + IndirWriteByte(&R0_, v2, HIBYTE(R34)); + v2 -= 2; + if (v2 < 0) + goto LABEL_12; + } + do { + IndirWriteByte(&R0_, v2, 0); + v2 -= 2; + } while (v2 >= 0); + } else { + R18_ = 2; + } +LABEL_12: + v3 = v5 + 1; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + v3 -= 2; + if (v3 < 0) { + R20_ = 1; + return; + } + } + IndirWriteByte(&R0_, v3, HIBYTE(R36)); + v4 = v3 - 2; + if (v4 >= 0) { + R20_ = v4 + 4; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + IndirWriteByte(&R0_, v4, HIBYTE(R36)); + v4 -= 2; + if (v4 < 0) + return; + } + do { + IndirWriteByte(&R0_, v4, 0xFFu); + v4 -= 2; + } while (v4 >= 0); + } else { + R20_ = 3; + } +} + +void XrayHdmaFunc_BeamAimedUUL(uint16 j) { // 0x91C1CA + int16 v2; + int16 v3; + int16 v4; + + uint16 v6 = j; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + j -= 2; + if ((j & 0x8000u) != 0) { + R18_ = 0; + goto LABEL_12; + } + } + IndirWriteByte(&R0_, j, HIBYTE(R34)); + v2 = j - 2; + if (v2 >= 0) { + R18_ = v2 + 4; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + IndirWriteByte(&R0_, v2, HIBYTE(R34)); + v2 -= 2; + if (v2 < 0) + goto LABEL_12; + } + do { + IndirWriteByte(&R0_, v2, 0); + v2 -= 2; + } while (v2 >= 0); + } else { + R18_ = 2; + } +LABEL_12: + v3 = v6 + 1; + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + v3 -= 2; + if (v3 < 0) { + R20_ = 1; + goto LABEL_23; + } + } + IndirWriteByte(&R0_, v3, HIBYTE(R34)); + v4 = v3 - 2; + if (v4 >= 0) { + R20_ = v4 + 4; + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + IndirWriteByte(&R0_, v4, HIBYTE(R36)); + v4 -= 2; + if (v4 < 0) + goto LABEL_23; + } + do { + IndirWriteByte(&R0_, v4, 0); + v4 -= 2; + } while (v4 >= 0); + } else { + R20_ = 3; + } +LABEL_23:; + uint16 v5 = R20_; + do { + IndirWriteByte(&R0_, v5, 0xFFu); + v5 += 2; + } while ((int16)(v5 - R18_) < 0); +} + +static Func_Y_V *const off_91C2B7[3] = { // 0x91C27F + XrayHdmaFunc_BeamAimedDDR, + XrayHdmaFunc_BeamAimedDD, + XrayHdmaFunc_BeamAimedDDL, +}; + +void XrayHdmaFunc_BeamAimedD(void) { + int16 v1; + uint16 v0; + + R34 = R22_; + R36 = R22_; + if (sign16(R28_ - 128)) { + v0 = 0; + } else if (sign16(R26_ - 128)) { + v0 = 2; + } else { + v0 = 4; + } + off_91C2B7[v0 >> 1](R24_ * 2); + v1 = R18_; + do { + IndirWriteWord(&R0_, v1, 0xFFu); + v1 -= 2; + } while (v1 >= 0); +} + +void XrayHdmaFunc_BeamAimedDDR(uint16 j) { // 0x91C2BD + uint16 v6 = j; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + j += 2; + if ((int16)(j - 460) >= 0) { + R18_ = j; + goto LABEL_12; + } + } + IndirWriteWord(&R0_, j, *(uint16 *)((char *)&R36 + 1)); + uint16 v2; + v2 = j + 2; + if ((int16)(v2 - 460) < 0) { + R18_ = v2 - 4; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + IndirWriteWord(&R0_, v2, *(uint16 *)((char *)&R36 + 1)); + v2 += 2; + if ((int16)(v2 - 460) >= 0) + goto LABEL_12; + } + do { + IndirWriteWord(&R0_, v2, 0xFFu); + v2 += 2; + } while ((int16)(v2 - 460) < 0); + } else { + R18_ = 458; + } +LABEL_12:; + uint16 v3 = v6 + 1; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + v3 += 2; + if ((int16)(v3 - 460) >= 0) { + R20_ = v3; + goto LABEL_23; + } + } + IndirWriteByte(&R0_, v3, HIBYTE(R34)); + uint16 v4; + v4 = v3 + 2; + if ((int16)(v4 - 460) < 0) { + R20_ = v4 - 4; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + IndirWriteByte(&R0_, v4, HIBYTE(R34)); + v4 += 2; + if ((int16)(v4 - 460) >= 0) + goto LABEL_23; + } + do { + IndirWriteByte(&R0_, v4, 0xFFu); + v4 += 2; + } while ((int16)(v4 - 460) < 0); + } else { + R20_ = 459; + } +LABEL_23:; + uint16 v5 = R18_; + do { + IndirWriteByte(&R0_, v5, 0); + v5 -= 2; + } while ((int16)(v5 - R20_) >= 0); + R18_ = R20_ - 1; +} + +void XrayHdmaFunc_BeamAimedDD(uint16 j) { // 0x91C381 + uint16 v5 = j; + if (R32) { + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + j += 2; + if ((int16)(j - 460) >= 0) { + R18_ = j; + goto LABEL_15; + } + } + IndirWriteWord(&R0_, j, *(uint16 *)((char *)&R36 + 1)); + uint16 v2 = j + 2; + if ((int16)(v2 - 460) < 0) { + R18_ = v2 - 4; + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + IndirWriteWord(&R0_, v2, *(uint16 *)((char *)&R36 + 1)); + v2 += 2; + if ((int16)(v2 - 460) >= 0) + goto LABEL_15; + } + do { + IndirWriteWord(&R0_, v2, 0); + v2 += 2; + } while ((int16)(v2 - 460) < 0); + } else { + R18_ = 458; + } + } else { + R18_ = j; + do { + IndirWriteWord(&R0_, j, 0); + j += 2; + } while ((int16)(j - 460) < 0); + } +LABEL_15:; + uint16 v3 = v5 + 1; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + v3 += 2; + if ((int16)(v3 - 460) >= 0) { + R20_ = v3; + return; + } + } + IndirWriteByte(&R0_, v3, HIBYTE(R34)); + uint16 v4 = v3 + 2; + if ((int16)(v4 - 460) < 0) { + R20_ = v4 - 4; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + IndirWriteByte(&R0_, v4, HIBYTE(R34)); + v4 += 2; + if ((int16)(v4 - 460) >= 0) + return; + } + do { + IndirWriteByte(&R0_, v4, 0xFFu); + v4 += 2; + } while ((int16)(v4 - 460) < 0); + } else { + R20_ = 459; + } +} + +void XrayHdmaFunc_BeamAimedDDL(uint16 j) { // 0x91C446 + uint16 v6 = j; + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + j += 2; + if ((int16)(j - 460) >= 0) { + R18_ = j; + goto LABEL_12; + } + } + IndirWriteWord(&R0_, j, *(uint16 *)((char *)&R36 + 1)); + uint16 v2; + v2 = j + 2; + if ((int16)(v2 - 460) < 0) { + R18_ = v2 - 4; + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + IndirWriteWord(&R0_, v2, *(uint16 *)((char *)&R36 + 1)); + v2 += 2; + if ((int16)(v2 - 460) >= 0) + goto LABEL_12; + } + do { + IndirWriteWord(&R0_, v2, 0); + v2 += 2; + } while ((int16)(v2 - 460) < 0); + } else { + R18_ = 458; + } +LABEL_12:; + uint16 v3 = v6 + 1; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + v3 += 2; + if ((int16)(v3 - 460) >= 0) { + R20_ = v3; + goto LABEL_23; + } + } + IndirWriteByte(&R0_, v3, HIBYTE(R34)); + uint16 v4; + v4 = v3 + 2; + if ((int16)(v4 - 460) < 0) { + R20_ = v4 - 4; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + IndirWriteByte(&R0_, v4, HIBYTE(R34)); + v4 += 2; + if ((int16)(v4 - 460) >= 0) + goto LABEL_23; + } + do { + IndirWriteByte(&R0_, v4, 0); + v4 += 2; + } while ((int16)(v4 - 460) < 0); + } else { + R20_ = 459; + } +LABEL_23:; + uint16 v5 = R20_; + do { + IndirWriteByte(&R0_, v5, 0xFFu); + v5 -= 2; + } while ((int16)(v5 - R18_) >= 0); +} + +void XrayHdmaFunc_BeamHoriz(void) { // 0x91C505 + int16 v1; + + uint16 v0 = 2 * (R24_ - 1); + IndirWriteWord(&R0_, v0, 0xFF00u); + v1 = v0 - 2; + do { + if (*(uint16 *)IndirPtr(&R0_, v1) == 255) + break; + IndirWriteWord(&R0_, v1, 0xFFu); + v1 -= 2; + } while (v1 >= 0); + uint16 v2 = 2 * R24_; + do { + if (*(uint16 *)IndirPtr(&R0_, v2) == 255) + break; + IndirWriteWord(&R0_, v2, 0xFFu); + v2 += 2; + } while ((int16)(v2 - 460) < 0); +} + +void CalculateXrayHdmaTable_OriginOnScreen(uint16 k, uint16 j) { // 0x91C54B + int16 v2; + uint16 v3; + + LOBYTE(v2) = HIBYTE(k); + HIBYTE(v2) = k; + R22_ = v2 & 0xFF00; + R24_ = j; + R26_ = R18_ - R20_; + R26_ += (R26_ & 0x8000u) != 0 ? 0x100 : 0; + R28_ = R20_ + R18_; + if (!sign16(R20_ + R18_ - 257)) + R28_ = R20_ + R18_ - 256; + if (!R20_ && (R18_ == 64 || R18_ == 192)) { + v3 = 8; + } else { + if (sign16(R26_ - 128)) { + if (sign16(R26_ - 64)) { + if (!sign16(R28_ - 64)) { + v3 = 0; + goto LABEL_16; + } + goto LABEL_13; + } + } else { + if (!sign16(R26_ - 192)) { +LABEL_13: + v3 = 2; + goto LABEL_16; + } + if (!sign16(R28_ - 192)) { + v3 = 6; + goto LABEL_16; + } + } + v3 = 4; + } +LABEL_16:; + uint16 v4 = R26_; + if (!sign16(R26_ - 128)) + v4 = R26_ - 128; + g_word_7E001E = kTanTable[v4]; + uint16 v5 = R28_; + if (!sign16(R28_ - 128)) + v5 = R28_ - 128; + R32 = kTanTable[v5]; + grapple_beam_unkD1E = 0; + static Func_V *const kXrayHdmaOnScreen_Funcs[5] = { + XrayHdmaOnScreen_BeamAimedR, + XrayHdmaOnScreen_BeamAimedU, + XrayHdmaOnScreen_BeamAimedD, + XrayHdmaOnScreen_BeamAimedL, + XrayHdmaOnScreen_BeamHoriz, + }; + + kXrayHdmaOnScreen_Funcs[v3 >> 1](); +} + +void XrayHdmaOnScreen_BeamAimedR(void) { // 0x91C5FF + int16 v1; + + uint16 v0 = 2 * (R24_ - 1); + IndirWriteWord(&R0_, v0, HIBYTE(R22_) | 0xFF00); + v1 = v0 - 2; + R34 = R22_; + R36 = R22_; + while (1) { + bool v2 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v2) + break; + IndirWriteWord(&R0_, v1, HIBYTE(R34) | 0xFF00); + v1 -= 2; + if (v1 < 0) + goto LABEL_6; + } + do { + IndirWriteWord(&R0_, v1, 0xFFu); + v1 -= 2; + } while (v1 >= 0); +LABEL_6:; + uint16 v3 = 2 * R24_; + while (1) { + bool v2 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v2) + break; + IndirWriteWord(&R0_, v3, HIBYTE(R36) | 0xFF00); + v3 += 2; + if ((int16)(v3 - 460) >= 0) + return; + } + do { + IndirWriteWord(&R0_, v3, 0xFFu); + v3 += 2; + } while ((int16)(v3 - 460) < 0); +} + +void XrayHdmaOnScreen_BeamAimedL(void) { // 0x91C660 + int16 v1; + + uint16 v0 = 2 * (R24_ - 1); + IndirWriteWord(&R0_, v0, R22_ & 0xFF00); + v1 = v0 - 2; + R34 = R22_; + R36 = R22_; + while (1) { + bool v2 = R36 >= R32; + R36 -= R32; + if (!v2) + break; + IndirWriteWord(&R0_, v1, R36 & 0xFF00); + v1 -= 2; + if (v1 < 0) + goto LABEL_6; + } + do { + IndirWriteWord(&R0_, v1, 0xFFu); + v1 -= 2; + } while (v1 >= 0); +LABEL_6:; + uint16 v3 = 2 * R24_; + while (1) { + bool v2 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v2) + break; + IndirWriteWord(&R0_, v3, R34 & 0xFF00); + v3 += 2; + if ((int16)(v3 - 460) >= 0) + return; + } + do { + IndirWriteWord(&R0_, v3, 0xFFu); + v3 += 2; + } while ((int16)(v3 - 460) < 0); +} + +void XrayHdmaOnScreen_BeamAimedU(void) { // 0x91C6C1 + uint16 v0 = 2 * (R24_ - 1); + IndirWriteByte(&R0_, v0++, HIBYTE(R22_)); + IndirWriteByte(&R0_, v0, HIBYTE(R22_)); + uint16 v1 = v0 - 3; + uint16 v2; + R34 = R22_; + R36 = R22_; + if (sign16(R26_ - 192)) { + v2 = 0; + } else if (sign16(R28_ - 192)) { + v2 = 2; + } else { + v2 = 4; + } + static Func_Y_V *const off_91C716[3] = { + XrayHdmaOnScreen_BeamAimedUUR, + XrayHdmaOnScreen_BeamAimedUU, + XrayHdmaOnScreen_BeamAimedUUL, + }; + off_91C716[v2 >> 1](v1); + uint16 v3 = 2 * R24_; + do { + if (*(uint16 *)IndirPtr(&R0_, v3) == 255) + break; + IndirWriteWord(&R0_, v3, 0xFFu); + v3 += 2; + } while ((int16)(v3 - 460) < 0); +} + +void XrayHdmaOnScreen_BeamAimedUUR(uint16 v0) { // 0x91C71C + int16 v2; + int16 v4; + + v4 = v0; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + IndirWriteByte(&R0_, v0, HIBYTE(R34)); + v0 -= 2; + if ((v0 & 0x8000u) != 0) + goto LABEL_7; + } + grapple_beam_unkD1E = v0; + do { + IndirWriteByte(&R0_, v0, 0xFFu); + v0 -= 2; + } while ((v0 & 0x8000u) == 0); +LABEL_7: + v2 = v4 + 1; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + IndirWriteByte(&R0_, v2, HIBYTE(R36)); + v2 -= 2; + if (v2 < 0) + return; + } + do { + IndirWriteByte(&R0_, v2, 0xFFu); + v2 -= 2; + } while (v2 >= 0); + if (grapple_beam_unkD1E) { + for (int i = grapple_beam_unkD1E - 2; i >= 0; i -= 2) + IndirWriteWord(&R0_, i, 0xFFu); + } +} + +void XrayHdmaOnScreen_BeamAimedUU(uint16 v0) { // 0x91C77F + int16 v2; + int16 v3; + + v3 = v0; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + IndirWriteByte(&R0_, v0, HIBYTE(R34)); + v0 -= 2; + if (v0 < 0) + goto LABEL_6; + } + do { + IndirWriteByte(&R0_, v0, 0); + v0 -= 2; + } while (v0 >= 0); +LABEL_6: + v2 = v3 + 1; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + IndirWriteByte(&R0_, v2, HIBYTE(R36)); + v2 -= 2; + if (v2 < 0) + return; + } + do { + IndirWriteByte(&R0_, v2, 0xFFu); + v2 -= 2; + } while (v2 >= 0); +} + +void XrayHdmaOnScreen_BeamAimedUUL(uint16 j) { // 0x91C7CB + int16 v2; + int16 v3; + int16 v5; + + uint16 v4 = j; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + IndirWriteByte(&R0_, j, HIBYTE(R34)); + j -= 2; + if ((j & 0x8000u) != 0) + goto LABEL_6; + } + do { + IndirWriteByte(&R0_, j, 0); + j -= 2; + } while ((j & 0x8000u) == 0); +LABEL_6: + v2 = v4 + 1; + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + IndirWriteByte(&R0_, v2, HIBYTE(R36)); + v2 -= 2; + if (v2 < 0) + return; + } + v5 = v2; + do { + IndirWriteByte(&R0_, v2, 0); + v2 -= 2; + } while (v2 >= 0); + v3 = v5 - 1; + do { + IndirWriteByte(&R0_, v3, 0xFFu); + v3 -= 2; + } while (v3 >= 0); +} + +void XrayHdmaOnScreen_BeamAimedD(void) { // 0x91C822 + int16 v3; + + uint16 v2; + uint16 v0 = 2 * (R24_ - 1); + IndirWriteByte(&R0_, v0++, HIBYTE(R22_)); + IndirWriteByte(&R0_, v0, HIBYTE(R22_)); + uint16 v1 = v0 + 1; + R34 = R22_; + R36 = R22_; + if (sign16(R28_ - 128)) { + v2 = 0; + } else if (sign16(R26_ - 128)) { + v2 = 2; + } else { + v2 = 4; + } + static Func_Y_V *const off_91C874[3] = { + XrayHdmaOnScreen_BeamAimedDDR, + XrayHdmaOnScreen_BeamAimedDD, + XrayHdmaOnScreen_BeamAimedDDL, + }; + off_91C874[v2 >> 1](v1); + v3 = 2 * (R24_ - 2); + do { + if (*(uint16 *)IndirPtr(&R0_, v3) == 255) + break; + IndirWriteWord(&R0_, v3, 0xFFu); + v3 -= 2; + } while (v3 >= 0); +} + +void XrayHdmaOnScreen_BeamAimedDDR(uint16 j) { // 0x91C87A + uint16 v4 = j; + while (1) { + bool v1 = __CFADD__uint16(R32, R36); + R36 += R32; + if (v1) + break; + IndirWriteWord(&R0_, j, *(uint16 *)((char *)&R36 + 1)); + j += 2; + if ((int16)(j - 460) >= 0) + goto LABEL_7; + } + grapple_beam_unkD1E = j; + do { + IndirWriteWord(&R0_, j, 0xFFu); + j += 2; + } while ((int16)(j - 460) < 0); +LABEL_7:; + uint16 v2 = v4 + 1; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + IndirWriteByte(&R0_, v2, HIBYTE(R34)); + v2 += 2; + if ((int16)(v2 - 460) >= 0) + return; + } + do { + IndirWriteByte(&R0_, v2, 0xFFu); + v2 += 2; + } while ((int16)(v2 - 460) < 0); + if (grapple_beam_unkD1E) { + uint16 v3 = grapple_beam_unkD1E + 2; + if ((int16)(grapple_beam_unkD1E - 458) < 0) { + do { + IndirWriteWord(&R0_, v3, 0xFFu); + v3 += 2; + } while ((int16)(v3 - 460) < 0); + } + } +} + +void XrayHdmaOnScreen_BeamAimedDD(uint16 j) { // 0x91C8E8 + uint16 v3 = j; + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + IndirWriteWord(&R0_, j, *(uint16 *)((char *)&R36 + 1)); + j += 2; + if ((int16)(j - 460) >= 0) + goto LABEL_6; + } + do { + IndirWriteWord(&R0_, j, 0); + j += 2; + } while ((int16)(j - 460) < 0); +LABEL_6:; + uint16 v2 = v3 + 1; + while (1) { + bool v1 = __CFADD__uint16(g_word_7E001E, R34); + R34 += g_word_7E001E; + if (v1) + break; + IndirWriteByte(&R0_, v2, HIBYTE(R34)); + v2 += 2; + if ((int16)(v2 - 460) >= 0) + return; + } + do { + IndirWriteByte(&R0_, v2, 0xFFu); + v2 += 2; + } while ((int16)(v2 - 460) < 0); +} + +void XrayHdmaOnScreen_BeamAimedDDL(uint16 j) { // 0x91C939 + uint16 v4 = j; + while (1) { + bool v1 = R36 >= R32; + R36 -= R32; + if (!v1) + break; + IndirWriteWord(&R0_, j, *(uint16 *)((char *)&R36 + 1)); + j += 2; + if ((int16)(j - 460) >= 0) + goto LABEL_6; + } + do { + IndirWriteWord(&R0_, j, 0); + j += 2; + } while ((int16)(j - 460) < 0); +LABEL_6:; + uint16 v2 = v4 + 1; + while (1) { + bool v1 = R34 >= g_word_7E001E; + R34 -= g_word_7E001E; + if (!v1) + break; + IndirWriteByte(&R0_, v2, HIBYTE(R34)); + v2 += 2; + if ((int16)(v2 - 460) >= 0) + return; + } + uint16 v5 = v2; + do { + IndirWriteByte(&R0_, v2, 0); + v2 += 2; + } while ((int16)(v2 - 460) < 0); + uint16 v3 = v5 - 1; + do { + IndirWriteByte(&R0_, v3, 0xFFu); + v3 += 2; + } while ((int16)(v3 - 460) < 0); +} + +void XrayHdmaOnScreen_BeamHoriz(void) { // 0x91C998 + int16 v1; + + uint16 v0 = 2 * (R24_ - 1); + if (R18_ == 64) + IndirWriteWord(&R0_, v0, HIBYTE(R22_) | 0xFF00); + else + IndirWriteWord(&R0_, v0, R22_ & 0xFF00); + v1 = v0 - 2; + do { + IndirWriteWord(&R0_, v1, 0xFFu); + v1 -= 2; + } while (v1 >= 0); + uint16 v2 = 2 * R24_; + do { + IndirWriteWord(&R0_, v2, 0xFFu); + v2 += 2; + } while ((int16)(v2 - 460) < 0); +} + +void XrayRunHandler(void) { // 0x91CAD6 +#define unk_91CAF2 (*(SpawnHdmaObject_Args*)RomPtr(0x91caf2)) + if (!time_is_frozen_flag && (button_config_run_b & joypad1_lastkeys) != 0) { + if (Xray_Initialize() & 1) + SpawnHdmaObject(0x91, &unk_91CAF2); + } +} + +void Xray_SetupStage1_FreezeTimeBackup(uint16 k) { // 0x91CAF9 + LOBYTE(time_is_frozen_flag) = 1; + *((uint8 *)hdma_object_A + (uint8)k) = reg_BG2HOFS; + *((uint8 *)hdma_object_A + (uint8)k + 1) = HIBYTE(reg_BG2HOFS); + *((uint8 *)hdma_object_B + (uint8)k) = reg_BG2VOFS; + *((uint8 *)hdma_object_B + (uint8)k + 1) = HIBYTE(reg_BG2VOFS); + *((uint8 *)hdma_object_C + (uint8)k) = reg_BG2SC; +} + +void Xray_SetupStage2_ReadBg1_2ndScreen(void) { // 0x91CB1C + unsigned int v1; + + uint16 v0 = vram_read_queue_tail; + v1 = vram_read_queue_tail; + *(uint16 *)((char *)&vram_read_queue[0].vram_target + vram_read_queue_tail) = ((reg_BG1SC & 0xFC) << 8) + 1024; + *(uint16 *)((char *)&vram_read_queue[0].dma_parameters + v1) = 129; + *(uint16 *)((char *)&vram_read_queue[0].dma_parameters + v0 + 1) = 57; + *(VoidP *)((char *)&vram_read_queue[0].src.addr + v0) = ADDR16_OF_RAM(ram4000) + 0x2800; + *(uint16 *)(&vram_read_queue[0].src.bank + v0) = 126; + *(uint16 *)((char *)&vram_read_queue[0].size + v0) = 2048; + vram_read_queue_tail = v0 + 9; +} + +void Xray_SetupStage3_ReadBg1_1stScreen(void) { // 0x91CB57 + unsigned int v1; + + uint16 v0 = vram_read_queue_tail; + v1 = vram_read_queue_tail; + *(uint16 *)((char *)&vram_read_queue[0].vram_target + vram_read_queue_tail) = (reg_BG1SC & 0xFC) << 8; + *(uint16 *)((char *)&vram_read_queue[0].dma_parameters + v1) = 129; + *(uint16 *)((char *)&vram_read_queue[0].dma_parameters + v0 + 1) = 57; + *(VoidP *)((char *)&vram_read_queue[0].src.addr + v0) = ADDR16_OF_RAM(ram4000) + 0x2000; + *(uint16 *)(&vram_read_queue[0].src.bank + v0) = 126; + *(uint16 *)((char *)&vram_read_queue[0].size + v0) = 2048; + vram_read_queue_tail = v0 + 9; +} + +void Xray_SetupStage4(void) { // 0x91CB8E + unsigned int v3; + int16 v6; + unsigned int v8; + + R24_ = 4 * (((uint8)layer1_y_pos + (uint8)bg1_y_offset) & 0xF0); + R24_ += (uint8)((layer1_x_pos + bg1_x_offset) & 0xF0) >> 3; + R24_ += 4 * ((layer1_x_pos + bg1_x_offset) & 0x100); + R22_ = 0; + R20_ = 16; + do { + R18_ = 16; + R26_ = R24_ & 0x7E0; + R28_ = R24_ & 0x1F; + g_word_7E001E = 0; + do { + if (!sign16(g_word_7E001E + R28_ - 32)) { + R26_ = (R26_ + 1024) & 0x7E0; + R28_ = 0; + g_word_7E001E = 0; + } + uint16 v0 = g_word_7E001E + R28_ + R26_; + uint16 v11 = ram4000.xray_tilemaps[v0 + 4096]; + uint16 v10 = ram4000.xray_tilemaps[v0 + 4097]; + uint16 v9 = ram4000.xray_tilemaps[v0 + 4128]; + uint16 v1 = ram4000.xray_tilemaps[v0 + 4129]; + uint16 v2 = R22_; + v3 = R22_; + *(uint16 *)((char *)&ram4000.xray_tilemaps[33] + R22_) = v1; + *(uint16 *)((char *)&ram4000.xray_tilemaps[32] + v3) = v9; + *(uint16 *)((char *)&ram4000.xray_tilemaps[1] + v2) = v10; + *(uint16 *)((char *)ram4000.xray_tilemaps + v2) = v11; + R22_ += 4; + g_word_7E001E += 2; + --R18_; + } while (R18_); + Xray_SetupStage4_Func1(); + R32 = R24_ & 0x400; + R24_ = (R24_ & 0x400) + ((R24_ + 64) & 0x3FF); + R22_ += 64; + --R20_; + } while (R20_); + assert((uint16)(layer1_y_pos >> 12) == 0); + uint16 prod = Mult8x8(layer1_y_pos >> 4, room_width_in_blocks); + v6 = layer1_x_pos >> 4; + R34 = prod + v6; + R22_ = 0; + R20_ = 16; + do { + Xray_SetupStage4_Func2(); + R18_ = 16; + R36 = R34; + do { + Xray_SetupStage4_Func3(); + --R18_; + } while (R18_); + uint16 v12 = R22_; + R22_ += 1984; + Xray_SetupStage4_Func3(); + R22_ = v12 + 64; + R34 += room_width_in_blocks; + --R20_; + } while (R20_); + LoadXrayBlocks(); + uint16 v7 = vram_read_queue_tail; + v8 = vram_read_queue_tail; + *(uint16 *)((char *)&vram_read_queue[0].vram_target + vram_read_queue_tail) = (reg_BG2SC & 0xFC) << 8; + *(uint16 *)((char *)&vram_read_queue[0].dma_parameters + v8) = 129; + *(uint16 *)((char *)&vram_read_queue[0].dma_parameters + v7 + 1) = 57; + *(VoidP *)((char *)&vram_read_queue[0].src.addr + v7) = 0x5000; + *(uint16 *)(&vram_read_queue[0].src.bank + v7) = 126; + *(uint16 *)((char *)&vram_read_queue[0].size + v7) = 2048; + vram_read_queue_tail = v7 + 9; +} + +void Xray_SetupStage4_Func1(void) { // 0x91CCF1 + int16 v0; + + R32 = R26_; + v0 = g_word_7E001E + R28_; + if (!sign16(g_word_7E001E + R28_ - 32)) { + R32 = (R32 + 1024) & 0x7E0; + v0 = 0; + } + uint16 v1 = R32 + v0; + uint16 v6 = ram4000.xray_tilemaps[v1 + 4096]; + uint16 v5 = ram4000.xray_tilemaps[v1 + 4097]; + uint16 v4 = ram4000.xray_tilemaps[v1 + 4128]; + uint16 v3 = ram4000.xray_tilemaps[v1 + 4129]; + uint16 v2 = R22_ + 1984; + *(uint16 *)((char *)&ram4000.xray_tilemaps[33] + (uint16)(R22_ + 1984)) = v3; + *(uint16 *)((char *)&ram4000.xray_tilemaps[32] + v2) = v4; + *(uint16 *)((char *)&ram4000.xray_tilemaps[1] + v2) = v5; + *(uint16 *)((char *)ram4000.xray_tilemaps + v2) = v6; +} + +void Xray_SetupStage4_Func2(void) { // 0x91CD42 + unsigned int v2; + int16 v3; + unsigned int v7; + unsigned int v11; + int16 v17; + + PairU16 pay = Xray_HandleXrayedBlock(R34 - 1); + uint16 v1 = pay.k; + v2 = pay.j; + v3 = v2; + if (v1 != (uint16)FUNC16(Xray_Func9)) { + if (v1 != (uint16)FUNC16(Xray_Func11)) + return; + v17 = v2; + uint16 v4 = *(uint16 *)&RomPtr_91(R3_.addr)[(uint16)(v2 + 8)]; + uint16 top_left = tile_table.tables[v4].top_left; + uint16 top_right = tile_table.tables[v4].top_right; + uint16 bottom_left = tile_table.tables[v4].bottom_left; + uint16 bottom_right = tile_table.tables[v4].bottom_right; + uint16 v6 = R22_; + v7 = R22_; + *(uint16 *)((char *)&ram4000.xray_tilemaps[97] + R22_) = bottom_right; + *(uint16 *)((char *)&ram4000.xray_tilemaps[96] + v7) = bottom_left; + *(uint16 *)((char *)&ram4000.xray_tilemaps[65] + v6) = top_right; + *(uint16 *)((char *)&ram4000.xray_tilemaps[64] + v6) = top_left; + v3 = v17; + } + uint16 v8 = *(uint16 *)&RomPtr_91(R3_.addr)[(uint16)(v3 + 4)]; + uint16 v18 = tile_table.tables[v8].top_left; + uint16 v16 = tile_table.tables[v8].top_right; + uint16 v14 = tile_table.tables[v8].bottom_left; + uint16 v9 = tile_table.tables[v8].bottom_right; + uint16 v10 = R22_; + v11 = R22_; + *(uint16 *)((char *)&ram4000.xray_tilemaps[33] + R22_) = v9; + *(uint16 *)((char *)&ram4000.xray_tilemaps[32] + v11) = v14; + *(uint16 *)((char *)&ram4000.xray_tilemaps[1] + v10) = v16; + *(uint16 *)((char *)ram4000.xray_tilemaps + v10) = v18; +} + +void CallXrayFunc(uint32 ea, uint16 j) { + switch (ea) { + case fnXray_Func6: Xray_Func6(); return; + case fnXray_Func6B: Xray_Func6B(); return; + case fnXray_Func7: Xray_Func7(j); return; + case fnXray_Func9: Xray_Func9(j); return; + case fnXray_Func10: Xray_Func10(j); return; + case fnXray_Func11: Xray_Func11(j); return; + default: Unreachable(); + } +} +void Xray_SetupStage4_Func3(void) { // 0x91CDBE + PairU16 v0; + + v0 = Xray_HandleXrayedBlock(R36); + if (v0.k == 0xFFFF) + Xray_Func21(v0.j); + else + CallXrayFunc(R0_.addr | 0x910000, v0.j); +} + +uint16 Xray_Func21(uint16 j) { // 0x91CDCB + R22_ += 4; + ++R36; + return j; +} + +#define stru_91D2D6 ((XrayBlockData*)RomPtr(0x91d2d6)) + +PairU16 Xray_HandleXrayedBlock(uint16 k) { // 0x91CDD6 + VoidP value; + uint16 j; + + R38 = BTS[k]; + R40 = level_data[k] & 0xF000; + for (int i = 0; ; ++i) { + value = stru_91D2D6[i].value; + if (value == 0xFFFF) + break; + if (value == R40) { + R0_.addr = stru_91D2D6[i].addr; + for (j = 0; ; j += 4) { + value = *(uint16 *)&RomPtr_91(R0_.addr)[j]; + if (value == 0xFFFF) + break; + if (value == 0xFF00 || value == R38) { + R3_.addr = *(uint16 *)&RomPtr_91(R0_.addr)[(uint16)(j + 2)]; + j = 0; + value = *(uint16 *)RomPtr_91(R3_.addr); + R0_.addr = value; + return MakePairU16(value, j); + } + } + return MakePairU16(value, j); + } + } + return MakePairU16(value, 0); +} + +void Xray_SomeDivide(void) { // 0x91CE2C + R44 = R36 / room_width_in_blocks; + R42 = R36 % room_width_in_blocks; +} + +uint16 Xray_Func5(void) { // 0x91CE51 + uint16 v1 = R42; + uint16 RegWord = room_width_in_blocks * (uint8)R44; + R46 = BTS[(uint16)(RegWord + v1)]; + R48 = level_data[RegWord + v1] & 0xF000; + return R48; +} + +void Xray_Func6(void) { // 0x91CE79 + Xray_SomeDivide(); + R48 = R40; + uint16 v0 = R38; + if (R38) { + if ((R38 & 0x80) != 0) + v0 = R38 | 0xFF00; + R46 = v0; + Xray_Func6D(); + } else { + Xray_Func20(); + } +} + +void Xray_Func6D(void) { // 0x91CE8E + uint16 v1; + do { + do { + if ((int16)(R46 + R44) < 0) { + Xray_Func13(0xFFu); + Xray_Func21(0); + return; + } + R44 += R46; + v1 = Xray_Func5(); + } while (v1 == 0xD000); + if (v1 != 20480) { + Xray_Func20(); + return; + } + } while ((R46 & 0x80) == 0); + R46 = (uint8)R46 ^ 0xFF00; + Xray_Func6C(); +} + +void Xray_Func6B(void) { // 0x91CEBB + Xray_SomeDivide(); + R48 = R40; + uint16 v0 = R38; + if (R38) { + if ((R38 & 0x80) != 0) + v0 = R38 | 0xFF00; + R46 = v0; + Xray_Func6C(); + } else { + Xray_Func20(); + } +} + +void Xray_Func6C(void) { // 0x91CED0 + while (1) { + if ((int16)(R46 + R42) < 0) { + Xray_Func13(0xFFu); + Xray_Func21(0); // ?? + return; + } + R42 += R46; + uint16 v1 = Xray_Func5(); + if (v1 == 0xD000) { + Xray_Func6D(); + return; + } + if (v1 != 20480) + break; + if ((R46 & 0x80) != 0) + R46 = (uint8)R46 ^ 0xFF00; + } + Xray_Func20(); +} + +#define stru_91D2D6 ((XrayBlockData*)RomPtr(0x91d2d6)) + +void Xray_Func20(void) { // 0x91CEFD + int i; + int16 v1; + + if (stru_91D2D6[1].value == R48) { + R0_.addr = stru_91D2D6[1].addr; + for (i = 0; ; i += 4) { + v1 = *(uint16 *)&RomPtr_91(R0_.addr)[i]; + if (v1 == -1) + break; + if (v1 == -256 || v1 == R46) { + R3_.addr = *(uint16 *)&RomPtr_91(R0_.addr)[(uint16)(i + 2)] + 2; + Xray_Func12(0); + Xray_Func21(0); + return; + } + } + } + Xray_Func21(i); +} + +uint16 Xray_Func7(uint16 j) { // 0x91CF36 + uint16 v1 = j + 2; + Xray_Func12(v1); + return Xray_Func21(v1); +} + +uint16 Xray_Func8(uint16 j) { // 0x91CF3E + uint16 v1 = j + 2; + if (area_index == 1) + Xray_Func12(v1); + return Xray_Func21(v1); +} + +uint16 Xray_Func9(uint16 j) { // 0x91CF4E + uint16 v1 = j + 2; + Xray_Func12(v1); + if (R18_ != 1) { + v1 += 2; + Xray_Func14(v1); + } + return Xray_Func21(v1); +} + +uint16 Xray_Func10(uint16 j) { // 0x91CF62 + uint16 v1 = j + 2; + Xray_Func12(v1); + v1 += 2; + Xray_Func15(v1); + return Xray_Func21(v1); +} + +uint16 Xray_Func11(uint16 j) { // 0x91CF6F + unsigned int v8; + + uint16 v1 = j + 2; + Xray_Func12(v1); + uint16 v2 = v1 + 2; + if (R18_ != 1) + Xray_Func14(v2); + uint16 v3 = v2 + 2; + Xray_Func15(v3); + uint16 v4 = v3 + 2; + if (R18_ != 1) { + uint16 v5 = *(uint16 *)&RomPtr_91(R3_.addr)[v4]; + uint16 top_left = tile_table.tables[v5].top_left; + uint16 top_right = tile_table.tables[v5].top_right; + uint16 bottom_left = tile_table.tables[v5].bottom_left; + uint16 bottom_right = tile_table.tables[v5].bottom_right; + uint16 v7 = R22_; + v8 = R22_; + *(uint16 *)((char *)&ram4000.xray_tilemaps[99] + R22_) = bottom_right; + *(uint16 *)((char *)&ram4000.xray_tilemaps[98] + v8) = bottom_left; + *(uint16 *)((char *)&ram4000.xray_tilemaps[67] + v7) = top_right; + *(uint16 *)((char *)&ram4000.xray_tilemaps[66] + v7) = top_left; + } + return Xray_Func21(v4); +} + +void Xray_Func12(uint16 j) { // 0x91CFBF + uint8 *v1 = RomPtr_91(R3_.addr); + Xray_Func13(*(uint16 *)&v1[j]); +} + +void Xray_Func13(uint16 a) { // 0x91CFC1 + unsigned int v3; + + uint16 v1 = a; + uint16 top_left = tile_table.tables[v1].top_left; + uint16 top_right = tile_table.tables[v1].top_right; + uint16 bottom_left = tile_table.tables[v1].bottom_left; + uint16 v2 = R22_; + v3 = R22_; + *(uint16 *)((char *)&ram4000.xray_tilemaps[33] + R22_) = tile_table.tables[v1].bottom_right; + *(uint16 *)((char *)&ram4000.xray_tilemaps[32] + v3) = bottom_left; + *(uint16 *)((char *)&ram4000.xray_tilemaps[1] + v2) = top_right; + *(uint16 *)((char *)ram4000.xray_tilemaps + v2) = top_left; +} + +void Xray_Func14(uint16 j) { // 0x91CFEE + unsigned int v4; + + uint16 v1 = *(uint16 *)&RomPtr_91(R3_.addr)[j]; + uint16 top_left = tile_table.tables[v1].top_left; + uint16 top_right = tile_table.tables[v1].top_right; + uint16 bottom_left = tile_table.tables[v1].bottom_left; + uint16 bottom_right = tile_table.tables[v1].bottom_right; + uint16 v3 = R22_; + v4 = R22_; + *(uint16 *)((char *)&ram4000.xray_tilemaps[35] + R22_) = bottom_right; + *(uint16 *)((char *)&ram4000.xray_tilemaps[34] + v4) = bottom_left; + *(uint16 *)((char *)&ram4000.xray_tilemaps[3] + v3) = top_right; + *(uint16 *)((char *)&ram4000.xray_tilemaps[2] + v3) = top_left; +} + +void Xray_Func15(uint16 j) { // 0x91D01D + unsigned int v4; + + uint16 v1 = *(uint16 *)&RomPtr_91(R3_.addr)[j]; + uint16 top_left = tile_table.tables[v1].top_left; + uint16 top_right = tile_table.tables[v1].top_right; + uint16 bottom_left = tile_table.tables[v1].bottom_left; + uint16 bottom_right = tile_table.tables[v1].bottom_right; + uint16 v3 = R22_; + v4 = R22_; + *(uint16 *)((char *)&ram4000.xray_tilemaps[97] + R22_) = bottom_right; + *(uint16 *)((char *)&ram4000.xray_tilemaps[96] + v4) = bottom_left; + *(uint16 *)((char *)&ram4000.xray_tilemaps[65] + v3) = top_right; + *(uint16 *)((char *)&ram4000.xray_tilemaps[64] + v3) = top_left; +} + +void LoadBlockToXrayTilemap(uint16 a, uint16 k, uint16 j) { // 0x91D04C + R40 = a; + R24_ = layer1_x_pos >> 4; + if ((int16)(k - (layer1_x_pos >> 4)) >= 0) { + R24_ = k - (layer1_x_pos >> 4); + if ((((__PAIR32__(k - (layer1_x_pos >> 4), k) - ((layer1_x_pos >> 4) | 0x100000)) >> 16) & 0x8000u) != 0) { + R26_ = layer1_y_pos >> 4; + if ((int16)(j - (layer1_y_pos >> 4)) >= 0) { + R26_ = j - (layer1_y_pos >> 4); + if ((((__PAIR32__(j - (layer1_y_pos >> 4), j) - ((layer1_y_pos >> 4) | 0x100000)) >> 16) & 0x8000u) != 0) { + R22_ = 4 * (R24_ + 32 * R26_); + if ((R40 & 0x800) != 0) + Xray_Func16(R40 & 0x3FF); + else + Xray_Func13(R40 & 0x3FF); + } + } + } + } +} + +void Xray_Func16(uint16 a) { // 0x91D0A6 + unsigned int v3; + + uint16 v1 = a; + uint16 top_left = tile_table.tables[v1].top_left; + uint16 top_right = tile_table.tables[v1].top_right; + uint16 bottom_left = tile_table.tables[v1].bottom_left; + uint16 v2 = R22_; + v3 = R22_; + *(uint16 *)((char *)&ram4000.xray_tilemaps[1] + R22_) = tile_table.tables[v1].bottom_right; + *(uint16 *)((char *)ram4000.xray_tilemaps + v3) = bottom_left; + *(uint16 *)((char *)&ram4000.xray_tilemaps[33] + v2) = top_right; + *(uint16 *)((char *)&ram4000.xray_tilemaps[32] + v2) = top_left; +} + +void Xray_SetupStage5(void) { // 0x91D0D3 + unsigned int v1; + + if ((CanXrayShowBlocks() & 2) == 0) { + if (earthquake_timer) { + reg_BG1HOFS = layer1_x_pos + bg1_x_offset; + reg_BG1VOFS = layer1_y_pos + bg1_y_offset; + } + reg_BG2HOFS = reg_BG1HOFS & 0xF; + reg_BG2VOFS = reg_BG1VOFS & 0xF; + reg_BG2SC = 73; + } + uint16 v0 = vram_read_queue_tail; + v1 = vram_read_queue_tail; + *(uint16 *)((char *)&vram_read_queue[0].vram_target + vram_read_queue_tail) = ((reg_BG2SC & 0xFC) << 8) + 1024; + *(uint16 *)((char *)&vram_read_queue[0].dma_parameters + v1 + 1) = 57; + *(VoidP *)((char *)&vram_read_queue[0].src.addr + v0) = 0x5800; + *(uint16 *)(&vram_read_queue[0].src.bank + v0) = 126; + *(uint16 *)((char *)&vram_read_queue[0].size + v0) = 2048; + vram_read_queue_tail = v0 + 9; +} + +void CanXrayShowBlocks_(void) { // 0x91D141 + CanXrayShowBlocks(); +} + +uint8 CanXrayShowBlocks(void) { // 0x91D143 + uint8 result = room_ptr; + if (room_ptr != (uint16)addr_kRoom_a66a && room_ptr != (uint16)addr_kRoom_cefb) { + result = fx_type; + if (fx_type != 36) + return boss_id; + } + return result; +} + +void Xray_SetupStage6(void) { // 0x91D173 + VramWriteEntry *v1; + + if ((CanXrayShowBlocks() & 2) == 0) { + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 2048; + v1->src.addr = ADDR16_OF_RAM(ram4000); + *(uint16 *)&v1->src.bank = 126; + v1->vram_dst = (reg_BG2SC & 0xFC) << 8; + vram_write_queue_tail = v0 + 7; + } +} + +void Xray_SetupStage7(void) { // 0x91D1A0 + VramWriteEntry *v1; + + if ((CanXrayShowBlocks() & 2) == 0) { + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 2048; + v1->src.addr = 0x4800; + *(uint16 *)&v1->src.bank = 126; + v1->vram_dst = ((reg_BG2SC & 0xFC) << 8) + 1024; + vram_write_queue_tail = v0 + 7; + } + mov24((LongPtr *)&demo_enable, 0x9800E4); + mov24((LongPtr *)((char *)&demo_num_input_frames + 1), 0x98C8E4u); + mov24((LongPtr *)&demo_input_prev_new, 0x999098u); + *(uint16 *)((char *)&demo_backup_prev_controller_input + 1) = 0; + demo_input_pre_instr = 0; + demo_input_instr_timer = 0; + demo_input_instr_ptr = 0; + demo_input = 0; + demo_input_new = 0; + if (samus_pose_x_dir == 4) + xray_angle = 192; + else + xray_angle = 64; +} + +void HdmaobjPreInstr_XraySetup(uint16 k) { // 0x91D27F + int16 v1; + + v1 = 4096; + if (fx_type == 36) { + if (!sign16((reg_COLDATA[0] & 0x1F) - 7)) + goto LABEL_5; + goto LABEL_4; + } + v1 = 0x2000; + if ((CanXrayShowBlocks() & 2) == 0) { + v1 = 0x4000; +LABEL_4: + *(uint16 *)®_COLDATA[0] = 0x27; + *(uint16 *)®_COLDATA[1] = 0x47; + *(uint16 *)®_COLDATA[2] = 0x87; + } +LABEL_5: + fx_layer_blending_config_c |= v1; +} + +void Xray_SetupStage8_SetBackdropColor(void) { // 0x91D2BC + palette_buffer[0] = 3171; +} + +void sub_91D2D1(void) { // 0x91D2D1 + ; +} + +void GameState_28_Unused_(void) { // 0x91D4DA + Unreachable(); +} + +void VariaSuitPickup(void) { // 0x91D4E4 + suit_pickup_color_math_R = 48; + suit_pickup_color_math_G = 80; + suit_pickup_color_math_B = 0x80; + suit_pickup_palette_transition_color = 0; + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 0; + used_for_ball_bounce_on_landing = 0; + samus_x_accel_mode = 0; + elevator_status = 0; + substate = 0; + suit_pickup_light_beam_pos = 0; + suit_pickup_light_beam_widening_speed = 256; + for (int i = 510; i >= 0; i -= 2) + hdma_table_1[i >> 1] = 255; + if (samus_movement_type == 3 || samus_movement_type == 20) + QueueSfx1_Max9(0x32u); + if ((equipped_items & 0x20) != 0) + samus_pose = kPose_9B_FaceF_VariaGravitySuit; + else + samus_pose = kPose_00_FaceF_Powersuit; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + CallSomeSamusCode(0x15u); + samus_x_pos = layer1_x_pos + 120; + samus_prev_x_pos = layer1_x_pos + 120; + samus_y_pos = layer1_y_pos + 136; + samus_prev_y_pos = layer1_y_pos + 136; + QueueSfx2_Max6(0x56u); + static const SpawnHdmaObject_Args unk_91D59B = { 0x41, 0x26, 0xd5a2 }; + SpawnHdmaObject(0x91, &unk_91D59B); +} + +void GravitySuitPickup(void) { // 0x91D5BA + suit_pickup_color_math_R = 48; + suit_pickup_color_math_G = 73; + suit_pickup_color_math_B = -112; + suit_pickup_palette_transition_color = 1; + Samus_CancelSpeedBoost(); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 0; + used_for_ball_bounce_on_landing = 0; + samus_x_accel_mode = 0; + elevator_status = 0; + substate = 0; + suit_pickup_light_beam_pos = 0; + suit_pickup_light_beam_widening_speed = 256; + for (int i = 510; i >= 0; i -= 2) + hdma_table_1[i >> 1] = 255; + if (samus_movement_type == kMovementType_03_SpinJumping || samus_movement_type == kMovementType_14_WallJumping) + QueueSfx1_Max9(0x32u); + if ((equipped_items & 1) != 0) + samus_pose = kPose_9B_FaceF_VariaGravitySuit; + else + samus_pose = kPose_00_FaceF_Powersuit; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + CallSomeSamusCode(0x15u); + samus_x_pos = layer1_x_pos + 120; + samus_prev_x_pos = layer1_x_pos + 120; + samus_y_pos = layer1_y_pos + 136; + samus_prev_y_pos = layer1_y_pos + 136; + QueueSfx2_Max6(0x56u); + static const SpawnHdmaObject_Args unk_91D673 = { 0x41, 0x26, 0xd67a }; + SpawnHdmaObject(0x91, &unk_91D673); +} + +void InitializeSuitPickupHdma(void) { // 0x91D692 + reg_TM = 19; + reg_TMW = 19; + reg_TS = 4; + reg_TSW = 4; + next_gameplay_CGWSEL = 16; + reg_W12SEL = 0; + reg_W34SEL = 2; + reg_WOBJSEL = 32; + next_gameplay_CGADSUB = 51; + reg_COLDATA[0] = suit_pickup_color_math_R; + reg_COLDATA[1] = suit_pickup_color_math_G; + reg_COLDATA[2] = suit_pickup_color_math_B; + mov24((LongPtr *)&demo_enable, 0x9800E4u); + mov24((LongPtr *)((char *)&demo_num_input_frames + 1), 0x98C8E4u); + mov24((LongPtr *)&demo_input_prev_new, 0x999098u); + *(uint16 *)((char *)&demo_backup_prev_controller_input + 1) = 0; +} + +#define off_91D727 ((uint16*)RomPtr(0x91d727)) + +static Func_U8 *const off_91D72D[11] = { // 0x91D6F7 + Samus_HandleScrewAttackSpeedBoostingPals, + Samus_SpeedBoosterShinePals, + (Func_U8 *)HandleMiscSamusPalette, + 0, + 0, + 0, + Samus_HandleShinesparkingPals, + Samus_HandleCrystalFlashPals, + Samus_HandleXrayPals, + HandleVisorPalette, + nullsub_164, +}; + +void Samus_HandlePalette(void) { + if ((samus_special_super_palette_flags & 0x8000u) == 0 + && (HandleBeamChargePalettes() & 1 + || !(off_91D72D[timer_for_shine_timer]() & 1))) { + CopyToSamusSuitPalette(off_91D727[samus_suit_palette_index >> 1]); + } + HandleMiscSamusPalette(); +} +#define kSamusPalette_HyperBeam ((uint16*)RomPtr(0x91d829)) +#define kSamusPalette_NonPseudoScrew ((uint16*)RomPtr(0x91d7d5)) +#define kSamusPalette_PseudoScrew ((uint16*)RomPtr(0x91d7ff)) +uint8 HandleBeamChargePalettes(void) { // 0x91D743 + if (charged_shot_glow_timer) { + if (hyper_beam_flag) { + if ((charged_shot_glow_timer & 1) == 0) { + if ((charged_shot_glow_timer & 0x1E) == 0) { + charged_shot_glow_timer = 0; + return 1; + } + CopyToSamusSuitPalette(kSamusPalette_HyperBeam[(uint8)(charged_shot_glow_timer & 0x1E) >> 1]); + } + --charged_shot_glow_timer; + return 0; + } + if (--charged_shot_glow_timer) { + for (int i = 28; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 193] = 1023; + return 0; + } else { + return 1; + } + } else if (grapple_beam_function == (uint16)FUNC16(GrappleBeamFunc_Inactive) + && flare_counter + && !sign16(flare_counter - 60)) { + if (samus_contact_damage_index == 4) + R36 = kSamusPalette_PseudoScrew[samus_suit_palette_index >> 1]; + else + R36 = kSamusPalette_NonPseudoScrew[samus_suit_palette_index >> 1]; + uint16 v0 = *(uint16 *)RomPtr_91(R36 + samus_charge_palette_index); + CopyToSamusSuitPalette(v0); + uint16 v1 = samus_charge_palette_index + 2; + if (!sign16(samus_charge_palette_index - 10)) + v1 = 0; + samus_charge_palette_index = v1; + return 0; + } else { + samus_charge_palette_index = 0; + return HandleVisorPalette(); + } +} + +#define word_9BA3C0 ((uint16*)RomPtr(0x9ba3c0)) +uint8 HandleVisorPalette(void) { // 0x91D83F + int16 v2; + uint16 v3; + char v4; // t0 + + if (timer_for_shine_timer == 8) + return 0; + if (fx_layer_blending_config_a == 40 || fx_layer_blending_config_a == 42) { + uint16 v1 = samus_visor_palette_timer_index - 1; + samus_visor_palette_timer_index = v1; + if ((uint8)v1) + return 0; + samus_visor_palette_timer_index = v1 | 5; + palette_buffer[196] = word_9BA3C0[(uint16)((uint16)(v1 | 5) >> 8) >> 1]; + v2 = ((uint16)(v1 | 5) >> 8) + 2; + if (sign16(v2 - 12)) { + v4 = v2; + LOBYTE(v3) = HIBYTE(v2); + HIBYTE(v3) = v4; + R18_ = v3; + samus_visor_palette_timer_index = v3 | (uint8)samus_visor_palette_timer_index; + } else { + samus_visor_palette_timer_index = (uint8)samus_visor_palette_timer_index | 0x600; + } + return 0; + } else { + samus_visor_palette_timer_index = 1537; + return 0; + } +} + +#define kSamus_SpeedBoostingPalettes ((uint16*)RomPtr(0x91d998)) +#define kSamus_HyperBeamPalettes ((uint16*)RomPtr(0x91d99e)) + +void HandleMiscSamusPalette(void) { // 0x91D8A5 + if (!samus_special_super_palette_flags) { + uint16 v0 = samus_hurt_flash_counter; + if (!samus_hurt_flash_counter) + return; + if (samus_hurt_flash_counter == 2) { + if (!cinematic_function + && (frame_handler_beta != (uint16)FUNC16(j_HandleDemoRecorder_2_0) + || samus_pose != kPose_54_FaceL_Knockback)) { + QueueSfx1_Max6(0x35u); + goto LABEL_14; + } + v0 = samus_hurt_flash_counter; + } + if (!sign16(v0 - 7)) + goto LABEL_17; + if ((v0 & 1) != 0) { + CopyToSamusSuitPalette(addr_word_9BA380); + goto LABEL_17; + } +LABEL_14: + if (cinematic_function) + CopyToSamusSuitPalette(addr_word_9BA3A0); + else + Samus_LoadSuitPalette(); +LABEL_17:; + uint16 v1 = samus_hurt_flash_counter + 1; + samus_hurt_flash_counter = v1; + if (v1 == 40) { + if (grapple_beam_function == (uint16)FUNC16(GrappleBeamFunc_Inactive)) { + if (samus_movement_type == kMovementType_03_SpinJumping || samus_movement_type == kMovementType_14_WallJumping) { + CallSomeSamusCode(0x1Cu); + } else if (!sign16(flare_counter - 16) && (button_config_shoot_x & joypad1_lastkeys) != 0) { + play_resume_charging_beam_sfx = 1; + } + } else if (sign16(grapple_beam_function + 0x37AA)) { + QueueSfx1_Max9(6u); + } + } else if (!sign16(v1 - 60)) { + samus_hurt_flash_counter = 0; + } + return; + } + if ((samus_special_super_palette_flags & 0x8000u) != 0) { + CopyToSamusSuitPalette(kSamus_HyperBeamPalettes[samus_charge_palette_index]); + bool v2 = (--special_samus_palette_timer & 0x8000u) != 0; + if (!special_samus_palette_timer || v2) { + special_samus_palette_timer = special_samus_palette_frame; + if (!sign16(++samus_charge_palette_index - 10)) + samus_charge_palette_index = 0; + } + } else { + if ((samus_special_super_palette_flags & 1) != 0) + CopyToSamusSuitPalette(kSamus_SpeedBoostingPalettes[samus_suit_palette_index >> 1]); + else + Samus_LoadSuitPalette(); + ++samus_special_super_palette_flags; + } +} + +#define kSamusPal_ScrewAttack ((uint16*)RomPtr(0x91da4a)) +#define kSamusPal_SpeedBoost ((uint16*)RomPtr(0x91daa9)) + +uint8 Samus_HandleScrewAttackSpeedBoostingPals(void) { // 0x91D9B2 + if ((samus_suit_palette_index & 4) == 0) { + Samus_GetTopBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R20_)) + return 1; + } else if (sign16(fx_y_pos - R20_) && (fx_liquid_options & 4) == 0) { + return 1; + } + } + if (samus_movement_type == kMovementType_03_SpinJumping) { + if ((equipped_items & 8) == 0) + goto LABEL_10; + if (samus_anim_frame) { + if (!sign16(samus_anim_frame - 27)) + return 0; + goto LABEL_18; + } + goto LABEL_21; + } + if (samus_movement_type == kMovementType_14_WallJumping) { + if ((equipped_items & 8) == 0) + return 1; + if (!sign16(samus_anim_frame - 3)) { +LABEL_18: + R36 = kSamusPal_ScrewAttack[samus_suit_palette_index >> 1]; + uint16 v1 = *(uint16 *)RomPtr_91(R36 + special_samus_palette_frame); + CopyToSamusSuitPalette(v1); + uint16 v2 = special_samus_palette_frame + 2; + if (!sign16(special_samus_palette_frame - 10)) + v2 = 0; + special_samus_palette_frame = v2; + return 1; + } +LABEL_21: + special_samus_palette_frame = 0; + return 1; + } +LABEL_10: + if ((speed_boost_counter & 0xFF00) != 1024) + return 1; + bool v3 = (--special_samus_palette_timer & 0x8000u) != 0; + if (!special_samus_palette_timer || v3) { + special_samus_palette_timer = 4; + R36 = kSamusPal_SpeedBoost[samus_suit_palette_index >> 1]; + uint16 v4 = *(uint16 *)RomPtr_91(R36 + special_samus_palette_frame); + CopyToSamusSuitPalette(v4); + uint16 v5 = special_samus_palette_frame + 2; + if (!sign16(special_samus_palette_frame - 6)) + v5 = 6; + special_samus_palette_frame = v5; + } + return 1; +} + +#define kSamusPal_SpeedBoostShine ((uint16*)RomPtr(0x91db10)) + +uint8 Samus_SpeedBoosterShinePals(void) { // 0x91DAC7 + uint16 v0 = samus_shine_timer; + if (samus_shine_timer == 170) { + uint16 v4 = samus_shine_timer; + QueueSfx3_Max9(0xCu); + v0 = v4; + } + samus_shine_timer = v0 - 1; + if ((int16)(v0 - 1) <= 0) { + special_samus_palette_frame = 0; + timer_for_shine_timer = 0; + return 0; + } else { + R36 = kSamusPal_SpeedBoostShine[samus_suit_palette_index >> 1]; + uint16 v1 = *(uint16 *)RomPtr_91(R36 + special_samus_palette_frame); + CopyToSamusSuitPalette(v1); + uint16 v2 = special_samus_palette_frame + 2; + if (!sign16(special_samus_palette_frame - 10)) + v2 = 0; + special_samus_palette_frame = v2; + return 1; + } +} + +#define kSamusPal_Shinespark ((uint16*)RomPtr(0x91db75)) +uint8 Samus_HandleShinesparkingPals(void) { // 0x91DB3A + bool v0 = (--samus_shine_timer & 0x8000u) != 0; + if (!samus_shine_timer || v0) { + timer_for_shine_timer = 0; + special_samus_palette_frame = 0; + return 0; + } else { + R36 = kSamusPal_Shinespark[samus_suit_palette_index >> 1]; + uint16 v1 = *(uint16 *)RomPtr_91(R36 + special_samus_palette_frame); + CopyToSamusSuitPalette(v1); + uint16 v2 = special_samus_palette_frame + 2; + if (!sign16(special_samus_palette_frame - 6)) + v2 = 0; + special_samus_palette_frame = v2; + return 1; + } +} + +#define stru_91DC00 ((SamusCrystalFlashPalTable*)RomPtr(0x91dc00)) +#define off_91DC28 ((uint16*)RomPtr(0x91dc28)) +uint8 Samus_HandleCrystalFlashPals(void) { // 0x91DB93 + if ((samus_shine_timer & 0x8000u) != 0) { + WriteBeamPalette_A(equipped_beams); + timer_for_shine_timer = 0; + special_samus_palette_frame = 0; + special_samus_palette_timer = 0; + samus_shine_timer = 0; + return 0; + } else { + if ((int16)--samus_shine_timer <= 0) { + samus_shine_timer = 5; + Samus_Copy6PalColors(off_91DC28[special_samus_palette_frame >> 1]); + uint16 v0 = special_samus_palette_frame + 2; + if (!sign16(special_samus_palette_frame - 10)) + v0 = 0; + special_samus_palette_frame = v0; + } + bool v1 = (int16)-- * (uint16 *)&suit_pickup_color_math_B < 0; + if (!*(uint16 *)&suit_pickup_color_math_B || v1) { + *(uint16 *)&suit_pickup_color_math_B = *(uint16 *)((char *)&stru_91DC00[0].timer + special_samus_palette_timer); + Samus_Copy10PalColors(*(VoidP *)((char *)&stru_91DC00[0].ptr + special_samus_palette_timer)); + uint16 v2 = special_samus_palette_timer + 4; + if (!sign16(special_samus_palette_timer - 36)) + v2 = 0; + special_samus_palette_timer = v2; + } + return 1; + } +} + +void Samus_Copy10PalColors(uint16 v0) { // 0x91DC34 + uint16 *v1 = (uint16 *)RomPtr_9B(v0); + palette_buffer[224] = *v1; + palette_buffer[225] = v1[1]; + palette_buffer[226] = v1[2]; + palette_buffer[227] = v1[3]; + palette_buffer[228] = v1[4]; + palette_buffer[229] = v1[5]; + palette_buffer[230] = v1[6]; + palette_buffer[231] = v1[7]; + palette_buffer[232] = v1[8]; + palette_buffer[233] = v1[9]; +} + +void Samus_Copy6PalColors(uint16 j) { // 0x91DC82 + uint16 *v1 = (uint16 *)RomPtr_9B(j); + palette_buffer[234] = *v1; + palette_buffer[235] = v1[1]; + palette_buffer[236] = v1[2]; + palette_buffer[237] = v1[3]; + palette_buffer[238] = v1[4]; + palette_buffer[239] = v1[5]; +} + +uint8 Samus_HandleXrayPals(void) { // 0x91DCB4 + if ((demo_timer_counter & 0x8000u) != 0) { + timer_for_shine_timer = 0; + special_samus_palette_frame = 0; + special_samus_palette_timer = 0; + demo_timer_counter = 0; + return 0; + } else { + if (!demo_timer_counter) { + if (sign16(demo_input_pre_instr - 2)) { + bool v0 = (--special_samus_palette_timer & 0x8000u) != 0; + if (!special_samus_palette_timer || v0) { + special_samus_palette_timer = 5; + palette_buffer[196] = word_9BA3C0[special_samus_palette_frame >> 1]; + if (sign16(special_samus_palette_frame - 4)) + special_samus_palette_frame += 2; + } + return 1; + } + special_samus_palette_frame = 6; + special_samus_palette_timer = 1; + demo_timer_counter = 1; + } + bool v2 = (--special_samus_palette_timer & 0x8000u) != 0; + if (special_samus_palette_timer && !v2) + return 1; + special_samus_palette_timer = 5; + palette_buffer[196] = word_9BA3C0[special_samus_palette_frame >> 1]; + uint16 v3 = special_samus_palette_frame + 2; + if (!sign16(special_samus_palette_frame - 10)) + v3 = 6; + special_samus_palette_frame = v3; + return 1; + } +} + +uint8 nullsub_164(void) { // 0x91DD31 + return 0; +} + +void CopyToSamusSuitPalette(uint16 k) { // 0x91DD5B + uint16 *v1 = (uint16 *)RomPtr_9B(k); + palette_buffer[192] = *v1; + palette_buffer[193] = v1[1]; + palette_buffer[194] = v1[2]; + palette_buffer[195] = v1[3]; + palette_buffer[196] = v1[4]; + palette_buffer[197] = v1[5]; + palette_buffer[198] = v1[6]; + palette_buffer[199] = v1[7]; + palette_buffer[200] = v1[8]; + palette_buffer[201] = v1[9]; + palette_buffer[202] = v1[10]; + palette_buffer[203] = v1[11]; + palette_buffer[204] = v1[12]; + palette_buffer[205] = v1[13]; + palette_buffer[206] = v1[14]; + palette_buffer[207] = v1[15]; +} + +void CopyToSamusSuitTargetPalette(uint16 k) { // 0x91DDD7 + uint16 *v1 = (uint16 *)RomPtr_9B(k); + target_palettes[192] = *v1; + target_palettes[193] = v1[1]; + target_palettes[194] = v1[2]; + target_palettes[195] = v1[3]; + target_palettes[196] = v1[4]; + target_palettes[197] = v1[5]; + target_palettes[198] = v1[6]; + target_palettes[199] = v1[7]; + target_palettes[200] = v1[8]; + target_palettes[201] = v1[9]; + target_palettes[202] = v1[10]; + target_palettes[203] = v1[11]; + target_palettes[204] = v1[12]; + target_palettes[205] = v1[13]; + target_palettes[206] = v1[14]; + target_palettes[207] = v1[15]; +} + +void Samus_CancelSpeedBoost(void) { // 0x91DE53 + if (samus_has_momentum_flag) { + samus_has_momentum_flag = 0; + speed_boost_counter = 0; + special_samus_palette_frame = 0; + special_samus_palette_timer = 0; + if ((equipped_items & 0x20) != 0) { + CopyToSamusSuitPalette(addr_kSamusPalette_GravitySuit); + } else if ((equipped_items & 1) != 0) { + CopyToSamusSuitPalette(addr_kSamusPalette_VariaSuit); + } else { + CopyToSamusSuitPalette(addr_kSamusPalette_PowerSuit); + } + } + if ((speed_echoes_index & 0x8000u) == 0) { + speed_echoes_index = -1; + if (samus_pose_x_dir == 4) { + speed_echo_xspeed[0] = -8; + speed_echo_xspeed[1] = -8; + } else { + speed_echo_xspeed[0] = 8; + speed_echo_xspeed[1] = 8; + } + } +} + +void Samus_LoadSuitPalette(void) { // 0x91DEBA + if ((equipped_items & 0x20) != 0) { + CopyToSamusSuitPalette(addr_kSamusPalette_GravitySuit); + } else if ((equipped_items & 1) != 0) { + CopyToSamusSuitPalette(addr_kSamusPalette_VariaSuit); + } else { + CopyToSamusSuitPalette(addr_kSamusPalette_PowerSuit); + } +} + +void Samus_LoadSuitTargetPalette(void) { // 0x91DEE6 + if ((equipped_items & 0x20) != 0) { + CopyToSamusSuitTargetPalette(addr_kSamusPalette_GravitySuit); + } else if ((equipped_items & 1) != 0) { + CopyToSamusSuitTargetPalette(addr_kSamusPalette_VariaSuit); + } else { + CopyToSamusSuitTargetPalette(addr_kSamusPalette_PowerSuit); + } +} + +void Samus_RestoreHealth(uint16 a) { // 0x91DF12 + R18_ = a; + uint16 v1 = a + samus_health; + samus_health = v1; + if ((int16)(v1 - samus_max_health) >= 0) { + uint16 v2 = samus_reserve_health + v1 - samus_max_health; + if ((int16)(v2 - samus_max_reserve_health) >= 0) + v2 = samus_max_reserve_health; + samus_reserve_health = v2; + if (v2) { + if (!reserve_health_mode) + reserve_health_mode = 1; + } + samus_health = samus_max_health; + } +} + +void Samus_DealDamage(uint16 a) { // 0x91DF51 + R18_ = a; + if ((a & 0x8000u) == 0) { + if (a != 300 && !time_is_frozen_flag) { + samus_health -= R18_; + if ((samus_health & 0x8000u) != 0) + samus_health = 0; + } + } else { + InvalidInterrupt_Crash(); + } +} + +void Samus_RestoreMissiles(uint16 a) { // 0x91DF80 + uint16 v1 = samus_missiles + a; + samus_missiles = v1; + if ((int16)(v1 - samus_max_missiles) >= 0) { + R18_ = v1 - samus_max_missiles; + if (sign16(samus_max_missiles - 99)) { + samus_reserve_missiles += R18_; + if ((int16)(samus_reserve_missiles - samus_max_missiles) >= 0) + samus_reserve_missiles = samus_max_missiles; + } else { + samus_reserve_missiles += R18_; + if (!sign16(samus_reserve_missiles - 99)) + samus_reserve_missiles = 99; + } + samus_missiles = samus_max_missiles; + } +} + +void Samus_RestoreSuperMissiles(uint16 a) { // 0x91DFD3 + uint16 v1 = samus_super_missiles + a; + samus_super_missiles = v1; + if ((int16)(v1 - samus_max_super_missiles) >= 0 && v1 != samus_max_super_missiles) + samus_super_missiles = samus_max_super_missiles; +} + +void Samus_RestorePowerBombs(uint16 a) { // 0x91DFF0 + uint16 v1 = samus_power_bombs + a; + samus_power_bombs = v1; + if ((int16)(v1 - samus_max_power_bombs) >= 0 && v1 != samus_max_power_bombs) + samus_power_bombs = samus_max_power_bombs; +} + +void Samus_Initialize(void) { // 0x91E00D + static const uint16 word_909EAF = 0; + static const uint16 word_909EAD = 1; + static const uint16 word_909EB3 = 0; + static const uint16 word_909EB1 = 1; + static const uint16 word_909EA1 = 0x1c00; + static const uint16 word_909EA7 = 0; + R18_ = debug_invincibility; + uint16 v0 = 0xE0B; + do + *RomPtr_RAM(v0--) = 0; + while ((int16)(v0 - 0xA02) >= 0); + if (game_state != kGameState_40_TransitionToDemo) { + frame_handler_alfa = FUNC16(EmptyFunction); + if (loading_game_state == kGameState_34_CeresGoesBoom) { + frame_handler_beta = FUNC16(SetContactDamageIndexAndUpdateMinimap); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + samus_momentum_routine_index = -1; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; + Samus_LoadSuitPalette(); + samus_input_handler = FUNC16(Samus_InputHandler_E913); + } else { + frame_handler_beta = FUNC16(Samus_Func16); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + samus_momentum_routine_index = 0; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; + samus_input_handler = FUNC16(Samus_InputHandler_E913); + debug_invincibility = R18_; + } + } + samus_new_pose = -1; + samus_new_pose_interrupted = -1; + samus_new_pose_transitional = -1; + if (area_index == 6) + frame_handler_gamma = FUNC16(Samus_Func3); + else + frame_handler_gamma = FUNC16(nullsub_152); + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + UNUSED_word_7E0A5E = -2764; + samus_prev_health_for_flash = 50; + samus_visor_palette_timer_index = 1537; + uint16 v1 = 0; + do { + projectile_bomb_pre_instructions[v1 >> 1] = FUNC16(ProjPreInstr_Empty); + v1 += 2; + } while ((int16)(v1 - 20) < 0); + grapple_beam_function = FUNC16(GrappleBeamFunc_Inactive); + enable_horiz_slope_coll = 3; + samus_hurt_flash_counter = 0; + samus_special_super_palette_flags = 0; + absolute_moved_last_frame_x_fract = word_909EAF; + absolute_moved_last_frame_x = word_909EAD; + absolute_moved_last_frame_y_fract = word_909EB3; + absolute_moved_last_frame_y = word_909EB1; + for (int i = 510; i >= 0; i -= 2) + hdma_table_1[i >> 1] = 255; + samus_y_subaccel = word_909EA1; + samus_y_accel = word_909EA7; + fx_y_pos = -1; + lava_acid_y_pos = -1; + UpdateBeamTilesAndPalette(); + cinematic_function = 0; + samus_pose = kPose_00_FaceF_Powersuit; + *(uint16 *)&samus_pose_x_dir = 0; + samus_prev_pose = 0; + *(uint16 *)&samus_prev_pose_x_dir = 0; + samus_last_different_pose = 0; + *(uint16 *)&samus_last_different_pose_x_dir = 0; + enemy_index_to_shake = -1; + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + samus_hurt_flash_counter = 0; + debug_invincibility = 0; + if (game_state == kGameState_40_TransitionToDemo) + LoadDemoData(); + samus_prev_health_for_flash = samus_health; +} + +uint8 Xray_Initialize(void) { // 0x91E16D + static const uint8 byte_91E291[28] = { + 1, 1, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, + }; + + if (cooldown_timer == 7 && bomb_counter == 5 && samus_x_speed_divisor == 2 + || !sign16(samus_pose - kPose_A4_FaceR_LandJump) + && (sign16(samus_pose - kPose_A8_FaceR_Grappling) + || !sign16(samus_pose - kPose_E0_FaceR_LandJump_AimU) && sign16(samus_pose - kPose_E8_FaceR_Drained_CrouchFalling)) + || game_state != 8 + || power_bomb_explosion_status + || samus_y_speed + || samus_y_subspeed + || !byte_91E291[samus_prev_movement_type]) { + return 0; + } + if (byte_91E291[samus_movement_type] == 1) { + if (samus_pose_x_dir == 4) + samus_new_pose_interrupted = kPose_D6_FaceL_Xray_Stand; + else + samus_new_pose_interrupted = kPose_D5_FaceR_Xray_Stand; + } else { + if (byte_91E291[samus_movement_type] != 2) + return 0; + if (samus_pose_x_dir == 4) + samus_new_pose_interrupted = kPose_DA_FaceL_Xray_Crouch; + else + samus_new_pose_interrupted = kPose_D9_FaceR_Xray_Crouch; + } + time_is_frozen_flag = 1; + samus_special_transgfx_index = 5; + for (int i = 510; i >= 0; i -= 2) + hdma_table_1[i >> 1] = 255; + DisableEnemyProjectiles(); + DisablePLMs(); + DisableAnimtiles(); + DisablePaletteFx(); + mov24((LongPtr *)&demo_enable, 0x980001); + *(uint16 *)((char *)&demo_num_input_frames + 1) = 0; + demo_input_prev = -26424; + mov24((LongPtr *)&demo_input_prev_new, 0x999098); + *(uint16 *)((char *)&demo_backup_prev_controller_input + 1) = 0; + demo_input_pre_instr = 0; + demo_input_instr_timer = 0; + demo_input_instr_ptr = 0; + demo_input = 0; + demo_input_new = 0; + if (samus_pose_x_dir == 4) + xray_angle = 192; + else + xray_angle = 64; + return 1; +} + +void ResponsibleForXrayStandupGlitch(void) { // 0x91E2AD + if (samus_movement_type == kMovementType_05_Crouching) { + if (samus_pose_x_dir == 4) + samus_pose = kPose_28_FaceL_Crouch; + else + samus_pose = kPose_27_FaceR_Crouch; + } else if (samus_pose_x_dir == kPose_04_FaceL_AimU) { + samus_pose = kPose_02_FaceL_Normal; + } else { + samus_pose = kPose_01_FaceR_Normal; + } + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + samus_input_handler = FUNC16(Samus_InputHandler_E913); + demo_timer_counter = -1; + R18_ = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)) - samus_y_radius; + if ((R18_ & 0x8000u) == 0) { + samus_y_pos -= R18_; + samus_prev_y_pos = samus_y_pos; + } + EnableEnemyProjectiles(); + EnablePLMs(); + EnableAnimtiles(); + EnablePaletteFx(); +} + +void MakeSamusFaceForward(void) { // 0x91E3F6 + if ((equipped_items & 0x20) != 0 || (equipped_items & 1) != 0) + samus_pose = kPose_9B_FaceF_VariaGravitySuit; + else + samus_pose = kPose_00_FaceF_Powersuit; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + if (samus_y_radius != 24) { + samus_y_pos -= 3; + samus_prev_y_pos = samus_y_pos; + } + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func13); + frame_handler_beta = FUNC16(SetContactDamageIndexAndUpdateMinimap); + samus_new_pose = -1; + samus_new_pose_interrupted = -1; + samus_new_pose_transitional = -1; + samus_momentum_routine_index = 0; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; + CallSomeSamusCode(0x1Fu); + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 0; + used_for_ball_bounce_on_landing = 0; + samus_x_accel_mode = 0; + flare_counter = 0; + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 0; + flare_slow_sparks_anim_timer = 0; + flare_fast_sparks_anim_timer = 0; + Samus_LoadSuitPalette(); +} + +static Func_U8 *const kSomeMotherBrainScripts[5] = { // 0x91E4AD + SomeMotherBrainScripts_0, + SomeMotherBrainScripts_1, + SomeMotherBrainScripts_2, + SomeMotherBrainScripts_3_EnableHyperBeam, + SomeMotherBrainScripts_4, +}; + +void SomeMotherBrainScripts(uint16 a) { + if (kSomeMotherBrainScripts[a]() & 1) { + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + samus_new_pose = -1; + samus_new_pose_interrupted = -1; + samus_new_pose_transitional = -1; + samus_momentum_routine_index = 0; + samus_special_transgfx_index = 0; + samus_hurt_switch_index = 0; + } +} + +uint8 SomeMotherBrainScripts_0(void) { // 0x91E4F8 + R18_ = 21 - samus_y_radius; + samus_y_pos -= 21 - samus_y_radius; + samus_prev_y_pos = samus_y_pos; + if (samus_pose_x_dir == 4) + samus_pose = kPose_E9_FaceL_Drained_CrouchFalling; + else + samus_pose = kPose_E8_FaceR_Drained_CrouchFalling; + samus_anim_frame_skip = 2; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_y_radius = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)); + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 2; + flare_counter = 0; + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 0; + flare_slow_sparks_anim_timer = 0; + flare_fast_sparks_anim_timer = 0; + Samus_LoadSuitPalette(); + return 1; +} + +uint8 SomeMotherBrainScripts_1(void) { // 0x91E571 + samus_anim_frame_timer = 16; + samus_anim_frame = 0; + if (samus_pose_x_dir == 4) + samus_pose = kPose_EB_FaceL_Drained_Stand; + else + samus_pose = kPose_EA_FaceR_Drained_Stand; + frame_handler_gamma = FUNC16(nullsub_152); + return 1; +} + +uint8 SomeMotherBrainScripts_2(void) { // 0x91E59B + if (samus_pose == kPose_E8_FaceR_Drained_CrouchFalling || samus_pose == kPose_E9_FaceL_Drained_CrouchFalling) { + samus_anim_frame_timer = 1; + samus_anim_frame = 13; + } else if (samus_pose == kPose_EA_FaceR_Drained_Stand || samus_pose == kPose_EB_FaceL_Drained_Stand) { + samus_anim_frame_timer = 1; + samus_anim_frame = 4; + } + samus_y_radius = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)); + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 2; + return 1; +} + +uint8 SomeMotherBrainScripts_3_EnableHyperBeam(void) { // 0x91E5F0 + equipped_beams = 4105; + UpdateBeamTilesAndPalette(); + SpawnPalfxObject(addr_stru_8DE1F0); + hyper_beam_flag = FUNC16(Samus_InputHandler); + play_resume_charging_beam_sfx = 0; + return 0; +} + +uint8 SomeMotherBrainScripts_4(void) { // 0x91E60C + samus_anim_frame_timer = 16; + samus_anim_frame = 8; + if (samus_pose_x_dir == 4) + samus_pose = kPose_E9_FaceL_Drained_CrouchFalling; + else + samus_pose = kPose_E8_FaceR_Drained_CrouchFalling; + return 1; +} + +void nullsub_17(void) {} + +static Func_V *const off_91E6E1[28] = { // 0x91E633 + SamusFunc_E633_0, + nullsub_17, + nullsub_17, + SamusFunc_E633_3, + SamusFunc_E633_4, + nullsub_17, + nullsub_17, + nullsub_17, + SamusFunc_E633_4, + nullsub_17, + nullsub_17, + nullsub_17, + nullsub_17, + nullsub_17, + nullsub_17, + nullsub_17, + nullsub_17, + SamusFunc_E633_17, + SamusFunc_E633_17, + SamusFunc_E633_17, + SamusFunc_E633_20, + nullsub_17, + nullsub_17, + nullsub_17, + nullsub_17, + nullsub_17, + nullsub_17, + nullsub_17, +}; + +void SamusFunc_E633(void) { + off_91E6E1[samus_movement_type](); + if ((equipped_items & 0x2000) != 0) { + if (samus_has_momentum_flag && !speed_boost_counter) { + special_samus_palette_timer = speed_boost_counter; + special_samus_palette_frame = 0; + speed_boost_counter = kSpeedBoostToCtr[0]; + } + } else { + speed_echoes_index = 0; + speed_echo_xspeed[0] = 0; + speed_echo_xspeed[1] = 0; + samus_has_momentum_flag = 0; + speed_boost_counter = 0; + special_samus_palette_frame = 0; + special_samus_palette_timer = 0; + speed_echo_xpos[0] = 0; + speed_echo_xpos[1] = 0; + speed_echo_ypos[0] = 0; + speed_echo_ypos[1] = 0; + } + if (grapple_beam_function == (uint16)FUNC16(GrappleBeamFunc_Inactive)) { + if ((equipped_beams & 0x1000) != 0) { + if (!sign16(flare_counter - 16)) + QueueSfx1_Max6(0x41u); + } else { + flare_counter = 0; + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 0; + flare_slow_sparks_anim_timer = 0; + flare_fast_sparks_anim_timer = 0; + } + } else { + LoadProjectilePalette(2u); + QueueSfx1_Max6(6u); + } + Samus_LoadSuitPalette(); + if (sign16(samus_health - 31)) + QueueSfx3_Max6(2u); +} + +void Samus_UpdatePreviousPose_0(void) { // 0x91E719 + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; +} + +void SamusFunc_E633_0(void) { // 0x91E733 + if (samus_pose) { + if (samus_pose == kPose_9B_FaceF_VariaGravitySuit && (equipped_items & 1) == 0 && (equipped_items & 0x20) == 0) { + samus_pose = kPose_00_FaceF_Powersuit; + goto LABEL_10; + } + } else if ((equipped_items & 1) != 0 || (equipped_items & 0x20) != 0) { + samus_pose = kPose_9B_FaceF_VariaGravitySuit; +LABEL_10: + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + Samus_UpdatePreviousPose_0(); + } +} + +void SamusFunc_E633_3(void) { // 0x91E776 + if (samus_pose_x_dir == 4) + *(uint16 *)&samus_prev_pose_x_dir = 260; + else + *(uint16 *)&samus_prev_pose_x_dir = 264; + if (samus_pose != kPose_81_FaceR_Screwattack && samus_pose != kPose_82_FaceL_Screwattack) { + if (samus_pose != kPose_1B_FaceR_SpaceJump && samus_pose != kPose_1C_FaceL_SpaceJump) + goto LABEL_18; + if ((equipped_items & 8) != 0) { + if (samus_pose_x_dir == 4) + samus_pose = kPose_82_FaceL_Screwattack; + else + samus_pose = kPose_81_FaceR_Screwattack; + goto LABEL_18; + } + goto LABEL_15; + } + if ((equipped_items & 8) == 0) { +LABEL_15: + if (samus_pose_x_dir == 4) + samus_pose = kPose_1A_FaceL_SpinJump; + else + samus_pose = kPose_19_FaceR_SpinJump; + } +LABEL_18: + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + if (samus_pose_x_dir == 4) + *(uint16 *)&samus_prev_pose_x_dir = 772; + else + *(uint16 *)&samus_prev_pose_x_dir = 776; + Samus_UpdatePreviousPose_0(); +} + +void SamusFunc_E633_4(void) { // 0x91E83A + if ((equipped_items & 2) != 0) { + if (samus_pose_x_dir == 4) + samus_pose = kPose_7A_FaceL_Springball_Ground; + else + samus_pose = kPose_79_FaceR_Springball_Ground; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + Samus_UpdatePreviousPose_0(); + } +} + +void SamusFunc_E633_17(void) { // 0x91E867 + if ((equipped_items & 2) == 0) { + if (samus_pose_x_dir == 4) + samus_pose = kPose_41_FaceL_Morphball_Ground; + else + samus_pose = kPose_1D_FaceR_Morphball_Ground; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + Samus_UpdatePreviousPose_0(); + } +} + +void SamusFunc_E633_20(void) { // 0x91E894 + if ((equipped_items & 8) != 0) + samus_anim_frame = 23; + else + samus_anim_frame = 3; +} + +void nullsub_18(void) { +} + +static Func_V *const kSamus_HandleTransFromBlockColl[6] = { // 0x91E8B6 + nullsub_18, + Samus_HandleTransFromBlockColl_1, + Samus_HandleTransFromBlockColl_2, + Samus_HandleTransFromBlockColl_3, + Samus_HandleTransFromBlockColl_4, + Samus_HandleTransFromBlockColl_5, +}; + +void Samus_HandleTransFromBlockColl(void) { + if (input_to_pose_calc) + kSamus_HandleTransFromBlockColl[(uint16)(2 * (uint8)input_to_pose_calc) >> 1](); +} +void Samus_HandleTransFromBlockColl_3(void) { // 0x91E8D8 + samus_new_pose = samus_pose; + samus_momentum_routine_index = 5; +} + +void Samus_HandleTransFromBlockColl_4(void) { // 0x91E8E5 + samus_new_pose = samus_pose; + samus_momentum_routine_index = 5; +} + +#define word_91E921 ((uint16*)RomPtr(0x91e921)) + +uint8 nullsub_18_U8(void) { + return 0; +} + +static Func_U8 *const off_91E951[6] = { // 0x91E8F2 + Samus_HandleTransFromBlockColl_1_0, + Samus_HandleTransFromBlockColl_1_1, + Samus_HandleTransFromBlockColl_1_2, + Samus_HandleTransFromBlockColl_1_3, + nullsub_18_U8, + Samus_HandleTransFromBlockColl_1_5, +}; + +void Samus_HandleTransFromBlockColl_2(void) { + + if (HIBYTE(input_to_pose_calc) != 4) { + uint16 v0 = 4 * HIBYTE(input_to_pose_calc); + if (samus_pose_x_dir == 4) + samus_new_pose = word_91E921[(v0 >> 1) + 1]; + else + samus_new_pose = word_91E921[v0 >> 1]; + samus_momentum_routine_index = 5; + } +} + +void Samus_HandleTransFromBlockColl_1(void) { // 0x91E931 + if (HIBYTE(input_to_pose_calc) != 4) { + if (off_91E951[(uint16)(2 * HIBYTE(input_to_pose_calc)) >> 1]() & 1) + samus_momentum_routine_index = 0; + else + samus_momentum_routine_index = 5; + } +} +#define word_91E9F3 ((uint16*)RomPtr(0x91e9f3)) +uint8 Samus_HandleTransFromBlockColl_1_0(void) { // 0x91E95D + int16 v0; + + if (samus_prev_movement_type2 == kMovementType_03_SpinJumping + || samus_prev_movement_type2 == kMovementType_14_WallJumping) { + if (samus_pose_x_dir == 4) + samus_new_pose = kPose_A7_FaceL_LandSpinJump; + else + samus_new_pose = kPose_A6_FaceR_LandSpinJump; + return 0; + } else { + v0 = *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)); + if (v0 == 255) { + if (samus_pose_x_dir == 4) + samus_new_pose = kPose_A5_FaceL_LandJump; + else + samus_new_pose = kPose_A4_FaceR_LandJump; + return 0; + } else { + if (v0 != 2 && v0 != 7) + goto LABEL_6; + if ((button_config_shoot_x & joypad1_lastkeys) == 0) { + v0 = *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)); +LABEL_6: + samus_new_pose = word_91E9F3[v0]; + return 0; + } + if (samus_pose_x_dir == 4) + samus_new_pose = kPose_E7_FaceL_LandJump_Fire; + else + samus_new_pose = kPose_E6_FaceR_LandJump_Fire; + return 0; + } + } +} + +uint8 Samus_HandleTransFromBlockColl_1_1(void) { // 0x91EA07 + int16 v0; + + v0 = 2 * used_for_ball_bounce_on_landing; + if (2 * used_for_ball_bounce_on_landing) { + if (v0 == 2) { + samus_new_pose = samus_pose; + return 0; + } + if (v0 != 4) { + Unreachable(); + while (1) + ; + } + } else if (!sign16(samus_y_speed - 3)) { + samus_new_pose = samus_pose; + return 0; + } + if (samus_pose_x_dir == 4) + samus_new_pose = kPose_41_FaceL_Morphball_Ground; + else + samus_new_pose = kPose_1D_FaceR_Morphball_Ground; + return 0; +} + +uint8 Samus_HandleTransFromBlockColl_1_2(void) { // 0x91EA48 + if (samus_pose_x_dir == 4) + samus_new_pose = 66; + else + samus_new_pose = 32; + return 0; +} + +uint8 Samus_HandleTransFromBlockColl_1_3(void) { // 0x91EA63 + int16 v1; + + if ((button_config_jump_a & joypad1_lastkeys) != 0) { + samus_new_pose = samus_pose; + return 0; + } + v1 = 2 * (uint8)used_for_ball_bounce_on_landing; + if (v1) { + if (v1 == 2) { + samus_new_pose = samus_pose; + return 0; + } + if (v1 != 4) { + Unreachable(); + while (1) + ; + } + } else if (!sign16(samus_y_speed - 3)) { + samus_new_pose = samus_pose; + return 0; + } + if (samus_pose_x_dir == 4) + samus_new_pose = kPose_7A_FaceL_Springball_Ground; + else + samus_new_pose = 121; + return 0; +} + +uint8 Samus_HandleTransFromBlockColl_1_5(void) { // 0x91EAB6 + samus_new_pose = samus_pose; + return 0; +} + +void Samus_HandleTransFromBlockColl_5(void) { // 0x91EABE + if (samus_pose_x_dir == 4) + samus_new_pose = kPose_84_FaceL_Walljump; + else + samus_new_pose = kPose_83_FaceR_Walljump; + samus_momentum_routine_index = 5; +} + +#define word_91EB74 ((uint16*)RomPtr(0x91eb74)) + +uint8 Samus_CheckWalkedIntoSomething(void) { // 0x91EADE + int16 v0; + + if (samus_collides_with_solid_enemy && samus_movement_type == 1) { + v0 = samus_pose; + goto LABEL_13; + } + if (samus_new_pose == 0xFFFF || *(&kPoseParams[0].movement_type + (uint16)(8 * samus_new_pose)) != 1) + goto LABEL_14; + if (samus_pose_x_dir != 4) { + R18_ = 1; + samus_collision_direction = 1; + R20_ = 0; + if (!Samus_CheckSolidEnemyColl()) { + R18_ = 1; + samus_collision_direction = 1; + R20_ = 0; + goto LABEL_10; + } +LABEL_11: + v0 = samus_new_pose; +LABEL_13: + samus_new_pose = word_91EB74[(uint16)(2 + * *(&kPoseParams[0].direction_shots_fired + + (uint16)(8 * v0))) >> 1]; + samus_collides_with_solid_enemy = 0; + return 1; + } + R18_ = 1; + R20_ = 0; + samus_collision_direction = 0; + if (Samus_CheckSolidEnemyColl()) + goto LABEL_11; + R18_ = -1; + R20_ = 0; + samus_collision_direction = 0; +LABEL_10: + if (Samus_MoveRight_NoSolidColl() & 1) + goto LABEL_11; +LABEL_14: + samus_collides_with_solid_enemy = 0; + return 0; +} + +void nullsub_19(void) {} +void nullsub_20(void) {} +void nullsub_21(void) {} +void nullsub_22(void) {} +static Func_V *const kSamus_HandleTransitionsA[9] = { // 0x91EB88 + nullsub_18, + Samus_HandleTransitionsA_1, + Samus_HandleTransitionsA_2, + nullsub_21, + nullsub_22, + Samus_HandleTransitionsA_5, + Samus_HandleTransitionsA_6, + Samus_HandleTransitionsA_7, + Samus_HandleTransitionsA_8, +}; +static Func_V *const kSamus_HandleTransitionsB[11] = { + nullsub_18, + Samus_HandleTransitionsB_1, + Samus_HandleTransitionsB_2, + Samus_HandleTransitionsB_3, + Samus_HandleTransitionsB_4, + Samus_HandleTransitionsB_5, + nullsub_19, + nullsub_20, + Samus_HandleTransitionsB_8, + Samus_HandleTransitionsB_9, + Samus_HandleTransitionsB_10, +}; +static Func_V *const kSamus_HandleTransitionsC[9] = { + nullsub_18, + Samus_HandleTransitionsC_1, + Samus_HandleTransitionsC_2, + Samus_HandleTransitionsC_3, + Samus_HandleTransitionsC_4, + Samus_HandleTransitionsC_5, + Samus_HandleTransitionsC_6, + Samus_HandleTransitionsC_7, + Samus_HandleTransitionsC_8, +}; + +void Samus_HandleTransitions(void) { + if ((samus_new_pose_transitional & 0x8000u) == 0) { + if (samus_hurt_switch_index != 3) { + if (samus_hurt_switch_index == 1) + goto LABEL_7; + goto LABEL_6; + } + if (samus_special_transgfx_index != 9) { +LABEL_6: + samus_pose = samus_new_pose_transitional; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); +LABEL_7: + kSamus_HandleTransitionsC[samus_hurt_switch_index](); +LABEL_15: + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + goto LABEL_16; + } + } + if ((samus_new_pose_interrupted & 0x8000u) == 0) { + samus_pose = samus_new_pose_interrupted; + if (!(SamusFunc_F404() & 1)) + kSamus_HandleTransitionsB[samus_special_transgfx_index](); + goto LABEL_15; + } + Samus_CheckWalkedIntoSomething(); + if ((samus_new_pose & 0x8000u) == 0) { + samus_pose = samus_new_pose; + if (!(SamusFunc_F404() & 1)) + kSamus_HandleTransitionsA[samus_momentum_routine_index](); + goto LABEL_15; + } +LABEL_16: + input_to_pose_calc = 0; +} + +void Samus_HandleTransitionsA_1(void) { // 0x91EC50 + if (samus_x_base_speed || samus_x_base_subspeed) { + uint16 v0 = (__PAIR32__(samus_x_extra_run_speed, samus_x_base_subspeed) + + __PAIR32__(samus_x_base_speed, samus_x_extra_run_subspeed)) >> 16; + samus_x_base_subspeed += samus_x_extra_run_subspeed; + samus_x_base_speed = v0; + samus_x_accel_mode = 2; + Samus_CancelSpeedBoost(); + samus_x_extra_run_subspeed = 0; + samus_x_extra_run_speed = 0; + SamusFunc_EC80(); + } else { + Samus_HandleTransitionsA_2(); + } +} + +void Samus_HandleTransitionsA_6(void) { // 0x91EC85 + samus_x_accel_mode = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + Samus_HandleTransitionsA_8(); +} + +void Samus_HandleTransitionsA_8(void) { // 0x91EC8E + Samus_CancelSpeedBoost(); + samus_x_extra_run_subspeed = 0; + samus_x_extra_run_speed = 0; + SamusFunc_EC80(); +} + + + +void Samus_HandleTransitionsA_2(void) { // 0x91ECD0 + samus_x_accel_mode = 0; + Samus_CancelSpeedBoost(); +} + +static const uint16 word_91ED36[12] = { // 0x91ECDA + 5, 5, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +void Samus_HandleTransitionsA_7(void) { + if (sign16(samus_pose - kPose_DB)) { + R18_ = word_91ED36[samus_pose - 53]; + if (!R18_) + goto LABEL_5; + R20_ = 0; +LABEL_4: + samus_y_radius = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)); + Samus_CollDetectChangedPose(); +LABEL_5: + samus_y_pos += R18_; + samus_prev_y_pos = samus_y_pos; + if (used_for_ball_bounce_on_landing) { + used_for_ball_bounce_on_landing = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 0; + } + return; + } + if (!sign16(samus_pose - kPose_F1_FaceR_CrouchTrans_AimU) && sign16(samus_pose - kPose_F7_FaceR_StandTrans_AimU)) { + R18_ = 5; + R20_ = 0; + goto LABEL_4; + } +} + +static Func_U8 *const kSamus_HandleTransitionsB_1[28] = { // 0x91ED4E + Samus_HandleTransitionsB_1_0, + Samus_HandleTransitionsB_1_0, + Samus_HandleTransitionsB_1_0, + Samus_HandleTransitionsB_1_0, + Samus_HandleTransitionsB_1_4, + Samus_HandleTransitionsB_1_0, + Samus_HandleTransitionsB_1_6, + Samus_HandleTransitionsB_1_7, + Samus_HandleTransitionsB_1_4, + Samus_HandleTransitionsB_1_4, + Samus_HandleTransitionsB_1_10, + Samus_HandleTransitionsB_1_11, + Samus_HandleTransitionsB_1_11, + Samus_HandleTransitionsB_1_0, + Samus_HandleTransitionsB_1_11, + Samus_HandleTransitionsB_1_11, + Samus_HandleTransitionsB_1_0, + Samus_HandleTransitionsB_1_4, + Samus_HandleTransitionsB_1_4, + Samus_HandleTransitionsB_1_4, + Samus_HandleTransitionsB_1_0, + Samus_HandleTransitionsB_1_0, + Samus_HandleTransitionsB_1_10, + Samus_HandleTransitionsB_1_11, + Samus_HandleTransitionsB_1_11, + Samus_HandleTransitionsB_1_11, + Samus_HandleTransitionsB_1_11, + Samus_HandleTransitionsB_1_11, +}; + +void Samus_HandleTransitionsB_1(void) { + kSamus_HandleTransitionsB_1[samus_prev_movement_type2](); + Samus_SetSpeedForKnockback_Y(); + bomb_jump_dir = 0; + samus_contact_damage_index = 0; + samus_hurt_flash_counter = 1; +} + +uint8 Samus_HandleTransitionsB_1_10(void) { // 0x91EDA2 + return 0; +} + +uint8 Samus_HandleTransitionsB_1_11(void) { // 0x91EDA4 + return 0; +} + +uint8 Samus_HandleTransitionsB_1_6(void) { // 0x91EDA6 + if (frame_handler_gamma == (uint16)FUNC16(Samus_Func9)) + return 0; + else + return Samus_HandleTransitionsB_1_0(); +} + +uint8 Samus_HandleTransitionsB_1_0(void) { // 0x91EDB0 + if (samus_pose_x_dir == 4) { + if (knockback_x_dir) { + if ((joypad1_lastkeys & 0x200) != 0) + knockback_dir = 5; + else + knockback_dir = 2; + } else if ((joypad1_lastkeys & 0x200) != 0) { + knockback_dir = 4; + } else { + knockback_dir = 1; + } + } else if (knockback_x_dir) { + if ((joypad1_lastkeys & 0x100) != 0) + knockback_dir = 5; + else + knockback_dir = 2; + } else if ((joypad1_lastkeys & 0x100) != 0) { + knockback_dir = 4; + } else { + knockback_dir = 1; + } + samus_movement_handler = FUNC16(Samus_MoveHandler_Knockback); + return 1; +} + +uint8 Samus_HandleTransitionsB_1_4(void) { // 0x91EE27 + if (samus_pose_x_dir == 4) + knockback_dir = 1; + else + knockback_dir = 2; + samus_movement_handler = FUNC16(Samus_MoveHandler_Knockback); + return 0; +} + +uint8 Samus_HandleTransitionsB_1_7(void) { // 0x91EE48 + if (samus_pose_x_dir == 4) + knockback_dir = 1; + else + knockback_dir = 2; + samus_movement_handler = FUNC16(Samus_MoveHandler_Knockback); + return 1; +} + +void Samus_HandleTransitionsB_2(void) { // 0x91EE69 + knockback_dir = 0; + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + samus_y_speed = 0; + samus_y_subspeed = 0; + samus_y_dir = 0; + Samus_AlignBottomWithPrevPose(); +} + +void Samus_HandleTransitionsB_3(void) { // 0x91EE80 + bomb_jump_dir = (uint8)bomb_jump_dir | 0x800; + samus_movement_handler = FUNC16(Samus_MoveHandler_BombJumpStart); + if (samus_input_handler != (uint16)FUNC16(Samus_InputHandler_E91D)) + samus_input_handler = FUNC16(nullsub_152); +} + +void Samus_HandleTransitionsB_4(void) { // 0x91EEA1 + Samus_InitJump(); +} + +void Samus_HandleTransitionsB_5(void) { // 0x91EEA6 + switch (samus_movement_type) { + case kMovementType_00_Standing: + goto LABEL_5; + case kMovementType_05_Crouching: + if (samus_pose_x_dir == 4) + xray_angle = 192; + else + xray_angle = 64; + goto LABEL_11; + case kMovementType_15_RanIntoWall: + case kMovementType_01_Running: +LABEL_5: + if (samus_pose_x_dir == 4) + xray_angle = 192; + else + xray_angle = 64; +LABEL_11: + samus_anim_frame = 2; + samus_anim_frame_timer = 63; + samus_movement_handler = FUNC16(SamusMovementType_Xray); + samus_input_handler = FUNC16(Samus_Func20_); + timer_for_shine_timer = 8; + special_samus_palette_timer = 1; + special_samus_palette_frame = 0; + samus_shine_timer = 0; + flare_counter = 0; + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 0; + flare_slow_sparks_anim_timer = 0; + flare_fast_sparks_anim_timer = 0; + QueueSfx1_Max6(9u); + break; + } +} + +void Samus_HandleTransitionsB_8(void) { // 0x91EF3B + samus_y_pos -= 5; + samus_prev_y_pos = samus_y_pos; + frame_handler_alfa = FUNC16(EmptyFunction); +} + +void Samus_HandleTransitionsB_9(void) { // 0x91EF4F + int16 v0; + int16 v1; + + GrappleBeamFunc_BD95(); + v0 = samus_x_pos - samus_prev_x_pos; + if ((int16)(samus_x_pos - samus_prev_x_pos) < 0) { + if (sign16(v0 + 12)) + samus_prev_x_pos = samus_x_pos + 12; + } else if (!sign16(v0 - 13)) { + samus_prev_x_pos = samus_x_pos - 12; + } + v1 = samus_y_pos - samus_prev_y_pos; + if ((int16)(samus_y_pos - samus_prev_y_pos) < 0) { + if (sign16(v1 + 12)) + samus_prev_y_pos = samus_y_pos + 12; + } else if (!sign16(v1 - 13)) { + samus_prev_y_pos = samus_y_pos - 12; + } + Samus_CancelSpeedBoost(); + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; +} + +void Samus_HandleTransitionsB_10(void) { // 0x91EFBC + GrappleBeamFunc_BEEB(); + Samus_HandleTransitionsB_9B(); +} + +void Samus_HandleTransitionsB_9B(void) { // 0x91EF53 + int16 v0; + int16 v1; + + v0 = samus_x_pos - samus_prev_x_pos; + if ((int16)(samus_x_pos - samus_prev_x_pos) < 0) { + if (sign16(v0 + 12)) + samus_prev_x_pos = samus_x_pos + 12; + } else if (!sign16(v0 - 13)) { + samus_prev_x_pos = samus_x_pos - 12; + } + v1 = samus_y_pos - samus_prev_y_pos; + if ((int16)(samus_y_pos - samus_prev_y_pos) < 0) { + if (sign16(v1 + 12)) + samus_prev_y_pos = samus_y_pos + 12; + } else if (!sign16(v1 - 13)) { + samus_prev_y_pos = samus_y_pos - 12; + } + Samus_CancelSpeedBoost(); + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_x_extra_run_speed = 0; + samus_x_extra_run_subspeed = 0; +} + + +void nullsub_23(void) { // 0x91EFDE +} + + +static Func_V *const kSamus_HandleTransitionsA_5[7] = { // 0x91EFC4 + sub_91EFC3, + Samus_HandleTransitionsA_5_1, + Samus_HandleTransitionsA_5_2, + nullsub_23, + Samus_HandleTransitionsA_5_4, + Samus_HandleTransitionsA_5_5, + Samus_HandleTransitionsA_5_6, +}; +void Samus_HandleTransitionsA_5(void) { + kSamus_HandleTransitionsA_5[(uint16)(2 * (uint8)input_to_pose_calc) >> 1](); +} + +void Samus_HandleTransitionsA_5_4(void) { // 0x91EFDF + samus_y_subspeed = 0; + samus_y_speed = 0; + UNUSED_word_7E0B1A = 0; + samus_y_dir = 2; +} + +void Samus_HandleTransitionsA_5_2(void) { // 0x91EFEF + if (samus_y_dir != 1) { + used_for_ball_bounce_on_landing = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_is_falling_flag = 1; + samus_y_dir = 2; + } + UNUSED_word_7E0A18 = 0; +} + +void sub_91EFC3(void) {} +uint8 sub_91EFC3_rv(void) { return 0; } + +static Func_U8 *const kSamus_HandleTransitionsA_5_1[6] = { // 0x91F010 + Samus_HandleTransitionsA_5_1_0, + Samus_MorphBallBounceNoSpringballTrans, + Samus_HandleTransitionsA_5_1_2, + Samus_MorphBallBounceSpringballTrans, + sub_91EFC3_rv, + Samus_HandleTransitionsA_5_1_5, +}; + +void Samus_HandleTransitionsA_5_1(void) { + HandleLandingSoundEffectsAndGfx(); + if (HIBYTE(input_to_pose_calc) == 4) { + SamusFunc_F1D3(); + } else if (!(kSamus_HandleTransitionsA_5_1[(uint16)(2 * HIBYTE(input_to_pose_calc)) >> 1]() & 1)) { + UNUSED_word_7E0A18 = 0; + samus_x_accel_mode = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + SamusFunc_F1D3(); + } +} + +void HandleLandingSoundEffectsAndGfx(void) { // 0x91F046 + if ((samus_prev_movement_type2 == kMovementType_03_SpinJumping + || samus_prev_movement_type2 == kMovementType_14_WallJumping) + && !cinematic_function) { + if (samus_prev_pose == kPose_81_FaceR_Screwattack || samus_prev_pose == kPose_82_FaceL_Screwattack) + QueueSfx1_Max6(0x34u); + else + QueueSfx1_Max6(0x32u); + } + if (samus_y_speed && !sign16(samus_y_speed - 5)) { + if (!cinematic_function) + QueueSfx3_Max6(4u); + } else { + if (!samus_y_subspeed) + return; + if (!cinematic_function) + QueueSfx3_Max6(5u); + } + HandleLandingGraphics(); +} + +static Func_V *const off_91F0AE[8] = { // 0x91F0A5 + HandleLandingGraphics_Crateria, + HandleLandingGraphics_Brinstar, + HandleLandingGraphics_Norfair, + HandleLandingGraphics_Norfair, + HandleLandingGraphics_Maridia, + HandleLandingGraphics_Tourian, + HandleLandingGraphics_Ceres, + HandleLandingGraphics_Ceres, +}; +void HandleLandingGraphics(void) { + off_91F0AE[(area_index)](); +} + +void HandleLandingGraphics_Ceres(void) { // 0x91F0BE + atmospheric_gfx_frame_and_type[2] = 0; + atmospheric_gfx_frame_and_type[3] = 0; +} +static const uint8 g_byte_91F0F3[17] = { // 0x91F0C5 + 1, 0, 0, 0, 0, 2, 0, 4, + 0, 4, 4, 4, 4, 0, 4, 0, + 0, +}; +void HandleLandingGraphics_Crateria(void) { + if (cinematic_function) + goto LABEL_13; + if (room_index == 28) { + HandleLandingGraphics_Norfair(); + return; + } + if ((int16)(room_index - 16) >= 0) + goto LABEL_13; + if ((g_byte_91F0F3[room_index] & 1) == 0) { + if ((g_byte_91F0F3[room_index] & 2) != 0) { + if (!sign16(samus_y_pos - 944)) + goto LABEL_14; + } else if ((g_byte_91F0F3[room_index] & 4) != 0) { + goto LABEL_14; + } +LABEL_13: + HandleLandingGraphics_Ceres(); + return; + } + if (fx_type != 10) + goto LABEL_13; +LABEL_14: + HandleLandingGraphics_Maridia(); +} + +void HandleLandingGraphics_Maridia(void) { // 0x91F116 + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) == 0) { + if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) + return; +LABEL_7: + atmospheric_gfx_frame_and_type[2] = 256; + atmospheric_gfx_frame_and_type[3] = 256; + atmospheric_gfx_anim_timer[2] = 3; + atmospheric_gfx_anim_timer[3] = 3; + atmospheric_gfx_x_pos[2] = samus_x_pos + 4; + atmospheric_gfx_x_pos[3] = samus_x_pos - 3; + atmospheric_gfx_y_pos[2] = R18_ - 4; + atmospheric_gfx_y_pos[3] = R18_ - 4; + return; + } + if ((lava_acid_y_pos & 0x8000u) != 0 || !sign16(lava_acid_y_pos - R18_)) + goto LABEL_7; +} + +void HandleLandingGraphics_Norfair(void) { // 0x91F166 + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) == 0) { + if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) + return; +LABEL_7: + atmospheric_gfx_frame_and_type[2] = 1536; + atmospheric_gfx_frame_and_type[3] = 1536; + atmospheric_gfx_anim_timer[2] = 3; + atmospheric_gfx_anim_timer[3] = 3; + atmospheric_gfx_x_pos[2] = samus_x_pos + 8; + atmospheric_gfx_x_pos[3] = samus_x_pos - 8; + atmospheric_gfx_y_pos[2] = R18_; + atmospheric_gfx_y_pos[3] = R18_; + return; + } + if ((lava_acid_y_pos & 0x8000u) != 0 || !sign16(lava_acid_y_pos - R18_)) + goto LABEL_7; +} + +void HandleLandingGraphics_Brinstar(void) { // 0x91F1B2 + if (room_index == 8) + HandleLandingGraphics_Norfair(); + else + HandleLandingGraphics_Tourian(); +} + +void HandleLandingGraphics_Tourian(void) { // 0x91F1BA + if (!sign16(room_index - 5) && (sign16(room_index - 9) || room_index == 11)) { + HandleLandingGraphics_Norfair(); + } else { + atmospheric_gfx_frame_and_type[2] = 0; + atmospheric_gfx_frame_and_type[3] = 0; + } +} + +void SamusFunc_F1D3(void) { // 0x91F1D3 + samus_is_falling_flag = 0; + UNUSED_word_7E0B1A = 0; + UNUSED_word_7E0B2A = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 0; + UNUSED_word_7E0B38 = 0; + used_for_ball_bounce_on_landing = 0; +} + +uint8 Samus_HandleTransitionsA_5_1_0(void) { // 0x91F1EC + if (samus_input_handler != (uint16)FUNC16(Samus_InputHandler_E91D)) + samus_input_handler = FUNC16(HandleAutoJumpHack); + return 0; +} +static const uint16 g_word_909EB5 = 1; +static const uint16 g_word_909EB7 = 0; +uint8 Samus_MorphBallBounceNoSpringballTrans(void) { // 0x91F1FC + int16 v0; + + v0 = 2 * used_for_ball_bounce_on_landing; + if (2 * used_for_ball_bounce_on_landing) { + if (v0 == 2) { + ++used_for_ball_bounce_on_landing; + samus_y_dir = 1; + samus_y_subspeed = g_word_909EB7; + samus_y_speed = g_word_909EB5 - 1; + return 1; + } + if (v0 != 4) { + Unreachable(); + while (1) + ; + } + } else if (!sign16(samus_y_speed - 3)) { + ++used_for_ball_bounce_on_landing; + samus_y_dir = 1; + samus_y_subspeed = g_word_909EB7; + samus_y_speed = g_word_909EB5; + return 1; + } + used_for_ball_bounce_on_landing = 0; + samus_y_dir = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + return 0; +} + +uint8 Samus_HandleTransitionsA_5_1_2(void) { // 0x91F253 + used_for_ball_bounce_on_landing = 0; + enable_horiz_slope_coll = 3; + return 0; +} + +uint8 Samus_MorphBallBounceSpringballTrans(void) { // 0x91F25E + int16 v1; + + if ((button_config_jump_a & joypad1_lastkeys) != 0) { + used_for_ball_bounce_on_landing = 0; + Samus_InitJump(); + return 1; + } + v1 = 2 * (uint8)used_for_ball_bounce_on_landing; + if (v1) { + if (v1 == 2) { + used_for_ball_bounce_on_landing = 1538; + samus_y_dir = 1; + samus_y_subspeed = g_word_909EB7; + samus_y_speed = g_word_909EB5 - 1; + return 1; + } + if (v1 != 4) { + Unreachable(); + while (1) + ; + } + } else if (!sign16(samus_y_speed - 3)) { + used_for_ball_bounce_on_landing = 1537; + samus_y_dir = 1; + samus_y_subspeed = g_word_909EB7; + samus_y_speed = g_word_909EB5; + return 1; + } + used_for_ball_bounce_on_landing = 0; + samus_y_dir = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + return 0; +} + +uint8 Samus_HandleTransitionsA_5_1_5(void) { // 0x91F2CE + used_for_ball_bounce_on_landing = 0; + return 0; +} + +void Samus_HandleTransitionsA_5_5(void) { // 0x91F2D3 + samus_x_accel_mode = 0; + samus_collides_with_solid_enemy = 0; + samus_is_falling_flag = 0; + UNUSED_word_7E0B1A = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + UNUSED_word_7E0A18 = 0; + QueueSfx3_Max6(5u); +} + +void Samus_HandleTransitionsA_5_6(void) { // 0x91F2F0 + if (samus_collides_with_solid_enemy) { + if (samus_prev_movement_type2 == 9) { + enable_horiz_slope_coll = samus_pose_x_dir != 4; + UNUSED_word_7E0A18 = 0; + } + } +} + +void Samus_HandleTransitionsC_1(void) { // 0x91F31D + knockback_dir = 0; + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + used_for_ball_bounce_on_landing = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_is_falling_flag = 1; + samus_y_dir = 2; + Samus_AlignBottomWithPrevPose(); + if (samus_input_handler != (uint16)FUNC16(Samus_InputHandler_E91D)) + samus_input_handler = FUNC16(Samus_InputHandler_E913); +} + +void Samus_HandleTransitionsC_2(void) { // 0x91F34E + Samus_AlignBottomWithPrevPose(); + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + if (game_state == kGameState_42_PlayingDemo) + samus_input_handler = FUNC16(Samus_InputHandler_E91D); + else + samus_input_handler = FUNC16(Samus_InputHandler_E913); +} + +void Samus_HandleTransitionsC_3(void) { // 0x91F36E + used_for_ball_bounce_on_landing = 0; + samus_anim_frame_timer += samus_anim_frame_buffer; +} + +void Samus_HandleTransitionsC_4(void) { // 0x91F37C + samus_x_pos = layer1_x_pos + 128; + samus_prev_x_pos = layer1_x_pos + 128; + samus_y_pos = layer1_y_pos + 128; + samus_prev_y_pos = layer1_y_pos + 128; +} + +void Samus_HandleTransitionsC_5(void) { // 0x91F397 + samus_y_pos += 5; + samus_prev_y_pos = samus_y_pos; +} + +void Samus_HandleTransitionsC_6(void) { // 0x91F3A5 + HandleJumpTransition(); +} + +void Samus_HandleTransitionsC_7(void) { // 0x91F3AA + int16 v0; + int16 v1; + + v0 = samus_x_pos - samus_prev_x_pos; + if ((int16)(samus_x_pos - samus_prev_x_pos) < 0) { + if (sign16(v0 + 12)) + samus_prev_x_pos = samus_x_pos + 12; + } else if (!sign16(v0 - 13)) { + samus_prev_x_pos = samus_x_pos - 12; + } + v1 = samus_y_pos - samus_prev_y_pos; + if ((int16)(samus_y_pos - samus_prev_y_pos) < 0) { + if (sign16(v1 + 12)) + samus_prev_y_pos = samus_y_pos + 12; + } else if (!sign16(v1 - 13)) { + samus_prev_y_pos = samus_y_pos - 12; + } +} + +void Samus_HandleTransitionsC_8(void) { // 0x91F3FD + Samus_HandleTransitionsC_1(); + Samus_HandleTransitionsC_3(); +} + +uint8 SamusFunc_F404(void) { // 0x91F404 + SamusPose v1; + + v1 = samus_pose; + if (samus_pose != samus_prev_pose) { + HandleCollDueToChangedPose(); + SamusFunc_F433(); + HandleJumpTransition(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_anim_frame_skip = 0; + } + return v1 != samus_pose; +} + +void SamusFunc_F433(void) { // 0x91F433 + *(uint16 *)&samus_pose_x_dir = *(uint16 *)(&kPoseParams[0].pose_x_dir + (uint16)(8 * samus_pose)); + SamusFunc_F468(); + if ((samus_prev_movement_type2 == kMovementType_03_SpinJumping + || samus_prev_movement_type2 == kMovementType_14_WallJumping) + && (equipped_items & 8) != 0) { + Samus_LoadSuitPalette(); + } +} + +static Func_U8 *const off_91F4A2[28] = { // 0x91F468 + SamusFunc_F468_Standing, + SamusFunc_F468_Running, + SamusFunc_F468_NormalJump, + SamusFunc_F468_SpinJump, + SamusFunc_F468_MorphBall, + SamusFunc_F468_Crouching, + SamusFunc_F468_Falling, + SamusFunc_F468_Unused, + SamusFunc_F468_MorphBall, + SamusFunc_F468_Unused, + SamusFunc_F468_Unused, + SamusFunc_F468_Unused, + SamusFunc_F468_Unused, + SamusFunc_F468_Unused, + SamusFunc_F468_TurningAroundOnGround, + SamusFunc_F468_CrouchTransEtc, + SamusFunc_F468_Moonwalking, + SamusFunc_F468_Springball, + SamusFunc_F468_Springball, + SamusFunc_F468_Springball, + SamusFunc_F468_WallJumping, + SamusFunc_F468_Unused, + SamusFunc_F468_Unused, + SamusFunc_F468_TurnAroundJumping, + SamusFunc_F468_TurnAroundFalling, + SamusFunc_F468_DamageBoost, + SamusFunc_F468_Unused, + SamusFunc_F468_Shinespark, +}; + +void SamusFunc_F468(void) { + if (off_91F4A2[samus_movement_type]() & 1) { + *(uint16 *)&samus_pose_x_dir = *(uint16 *)(&kPoseParams[0].pose_x_dir + (uint16)(8 * samus_pose)); + if ((*(uint16 *)&samus_pose_x_dir & 0xFF00) == 3584) { + off_91F4A2[14](); + *(uint16 *)&samus_pose_x_dir = *(uint16 *)(&kPoseParams[0].pose_x_dir + (uint16)(8 * samus_pose)); + } + } +} + +uint8 SamusFunc_F468_Unused(void) { // 0x91F4DA + return 0; +} + +uint8 SamusFunc_F468_Standing(void) { // 0x91F4DC + if ((!*(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)) + || *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)) == 9) + && (!*(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_prev_pose)) + || *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_prev_pose)) == 9)) { + samus_anim_frame_skip = 1; + } + return 0; +} + +uint8 SamusFunc_F468_Running(void) { // 0x91F50C + if (samus_prev_movement_type2 == 1) + samus_anim_frame_skip = FUNC16(Samus_InputHandler); + if (!UNUSED_word_7E0DF8) + return 0; + if (samus_pose == (kPose_44_FaceL_Turn_Crouch | kPose_01_FaceR_Normal)) { + samus_pose = kPose_25_FaceR_Turn_Stand; + return 1; + } + if (samus_pose == (kPose_44_FaceL_Turn_Crouch | kPose_02_FaceL_Normal)) { + samus_pose = kPose_26_FaceL_Turn_Stand; + return 1; + } + return 0; +} + +uint8 SamusFunc_F468_NormalJump(void) { // 0x91F543 + if (samus_pose != kPose_4E_FaceL_Jump_NoAim_NoMove_NoGun) { + if (samus_pose == kPose_4D_FaceR_Jump_NoAim_NoMove_NoGun || samus_pose == kPose_15_FaceR_Jump_AimU) { +LABEL_7: + if (samus_shine_timer) { + samus_pose = kPose_C7_FaceR_ShinesparkWindup_Vert; +LABEL_11: + Projectile_Func7_Shinespark(); + if (samus_prev_movement_type2 == kMovementType_02_NormalJumping) + samus_prev_y_pos = --samus_y_pos; + return 1; + } + goto LABEL_14; + } + if (samus_pose != kPose_16_FaceL_Jump_AimU && samus_pose != kPose_6A_FaceL_Jump_AimUL) { + if (samus_pose != kPose_69_FaceR_Jump_AimUR) + goto LABEL_14; + goto LABEL_7; + } + } + if (samus_shine_timer) { + samus_pose = kPose_C8_FaceL_ShinesparkWindup_Vert; + goto LABEL_11; + } +LABEL_14: + if (samus_x_extra_run_speed || samus_x_extra_run_subspeed) + samus_x_accel_mode = 2; + else + samus_x_accel_mode = 0; + if ((samus_pose == kPose_15_FaceR_Jump_AimU || samus_pose == kPose_16_FaceL_Jump_AimU) + && (samus_prev_pose == kPose_55_FaceR_Jumptrans_AimU || samus_prev_pose == kPose_56_FaceL_Jumptrans_AimU)) { + samus_anim_frame_skip = 1; + } + if ((button_config_shoot_x & joypad1_newkeys) != 0) + new_projectile_direction_changed_pose = *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)) | 0x8000; + return 0; +} + +uint8 SamusFunc_F468_Crouching(void) { // 0x91F5EB + if ((samus_pose == kPose_85_FaceR_Crouch_AimU || samus_pose == kPose_86_FaceL_Crouch_AimU) + && (samus_prev_pose == kPose_F1_FaceR_CrouchTrans_AimU || samus_prev_pose == kPose_F2_FaceL_CrouchTrans_AimU)) { + samus_anim_frame_skip = 1; + } + return 0; +} + +uint8 SamusFunc_F468_Falling(void) { // 0x91F60D + if (samus_x_extra_run_speed || samus_x_extra_run_subspeed) + samus_x_accel_mode = 2; + else + samus_x_accel_mode = 0; + return 0; +} + +uint8 SamusFunc_F468_SpinJump(void) { // 0x91F624 + if (samus_prev_movement_type2 == kMovementType_03_SpinJumping + || samus_prev_movement_type2 == kMovementType_14_WallJumping) { + samus_anim_frame_skip = 1; + if ((samus_prev_pose_x_dir & 0xF) == 8) { + if (*(uint16 *)&samus_pose_x_dir != 772) + goto LABEL_9; + } else if ((samus_prev_pose_x_dir & 0xF) != 4 || *(uint16 *)&samus_pose_x_dir != 776) { + goto LABEL_9; + } + uint16 v0 = (__PAIR32__(samus_x_extra_run_speed, samus_x_base_subspeed) + + __PAIR32__(samus_x_base_speed, samus_x_extra_run_subspeed)) >> 16; + samus_x_base_subspeed += samus_x_extra_run_subspeed; + samus_x_base_speed = v0; + Samus_CancelSpeedBoost(); + samus_x_extra_run_subspeed = 0; + samus_x_extra_run_speed = 0; + samus_x_accel_mode = 1; + } +LABEL_9: + if (samus_pose_x_dir == 4) { + if ((equipped_items & 0x20) == 0) { + Samus_GetTopBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R20_)) + return 0; + } else if (sign16(fx_y_pos - R20_) && (fx_liquid_options & 4) == 0) { + return 0; + } + } + if ((equipped_items & 8) != 0) { + samus_pose = kPose_82_FaceL_Screwattack; + goto LABEL_40; + } + if ((equipped_items & 0x200) != 0) { + QueueSfx1_Max6(0x3Eu); + samus_pose = kPose_1C_FaceL_SpaceJump; + return 0; + } + if (!samus_anim_frame_skip && !cinematic_function) { +LABEL_22: + QueueSfx1_Max6(0x31u); + return 0; + } + return 0; + } + if ((equipped_items & 0x20) == 0) { + Samus_GetTopBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R20_)) + return 0; + } else if (sign16(fx_y_pos - R20_) && (fx_liquid_options & 4) == 0) { + return 0; + } + } + if ((equipped_items & 8) != 0) { + samus_pose = kPose_81_FaceR_Screwattack; +LABEL_40: + if (!samus_anim_frame_skip) + QueueSfx1_Max6(0x33u); + return 0; + } + if ((equipped_items & 0x200) == 0) { + if (samus_anim_frame_skip || cinematic_function) + return 0; + goto LABEL_22; + } + QueueSfx1_Max6(0x3Eu); + samus_pose = kPose_1B_FaceR_SpaceJump; + return 0; +} +static Func_U8 *const off_91F790[12] = { // 0x91F758 + Samus_CrouchTrans, + Samus_CrouchTrans, + Samus_MorphTrans, + Samus_MorphTrans, + MaybeUnused_sub_91F7F4, + MaybeUnused_sub_91F840, + Samus_StandOrUnmorphTrans, + Samus_StandOrUnmorphTrans, + Samus_StandOrUnmorphTrans, + Samus_StandOrUnmorphTrans, + Samus_StandOrUnmorphTrans, + Samus_StandOrUnmorphTrans, +}; +static Func_U8 *const off_91F7A8[4] = { + Samus_MorphTrans, + Samus_MorphTrans, + Samus_StandOrUnmorphTrans, + Samus_StandOrUnmorphTrans, +}; +uint8 SamusFunc_F468_CrouchTransEtc(void) { + uint16 v0; + if (sign16(samus_pose - kPose_F1_FaceR_CrouchTrans_AimU)) { + if (sign16(samus_pose - kPose_DB)) { + v0 = 2 * (samus_pose - 53); +LABEL_4: + samus_momentum_routine_index = 7; + return off_91F790[v0 >> 1](); + } + return off_91F7A8[samus_pose - 219](); + } else { + if (sign16(samus_pose - kPose_F7_FaceR_StandTrans_AimU)) { + v0 = 0; + goto LABEL_4; + } + samus_momentum_routine_index = 7; + } + return 0; +} + +uint8 Samus_CrouchTrans(void) { // 0x91F7B0 + if (!sign16((speed_boost_counter & 0xFF00) - 1024)) { + samus_shine_timer = 180; + timer_for_shine_timer = 1; + special_samus_palette_frame = 0; + } + return 0; +} + +uint8 Samus_StandOrUnmorphTrans(void) { // 0x91F7CC + return 0; +} + +uint8 Samus_MorphTrans(void) { // 0x91F7CE + if ((equipped_items & 4) != 0) { + if (samus_prev_movement_type2 == kMovementType_03_SpinJumping) + samus_x_accel_mode = 2; + bomb_spread_charge_timeout_counter = 0; + return 0; + } else { + samus_pose = samus_prev_pose; + return 1; + } +} + +uint8 MaybeUnused_sub_91F7F4(void) { // 0x91F7F4 + if (samus_prev_movement_type2 == kMovementType_08_MorphBallFalling + || samus_prev_movement_type2 == kMovementType_13_SpringBallFalling) { + if ((equipped_items & 2) != 0) + samus_pose = kPose_7D_FaceR_Springball_Fall; + else + samus_pose = kPose_31_FaceR_Morphball_Air; + } else if ((equipped_items & 2) != 0) { + samus_pose = kPose_79_FaceR_Springball_Ground; + } else { + samus_pose = kPose_1D_FaceR_Morphball_Ground; + } + return 1; +} + +uint8 MaybeUnused_sub_91F840(void) { // 0x91F840 + if (samus_prev_movement_type2 == kMovementType_08_MorphBallFalling + || samus_prev_movement_type2 == kMovementType_13_SpringBallFalling) { + if ((equipped_items & 2) != 0) + samus_pose = kPose_7E_FaceL_Springball_Fall; + else + samus_pose = kPose_32_FaceL_Morphball_Air; + } else if ((equipped_items & 2) != 0) { + samus_pose = kPose_7A_FaceL_Springball_Ground; + } else { + samus_pose = kPose_41_FaceL_Morphball_Ground; + } + return 1; +} + +uint8 SamusFunc_F468_Moonwalking(void) { // 0x91F88C + if (moonwalk_flag) + return 0; + if (samus_pose_x_dir == 4) + samus_pose = kPose_25_FaceR_Turn_Stand; + else + samus_pose = kPose_26_FaceL_Turn_Stand; + return 1; +} + +uint8 SamusFunc_F468_DamageBoost(void) { // 0x91F8AE + return SamusFunc_F468_DamageBoost_(); +} + +uint8 MaybeUnused_sub_91F8B0(void) { // 0x91F8B0 + if (samus_pose_x_dir == 4) + samus_pose = kPose_54_FaceL_Knockback; + else + samus_pose = kPose_53_FaceR_Knockback; + return 1; +} + +uint8 SamusFunc_F468_DamageBoost_(void) { // 0x91F8CB + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); + return 0; +} + +#define kSamusTurnPose_Standing ((uint8*)RomPtr(0x91f9c2)) +#define kSamusTurnPose_Crouching ((uint8*)RomPtr(0x91f9cc)) +#define kSamusTurnPose_Jumping ((uint8*)RomPtr(0x91f9d6)) +#define kSamusTurnPose_Falling ((uint8*)RomPtr(0x91f9e0)) +#define kSamusTurnPose_Moonwalk ((uint8*)RomPtr(0x91f9ea)) +uint8 SamusFunc_F468_TurningAroundOnGround(void) { // 0x91F8D3 + if (samus_prev_pose && samus_prev_pose != kPose_9B_FaceF_VariaGravitySuit) { + uint16 v0 = *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_prev_pose)); + if (samus_prev_movement_type2 == kMovementType_10_Moonwalking) { + new_projectile_direction_changed_pose = *(&kPoseParams[0].direction_shots_fired + + (uint16)(8 * samus_prev_pose)) | 0x100; + if ((button_config_jump_a & joypad1_lastkeys) != 0) { + samus_pose = kSamusTurnPose_Moonwalk[v0]; + goto LABEL_9; + } + } else if (samus_prev_movement_type2 == 5) { + samus_pose = kSamusTurnPose_Crouching[*(&kPoseParams[0].direction_shots_fired + + (uint16)(8 * samus_prev_pose))]; + goto LABEL_9; + } + samus_pose = kSamusTurnPose_Standing[v0]; + } +LABEL_9:; + uint16 v1 = (__PAIR32__(samus_x_extra_run_speed, samus_x_base_subspeed) + + __PAIR32__(samus_x_base_speed, samus_x_extra_run_subspeed)) >> 16; + samus_x_base_subspeed += samus_x_extra_run_subspeed; + samus_x_base_speed = v1; + samus_x_extra_run_subspeed = 0; + samus_x_extra_run_speed = 0; + samus_x_accel_mode = 1; + return 1; +} + +uint8 SamusFunc_F468_TurnAroundJumping(void) { // 0x91F952 + samus_pose = kSamusTurnPose_Jumping[*(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_prev_pose))]; + uint16 v0 = (__PAIR32__(samus_x_extra_run_speed, samus_x_base_subspeed) + + __PAIR32__(samus_x_base_speed, samus_x_extra_run_subspeed)) >> 16; + samus_x_base_subspeed += samus_x_extra_run_subspeed; + samus_x_base_speed = v0; + samus_x_extra_run_subspeed = 0; + samus_x_extra_run_speed = 0; + samus_x_accel_mode = 1; + return 1; +} + +uint8 SamusFunc_F468_TurnAroundFalling(void) { // 0x91F98A + samus_pose = kSamusTurnPose_Falling[*(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_prev_pose))]; + uint16 v0 = (__PAIR32__(samus_x_extra_run_speed, samus_x_base_subspeed) + + __PAIR32__(samus_x_base_speed, samus_x_extra_run_subspeed)) >> 16; + samus_x_base_subspeed += samus_x_extra_run_subspeed; + samus_x_base_speed = v0; + samus_x_extra_run_subspeed = 0; + samus_x_extra_run_speed = 0; + samus_x_accel_mode = 1; + return 1; +} + +uint8 SamusFunc_F468_MorphBall(void) { // 0x91F9F4 + if (samus_prev_movement_type2 == kMovementType_04_MorphBallOnGround + || samus_prev_movement_type2 == kMovementType_08_MorphBallFalling) { + samus_anim_frame_skip = FUNC16(Samus_InputHandler); + } + SamusFunc_FA0A(); + return 0; +} + +void SamusFunc_FA0A(void) { // 0x91FA0F + if (samus_prev_pose_x_dir == 8) { + if (samus_pose_x_dir != 4) + return; + goto LABEL_5; + } + if (samus_pose_x_dir == 8) { +LABEL_5:; + uint16 v0 = (__PAIR32__(samus_x_extra_run_speed, samus_x_base_subspeed) + + __PAIR32__(samus_x_base_speed, samus_x_extra_run_subspeed)) >> 16; + samus_x_base_subspeed += samus_x_extra_run_subspeed; + samus_x_base_speed = v0; + Samus_CancelSpeedBoost(); + samus_x_extra_run_subspeed = 0; + samus_x_extra_run_speed = 0; + samus_x_accel_mode = 1; + } +} + +uint8 SamusFunc_F468_Springball(void) { // 0x91FA56 + if (samus_prev_movement_type2 == kMovementType_11_SpringBallOnGround + || samus_prev_movement_type2 == kMovementType_12_SpringBallInAir + || samus_prev_movement_type2 == kMovementType_13_SpringBallFalling) { + samus_anim_frame_skip = FUNC16(Samus_InputHandler); + } + SamusFunc_FA0A(); + return 0; +} + +uint8 SamusFunc_F468_WallJumping(void) { // 0x91FA76 + Samus_GetBottomBoundary(); + if ((fx_y_pos & 0x8000u) != 0) { + if ((lava_acid_y_pos & 0x8000u) == 0 && sign16(lava_acid_y_pos - R18_)) + return 0; + } else if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + return 0; + } + atmospheric_gfx_frame_and_type[3] = 1536; + atmospheric_gfx_anim_timer[3] = 3; + atmospheric_gfx_y_pos[3] = R18_; + if (samus_pose_x_dir != 8) { + atmospheric_gfx_x_pos[3] = samus_x_pos + 6; + return 0; + } + atmospheric_gfx_x_pos[3] = samus_x_pos - 6; + return 0; +} + +static uint16 kSamusFunc_F468_Shinespark[6] = { // 0x91FACA + (uint16)fnSamus_MoveHandler_Shinespark_Horiz, + (uint16)fnSamus_MoveHandler_Shinespark_Horiz, + (uint16)fnSamus_MoveHandlerVerticalShinespark, + (uint16)fnSamus_MoveHandlerVerticalShinespark, + (uint16)fnSamus_MoveHandler_Shinespark_Diag, + (uint16)fnSamus_MoveHandler_Shinespark_Diag, +}; +uint8 SamusFunc_F468_Shinespark(void) { + if (sign16(samus_pose - kPose_CF_FaceR_Ranintowall_AimUR)) { + samus_movement_handler = kSamusFunc_F468_Shinespark[samus_pose - 201]; + samus_input_handler = FUNC16(nullsub_152); + speed_echoes_index = 0; + speed_echo_xspeed[0] = 0; + speed_echo_xspeed[1] = 0; + speed_echo_xpos[0] = 0; + speed_echo_xpos[1] = 0; + QueueSfx3_Max9(0xFu); + } + return 0; +} +static const uint16 kSamusPhys_AnimDelayInWater = 3; +static const uint16 kSamusPhys_AnimDelayInAcid = 2; + +void Samus_SetAnimationFrameIfPoseChanged(void) { // 0x91FB08 + if ((equipped_items & 0x20) != 0) + goto LABEL_7; + R18_ = samus_y_pos + *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)) - 1; + if ((fx_y_pos & 0x8000u) == 0) { + if (sign16(fx_y_pos - R18_) && (fx_liquid_options & 4) == 0) { + R18_ = kSamusPhys_AnimDelayInWater; + goto LABEL_11; + } +LABEL_7: + R18_ = samus_x_speed_divisor; + goto LABEL_11; + } + if ((lava_acid_y_pos & 0x8000u) != 0 || !sign16(lava_acid_y_pos - R18_)) + goto LABEL_7; + R18_ = kSamusPhys_AnimDelayInAcid; +LABEL_11: + if ((samus_anim_frame_skip & 0x8000u) == 0 && samus_pose != samus_prev_pose) { + samus_anim_frame = samus_anim_frame_skip; + samus_anim_frame_timer = R18_ + + *RomPtr_91( + kSamusAnimationDelayData[samus_pose] + + samus_anim_frame_skip); + } +} + +void SamusFunc_EC80(void) { // 0x91FB8E + if (samus_prev_movement_type2 != kMovementType_06_Falling && samus_movement_type == kMovementType_06_Falling) { + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 2; + } +} + +void UNUSED_sub_91FC42(void); + +void nullsub_24(void) {} +void nullsub_25(void) {} + +static Func_V *const kHandleJumpTrans[28] = { // 0x91FBBB + nullsub_24, + nullsub_24, + HandleJumpTransition_NormalJump, + HandleJumpTransition_SpinJump, + nullsub_24, + nullsub_24, + nullsub_24, + nullsub_24, + nullsub_24, + nullsub_24, + nullsub_24, + nullsub_24, + nullsub_24, + UNUSED_sub_91FC42, + nullsub_24, + nullsub_24, + nullsub_24, + nullsub_24, + HandleJumpTransition_SpringBallInAir, + nullsub_24, + HandleJumpTransition_WallJump, + nullsub_24, + nullsub_24, + nullsub_24, + nullsub_24, + nullsub_25, + nullsub_24, + nullsub_24, +}; + +void HandleJumpTransition(void) { + kHandleJumpTrans[(samus_movement_type)](); +} + + +void HandleJumpTransition_WallJump(void) { // 0x91FC08 + if (samus_prev_movement_type2 != kMovementType_14_WallJumping) + Samus_InitWallJump(); +} + +void HandleJumpTransition_SpringBallInAir(void) { // 0x91FC18 + if (samus_pose == kPose_7F_FaceR_Springball_Air) { + if (samus_prev_movement_type2 != kMovementType_11_SpringBallOnGround) + return; +LABEL_6: + Samus_InitJump(); + return; + } + if (samus_pose == kPose_80_FaceL_Springball_Air && samus_prev_movement_type2 == kMovementType_11_SpringBallOnGround) + goto LABEL_6; +} + +void UNUSED_sub_91FC42(void) { // 0x91FC42 + if (samus_pose == (kPose_44_FaceL_Turn_Crouch | kPose_01_FaceR_Normal | 0x20)) { + if (samus_prev_pose != 100) + return; +LABEL_6: + Samus_InitJump(); + return; + } + if (samus_pose == (kPose_44_FaceL_Turn_Crouch | kPose_02_FaceL_Normal | 0x20) && samus_prev_pose == 99) + goto LABEL_6; +} + +void HandleJumpTransition_NormalJump(void) { // 0x91FC66 + if (samus_pose == kPose_4B_FaceR_Jumptrans + || samus_pose == kPose_4C_FaceL_Jumptrans + || !sign16(samus_pose - kPose_55_FaceR_Jumptrans_AimU) && sign16(samus_pose - kPose_5B)) { + if (samus_prev_pose == kPose_27_FaceR_Crouch || samus_prev_pose == kPose_28_FaceL_Crouch) + samus_y_pos -= 10; + Samus_InitJump(); + } +} + +void HandleJumpTransition_SpinJump(void) { // 0x91FC99 + if (samus_prev_movement_type2 != kMovementType_03_SpinJumping + && samus_prev_movement_type2 != kMovementType_14_WallJumping) { + Samus_InitJump(); + } +} + +void Samus_Func20(void) { // 0x91FCAF + if (samus_movement_type == 14) { + if (samus_anim_frame == 2 && samus_anim_frame_timer == 1) { + if (samus_pose_x_dir == 4) { + if (samus_pose == kPose_25_FaceR_Turn_Stand) + samus_pose = kPose_D6_FaceL_Xray_Stand; + else + samus_pose = kPose_DA_FaceL_Xray_Crouch; + } else if (samus_pose == kPose_26_FaceL_Turn_Stand) { + samus_pose = kPose_D5_FaceR_Xray_Stand; + } else { + samus_pose = kPose_D9_FaceR_Xray_Crouch; + } + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + } + } else { + if (samus_pose_x_dir == 4) { + if ((button_config_right & joypad1_lastkeys) == 0) + return; + xray_angle = 256 - xray_angle; + if (samus_movement_type == 5) + samus_pose = kPose_44_FaceL_Turn_Crouch; + else + samus_pose = kPose_26_FaceL_Turn_Stand; + } else { + if ((button_config_left & joypad1_lastkeys) == 0) + return; + xray_angle = 256 - xray_angle; + if (samus_movement_type == kMovementType_05_Crouching) + samus_pose = kPose_43_FaceR_Turn_Crouch; + else + samus_pose = kPose_25_FaceR_Turn_Stand; + } + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + } +} + +static Func_U8 *const off_91FE8A[4] = { // 0x91FDAE + HandleCollDueToChangedPose_Solid_NoColl, + HandleCollDueToChangedPose_Solid_CollAbove, + HandleCollDueToChangedPose_Solid_CollBelow, + HandleCollDueToChangedPose_Solid_CollBoth, +}; +static Func_U8 *const off_91FE92[4] = { + HandleCollDueToChangedPose_Block_NoColl, + HandleCollDueToChangedPose_Block_CollAbove, + HandleCollDueToChangedPose_Block_CollBelow, + HandleCollDueToChangedPose_Block_CollBoth, +}; + +void HandleCollDueToChangedPose(void) { + int16 v0; + + if (samus_pose) { + if (samus_pose != kPose_9B_FaceF_VariaGravitySuit) { + solid_enemy_collision_flags = 0; + block_collision_flags = 0; + R18_ = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)); + v0 = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_prev_pose)); + if (sign16(v0 - R18_)) { + samus_y_radius = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_prev_pose)); + samus_y_radius_diff = R18_ - v0; + R18_ -= v0; + R20_ = 0; + samus_collision_direction = 2; + samus_collision_flag = Samus_CheckSolidEnemyColl(); + if (samus_collision_flag) + solid_enemy_collision_flags = 1; + samus_space_to_move_up_enemy = R18_; + R18_ = samus_y_radius_diff; + R20_ = 0; + samus_collision_direction = 3; + samus_collision_flag = Samus_CheckSolidEnemyColl(); + if (samus_collision_flag) + solid_enemy_collision_flags |= 2u; + samus_space_to_move_down_enemy = R18_; + if (off_91FE8A[solid_enemy_collision_flags]() & 1) + goto LABEL_15; + R18_ = -samus_y_radius_diff; + R20_ = 0; + if (Samus_CollDetectChangedPose() & 1) + block_collision_flags = 1; + samus_space_to_move_up_blocks = R18_; + R18_ = samus_y_radius_diff; + R20_ = 0; + if (Samus_CollDetectChangedPose() & 1) + block_collision_flags |= 2u; + samus_space_to_move_down_blocks = R18_; + if (off_91FE92[block_collision_flags]() & 1) + LABEL_15: + samus_pose = samus_prev_pose; + } + } + } +} + +uint8 HandleCollDueToChangedPose_Solid_NoColl(void) { // 0x91FE9A + return 0; +} + +uint8 HandleCollDueToChangedPose_Solid_CollBoth(void) { // 0x91FE9C + return 0; +} + +uint8 HandleCollDueToChangedPose_Solid_CollAbove(void) { // 0x91FE9E + R18_ = samus_y_radius_diff - samus_space_to_move_up_enemy; + R20_ = 0; + uint16 v1 = samus_y_radius; + samus_y_radius = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)); + samus_collision_direction = 3; + samus_collision_flag = Samus_CheckSolidEnemyColl(); + if (samus_collision_flag) { + samus_y_radius = v1; + return 1; + } else { + samus_space_to_move_up_enemy = R18_; + samus_y_radius = v1; + return 0; + } +} + +uint8 HandleCollDueToChangedPose_Solid_CollBelow(void) { // 0x91FEDF + R18_ = samus_y_radius_diff - samus_space_to_move_down_enemy; + R20_ = 0; + uint16 v1 = samus_y_radius; + samus_y_radius = *(&kPoseParams[0].y_radius + (uint16)(8 * samus_pose)); + samus_collision_direction = 2; + samus_collision_flag = Samus_CheckSolidEnemyColl(); + if (samus_collision_flag) { + samus_y_radius = v1; + return 1; + } else { + samus_space_to_move_down_enemy = R18_; + samus_y_radius = v1; + return 0; + } +} + +uint8 HandleCollDueToChangedPose_Block_CollAbove(void) { // 0x91FF20 + R18_ = samus_y_radius_diff - samus_space_to_move_up_blocks; + R20_ = 0; + if (Samus_CollDetectChangedPose() & 1) + return 1; + if ((solid_enemy_collision_flags & 2) != 0) + return HandleCollDueToChangedPose_Block_CollBoth(); + samus_y_pos += R18_; + samus_prev_y_pos = samus_y_pos; + return 0; +} + +uint8 HandleCollDueToChangedPose_Block_CollBelow(void) { // 0x91FF49 + R18_ = samus_space_to_move_down_blocks - samus_y_radius_diff; + R20_ = 0; + if (Samus_CollDetectChangedPose() & 1) + return 1; + if ((solid_enemy_collision_flags & 1) != 0) + return HandleCollDueToChangedPose_Block_CollBoth(); + samus_y_pos -= R18_; + samus_prev_y_pos = samus_y_pos; + return 0; +} + +uint8 HandleCollDueToChangedPose_Block_NoColl(void) { // 0x91FF76 + int16 v0; + + v0 = 2 * solid_enemy_collision_flags; + if (!(2 * solid_enemy_collision_flags)) + return 0; + switch (v0) { + case 2: + samus_y_pos += samus_space_to_move_up_enemy; + samus_prev_y_pos = samus_y_pos; + return 0; + case 4: + samus_y_pos -= samus_space_to_move_down_enemy; + samus_prev_y_pos = samus_y_pos; + return 0; + case 6: + return HandleCollDueToChangedPose_Block_CollBoth(); + default: + Unreachable(); + while (1) + ; + } +} + +uint8 HandleCollDueToChangedPose_Block_CollBoth(void) { // 0x91FFA7 + SamusPose v1; + + if (sign16(samus_y_radius - 8)) + return 1; + if (samus_pose_x_dir == 4) + v1 = kPose_28_FaceL_Crouch; + else + v1 = kPose_27_FaceR_Crouch; + samus_pose = v1; + R18_ = *(&kPoseParams[0].y_radius + (uint16)(8 * v1)); + if (sign16(samus_y_radius - R18_)) { + R18_ = samus_y_radius - R18_; + samus_y_pos += R18_; + samus_prev_y_pos = samus_y_pos; + } + return 0; +} diff --git a/src/sm_92.c b/src/sm_92.c new file mode 100644 index 0000000..79548ec --- /dev/null +++ b/src/sm_92.c @@ -0,0 +1,65 @@ +// Samus animations + +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" + +#define kSamus_AnimationDefinitionPtrs ((uint16*)RomPtr(0x92d94e)) +#define kSamus_TileDefs_TopHalf ((uint16*)RomPtr(0x92d91e)) +#define kSamus_TileDefs_BottomHalf ((uint16*)RomPtr(0x92d938)) + +void SetSamusTilesDefsForCurAnim(void) { // 0x928000 + int16 v2; + + R18_ = 4 * samus_anim_frame; + R20_ = 4 * samus_anim_frame + 2; + uint16 v0 = 4 * samus_anim_frame + kSamus_AnimationDefinitionPtrs[samus_pose]; + R22_ = get_SamusTileAnimationDefs(v0)->top_half_idx; + tempB24 = get_SamusTileAnimationDefs(v0 + 1)->top_half_idx; + R18_ = 7 * tempB24; + nmi_copy_samus_top_half_src = 7 * tempB24 + kSamus_TileDefs_TopHalf[R22_]; + LOBYTE(nmi_copy_samus_halves) = 1; + uint16 v1 = R20_ + kSamus_AnimationDefinitionPtrs[samus_pose]; + v2 = *RomPtr_92(v1); + if (v2 != 255) { + tempB26 = *RomPtr_92(v1 + 1); + R20_ = 7 * tempB26; + nmi_copy_samus_bottom_half_src = 7 * tempB26 + kSamus_TileDefs_BottomHalf[v2]; + HIBYTE(nmi_copy_samus_halves) = 1; + } +} + +uint8 PlaySamusFanfare(void) { // 0x92ED24 + if (substate) { + if (substate == 5) + PlayRoomMusicTrackAfterAFrames(0x168u); + } else { + QueueMusic_DelayedY(1u, 0xEu); + } + if (sign16(substate - 359)) { + ++substate; + return 0; + } else { + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + substate = 0; + return 1; + } +} + +void Unused_SamusTileViewer(void) { // 0x92ED7A + DrawSamusSpritemap(0x182u, 0x40u, 0x40u); + DrawSamusSpritemap(0x183u, 0xC0u, 0x40u); + DrawSamusSpritemap(0x184u, 0x80, 0x60u); + DrawSamusSpritemap(0x185u, 0x80, 0x50u); +} + +void DrawSamusSuitExploding(void) { // 0x92EDBE + if (samus_pose_x_dir == 4) + R18_ = g_word_7E0DE4 + 2085; + else + R18_ = g_word_7E0DE4 + 2076; + DrawSamusSpritemap(R18_, samus_x_pos, samus_y_pos); +} diff --git a/src/sm_93.c b/src/sm_93.c new file mode 100644 index 0000000..89e6694 --- /dev/null +++ b/src/sm_93.c @@ -0,0 +1,292 @@ +// Projectiles +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" + +#define kProjectileData_UnchargedBeams ((uint16*)RomPtr(0x9383c1)) +#define kProjectileData_ChargedBeams ((uint16*)RomPtr(0x9383d9)) +#define kProjectileData_NonBeams ((uint16*)RomPtr(0x9383f1)) +#define kShinesparkEchoSpazer_ProjectileData ((uint16*)RomPtr(0x938403)) +#define kRunInstrForSuperMissile ((uint16*)RomPtr(0x93842b)) +#define g_stru_938691 (*(ProjectileDamagesAndInstrPtr*)RomPtr(0x938691)) +#define g_stru_938679 (*(ProjectileDamagesAndInstrPtr*)RomPtr(0x938679)) +#define kProjInstrList_Explosion (*(ProjectileDamagesAndInstrPtr*)RomPtr(0x938681)) +#define g_off_938413 ((uint16*)RomPtr(0x938413)) + +void InitializeProjectile(uint16 k) { // 0x938000 + ProjectileDataTable *ProjectileDataTable; + int16 damage; + + int v1 = k >> 1; + R18_ = 2 * (projectile_dir[v1] & 0xF); + uint16 v2 = projectile_type[v1], v3; + if ((v2 & 0xF00) != 0) { + v3 = kProjectileData_NonBeams[HIBYTE(v2) & 0xF]; + } else if ((v2 & 0x10) != 0) { + v3 = kProjectileData_ChargedBeams[projectile_type[v1] & 0xF]; + } else { + v3 = kProjectileData_UnchargedBeams[projectile_type[v1] & 0xF]; + } + ProjectileDataTable = get_ProjectileDataTable(v3); + damage = ProjectileDataTable->damage; + projectile_damage[v1] = ProjectileDataTable->damage; + if (damage < 0) + InvalidInterrupt_Crash(); + uint8 *v6 = RomPtr_93(R18_ + v3 + 2); + uint16 v7 = *(uint16 *)v6; + projectile_bomb_instruction_ptr[v1] = *(uint16 *)v6; + uint8 *v8 = RomPtr_93(v7); + projectile_x_radius[v1] = v8[4]; + projectile_y_radius[v1] = v8[5]; + projectile_bomb_instruction_timers[v1] = 1; +} + +void InitializeInstrForSuperMissile(uint16 v0) { // 0x938071 + int16 v4; + + int v1 = v0 >> 1; + uint16 v2 = kRunInstrForSuperMissile[HIBYTE(projectile_type[v1]) & 0xF]; + uint8 *v3 = RomPtr_93(v2); + v4 = *(uint16 *)v3; + projectile_damage[v1] = *(uint16 *)v3; + if (v4 < 0) + InvalidInterrupt_Crash(); + projectile_bomb_instruction_ptr[v1] = *(uint16 *)RomPtr_93(v2 + 2); + projectile_bomb_instruction_timers[v1] = 1; +} + +void InitializeInstrForMissile(uint16 v0) { // 0x9380A0 + int16 v4; + + int v1 = v0 >> 1; + uint16 v2 = kProjectileData_NonBeams[HIBYTE(projectile_type[v1]) & 0xF]; + uint8 *v3 = RomPtr_93(v2); + v4 = *(uint16 *)v3; + projectile_damage[v1] = *(uint16 *)v3; + if (v4 < 0) + InvalidInterrupt_Crash(); + projectile_bomb_instruction_ptr[v1] = *(uint16 *)RomPtr_93(v2 + 2); + projectile_bomb_instruction_timers[v1] = 1; +} + +void KillProjectileInner(uint16 k) { // 0x9380CF + int v1 = k >> 1; + if ((projectile_type[v1] & 0xF00) != 0) { + if (!cinematic_function) + QueueSfx2_Max6(7u); + uint16 v2 = projectile_type[v1]; + projectile_type[v1] = v2 & 0xF0FF | 0x800; + if ((v2 & 0x200) != 0) { + projectile_bomb_instruction_ptr[v1] = HIWORD(g_stru_938691.damages); + earthquake_type = 20; + earthquake_timer = 30; + } else { + projectile_bomb_instruction_ptr[v1] = *(&g_stru_938679.instr_ptr + 1); + } + if (!sign16(cooldown_timer - 21)) + cooldown_timer = 20; + } else { + projectile_type[v1] = projectile_type[v1] & 0xF0FF | 0x700; + projectile_bomb_instruction_ptr[v1] = HIWORD(g_stru_938679.damages); + QueueSfx2_Max6(0xCu); + } + projectile_bomb_instruction_timers[v1] = 1; + projectile_damage[v1] = 8; +} + +void InitializeBombExplosion(uint16 k) { // 0x93814E + int v1 = k >> 1; + projectile_bomb_instruction_ptr[v1] = HIWORD(kProjInstrList_Explosion.damages); + projectile_bomb_instruction_timers[v1] = 1; +} + +void InitializeShinesparkEchoOrSpazerSba(uint16 k) { // 0x938163 + int16 v4; + + int v1 = k >> 1; + R18_ = 2 * (projectile_dir[v1] & 0xF); + uint16 v2 = kShinesparkEchoSpazer_ProjectileData[LOBYTE(projectile_type[v1]) - 34]; + uint8 *v3 = RomPtr_93(v2); + v4 = *(uint16 *)v3; + projectile_damage[v1] = *(uint16 *)v3; + if (v4 < 0) + InvalidInterrupt_Crash(); + projectile_bomb_instruction_ptr[v1] = *(uint16 *)RomPtr_93(R18_ + v2 + 2); + projectile_bomb_instruction_timers[v1] = 1; +} + +void InitializeSbaProjectile(uint16 k) { // 0x9381A4 + int16 v3; + + int v1 = k >> 1; + uint8 *v2 = RomPtr_93(g_off_938413[projectile_type[v1] & 0xF]); + v3 = *(uint16 *)v2; + projectile_damage[v1] = *(uint16 *)v2; + if (v3 < 0) + InvalidInterrupt_Crash(); + projectile_bomb_instruction_ptr[v1] = *((uint16 *)v2 + 1); + projectile_bomb_instruction_timers[v1] = 1; +} + +void ProjectileInsts_GetValue(uint16 k) { // 0x9381D1 + int ip = projectile_bomb_instruction_ptr[k >> 1]; + int delta = (projectile_bomb_instruction_timers[k >> 1] == 1 && !sign16(get_ProjectileInstr(ip)->timer)) ? 0 : -8; + R22_ = get_ProjectileInstr(ip + delta)->field_6; +} + +uint16 CallProj93Instr(uint32 ea, uint16 j, uint16 k) { + switch (ea) { + case fnProj93Instr_Delete: return Proj93Instr_Delete(j, k); + case fnProj93Instr_Goto: return Proj93Instr_Goto(j, k); + case fnProj93Instr_GotoIfLess: return Proj93Instr_GotoIfLess(j, k); + default: return Unreachable(); + } +} + +void RunProjectileInstructions(void) { // 0x9381E9 + ProjectileInstr *v7; + ProjectileInstr *ProjectileInstr; + + uint16 v0 = projectile_index; + int v1 = projectile_index >> 1; + if (projectile_bomb_instruction_timers[v1]-- == 1) { + uint16 v3 = projectile_bomb_instruction_ptr[v1], timer; + while (1) { + ProjectileInstr = get_ProjectileInstr(v3); + timer = ProjectileInstr->timer; + if ((ProjectileInstr->timer & 0x8000u) == 0) + break; + R18_ = ProjectileInstr->timer; + v3 = CallProj93Instr(timer | 0x930000, v0, v3 + 2); + if (!v3) + return; + } + int v6 = v0 >> 1; + projectile_bomb_instruction_timers[v6] = timer; + v7 = get_ProjectileInstr(v3); + projectile_spritemap_pointers[v6] = v7->spritemap_ptr; + projectile_x_radius[v6] = v7->x_radius; + projectile_y_radius[v6] = v7->y_radius; + projectile_bomb_instruction_ptr[v6] = v3 + 8; + } +} + +uint16 Proj93Instr_Delete(uint16 k, uint16 j) { // 0x93822F + ClearProjectile(k); + return 0; +} + +uint16 Proj93Instr_Goto(uint16 k, uint16 j) { // 0x938239 + return *(uint16 *)RomPtr_93(j); +} + +uint16 Proj93Instr_GotoIfLess(uint16 k, uint16 j) { // 0x938240 + uint8 *v2 = RomPtr_93(j); + if ((int16)(*(uint16 *)v2 - projectile_variables[k >> 1]) >= 0) + return *((uint16 *)RomPtr_93(j) + 1); + else + return *((uint16 *)v2 + 2); +} + +void DrawPlayerExplosions2(void) { // 0x938254 + uint16 v0 = 8; + projectile_index = 8; + do { + int v1 = v0 >> 1; + if (!projectile_bomb_instruction_ptr[v1]) + goto LABEL_25; + uint16 v2, v3; + v2 = projectile_type[v1]; + if ((v2 & (kProjectileType_TypeMask | 0x10)) != 0) { + if (!sign16((v2 & 0xF00) - 768)) + goto LABEL_25; + } else if ((v2 & 0xC) != 0) { + if ((v0 & 2) != 0) { + if ((nmi_frame_counter_word & 2) == 0) + goto LABEL_25; + } else if ((nmi_frame_counter_word & 2) != 0) { + goto LABEL_25; + } + } else if ((v0 & 2) != 0) { + if ((nmi_frame_counter_word & 1) != 0) + goto LABEL_25; + } else if ((nmi_frame_counter_word & 1) == 0) { + goto LABEL_25; + } + if ((ceres_status & 0x8000u) == 0) { + R20_ = projectile_x_pos[v1] - layer1_x_pos; + v3 = projectile_y_pos[v1] - layer1_y_pos; + R18_ = v3; + } else { + CalcExplosion_Mode7(v0); + v3 = R18_; + } + if ((v3 & 0xFF00) != 0) { + if ((projectile_spritemap_pointers[v1] & 0x8000u) != 0){ + } + } else if ((projectile_spritemap_pointers[v1] & 0x8000u) != 0) { + DrawProjectileSpritemap(v0); + } + v0 = projectile_index; +LABEL_25: + v0 -= 2; + projectile_index = v0; + } while ((v0 & 0x8000u) == 0); + Samus_DrawShinesparkCrashEchoProjectiles(); + HandleProjectileTrails(); +} + +void sub_9382FD(void) { // 0x9382FD + uint16 v0 = 8; + projectile_index = 8; + do { + int v1 = v0 >> 1; + if (projectile_bomb_instruction_ptr[v1]) { + R20_ = projectile_x_pos[v1] - layer1_x_pos; + R18_ = projectile_y_pos[v1] - 8 - layer1_y_pos; + if ((R18_ & 0xFF00) != 0) { + } else if ((projectile_spritemap_pointers[v1] & 0x8000u) != 0) { + DrawProjectileSpritemap(v0); + } + v0 = projectile_index; + } + v0 -= 2; + projectile_index = v0; + } while ((v0 & 0x8000u) == 0); + HandleProjectileTrails(); +} + +void DrawBombAndProjectileExplosions(void) { // 0x93834D + uint16 v0 = 18, v2; + projectile_index = 18; + do { + int v1 = v0 >> 1; + if (!projectile_bomb_instruction_ptr[v1] || (int16)((projectile_type[v1] & 0xF00) - 768) < 0) + goto LABEL_16; + if ((projectile_type[v1] & 0xF00) == 768) { + if (!projectile_variables[v1]) + goto LABEL_16; +LABEL_9:; + uint16 v3 = projectile_x_pos[v1] - layer1_x_pos; + R20_ = v3; + if (!sign16(v3 - 304) || sign16(v3 + 48)) + goto LABEL_16; + v2 = projectile_y_pos[v1] - layer1_y_pos; + R18_ = v2; + goto LABEL_12; + } + if ((projectile_type[v1] & 0xF00) == 1280 || (ceres_status & 0x8000u) == 0) + goto LABEL_9; + CalcExplosion_Mode7(v0); + v2 = R18_; +LABEL_12: + if ((v2 & 0xFF00) != 0) + ; + else + DrawProjectileSpritemap(v0); + v0 = projectile_index; +LABEL_16: + v0 -= 2; + projectile_index = v0; + } while ((v0 & 0x8000u) == 0); +} diff --git a/src/sm_94.c b/src/sm_94.c new file mode 100644 index 0000000..ff38dab --- /dev/null +++ b/src/sm_94.c @@ -0,0 +1,3069 @@ +// Block properties, some cutscene graphics +#include "sm_rtl.h" +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" + +static const uint8 kAlignPos_Tab1[512] = { + 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 15, 14, 13, 12, 11, 10, 9, 9, 10, 11, 12, 13, 14, 15, 16, + 16, 14, 12, 10, 8, 6, 4, 2, 2, 4, 6, 8, 10, 12, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 12, 12, 12, 8, 8, 8, 8, 4, 4, 4, 4, 0, 0, 0, 0, + 14, 14, 12, 12, 10, 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 14, 13, 12, 11, 10, 9, + 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 12, 10, 8, 6, 4, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 6, 8, 10, 12, 14, + 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, + 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, + 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, + 20, 20, 20, 20, 20, 20, 20, 20, 16, 14, 12, 10, 8, 6, 4, 2, + 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 15, 12, 9, 6, 3, + 20, 20, 20, 20, 20, 20, 14, 11, 8, 5, 2, 0, 0, 0, 0, 0, + 16, 13, 10, 7, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const uint8 kAlignYPos_Tab0[512] = { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 15, 14, 13, 12, 11, 10, 9, 9, 10, 11, 12, 13, 14, 15, 16, + 16, 14, 12, 10, 8, 6, 4, 2, 2, 4, 6, 8, 10, 12, 14, 16, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 12, 12, 12, 8, 8, 8, 8, 4, 4, 4, 4, 0, 0, 0, 0, + 14, 14, 12, 12, 10, 10, 8, 8, 6, 6, 4, 4, 2, 2, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 16, 16, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 14, 13, 12, 11, 10, 9, + 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, + 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, + 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, + 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, + 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, + 20, 20, 20, 20, 20, 20, 20, 20, 16, 14, 12, 10, 8, 6, 4, 2, + 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 15, 12, 9, 6, 3, + 20, 20, 20, 20, 20, 20, 14, 11, 8, 5, 2, 0, 0, 0, 0, 0, + 16, 13, 10, 7, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + +////////////////////////////////////////////////////////////// +// BANK 94 +////////////////////////////////////////////////////////////// + +static const uint8 kTab948E54[20] = { + 0, 0, 0x80, 0x80, 0, 0x80, 0, 0x80, 0, 0, 0, 0x80, 0, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, +}; + +static const uint16 kBlockColl_Horiz_Slope_NonSquare_Tab[64] = { + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0, 0x100, + 0x1000, 0xb0, + 0x1000, 0xb0, + 0, 0x100, + 0, 0x100, + 0x1000, 0xc0, + 0, 0x100, + 0x1000, 0xc0, + 0x1000, 0xc0, + 0x800, 0xd8, + 0x800, 0xd8, + 0x600, 0xf0, + 0x600, 0xf0, + 0x600, 0xf0, + 0x4000, 0x80, + 0x4000, 0x80, + 0x6000, 0x50, + 0x6000, 0x50, + 0x6000, 0x50, +}; + +#define fnkPlmHeaderDefPtrs 0x949139 + +#define off_9492D9 ((uint16*)RomPtr(0x9492d9)) +#define off_9492E9 ((uint16*)RomPtr(0x9492e9)) +#define kPlmHeaderDefPtrs ((uint16*)RomPtr(0x949139)) + +uint16 PostGrappleColl_Horiz_Slope_NonSquare(uint16 k) { // 0x948000 + int16 v1; + char v3; + int16 v5; + char v6; + int16 v8; + + if (!(samus_collision_direction & 1)) { + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + v1 = samus_x_pos >> 4; + if (v1 != mod) + return -1; + temp_collision_DD4 = R32 & 0xF; + temp_collision_DD6 = 16 * (BTS[k] & 0x1F); + if ((BTS[k] & 0x40) != 0) { + if (BTS[k] & 0x80) + v3 = samus_y_pos ^ 0xF; + else + v3 = samus_y_pos; + uint16 v4 = temp_collision_DD6 + (v3 & 0xF); + uint16 result = (kAlignPos_Tab1[v4] & 0x1F) - temp_collision_DD4 - 1; + if ((kAlignPos_Tab1[v4] & 0x1F) - temp_collision_DD4 != 1 && (result & 0x8000u) != 0) + return -1; + return result; + } + return PostGrappleColl_Horiz_Solid(); + } + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + v5 = samus_x_pos >> 4; + if (v5 != mod) + return -1; + temp_collision_DD4 = R32 & 0xF; + temp_collision_DD6 = 16 * (BTS[k] & 0x1F); + if (BTS[k] & 0x40) + return PostGrappleColl_Horiz_Solid(); + if (BTS[k] & 0x80) + v6 = samus_y_pos ^ 0xF; + else + v6 = samus_y_pos; + uint16 v7 = temp_collision_DD6 + (v6 & 0xF); + v8 = (kAlignPos_Tab1[v7] & 0x1F) - temp_collision_DD4 - 1; + if ((kAlignPos_Tab1[v7] & 0x1F) - temp_collision_DD4 == 1 || v8 < 0) + return ~v8; + else + return -1; +} + +uint16 PostGrappleColl_Vert_Slope_NonSquare(uint16 k) { // 0x9480E0 + int16 v1; + int16 v3; + char v4; + int16 v6; + int16 v7; + char v8; + int16 v10; + + if (!(samus_collision_direction & 1)) { + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + v1 = samus_x_pos >> 4; + if (v1 != mod) + return -1; + temp_collision_DD4 = R32 & 0xF; + temp_collision_DD6 = 16 * (BTS[k] & 0x1F); + v3 = BTS[k]; + if (v3 & 0x80) { + if ((v3 & 0x40) != 0) + v4 = samus_x_pos ^ 0xF; + else + v4 = samus_x_pos; + uint16 v5 = temp_collision_DD6 + (v4 & 0xF); + uint16 result = (kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 - 1; + if ((kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 != 1 && (result & 0x8000u) != 0) + return -1; + return result; + } + return PostGrappleColl_Vert_Solid(); + } + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + v6 = samus_x_pos >> 4; + if (v6 != mod) + return -1; + temp_collision_DD4 = R32 & 0xF; + temp_collision_DD6 = 16 * (BTS[k] & 0x1F); + v7 = BTS[k]; + if (v7 & 0x80) + return PostGrappleColl_Vert_Solid(); + if ((v7 & 0x40) != 0) + v8 = samus_x_pos ^ 0xF; + else + v8 = samus_x_pos; + uint16 v9 = temp_collision_DD6 + (v8 & 0xF); + v10 = (kAlignYPos_Tab0[v9] & 0x1F) - temp_collision_DD4 - 1; + if ((kAlignYPos_Tab0[v9] & 0x1F) - temp_collision_DD4 == 1 || v10 < 0) + return ~v10; + else + return -1; +} + +uint16 PostGrappleColl_Horiz_Slope_Square(uint16 k) { // 0x9481B8 + temp_collision_DD4 = 4 * (BTS[k] & 0x1F); + temp_collision_DD6 = BTS[k] >> 6; + uint16 v1 = temp_collision_DD4 + (temp_collision_DD6 ^ ((uint8)(R32 & 8) >> 3)); + if (!R26_) { + if ((((uint8)samus_y_radius + (uint8)samus_y_pos - 1) & 8) == 0) { + if (!kTab948E54[v1]) + return -1; + goto LABEL_10; + } + goto LABEL_7; + } + if (R26_ != R28_ || (((uint8)samus_y_pos - (uint8)samus_y_radius) & 8) == 0) { +LABEL_7: + if (kTab948E54[v1]) + goto LABEL_10; + } + if (!kTab948E54[v1 ^ 2]) + return -1; +LABEL_10: + if (samus_collision_direction & 1) + return R32 & 7; + else + return R32 & 7 ^ 7; +} + +uint16 PostGrappleColl_Vertical_Slope_Square(uint16 k) { // 0x948230 + temp_collision_DD4 = 4 * (BTS[k] & 0x1F); + temp_collision_DD6 = BTS[k] >> 6; + uint16 v1 = temp_collision_DD4 + (temp_collision_DD6 ^ ((uint8)(R32 & 8) >> 2)); + if (!R26_) { + if ((((uint8)samus_x_radius + (uint8)samus_x_pos - 1) & 8) == 0) { + if (!kTab948E54[v1]) + return -1; + goto LABEL_10; + } + goto LABEL_7; + } + if (R26_ != R28_ || (((uint8)samus_x_pos - (uint8)samus_x_radius) & 8) == 0) { +LABEL_7: + if (kTab948E54[v1]) + goto LABEL_10; + } + if (!kTab948E54[v1 ^ 1]) + return -1; +LABEL_10: + if (samus_collision_direction & 1) + return R32 & 7; + else + return R32 & 7 ^ 7; +} + +uint16 ClearCarry_0(void) { // 0x9482A7 + return -1; +} + +uint16 PostGrappleColl_Horiz_Slope(void) { // 0x9482A9 + if ((BTS[cur_block_index] & 0x1Fu) < 5) + return PostGrappleColl_Horiz_Slope_Square(cur_block_index); + else + return PostGrappleColl_Horiz_Slope_NonSquare(cur_block_index); +} + +uint16 PostGrappleColl_Horiz_Solid(void) { // 0x9482BE + return R32 & 0xF; +} + +uint16 PostGrappleColl_Vert_Slope(void) { // 0x9482C5 + if ((BTS[cur_block_index] & 0x1Fu) < 5) + return PostGrappleColl_Vertical_Slope_Square(cur_block_index); + else + return PostGrappleColl_Vert_Slope_NonSquare(cur_block_index); +} + +uint16 PostGrappleColl_Vert_Solid(void) { // 0x9482DA + return R32 & 0xF; +} + +static Func_U16 *const kPostGrappleColl_Horiz[16] = { // 0x948321 + ClearCarry_0, + PostGrappleColl_Horiz_Slope, + ClearCarry_0, + ClearCarry_0, + ClearCarry_0, + ClearCarry_0, + ClearCarry_0, + ClearCarry_0, + PostGrappleColl_Horiz_Solid, + PostGrappleColl_Horiz_Solid, + PostGrappleColl_Horiz_Solid, + PostGrappleColl_Horiz_Solid, + PostGrappleColl_Horiz_Solid, + PostGrappleColl_Horiz_Solid, + PostGrappleColl_Horiz_Solid, + PostGrappleColl_Horiz_Solid, +}; +static Func_U16 *const kPostGrappleColl_Vert[16] = { + ClearCarry_0, + PostGrappleColl_Vert_Slope, + ClearCarry_0, + ClearCarry_0, + ClearCarry_0, + ClearCarry_0, + ClearCarry_0, + ClearCarry_0, + PostGrappleColl_Vert_Solid, + PostGrappleColl_Vert_Solid, + PostGrappleColl_Vert_Solid, + PostGrappleColl_Vert_Solid, + PostGrappleColl_Vert_Solid, + PostGrappleColl_Vert_Solid, + PostGrappleColl_Vert_Solid, + PostGrappleColl_Vert_Solid, +}; +uint16 PostGrappleColl_Horiz(uint16 k) { + cur_block_index = k >> 1; + return kPostGrappleColl_Horiz[(uint16)((uint8)((uint16)(level_data[k >> 1] & 0xF000) >> 8) >> 3) >> 1](); +} + +uint16 PostGrappleColl_Vert(uint16 k) { // 0x948338 + cur_block_index = k >> 1; + return kPostGrappleColl_Vert[(uint16)((uint8)((uint16)(level_data[k >> 1] & 0xF000) >> 8) >> 3) >> 1](); +} + +void PostGrappleCollisionDetect_Right(void) { // 0x94834F + int16 v0; + int16 v2; + + samus_collision_direction = 1; + distance_to_eject_samus_left = 0; + Samus_GetYposSpan(); + uint16 prod = Mult8x8((uint16)(samus_y_pos - samus_y_radius) >> 4, room_width_in_blocks); + R22_ = samus_x_subpos; + R24_ = samus_x_pos; + R32 = samus_x_radius + samus_x_pos - 1; + v0 = R32 >> 4; + cur_block_index = prod + v0; + uint16 v1 = 2 * cur_block_index; + do { + v2 = PostGrappleColl_Horiz(v1); + if (v2 >= 0) { + uint16 v3 = v2 + 1; + if (v3 >= distance_to_eject_samus_left) + distance_to_eject_samus_left = v3; + } + v1 += room_width_in_blocks + room_width_in_blocks; + --R26_; + } while ((R26_ & 0x8000u) == 0); +} + +void PostGrappleCollisionDetect_Left(void) { // 0x9483B1 + int16 v0; + int16 v2; + + samus_collision_direction = 0; + distance_to_eject_samus_right = 0; + Samus_GetYposSpan(); + uint16 prod = Mult8x8((uint16)(samus_y_pos - samus_y_radius) >> 4, room_width_in_blocks); + R22_ = samus_x_subpos; + R24_ = samus_x_pos; + R32 = samus_x_pos - samus_x_radius; + v0 = (uint16)(samus_x_pos - samus_x_radius) >> 4; + cur_block_index = prod + v0; + uint16 v1 = 2 * cur_block_index; + do { + v2 = PostGrappleColl_Horiz(v1); + if (v2 >= 0) { + uint16 v3 = v2 + 1; + if (v3 >= distance_to_eject_samus_right) + distance_to_eject_samus_right = v3; + } + v1 += room_width_in_blocks + room_width_in_blocks; + --R26_; + } while ((R26_ & 0x8000u) == 0); +} + +void PostGrappleCollisionDetect_Down(void) { // 0x94840F + int16 v0; + int16 v2; + + samus_collision_direction = 3; + distance_to_eject_samus_up = 0; + Samus_GetXposSpan(); + R22_ = samus_y_subpos; + R24_ = samus_y_pos; + R32 = samus_y_radius + samus_y_pos - 1; + uint16 prod = Mult8x8(R32 >> 4, room_width_in_blocks); + v0 = (uint16)(samus_x_pos - samus_x_radius) >> 4; + cur_block_index = prod + v0; + uint16 v1 = 2 * cur_block_index; + do { + v2 = PostGrappleColl_Vert(v1); + if (v2 >= 0) { + uint16 v3 = v2 + 1; + if (v3 >= distance_to_eject_samus_up) + distance_to_eject_samus_up = v3; + } + v1 += 2; + --R26_; + } while ((R26_ & 0x8000u) == 0); +} + +void PostGrappleCollisionDetect_Up(void) { // 0x94846A + int16 v0; + int16 v2; + + samus_collision_direction = 2; + distance_to_eject_samus_down = 0; + Samus_GetXposSpan(); + R22_ = samus_y_subpos; + R24_ = samus_y_pos; + R32 = samus_y_pos - samus_y_radius; + uint16 prod = Mult8x8((uint16)(samus_y_pos - samus_y_radius) >> 4, room_width_in_blocks); + v0 = (uint16)(samus_x_pos - samus_x_radius) >> 4; + cur_block_index = prod + v0; + uint16 v1 = 2 * cur_block_index; + do { + v2 = PostGrappleColl_Vert(v1); + if (v2 >= 0) { + uint16 v3 = v2 + 1; + if (v3 >= distance_to_eject_samus_down) + distance_to_eject_samus_down = v3; + } + v1 += 2; + --R26_; + } while ((R26_ & 0x8000u) == 0); +} + +void PostGrappleCollisionDetect_X(void) { // 0x9484C4 + PostGrappleCollisionDetect_Right(); + PostGrappleCollisionDetect_Left(); +} + +void PostGrappleCollisionDetect_Y(void) { // 0x9484CD + PostGrappleCollisionDetect_Down(); + PostGrappleCollisionDetect_Up(); +} + +uint8 BlockColl_Horiz_Slope_NonSquare(void) { // 0x9484D6 + uint16 v2; + + if ((current_slope_bts & 0x80) != 0 || __PAIR32__(samus_y_speed, samus_y_subspeed)) + return 0; + uint16 v1 = 4 * (current_slope_bts & 0x1F); + HIBYTE(v2) = R18_; + LOBYTE(v2) = HIBYTE(R20_); + if ((R18_ & 0x8000u) == 0) { + Multiply16x16(v2, kBlockColl_Horiz_Slope_NonSquare_Tab[(v1 >> 1) + 1]); + R20_ = mult_product_lo; + R18_ = mult_product_hi; + } else { + Multiply16x16(-v2, kBlockColl_Horiz_Slope_NonSquare_Tab[(v1 >> 1) + 1]); + Negate32(&mult_product_hi, &mult_product_lo, &R18_, &R20_); + } + return 0; +} + + +uint8 BlockColl_Vert_Slope_NonSquare(uint16 k) { // 0x9486FE + int16 v1; + int16 v3; + char v4; + uint16 v5; + int16 v6; + int16 v7; + int16 v8; + int16 v9; + char v10; + uint16 v11; + int16 v12; + int16 v13; + + if (samus_collision_direction & 1) { + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + v8 = samus_x_pos >> 4; + if (v8 == mod) { + temp_collision_DD4 = ((uint8)samus_y_radius + (uint8)R24_ - 1) & 0xF; + temp_collision_DD6 = 16 * (BTS[k] & 0x1F); + v9 = BTS[k]; + if (!(v9 & 0x80) + && ((v9 & 0x40) != 0 ? (v10 = samus_x_pos ^ 0xF) : (v10 = samus_x_pos), + (v11 = temp_collision_DD6 + (v10 & 0xF), + v12 = (kAlignYPos_Tab0[v11] & 0x1F) - temp_collision_DD4 - 1, + (kAlignYPos_Tab0[v11] & 0x1F) - temp_collision_DD4 == 1) + || v12 < 0)) { + v13 = R18_ + v12; + if (v13 < 0) + v13 = 0; + R18_ = v13; + R20_ = 0; + return 1; + } else { + return 0; + } + } else { + return 0; + } + } else { + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + v1 = samus_x_pos >> 4; + if (v1 == mod) { + temp_collision_DD4 = ((uint8)R24_ - (uint8)samus_y_radius) & 0xF ^ 0xF; + temp_collision_DD6 = 16 * (BTS[k] & 0x1F); + v3 = BTS[k]; + if ((v3 & 0x80) + && ((v3 & 0x40) != 0 ? (v4 = samus_x_pos ^ 0xF) : (v4 = samus_x_pos), + (v5 = temp_collision_DD6 + (v4 & 0xF), + v6 = (kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 - 1, + (kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 == 1) + || v6 < 0)) { + v7 = R18_ + v6; + if (v7 < 0) + v7 = 0; + R18_ = v7; + R20_ = 0; + return 1; + } else { + return 0; + } + } else { + return 0; + } + } +} + +void Samus_AlignYPosSlope(void) { // 0x9487F4 + int16 v0; + char v1; + int16 v2; + int16 v3; + char v4; + int16 v6; + + if ((enable_horiz_slope_coll & 2) != 0) { + R26_ = samus_x_pos; + R28_ = samus_y_radius + samus_y_pos - 1; + g_word_7E001E = 0; + R32 = 0; + CalculateBlockAt(); + if ((level_data[cur_block_index] & 0xF000) == 4096 + && (BTS[cur_block_index] & 0x1Fu) >= 5) { + temp_collision_DD4 = ((uint8)samus_y_radius + (uint8)samus_y_pos - 1) & 0xF; + temp_collision_DD6 = 16 * (BTS[cur_block_index] & 0x1F); + v0 = BTS[cur_block_index]; + if (!(v0 & 0x80)) { + v1 = (v0 & 0x40) != 0 ? samus_x_pos ^ 0xF : samus_x_pos; + v2 = (kAlignYPos_Tab0[(uint16)(temp_collision_DD6 + (v1 & 0xF))] & 0x1F) - temp_collision_DD4 - 1; + if (v2 < 0) { + samus_y_pos += v2; + samus_pos_adjusted_by_slope_flag = 1; + } + } + } + R26_ = samus_x_pos; + R28_ = samus_y_pos - samus_y_radius; + g_word_7E001E = 0; + R32 = 0; + CalculateBlockAt(); + if ((level_data[cur_block_index] & 0xF000) == 4096 + && (BTS[cur_block_index] & 0x1Fu) >= 5) { + temp_collision_DD4 = ((uint8)samus_y_pos - (uint8)samus_y_radius) & 0xF ^ 0xF; + temp_collision_DD6 = 16 * (BTS[cur_block_index] & 0x1F); + v3 = BTS[cur_block_index]; + if (v3 & 0x80) { + if ((v3 & 0x40) != 0) + v4 = samus_x_pos ^ 0xF; + else + v4 = samus_x_pos; + uint16 v5 = temp_collision_DD6 + (v4 & 0xF); + v6 = (kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 - 1; + if ((kAlignYPos_Tab0[v5] & 0x1F) - temp_collision_DD4 == 1 || v6 < 0) { + samus_y_pos -= v6; + samus_pos_adjusted_by_slope_flag = 1; + } + } + } + } +} + +uint8 BlockColl_Horiz_Slope_Square(uint16 a, uint16 k) { // 0x948D2B + int16 v4; + int16 v5; + + temp_collision_DD4 = 4 * a; + temp_collision_DD6 = BTS[k] >> 6; + uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R32 & 8) >> 3)); + if (!R26_) { + if ((((uint8)samus_y_radius + (uint8)samus_y_pos - 1) & 8) == 0) { + if (!kTab948E54[v2]) + return 0; + goto LABEL_10; + } + goto LABEL_7; + } + if (R26_ != R28_ || (((uint8)samus_y_pos - (uint8)samus_y_radius) & 8) == 0) { +LABEL_7: + if (kTab948E54[v2]) + goto LABEL_10; + } + if (!kTab948E54[v2 ^ 2]) + return 0; +LABEL_10: + R20_ = 0; + if ((R18_ & 0x8000u) != 0) { + v5 = samus_x_radius + (R32 | 7) + 1 - samus_x_pos; + if (v5 >= 0) + v5 = 0; + R18_ = v5; + samus_x_subpos = 0; + return 1; + } else { + v4 = (__PAIR32__((R32 & 0xFFF8) - samus_x_radius, R32 & 0xFFF8) - __PAIR32__(samus_x_pos, samus_x_radius)) >> 16; + if (v4 < 0) + v4 = 0; + R18_ = v4; + samus_x_subpos = -1; + return 1; + } +} + +uint8 BlockColl_Vert_Slope_Square(uint16 a, uint16 k) { // 0x948DBD + int16 v4; + int16 v5; + + temp_collision_DD4 = 4 * a; + temp_collision_DD6 = BTS[k] >> 6; + uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R32 & 8) >> 2)); + if (!R26_) { + if ((((uint8)samus_x_radius + (uint8)samus_x_pos - 1) & 8) == 0) { + if (!kTab948E54[v2]) + return 0; + goto LABEL_10; + } + goto LABEL_7; + } + if (R26_ != R28_ || (((uint8)samus_x_pos - (uint8)samus_x_radius) & 8) == 0) { +LABEL_7: + if (kTab948E54[v2]) + goto LABEL_10; + } + if (!kTab948E54[v2 ^ 1]) + return 0; +LABEL_10: + R20_ = 0; + if ((R18_ & 0x8000u) != 0) { + v5 = samus_y_radius + (R32 | 7) + 1 - samus_y_pos; + if (v5 >= 0) + v5 = 0; + R18_ = v5; + samus_y_subpos = 0; + return 1; + } else { + v4 = (__PAIR32__((R32 & 0xFFF8) - samus_y_radius, R32 & 0xFFF8) - __PAIR32__(samus_y_pos, samus_y_radius)) >> 16; + if (v4 < 0) + v4 = 0; + R18_ = v4; + samus_y_subpos = -1; + samus_pos_adjusted_by_slope_flag = 1; + return 1; + } +} + + +uint8 ClearCarry_1(void) { // 0x948E7D + return 0; +} + +uint8 ClearCarry_2(void) { // 0x948E7F + return 0; +} + +uint8 ClearCarry_3(void) { // 0x948E81 + return 0; +} + +void BlockColl_SpikeBlock_BTS0(void) { // 0x948E83 + if ((area_index != 3 || CheckBossBitForCurArea(1u) & 1) && !samus_invincibility_timer) { + samus_invincibility_timer = 60; + samus_knockback_timer = 10; + samus_periodic_damage += 60; + knockback_x_dir = ((*(uint16 *)&samus_pose_x_dir ^ 0xC) & 8) != 0; + } +} + +void BlockColl_SpikeBlock_BTS1(void) { // 0x948ECF + if (!samus_invincibility_timer) { + samus_invincibility_timer = 60; + samus_knockback_timer = 10; + samus_periodic_damage += 16; + knockback_x_dir = ((*(uint16 *)&samus_pose_x_dir ^ 0xC) & 8) != 0; + } +} + +void BlockColl_SpikeBlock_BTS3(void) { // 0x948F0A + if (!samus_invincibility_timer) { + samus_invincibility_timer = 60; + samus_knockback_timer = 10; + samus_periodic_damage += 16; + knockback_x_dir = ((*(uint16 *)&samus_pose_x_dir ^ 0xC) & 8) != 0; + } +} + +uint8 SetCarry(void) { + return 1; +} + +uint8 ClearCarry_4(void) { // 0x948F47 + return 0; +} + +uint8 BlockColl_Horiz_SolidShootGrappleBlock(void) { // 0x948F49 + int16 v0; + int16 v2; + + R20_ = 0; + if ((R18_ & 0x8000u) != 0) { + v2 = samus_x_radius + (R32 | 0xF) + 1 - samus_x_pos; + if (v2 >= 0) + v2 = 0; + R18_ = v2; + samus_x_subpos = 0; + return 1; + } else { + v0 = (R32 & 0xFFF0) - samus_x_radius - samus_x_pos; + if (v0 < 0) + v0 = 0; + R18_ = v0; + samus_x_subpos = -1; + return 1; + } +} + +uint8 BlockColl_Vert_SolidShootGrappleBlock(void) { // 0x948F82 + int16 v0; + int16 v2; + + R20_ = 0; + if ((R18_ & 0x8000u) != 0) { + v2 = samus_y_radius + (R32 | 0xF) + 1 - samus_y_pos; + if (v2 >= 0) + v2 = 0; + R18_ = v2; + samus_y_subpos = 0; + return 1; + } else { + v0 = (R32 & 0xFFF0) - samus_y_radius - samus_y_pos; + if (v0 < 0) + v0 = 0; + R18_ = v0; + samus_y_subpos = -1; + return 1; + } +} + +uint8 BlockColl_Horiz_Slope(void) { // 0x948FBB + uint16 v0 = BTS[cur_block_index] & 0x1F; + if (v0 < 5u) + return BlockColl_Horiz_Slope_Square(v0, cur_block_index); + current_slope_bts = BTS[cur_block_index]; + return BlockColl_Horiz_Slope_NonSquare(); +} + +uint8 BlockColl_Vert_Slope(void) { // 0x948FDA + uint16 v0 = BTS[cur_block_index] & 0x1F; + if (v0 < 5u) + return BlockColl_Vert_Slope_Square(v0, cur_block_index); + current_slope_bts = *(uint16 *)&BTS[cur_block_index]; + return BlockColl_Vert_Slope_NonSquare(cur_block_index); +} + +uint8 ClearCarry_5(void) { // 0x949018 + return 0; +} + +uint8 BlockColl_Vert_SpikeAir(void) { // 0x94901A + return 0; +} + +void SetCarry_Spikeblk(void) { +} + +static Func_V *const kBlockColl_SpikeBlock[16] = { // 0x94904B + BlockColl_SpikeBlock_BTS0, + BlockColl_SpikeBlock_BTS1, + SetCarry_Spikeblk, + BlockColl_SpikeBlock_BTS3, + SetCarry_Spikeblk, + SetCarry_Spikeblk, + SetCarry_Spikeblk, + SetCarry_Spikeblk, + SetCarry_Spikeblk, + SetCarry_Spikeblk, + SetCarry_Spikeblk, + SetCarry_Spikeblk, + SetCarry_Spikeblk, + SetCarry_Spikeblk, + SetCarry_Spikeblk, + SetCarry_Spikeblk, +}; + +uint8 BlockColl_Horiz_SpikeBlock(void) { + kBlockColl_SpikeBlock[(uint16)((2 * *(uint16 *)&BTS[cur_block_index]) & 0x1FF) >> 1](); + return BlockColl_Horiz_SolidShootGrappleBlock(); +} + +uint8 BlockColl_Vert_SpikeBlock(void) { // 0x94905D + kBlockColl_SpikeBlock[(uint16)((2 * *(uint16 *)&BTS[cur_block_index]) & 0x1FF) >> 1](); + return BlockColl_Vert_SolidShootGrappleBlock(); +} + +uint8 BlockColl_Horiz_SpecialAir(void) { // 0x94906F + int16 v0; + + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) != 0) { + R34 = off_9492D9[area_index]; + uint8 *v2 = RomPtr_94(R34); + return SpawnPLM(*(uint16 *)&v2[(uint16)(2 * (v0 & 0x7F))]) & 1; + } else { + SpawnPLM(kPlmHeaderDefPtrs[v0]); + return 0; + } +} + +uint8 BlockColl_Vert_SpecialAir(void) { // 0x94909D + int16 v0; + + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) != 0) { + R34 = off_9492D9[area_index]; + uint8 *v2 = RomPtr_94(R34); + return SpawnPLM(*(uint16 *)&v2[(uint16)(2 * (v0 & 0x7F))]) & 1; + } else { + SpawnPLM(kPlmHeaderDefPtrs[v0]); + return 0; + } +} + +uint8 BlockColl_Horiz_SpecialBlock(void) { // 0x9490CB + int16 v0; + + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) != 0) { + R34 = off_9492E9[area_index]; + uint8 *v3 = RomPtr_94(R34); + uint8 v4 = SpawnPLM(*(uint16 *)&v3[(uint16)(2 * (v0 & 0x7F))]) & 1; + if (v4) + return BlockColl_Horiz_SolidShootGrappleBlock(); + return v4; + } else { + uint8 v1 = SpawnPLM(kPlmHeaderDefPtrs[v0]) & 1; + if (v1 & 1) + return BlockColl_Horiz_SolidShootGrappleBlock(); + return v1; + } +} + +uint8 BlockColl_Vert_SpecialBlock(void) { // 0x949102 + int16 v0; + + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) != 0) { + R34 = off_9492E9[area_index]; + uint8 *v3 = RomPtr_94(R34); + uint8 v4 = SpawnPLM(*(uint16 *)&v3[(uint16)(2 * (v0 & 0x7F))]) & 1; + if (v4) + return BlockColl_Vert_SolidShootGrappleBlock(); + return v4; + } else { + uint8 v1 = SpawnPLM(kPlmHeaderDefPtrs[v0]) & 1; + if (v1) + return BlockColl_Vert_SolidShootGrappleBlock(); + return v1; + } +} + +#define off_94936B ((uint16*)RomPtr(0x94936b)) + +uint8 BlockColl_Horiz_BombableAir(void) { // 0x9492F9 + int16 v0; + + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) == 0) + SpawnPLM(off_94936B[v0]); + return 0; +} + +uint8 BlockColl_Vert_BombableAir(void) { // 0x949313 + int16 v0; + + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) == 0) + SpawnPLM(off_94936B[v0]); + return 0; +} + +uint8 BlockColl_Horiz_BombBlock(void) { // 0x94932D + int16 v0; + + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) != 0) + return BlockColl_Horiz_SolidShootGrappleBlock(); + uint8 v1 = SpawnPLM(off_94936B[v0]) & 1; + if (v1) + return BlockColl_Horiz_SolidShootGrappleBlock(); + else + return v1; +} + +uint8 BlockColl_Vert_BombBlock(void) { // 0x94934C + int16 v0; + + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) != 0) + return BlockColl_Vert_SolidShootGrappleBlock(); + uint8 v1 = SpawnPLM(off_94936B[v0]) & 1; + if (v1) + return BlockColl_Vert_SolidShootGrappleBlock(); + else + return v1; +} + +uint8 BlockColl_Horiz_Door(void) { // 0x94938B + door_transition_function = FUNC16(DoorTransitionFunction_HandleElevator); + door_bts = BTS[cur_block_index]; + uint16 v0 = *(uint16 *)RomPtr_8F(door_list_pointer + 2 * ((uint8)door_bts & 0x7Fu)); + if ((get_DoorDef(v0)->room_definition_ptr & 0x8000u) == 0) { + if (samus_pose < kGameState_9_HitDoorBlock) + elevator_flags = 1; + return BlockColl_Horiz_SolidShootGrappleBlock(); + } else { + door_def_ptr = v0; + game_state = kGameState_9_HitDoorBlock; + return 0; + } +} + +uint8 BlockColl_Vert_Door(void) { // 0x9493CE + door_transition_function = FUNC16(DoorTransitionFunction_HandleElevator); + door_bts = BTS[cur_block_index]; + uint16 v0 = *(uint16 *)RomPtr_8F(door_list_pointer + 2 * (door_bts & 0x7Fu)); + if (*(int16 *)RomPtr_83(v0) >= 0) { + if (samus_pose < kPose_09_MoveR_NoAim) + elevator_flags = 1; + return BlockColl_Vert_SolidShootGrappleBlock(); + } else { + door_def_ptr = v0; + game_state = kPose_09_MoveR_NoAim; + return 0; + } +} + +uint8 BlockReact_HorizExt(void) { // 0x949411 + int16 v0; + + LOBYTE(v0) = BTS[cur_block_index]; + if ((uint8)v0) { + if ((BTS[cur_block_index] & 0x80) != 0) + v0 |= 0xFF00u; + else + v0 = (uint8)v0; + cur_block_index += v0; + return 0xff; // special + } + return 0; +} + +uint8 BlockReact_VertExt(void) { // 0x949447 + uint16 v0; + if (BTS[cur_block_index]) { + if ((BTS[cur_block_index] & 0x80) != 0) { + temp_collision_DD4 = BTS[cur_block_index] | 0xFF00; + v0 = cur_block_index; + do { + v0 -= room_width_in_blocks; + ++temp_collision_DD4; + } while (temp_collision_DD4); + } else { + temp_collision_DD4 = BTS[cur_block_index]; + v0 = cur_block_index; + do { + v0 += room_width_in_blocks; + --temp_collision_DD4; + } while (temp_collision_DD4); + } + cur_block_index = v0; + return 0xff; // special + } + return 0; +} + +void Samus_GetYposSpan(void) { // 0x949495 + R26_ = (samus_y_pos - samus_y_radius) & 0xFFF0; + R26_ = (uint16)(samus_y_radius + samus_y_pos - 1 - R26_) >> 4; + R28_ = R26_; +} + +void Samus_GetXposSpan(void) { // 0x9494B5 + R26_ = (samus_x_pos - samus_x_radius) & 0xFFF0; + R26_ = (uint16)(samus_x_radius + samus_x_pos - 1 - R26_) >> 4; + R28_ = R26_; +} + +static Func_U8 *const kBlockColl_Horiz_CheckColl[16] = { // 0x949515 + ClearCarry_4, + BlockColl_Horiz_Slope, + ClearCarry_5, + BlockColl_Horiz_SpecialAir, + ClearCarry_4, + BlockReact_HorizExt, + ClearCarry_4, + BlockColl_Horiz_BombableAir, + BlockColl_Horiz_SolidShootGrappleBlock, + BlockColl_Horiz_Door, + BlockColl_Horiz_SpikeBlock, + BlockColl_Horiz_SpecialBlock, + BlockColl_Horiz_SolidShootGrappleBlock, + BlockReact_VertExt, + BlockColl_Horiz_SolidShootGrappleBlock, + BlockColl_Horiz_BombBlock, +}; +static Func_U8 *const kBlockColl_Vert_CheckColl[16] = { + ClearCarry_4, + BlockColl_Vert_Slope, + BlockColl_Vert_SpikeAir, + BlockColl_Vert_SpecialAir, + ClearCarry_4, + BlockReact_HorizExt, + ClearCarry_4, + BlockColl_Vert_BombableAir, + BlockColl_Vert_SolidShootGrappleBlock, + BlockColl_Vert_Door, + BlockColl_Vert_SpikeBlock, + BlockColl_Vert_SpecialBlock, + BlockColl_Vert_SolidShootGrappleBlock, + BlockReact_VertExt, + BlockColl_Vert_SolidShootGrappleBlock, + BlockColl_Vert_BombBlock, +}; + +uint8 BlockColl_Horiz_CheckColl(uint16 k) { + uint8 rv; + cur_block_index = k >> 1; + do { + rv = kBlockColl_Horiz_CheckColl[(level_data[cur_block_index] & 0xF000) >> 12](); + } while (rv & 0x80); + return rv; +} + +uint8 BlockColl_Vert_CheckColl(uint16 k) { // 0x94952C + uint8 rv; + cur_block_index = k >> 1; + do { + rv = kBlockColl_Vert_CheckColl[(level_data[cur_block_index] & 0xF000) >> 12](); + } while (rv & 0x80); + return rv; +} + +uint8 BlockColl_Handle_Horiz(void) { // 0x949543 + Samus_GetYposSpan(); + uint16 prod = Mult8x8((uint16)(samus_y_pos - samus_y_radius) >> 4, room_width_in_blocks); + uint16 v1; + R22_ = R20_ + samus_x_subpos; + uint16 v0 = R18_ + __CFADD__uint16(R20_, samus_x_subpos) + samus_x_pos; + R24_ = v0; + if ((R18_ & 0x8000u) == 0) + v1 = samus_x_radius + v0 - 1; + else + v1 = v0 - samus_x_radius; + R32 = v1; + uint16 v2 = 2 * (prod + (v1 >> 4)); + while (!(BlockColl_Horiz_CheckColl(v2) & 1)) { + v2 += room_width_in_blocks + room_width_in_blocks; + if ((--R26_ & 0x8000u) != 0) + return 0; + } + return 1; +} + +uint8 BlockColl_Handle_Vert_LeftToRight(void) { // 0x94959E + int16 v2; + + Samus_GetXposSpan(); + R22_ = R20_ + samus_y_subpos; + uint16 v0 = R18_ + __CFADD__uint16(R20_, samus_y_subpos) + samus_y_pos, v1; + R24_ = v0; + if ((R18_ & 0x8000u) == 0) + v1 = samus_y_radius + v0 - 1; + else + v1 = v0 - samus_y_radius; + R32 = v1; + uint16 prod = Mult8x8(v1 >> 4, room_width_in_blocks); + v2 = (uint16)(samus_x_pos - samus_x_radius) >> 4; + cur_block_index = prod + v2; + for (int i = 2 * cur_block_index; !(BlockColl_Vert_CheckColl(i) & 1); i += 2) { + if ((--R26_ & 0x8000u) != 0) + return 0; + } + return 1; +} + +uint8 BlockColl_Handle_Vert_RightToLeft(void) { // 0x9495F5 + int16 v2; + + Samus_GetXposSpan(); + R26_ = 0; + R22_ = R20_ + samus_y_subpos; + uint16 v0 = R18_ + __CFADD__uint16(R20_, samus_y_subpos) + samus_y_pos, v1; + R24_ = v0; + if ((R18_ & 0x8000u) == 0) + v1 = samus_y_radius + v0 - 1; + else + v1 = v0 - samus_y_radius; + R32 = v1; + uint16 prod = Mult8x8(v1 >> 4, room_width_in_blocks); + v2 = (uint16)(samus_x_radius + samus_x_pos - 1) >> 4; + cur_block_index = prod + v2; + for (int i = 2 * cur_block_index; !(BlockColl_Vert_CheckColl(i) & 1); i -= 2) { + if (R28_ < ++R26_) + return 0; + } + return 1; +} + +void AbsoluteValueOfInt32(void) { // 0x949653 + if ((R18_ & 0x8000u) != 0) { + R18_ = ~R18_; + bool v0 = R20_ == 0; + R20_ = -R20_; + if (v0) + ++R18_; + } +} + +void AbsoluteValueOfInt32_0(void) { // 0x949669 + if ((R18_ & 0x8000u) != 0) { + R18_ = ~R18_; + bool v0 = R20_ == 0; + R20_ = -R20_; + if (v0) + ++R18_; + } +} + +uint8 WallJumpBlockCollDetect(void) { // 0x94967F + samus_collision_direction |= 0xFu; + flag_samus_in_quicksand = 0; + if (BlockColl_Handle_Horiz()) { + AbsoluteValueOfInt32(); + samus_collision_flag = 1; + return 1; + } else { + AbsoluteValueOfInt32(); + samus_collision_flag = 0; + return 0; + } +} + +uint8 Samus_CollDetectChangedPose(void) { // 0x9496AB + if ((abs16(R18_) & 0xFFF8) == 0) + return CollDetectDueToPoseChange_SingleBlock(); + uint16 v3 = R18_; + uint16 v2 = R20_; + R18_ = R18_ & 0xFFF0 | 8; + R20_ = 0; + uint8 v1 = CollDetectDueToPoseChange_SingleBlock(); + if (v1) + return v1; + R20_ = v2; + R18_ = v3; + return CollDetectDueToPoseChange_SingleBlock(); +} + +uint8 CollDetectDueToPoseChange_SingleBlock(void) { // 0x9496E3 + char v0; // cf + + samus_collision_direction |= 0xFu; + flag_samus_in_quicksand = 0; + if (!(nmi_frame_counter_word & 1)) { + v0 = BlockColl_Handle_Vert_LeftToRight(); + if (!v0) + goto LABEL_6; + if (v0) { +LABEL_5: + AbsoluteValueOfInt32_0(); + samus_collision_flag = 1; + return 1; + } + } + if (BlockColl_Handle_Vert_RightToLeft()) + goto LABEL_5; +LABEL_6: + AbsoluteValueOfInt32_0(); + samus_collision_flag = 0; + return 0; +} + +uint8 Samus_MoveRight_NoSolidColl(void) { // 0x94971E + if (__PAIR32__(R20_, R18_) && (flag_samus_in_quicksand = 0, BlockColl_Handle_Horiz())) { + bool v0 = __CFADD__uint16(R20_, samus_x_subpos); + samus_x_subpos += R20_; + samus_x_pos += R18_ + v0; + samus_collision_flag = 1; + return 1; + } else { + bool v0 = __CFADD__uint16(R20_, samus_x_subpos); + samus_x_subpos += R20_; + samus_x_pos += R18_ + v0; + samus_collision_flag = 0; + return 0; + } +} + +uint8 Samus_MoveDown_NoSolidColl(void) { // 0x949763 + if (__PAIR32__(R20_, R18_)) { + samus_pos_adjusted_by_slope_flag = 0; + flag_samus_in_quicksand = 0; + if (!(nmi_frame_counter_word & 1)) { + bool v0; + v0 = BlockColl_Handle_Vert_LeftToRight(); + if (!v0) + goto LABEL_8; + if (v0) { +LABEL_6: + v0 = __CFADD__uint16(R20_, samus_y_subpos); + samus_y_subpos += R20_; + samus_y_pos += R18_ + v0; +LABEL_7: + samus_collision_flag = 1; + return 1; + } + } + if (BlockColl_Handle_Vert_RightToLeft()) + goto LABEL_6; + } +LABEL_8:; + bool v0 = __CFADD__uint16(R20_, samus_y_subpos); + samus_y_subpos += R20_; + samus_y_pos += R18_ + v0; + if (flag_samus_in_quicksand) + goto LABEL_7; + samus_collision_flag = 0; + return 0; +} + +uint8 BlockInsideReact_Slope(void) { // 0x9497BF + return 0; +} + +uint8 BlockInsideReact_ShootableAir(void) { // 0x9497D0 + samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; + return 0; +} + +void ClearCarry_8(void) { // 0x9497D8 +} + +uint8 MaybeUnused_sub_9497DA(void) { // 0x9497DA + ++samus_periodic_damage; + samus_x_extra_run_speed = 0; + samus_x_base_speed = 0; + return 0; +} + +uint8 MaybeUnused_sub_9497F2(void) { // 0x9497F2 + if (samus_y_dir == 1) { + samus_y_subaccel = 0; + samus_y_accel = 2; + } else { + samus_y_speed = 0; + samus_y_subspeed = 0; + } + return 0; +} + +uint8 ClearCarry_6(void) { // 0x949810 + return 0; +} + +uint8 ClearCarry_7(void) { // 0x949812 + return 0; +} + +uint8 BlockInsideReact_SpikeAir_BTS1(void) { // 0x949814 + ++samus_periodic_damage; + samus_x_speed_table_pointer = addr_kSamusSpeedTable_LavaAcid_X; + samus_y_subaccel = 0; + samus_y_accel = 0; + if (samus_y_dir == 1) { + samus_y_subaccel = 0; + samus_y_accel = 5; + } else { + samus_y_speed = 0; + samus_y_subspeed = 0; + extra_samus_y_subdisplacement = 0; + extra_samus_y_displacement = 2; + } + return 0; +} + +void nullsub_165(void) { // 0x9497D7 +} + +void BlockInsideReact_SpikeAir_BTS2(void) { // 0x949866 + if (!samus_contact_damage_index && !samus_invincibility_timer) { + samus_invincibility_timer = 60; + samus_knockback_timer = 10; + samus_periodic_damage += 16; + knockback_x_dir = ((*(uint16 *)&samus_pose_x_dir ^ 0xC) & 8) != 0; + } + samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; +} + +static Func_V *const kBlockInsideReact_SpikeAir[16] = { // 0x9498CC + ClearCarry_8, + ClearCarry_8, + BlockInsideReact_SpikeAir_BTS2, + nullsub_165, + nullsub_165, + nullsub_165, + nullsub_165, + nullsub_165, + nullsub_165, + nullsub_165, + nullsub_165, + nullsub_165, + nullsub_165, + nullsub_165, + nullsub_165, + nullsub_165, +}; + +uint8 BlockInsideReact_SpikeAir(void) { + kBlockInsideReact_SpikeAir[BTS[cur_block_index]](); + return 0; +} + +uint8 BlockInsideReact_Special_(void) { // 0x9498DC + samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; + return 0; +} + +void BlockInsideReact_SpecialAir_Default(void) { // 0x9498E3 + samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; +} + +void BlockInsideReact_SpecialAir_8(void) { // 0x9498EA + if ((area_index != 3 || CheckBossBitForCurArea(1u) & 1) && !samus_y_speed) { + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = 2; + } + samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; +} + +void BlockInsideReact_SpecialAir_9(void) { // 0x949910 + if ((area_index != 3 || CheckBossBitForCurArea(1u) & 1) && !samus_y_speed) { + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = -2; + } + samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; +} + +void BlockInsideReact_SpecialAir_10(void) { // 0x949936 + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = 2; + samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; +} + +void BlockInsideReact_SpecialAir_11(void) { // 0x949946 + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = -2; + samus_x_speed_table_pointer = addr_kSamusSpeedTable_Normal_X__plus__12; +} + +void BlockInsideReact_SpecialAir_70(void) { // 0x949956 + if (inside_block_reaction_samus_point == 1) + SpawnPLM(addr_kPlmHeader_B6FF); +} + +static const uint16 g_off_949B06[8] = { // 0x949B16 + 0x9a06, + 0x9a26, + 0x9a46, + 0x9a66, + 0x9a86, + 0x9aa6, + 0x9ac6, + 0x9ae6, +}; + +static Func_V *const off_949966[80] = { + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_8, + BlockInsideReact_SpecialAir_9, + BlockInsideReact_SpecialAir_10, + BlockInsideReact_SpecialAir_11, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_70, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, + BlockInsideReact_SpecialAir_Default, +}; + +uint8 BlockInsideReact_SpecialAir(void) { + int16 v0; + + v0 = BTS[cur_block_index] << 8; + if (v0 < 0) { + R34 = g_off_949B06[area_index]; + uint8 *v3 = RomPtr_94(R34); + SpawnPLM(*(uint16 *)&v3[(2 * (HIBYTE(v0) & 0x7F))]); + } else { + off_949966[v0 >> 8](); + } + return 0; +} + +void BlockInsideDetection(void) { // 0x949B60 + static Func_U8 *const kSamus_BlockInsideDetection[16] = { + BlockInsideReact_ShootableAir, + BlockInsideReact_Slope, + BlockInsideReact_SpikeAir, + BlockInsideReact_SpecialAir, + BlockInsideReact_ShootableAir, + BlockReact_HorizExt, + BlockInsideReact_ShootableAir, + BlockInsideReact_ShootableAir, + BlockInsideReact_Special_, + BlockInsideReact_Special_, + BlockInsideReact_Special_, + BlockInsideReact_Special_, + BlockInsideReact_Special_, + BlockReact_VertExt, + BlockInsideReact_Special_, + BlockInsideReact_Special_, + }; + + *(uint16 *)&samus_x_decel_mult = 0; + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = 0; + extra_samus_y_subdisplacement = 0; + extra_samus_y_displacement = 0; + inside_block_reaction_samus_point = 0; + R26_ = samus_x_pos; + samus_bottom_boundary_position = samus_y_radius + samus_y_pos - 1; + R28_ = samus_y_radius + samus_y_pos - 1; + g_word_7E001E = 0; + R32 = 0; + CalculateBlockAt(); + uint8 rv; + do { + rv = kSamus_BlockInsideDetection[(HIBYTE(level_data[cur_block_index]) & 0xF0) >> 4](); + } while (rv & 0x80); + inside_block_reaction_samus_point = 1; + if (((samus_bottom_boundary_position ^ samus_y_pos) & 0xFFF0) != 0) { + R26_ = samus_x_pos; + R28_ = samus_y_pos; + g_word_7E001E = 0; + R32 = 0; + CalculateBlockAt(); + do { + rv = kSamus_BlockInsideDetection[(HIBYTE(level_data[cur_block_index]) & 0xF0) >> 4](); + } while (rv & 0x80); + } + inside_block_reaction_samus_point = 2; + if (((samus_bottom_boundary_position ^ (uint16)(samus_y_pos - samus_y_radius)) & 0xFFF0) != 0 + && ((samus_y_pos ^ (samus_bottom_boundary_position ^ (uint16)(samus_y_pos - samus_y_radius)) & 0xFFF0) & 0xFFF0) != 0) { + R26_ = samus_x_pos; + R28_ = samus_y_pos - samus_y_radius; + g_word_7E001E = 0; + R32 = 0; + CalculateBlockAt(); + do { + rv = kSamus_BlockInsideDetection[(HIBYTE(level_data[cur_block_index]) & 0xF0) >> 4](); + } while (rv & 0x80); + } +} + +void CalculateBlockAt(void) { // 0x949C1D + int16 v0; + int16 v1; + + v0 = g_word_7E001E + R26_; + if ((int16)(g_word_7E001E + R26_) >= 0 + && sign16(v0 - 4096) + && (temp_collision_DD4 = (uint16)(v0 & 0xFFF0) >> 4, + v1 = R32 + R28_, + (int16)(R32 + R28_) >= 0) + && sign16(v1 - 4096)) { + uint16 RegWord = (uint16)(v1 & 0xFFF0) >> 4; + RegWord = Mult8x8(RegWord, room_width_in_blocks); + cur_block_index = temp_collision_DD4 + RegWord; + } else { + cur_block_index = -1; + } +} + +static const uint8 kBlockFunc_9C73_Tab0[36] = { // 0x949C73 + 3, 20, 0, + 10, 40, 1, + 5, 30, 0, + 10, 40, 1, + 20, 80, 0, + 20, 80, 1, + 20, 80, 0, + 20, 80, 1, + 30, 100, 0, + 30, 100, 1, + 30, 100, 0, + 30, 100, 1, +}; +static const int8 kBlockFunc_9C73_Tab1[18] = { + 0, 0, + 10, 0, + 50, 0, + 50, 3, + 0, -1, + 10, 2, + 0, -1, + 0, -1, + 0, -1, +}; + +void BlockFunc_9C73(uint16 v0) { + + int v1 = v0 >> 1; + if ((projectile_type[v1] & 0xF00) != 0) { + temp_collision_DD2 = kBlockFunc_9C73_Tab1[(uint16)(2 * (HIBYTE(projectile_type[v1]) & 0xF) + 1)]; + } else { + R18_ = projectile_type[v1] & 0xF; + temp_collision_DD2 = kBlockFunc_9C73_Tab0[(uint16)(R18_ + 2 * R18_ + 2)]; + } +} + +void BombOrPowerBomb_Func1(uint16 v0) { // 0x949CAC + int16 v2; + int16 v3; + + BlockFunc_9C73(v0); + int v1 = v0 >> 1; + v2 = projectile_x_pos[v1]; + if (v2 >= 0) { + R26_ = projectile_x_pos[v1]; + if ((int16)(HIBYTE(v2) - room_width_in_scrolls) < 0) { + v3 = projectile_y_pos[v1]; + if (v3 >= 0) { + R28_ = projectile_y_pos[v1]; + if ((int16)(HIBYTE(v3) - room_height_in_scrolls) < 0) { + g_word_7E001E = 0; + R32 = 0; + cur_block_index = 0; + CalculateBlockAt(); + if (temp_collision_DD2 == 2) + BlockColl_BombExplosion(v0); + else + BlockFunc_A06A(v0); + } + } + } + } +} + +void BlockColl_BombExplosion(uint16 k) { // 0x949CF4 + int16 v2; + + int v1 = k >> 1; + if (!projectile_variables[v1]) { + v2 = projectile_type[v1]; + if ((v2 & 1) == 0) { + projectile_type[v1] = v2 | 1; + if (cur_block_index != 0xFFFF) { + uint16 v3 = 2 * cur_block_index; + BlockBombedReact(2 * cur_block_index); + uint16 idx = BlockColl_GetBlockIndexAbove(v3); + BlockBombedReact(idx); + uint16 idx2 = BlockColl_GetBlockIndexRight(idx); + BlockBombedReact(idx2); + idx = BlockColl_GetBlockIndexLeft(idx2); + BlockBombedReact(idx); + idx = BlockColl_GetBlockIndexBelow(idx); + BlockBombedReact(idx); + } + } + } +} + +uint16 BlockColl_GetBlockIndexAbove(uint16 k) { // 0x949D34 + return k - room_width_in_blocks - room_width_in_blocks; +} + +uint16 BlockColl_GetBlockIndexRight(uint16 k) { // 0x949D3E + return room_width_in_blocks + room_width_in_blocks + k + 1 + 1; +} + +uint16 BlockColl_GetBlockIndexLeft(uint16 k) { // 0x949D49 + return k - 4; +} + +uint16 BlockColl_GetBlockIndexBelow(uint16 k) { // 0x949D4E + return room_width_in_blocks + room_width_in_blocks + k + 1 + 1; +} + +uint8 ClearCarry_9(void) { // 0x949D59 + return 0; +} + +uint8 SetCarry_0(void) { // 0x949D5B + return 1; +} + +uint8 sub_949D5D(void) { // 0x949D5D + if ((BTS[cur_block_index] & 0x1Fu) < 5) + return 1; + else + return BlockShotReactVert_Slope_NonSquare() & 1; +} + +uint8 BlockBombedReact_Special(void) { // 0x949D71 + int16 v0; + + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) != 0) { + uint16 *kBlockBombedReact_Region_Plm = (uint16 *)RomPtr_94(0x9e44); + R18_ = kBlockBombedReact_Region_Plm[area_index]; + uint8 *v2 = RomPtr_94(R18_); + SpawnPLM(*(uint16 *)&v2[(uint16)(2 * (v0 & 0x7F))]); + } else { + uint16 *kBlockBombedReact_Special_Plm = (uint16 *)RomPtr_94(0x9dA4); + SpawnPLM(kBlockBombedReact_Special_Plm[v0]); + } + return 1; +} + +uint8 BlockReact_ShootableAir(void) { // 0x949E55 + int16 v0; + uint16 *kBlockShotBombedReactionShootablePlm = (uint16 *)RomPtr_94(0x9ea6); + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) == 0) + SpawnPLM(kBlockShotBombedReactionShootablePlm[v0]); + return 0; +} + +uint8 BlockReact_Shootable(void) { // 0x949E73 + int16 v0; + + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) != 0) { + uint16 *kBlockShotBombGrappleReaction_ShootableBlock_RegionPlm = (uint16 *)RomPtr_94(0x9FC6); + R18_ = kBlockShotBombGrappleReaction_ShootableBlock_RegionPlm[area_index]; + uint8 *v2 = RomPtr_94(R18_); + SpawnPLM(*(uint16 *)&v2[(uint16)(2 * (v0 & 0x7F))]); + } else { + uint16 *kBlockShotBombedReactionShootablePlm = (uint16 *)RomPtr_94(0x9ea6); + SpawnPLM(kBlockShotBombedReactionShootablePlm[v0]); + } + return 1; +} + +uint8 BlockReact_BombableAir(void) { // 0x949FD6 + int16 v0; + + uint16 *kBlockShotBombGrappleReact_BombableBlockPlm = (uint16 *)RomPtr_94(0xA012); + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) == 0) + SpawnPLM(kBlockShotBombGrappleReact_BombableBlockPlm[v0]); + return 0; +} + +uint8 BlockReact_BombableBlock(void) { // 0x949FF4 + int16 v0; + + uint16 *kBlockShotBombGrappleReact_BombableBlockPlm = (uint16 *)RomPtr_94(0xA012); + v0 = BTS[cur_block_index]; + if ((v0 & 0x80) == 0) + SpawnPLM(kBlockShotBombGrappleReact_BombableBlockPlm[v0]); + return 1; +} + +static Func_U8 *const kBlockBombedReact[16] = { // 0x94A052 + ClearCarry_9, + ClearCarry_9, + ClearCarry_9, + ClearCarry_9, + BlockReact_ShootableAir, + BlockReact_HorizExt, + ClearCarry_9, + BlockReact_BombableAir, + SetCarry_0, + SetCarry_0, + SetCarry_0, + BlockBombedReact_Special, + BlockReact_Shootable, + BlockReact_VertExt, + SetCarry_0, + BlockReact_BombableBlock, +}; +void BlockBombedReact(uint16 v0) { + cur_block_index = v0 >> 1; + while (kBlockBombedReact[(level_data[cur_block_index] & 0xF000) >> 12]() & 0x80) {} +} + +void BlockFunc_A06A(uint16 k) { // 0x94A06A + int16 v2; + int16 v3; + + int v1 = k >> 1; + v2 = projectile_variables[v1]; + if (v2) { + if (v2 < 0) + projectile_variables[v1] = 0; + } else { + R18_ = HIBYTE(power_bomb_explosion_radius); + R20_ = (uint16)(HIBYTE(power_bomb_explosion_radius) + + 2 * HIBYTE(power_bomb_explosion_radius)) >> 2; + v3 = power_bomb_explosion_x_pos - HIBYTE(power_bomb_explosion_radius); + if (v3 < 0) + v3 = 0; + R22_ = (uint16)v3 >> 4; + uint16 v4 = (uint16)(R18_ + power_bomb_explosion_x_pos) >> 4; + if (v4 >= room_width_in_blocks) + v4 = room_width_in_blocks - 1; + R24_ = v4; + uint16 v5 = power_bomb_explosion_y_pos - R20_; + if ((int16)(power_bomb_explosion_y_pos - R20_) < 0) + v5 = 0; + R26_ = v5 >> 4; + uint16 v6 = (uint16)(R20_ + power_bomb_explosion_y_pos) >> 4; + if (v6 >= room_height_in_blocks) + v6 = room_height_in_blocks - 1; + R28_ = v6; + uint16 a = R26_ | ((uint8)R22_ << 8); + BlockFunc_A0F4(a); + BlockFunc_A11A(a); + BlockFunc_A0F4(R28_ | ((uint8)R22_ << 8)); + BlockFunc_A11A(R26_ | ((uint8)R24_ << 8)); + } +} + +void BlockFunc_A0F4(uint16 a) { // 0x94A0F4 + int16 v4; + + uint16 RegWord = Mult8x8(a, room_width_in_blocks); + uint16 v3 = 2 * (RegWord + HIBYTE(a)); + v4 = R24_ - R22_; + do { + BlockBombedReact(v3); + v3 += 2; + --v4; + } while (v4 >= 0); +} + + +void BlockFunc_A11A(uint16 a) { // 0x94A11A + int16 v4; + + uint16 RegWord = Mult8x8(a, room_width_in_blocks); + uint16 v3 = 2 * (RegWord + HIBYTE(a)); + v4 = R28_ - R26_; + do { + BlockBombedReact(v3); + v3 += room_width_in_blocks + room_width_in_blocks; + --v4; + } while (v4 >= 0); +} + + +uint8 BlockShotReactHoriz_Slope(void) { // 0x94A147 + if ((BTS[cur_block_index] & 0x1Fu) < 5) + return BlockShotReactVert_Slope_Square(BTS[cur_block_index] & 0x1F, cur_block_index); + else + return BlockShotReactVert_Slope_NonSquare(); +} + +uint8 SetCarry_1(void) { // 0x94A15C + return 1; +} + +uint8 BlockShotReactVert_Slope(void) { // 0x94A15E + if ((BTS[cur_block_index] & 0x1Fu) < 5) + return BlockShotReactHoriz_Slope_Square(BTS[cur_block_index] & 0x1F, cur_block_index); + else + return BlockShotReactHoriz_Slope_NonSquare(); +} + +uint8 SetCarry_2(void) { // 0x94A173 + return 1; +} + +uint8 BlockShotReactHoriz(uint16 k) { // 0x94A1B5 + static Func_U8 *const kBlockShotReactHoriz[16] = { + ClearCarry_9, + BlockShotReactHoriz_Slope, + ClearCarry_9, + ClearCarry_9, + BlockReact_ShootableAir, + BlockReact_HorizExt, + ClearCarry_9, + BlockReact_BombableAir, + SetCarry_0, + SetCarry_0, + SetCarry_0, + SetCarry_0, + BlockReact_Shootable, + BlockReact_VertExt, + SetCarry_0, + BlockReact_BombableBlock, + }; + + uint8 v1 = k >= room_size_in_blocks; + if (k < room_size_in_blocks) { + cur_block_index = k >> 1; + do { + v1 = kBlockShotReactHoriz[(level_data[cur_block_index] & 0xF000) >> 12](); + } while (v1 & 0x80); + if (v1) + --R40; + } + return v1; +} + +uint8 BlockShotReactVert(uint16 k) { // 0x94A1D6 + static Func_U8 *const kBlockShotReactVert[16] = { + ClearCarry_9, + BlockShotReactVert_Slope, + ClearCarry_9, + ClearCarry_9, + BlockReact_ShootableAir, + BlockReact_HorizExt, + ClearCarry_9, + BlockReact_BombableAir, + SetCarry_0, + SetCarry_0, + SetCarry_0, + SetCarry_0, + BlockReact_Shootable, + BlockReact_VertExt, + SetCarry_0, + BlockReact_BombableBlock, + }; + + uint8 v1 = k >= room_size_in_blocks; + if (k < room_size_in_blocks) { + cur_block_index = k >> 1; + do { + v1 = kBlockShotReactVert[(level_data[cur_block_index] & 0xF000) >> 12](); + } while (v1 & 0x80); + if (v1) + --R40; + } + return v1; +} + +void BlockGetSomePos1(uint16 k) { // 0x94A1F7 + int v1 = k >> 1; + R38 = (projectile_y_pos[v1] - projectile_y_radius[v1]) & 0xFFF0; + R38 = (uint16)(projectile_y_radius[v1] + projectile_y_pos[v1] - 1 - R38) >> 4; + R26_ = R38; + R40 = R38; +} + +void BlockGetSomePos2(uint16 k) { // 0x94A219 + int v1 = k >> 1; + R38 = (projectile_x_pos[v1] - projectile_x_radius[v1]) & 0xFFF0; + R38 = (uint16)(projectile_x_radius[v1] + projectile_x_pos[v1] - 1 - R38) >> 4; + R26_ = R38; + R40 = R38; +} + +uint8 BlockCollNoWaveBeamHoriz(uint16 k) { // 0x94A23B + int16 v2; + + g_word_7E001E = 0; + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = projectile_bomb_x_speed[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + BlockGetSomePos1(k); + uint16 prod = Mult8x8((uint16)(projectile_y_pos[v1] - projectile_y_radius[v1]) >> 4, room_width_in_blocks); + uint16 v3 = projectile_bomb_x_subpos[v1]; + bool v4 = __CFADD__uint16(R18_, v3); + uint16 v5 = R18_ + v3; + projectile_bomb_x_subpos[v1] = v5; + R22_ = v5; + uint16 v6 = R20_ + v4 + projectile_x_pos[v1], v7; + projectile_x_pos[v1] = v6; + R24_ = v6; + if ((R20_ & 0x8000u) != 0) + v7 = v6 - projectile_x_radius[v1]; + else + v7 = projectile_x_radius[v1] + v6 - 1; + R28_ = v7; + uint16 v8 = 2 * (prod + (v7 >> 4)); + if (!sign16(R38 - 16) || (int16)(HIBYTE(R28_) - room_width_in_scrolls) >= 0) + return 0; + do { + BlockShotReactHoriz(v8); + v8 += room_width_in_blocks + room_width_in_blocks; + --R38; + } while ((R38 & 0x8000u) == 0); + if ((R40 & 0x8000u) == 0) + return 0; + KillProjectile(k); + return 1; +} + +uint8 BlockCollNoWaveBeamVert(uint16 k) { // 0x94A2CA + int16 v2; + int16 v8; + int16 v9; + + g_word_7E001E = 0; + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = projectile_bomb_y_speed[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + BlockGetSomePos2(k); + uint16 v3 = projectile_bomb_y_subpos[v1]; + bool v4 = __CFADD__uint16(R18_, v3); + uint16 v5 = R18_ + v3; + projectile_bomb_y_subpos[v1] = v5; + R22_ = v5; + uint16 v6 = R20_ + v4 + projectile_y_pos[v1], v7; + projectile_y_pos[v1] = v6; + R24_ = v6; + if ((R20_ & 0x8000u) != 0) + v7 = v6 - projectile_y_radius[v1]; + else + v7 = projectile_y_radius[v1] + v6 - 1; + R28_ = v7; + v8 = (uint16)(projectile_x_pos[v1] - projectile_x_radius[v1]) >> 4; + v9 = 2 * (Mult8x8(v7 >> 4, room_width_in_blocks) + v8); + if (!sign16(R38 - 16) || (int16)(HIBYTE(R28_) - room_height_in_scrolls) >= 0) + return 0; + do { + BlockShotReactVert(v9); + v9 += 2; + --R38; + } while ((R38 & 0x8000u) == 0); + if ((R40 & 0x8000u) == 0) + return 0; + KillProjectile(k); + return 1; +} + +uint8 BlockCollWaveBeamHoriz(uint16 k) { // 0x94A352 + int16 v2; + int16 v8; + char v9; + int16 v10; + + g_word_7E001E = 0; + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = projectile_bomb_x_speed[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + BlockGetSomePos1(k); + uint16 prod = Mult8x8((uint16)(projectile_y_pos[v1] - projectile_y_radius[v1]) >> 4, room_width_in_blocks); + uint16 v3 = projectile_bomb_x_subpos[v1]; + bool v4 = __CFADD__uint16(R18_, v3); + uint16 v5 = R18_ + v3; + projectile_bomb_x_subpos[v1] = v5; + R22_ = v5; + uint16 v6 = R20_ + v4 + projectile_x_pos[v1], v7; + projectile_x_pos[v1] = v6; + R24_ = v6; + if ((R20_ & 0x8000u) != 0) + v7 = v6 - projectile_x_radius[v1]; + else + v7 = projectile_x_radius[v1] + v6 - 1; + R28_ = v7; + v8 = 2 * (prod + (v7 >> 4)); + if (sign16(R38 - 16)) { + v9 = HIBYTE(projectile_y_pos[v1]); + if (v9 >= 0 + && (int16)((uint8)v9 - room_height_in_scrolls) < 0 + && (int16)(HIBYTE(R28_) - room_width_in_scrolls) < 0) { + v10 = v8; + do { + BlockShotReactHoriz(v10); + v10 += room_width_in_blocks + room_width_in_blocks; + --R38; + } while ((R38 & 0x8000u) == 0); + } + } + return 0; +} + +uint8 BlockCollWaveBeamVert(uint16 k) { // 0x94A3E4 + int16 v2; + int16 v8; + int16 v9; + char v10; + int16 v11; + + g_word_7E001E = 0; + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = projectile_bomb_y_speed[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + BlockGetSomePos2(k); + uint16 v3 = projectile_bomb_y_subpos[v1]; + bool v4 = __CFADD__uint16(R18_, v3); + uint16 v5 = R18_ + v3; + projectile_bomb_y_subpos[v1] = v5; + R22_ = v5; + uint16 v6 = R20_ + v4 + projectile_y_pos[v1], v7; + projectile_y_pos[v1] = v6; + R24_ = v6; + if ((R20_ & 0x8000u) != 0) + v7 = v6 - projectile_y_radius[v1]; + else + v7 = projectile_y_radius[v1] + v6 - 1; + R28_ = v7; + uint16 prod = Mult8x8(v7 >> 4, room_width_in_blocks); + v8 = (uint16)(projectile_x_pos[v1] - projectile_x_radius[v1]) >> 4; + v9 = 2 * (prod + v8); + if (sign16(R38 - 16)) { + v10 = HIBYTE(projectile_x_pos[v1]); + if (v10 >= 0 + && (int16)((uint8)v10 - room_width_in_scrolls) < 0 + && (int16)(HIBYTE(R28_) - room_height_in_scrolls) < 0) { + v11 = v9; + do { + BlockShotReactVert(v11); + v11 += 2; + --R38; + } while ((R38 & 0x8000u) == 0); + } + } + return 0; +} + +uint8 BlockCollMissileHoriz(uint16 k) { // 0x94A46F + int16 v2; + + g_word_7E001E = 1; + R38 = 0; + R26_ = 0; + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = projectile_bomb_x_speed[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + uint16 prod = Mult8x8(projectile_y_pos[v1] >> 4, room_width_in_blocks); + uint16 v3 = projectile_bomb_x_subpos[v1]; + bool v4 = __CFADD__uint16(R18_, v3); + uint16 v5 = R18_ + v3; + projectile_bomb_x_subpos[v1] = v5; + R22_ = v5; + uint16 v6 = R20_ + v4 + projectile_x_pos[v1]; + projectile_x_pos[v1] = v6; + R24_ = v6; + R28_ = v6; + uint16 v7 = 2 * (prod + (v6 >> 4)); + if ((int16)(HIBYTE(R24_) - room_width_in_scrolls) >= 0 || !(BlockShotReactHoriz(v7) & 1)) + return 0; + KillProjectile(k); + return 1; +} + +uint8 BlockCollMissileVert(uint16 k) { // 0x94A4D9 + int16 v2; + int16 v7; + + g_word_7E001E = 1; + R38 = 0; + R26_ = 0; + R18_ = 0; + R20_ = 0; + int v1 = k >> 1; + v2 = projectile_bomb_y_speed[v1]; + if (v2 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v2; + uint16 v3 = projectile_bomb_y_subpos[v1]; + bool v4 = __CFADD__uint16(R18_, v3); + uint16 v5 = R18_ + v3; + projectile_bomb_y_subpos[v1] = v5; + R22_ = v5; + uint16 v6 = R20_ + v4 + projectile_y_pos[v1]; + projectile_y_pos[v1] = v6; + R24_ = v6; + R28_ = v6; + uint16 prod = Mult8x8(v6 >> 4, room_width_in_blocks); + v7 = projectile_x_pos[v1] >> 4; + uint16 v8 = 2 * (prod + v7); + if ((int16)(HIBYTE(R24_) - room_height_in_scrolls) >= 0 || !(BlockShotReactVert(v8) & 1)) + return 0; + KillProjectile(k); + return 1; +} + +uint8 BlockShotReactVert_Slope_NonSquare(void) { // 0x94A543 + int16 v2; + + uint16 v0 = cur_block_index; + uint16 v1 = projectile_index; + uint16 div = SnesDivide(cur_block_index, room_width_in_blocks); + v2 = projectile_y_pos[v1 >> 1] >> 4; + if (v2 == div) + return BlockShotReact_Slope_NonSquare(v1, v0) & 1; + else + return 0; +} + +uint8 BlockShotReactHoriz_Slope_NonSquare(void) { // 0x94A569 + int16 v2; + + uint16 v0 = cur_block_index; + uint16 v1 = projectile_index; + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + v2 = projectile_x_pos[v1 >> 1] >> 4; + if (v2 == mod) + return BlockShotReact_Slope_NonSquare(v1, v0) & 1; + else + return 0; +} + +uint8 BlockShotReact_Slope_NonSquare(uint16 j, uint16 k) { // 0x94A58F + int16 v3; + int16 v5; + uint16 v2; + + temp_collision_DD6 = 16 * (BTS[k] & 0x1F); + if ((BTS[k] & 0x40) != 0) + v2 = projectile_x_pos[j >> 1] ^ 0xF; + else + v2 = projectile_x_pos[j >> 1]; + uint16 v6 = temp_collision_DD6 + (v2 & 0xF); + if (!(BTS[k] & 0x80)) { + temp_collision_DD4 = projectile_y_pos[j >> 1] & 0xF; + v5 = kAlignYPos_Tab0[v6] & 0x1F; + if ((int16)(v5 - temp_collision_DD4) < 0 || v5 == temp_collision_DD4) { + R38 = 0; + R40 = 0; + return 1; + } else { + return 0; + } + } else { + temp_collision_DD4 = projectile_y_pos[j >> 1] & 0xF ^ 0xF; + v3 = kAlignYPos_Tab0[v6] & 0x1F; + if ((int16)(v3 - temp_collision_DD4) < 0 || v3 == temp_collision_DD4) { + R38 = 0; + R40 = 0; + return 1; + } else { + return 0; + } + } +} + +uint8 BlockCollSpreadBomb(uint16 k) { // 0x94A621 + static Func_U8 *const kBlockCollSpreadBomb[16] = { + ClearCarry_9, + sub_949D5D, + ClearCarry_9, + ClearCarry_9, + SetCarry_0, + BlockReact_HorizExt, + ClearCarry_9, + ClearCarry_9, + SetCarry_0, + SetCarry_0, + SetCarry_0, + SetCarry_0, + SetCarry_0, + BlockReact_VertExt, + SetCarry_0, + SetCarry_0, + }; + + + int v1 = k >> 1; + R26_ = projectile_x_pos[v1]; + R28_ = projectile_y_pos[v1]; + g_word_7E001E = 0; + R32 = 0; + cur_block_index = 0; + CalculateBlockAt(); + if (!projectile_variables[v1]) { + BlockColl_BombExplosion(k); + return 0; + } + if (cur_block_index == 0xFFFF) + return 1; + uint8 rv; + do { + rv = kBlockCollSpreadBomb[(level_data[cur_block_index] & 0xF000) >> 12](); + } while (rv & 0x80); + return rv; +} + +uint8 BlockShotReactVert_Slope_Square(uint16 a, uint16 k) { // 0x94A66A + temp_collision_DD4 = 4 * a; + temp_collision_DD6 = BTS[k] >> 6; + uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R28_ & 8) >> 3)); + if (!g_word_7E001E) { + if (!R26_) { + int v3 = projectile_index >> 1; + if (((projectile_y_pos[v3] - projectile_y_radius[v3]) & 8) != 0 + || !kTab948E54[v2]) { + uint16 v4 = v2 ^ 2; + if (((LOBYTE(projectile_y_radius[v3]) + LOBYTE(projectile_y_pos[v3]) - 1) & 8) == 0 + || !kTab948E54[v4]) { + return 0; + } + } + return 1; + } + if (R38) { + if (R38 == R26_ + && ((projectile_y_pos[projectile_index >> 1] - projectile_y_radius[projectile_index >> 1]) & 8) != 0) { + return kTab948E54[v2 ^ 2] != 0; + } + } else if (((LOBYTE(projectile_y_radius[projectile_index >> 1]) + LOBYTE(projectile_y_pos[projectile_index >> 1]) - 1) & 8) == 0) { + return kTab948E54[v2] != 0; + } + if (kTab948E54[v2] != 0) + return 1; + return kTab948E54[v2 ^ 2] != 0; + } + if ((projectile_y_pos[projectile_index >> 1] & 8) != 0) + v2 ^= 2u; + return kTab948E54[v2] != 0; +} + + +uint8 BlockShotReactHoriz_Slope_Square(uint16 a, uint16 k) { // 0x94A71A + temp_collision_DD4 = 4 * a; + temp_collision_DD6 = BTS[k] >> 6; + uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R28_ & 8) >> 2)); + if (!g_word_7E001E) { + if (!R26_) { + int v3 = projectile_index >> 1; + if (((projectile_x_pos[v3] - projectile_x_radius[v3]) & 8) != 0 + || kTab948E54[v2] == 0) { + uint16 v4 = v2 ^ 1; + if (((LOBYTE(projectile_x_radius[v3]) + LOBYTE(projectile_x_pos[v3]) - 1) & 8) == 0 + || kTab948E54[v4] == 0) { + return 0; + } + } + return 1; + } + if (R38) { + if (R38 == R26_ + && ((projectile_x_pos[projectile_index >> 1] - projectile_x_radius[projectile_index >> 1]) & 8) != 0) { + return kTab948E54[v2 ^ 1] != 0; + } + } else if (((LOBYTE(projectile_x_radius[projectile_index >> 1]) + LOBYTE(projectile_x_pos[projectile_index >> 1]) - 1) & 8) == 0) { + return kTab948E54[v2] != 0; + } + if (kTab948E54[v2] != 0) + return 1; + return kTab948E54[v2 ^ 1] != 0; + } + if ((projectile_x_pos[projectile_index >> 1] & 8) != 0) + v2 ^= 1u; + return kTab948E54[v2] != 0; +} + + +uint8 ClearCarryZero(void) { // 0x94A7C9 + return 0; +} + +uint8 ClearCarrySetZero(void) { // 0x94A7CD + return 1; +} + +uint8 BlockReactGrapple_GrappleBlock(void) { // 0x94A7D1 + static const uint16 kBlockReactGrapple_GrappleBlockPlm[4] = { + 0xd0d8, + 0xd0dc, + 0xd0e0, + 0xd0d8, + }; + + char v0; + + grapple_beam_flags &= ~0x8000u; + v0 = BTS[cur_block_index]; + if (v0 < 0) + return 0; + else + return SpawnPLM(kBlockReactGrapple_GrappleBlockPlm[v0 & 0x7F]); +} + +uint8 BlockReactGrapple_SpikeBlock(void) { // 0x94A7FD + static const uint16 kBlockReactGrapple_SpikeBlockPlm[16] = { + 0xd0e4, + 0xd0e4, + 0xd0e4, + 0xd0e8, + 0xd0e4, + 0xd0e4, + 0xd0e4, + 0xd0e4, + 0xd0e4, + 0xd0e4, + 0xd0e4, + 0xd0e4, + 0xd0e4, + 0xd0e4, + 0xd0e4, + 0xd0e4, + }; + char v0; + + v0 = BTS[cur_block_index]; + if (v0 < 0) + return 0; + else + return SpawnPLM(kBlockReactGrapple_SpikeBlockPlm[v0 & 0x7F]); +} + +uint8 BlockCollGrappleBeam(void) { // 0x94A85B + uint8 result; + + *(uint16 *)((char *)&grapple_beam_tmpD82 + 1) = grapple_beam_extension_x_velocity; + *(uint32 *)&grapple_beam_tmpD82 >>= 2; + if ((grapple_beam_extension_x_velocity & 0x8000u) != 0) + grapple_beam_tmpD84 |= 0xFFC0u; + *(uint16 *)((char *)&grapple_beam_y_quarter_subvel + 1) = grapple_beam_extension_y_velocity; + + *(uint32 *)&grapple_beam_y_quarter_subvel >>= 2; + if ((grapple_beam_extension_y_velocity & 0x8000u) != 0) + grapple_beam_y_quarter_vel |= 0xFFC0u; + grapple_beam_tmpD8A = 4; + while (1) { + uint16 v0 = (__PAIR32__(grapple_beam_tmpD84, grapple_beam_tmpD82) + __PAIR32__(grapple_beam_end_x_offset, grapple_beam_end_x_suboffset)) >> 16; + grapple_beam_end_x_suboffset += grapple_beam_tmpD82; + grapple_beam_end_x_offset = v0; + uint16 v1 = (__PAIR32__(grapple_beam_y_quarter_vel, grapple_beam_y_quarter_subvel) + __PAIR32__(grapple_beam_end_y_offset, grapple_beam_end_y_suboffset)) >> 16; + grapple_beam_end_y_suboffset += grapple_beam_y_quarter_subvel; + grapple_beam_end_y_offset = v1; + grapple_beam_end_x_subpos = grapple_beam_end_x_suboffset + samus_x_subpos; + grapple_beam_end_x_pos = grapple_beam_origin_x_offset + ((__PAIR32__(grapple_beam_end_x_offset, grapple_beam_end_x_suboffset) + + __PAIR32__(samus_x_pos, samus_x_subpos)) >> 16); + grapple_beam_end_y_subpos = grapple_beam_end_y_suboffset + samus_y_subpos; + grapple_beam_end_y_pos = grapple_beam_origin_y_offset + ((__PAIR32__(v1, grapple_beam_end_y_suboffset) + __PAIR32__(samus_y_pos, samus_y_subpos)) >> 16); + result = BlockReactGrapple(); + if ((result & 0x40) != 0 && (result & 1) != 0) + break; + if (!--grapple_beam_tmpD8A) + return result; + } + grapple_beam_end_x_pos = grapple_beam_end_x_pos & 0xFFF0 | 8; + grapple_beam_end_y_pos = grapple_beam_end_y_pos & 0xFFF0 | 8; + return result; +} + +uint8 BlockReactGrapple(void) { // 0x94A91F + int16 v0; + static Func_U8 *const kBlockReactGrapple[16] = { + ClearCarryZero, + ClearCarrySetZero, + ClearCarryZero, + ClearCarryZero, + BlockReact_ShootableAir, + BlockReact_HorizExt, + ClearCarryZero, + BlockReact_BombableAir, + ClearCarrySetZero, + ClearCarrySetZero, + BlockReactGrapple_SpikeBlock, + ClearCarrySetZero, + BlockReact_Shootable, + BlockReact_VertExt, + BlockReactGrapple_GrappleBlock, + BlockReact_BombableBlock, + }; + uint16 prod = Mult8x8(grapple_beam_end_y_pos >> 4, room_width_in_blocks); + v0 = grapple_beam_end_x_pos >> 4; + cur_block_index = prod + v0; + uint8 rv; + do { + rv = kBlockReactGrapple[(level_data[cur_block_index] & 0xF000) >> 12](); + } while (rv & 0x80); + return rv; +} + +const int16 kSinCosTable8bit_Sext[320] = { // 0x94A957 + -256, -255, -255, -255, -254, -254, -253, -252, -251, -249, -248, -246, -244, -243, -241, -238, + -236, -234, -231, -228, -225, -222, -219, -216, -212, -209, -205, -201, -197, -193, -189, -185, + -181, -176, -171, -167, -162, -157, -152, -147, -142, -136, -131, -126, -120, -115, -109, -103, + -97, -92, -86, -80, -74, -68, -62, -56, -49, -43, -37, -31, -25, -18, -12, -6, + 0, 6, 12, 18, 25, 31, 37, 43, 49, 56, 62, 68, 74, 80, 86, 92, + 97, 103, 109, 115, 120, 126, 131, 136, 142, 147, 152, 157, 162, 167, 171, 176, + 181, 185, 189, 193, 197, 201, 205, 209, 212, 216, 219, 222, 225, 228, 231, 234, + 236, 238, 241, 243, 244, 246, 248, 249, 251, 252, 253, 254, 254, 255, 255, 255, + 256, 255, 255, 255, 254, 254, 253, 252, 251, 249, 248, 246, 244, 243, 241, 238, + 236, 234, 231, 228, 225, 222, 219, 216, 212, 209, 205, 201, 197, 193, 189, 185, + 181, 176, 171, 167, 162, 157, 152, 147, 142, 136, 131, 126, 120, 115, 109, 103, + 97, 92, 86, 80, 74, 68, 62, 56, 49, 43, 37, 31, 25, 18, 12, 6, + 0, -6, -12, -18, -25, -31, -37, -43, -49, -56, -62, -68, -74, -80, -86, -92, + -97, -103, -109, -115, -120, -126, -131, -136, -142, -147, -152, -157, -162, -167, -171, -176, + -181, -185, -189, -193, -197, -201, -205, -209, -212, -216, -219, -222, -225, -228, -231, -234, + -236, -238, -241, -243, -244, -246, -248, -249, -251, -252, -253, -254, -254, -255, -255, -255, + -256, -255, -255, -255, -254, -254, -253, -252, -251, -249, -248, -246, -244, -243, -241, -238, + -236, -234, -231, -228, -225, -222, -219, -216, -212, -209, -205, -201, -197, -193, -189, -185, + -181, -176, -171, -167, -162, -157, -152, -147, -142, -136, -131, -126, -120, -115, -109, -103, + -97, -92, -86, -80, -74, -68, -62, -56, -49, -43, -37, -31, -25, -18, -12, -6, +}; + +void BlockFunc_A957(void) { + int16 v5; + int16 v7; + + uint16 v0 = grapple_beam_tmpD82, v2, v3; + if ((grapple_beam_flags & 0x8000u) == 0) { + int v1 = grapple_beam_tmpD82 >> 1; + if ((kSinCosTable8bit_Sext[v1 + 64] & 0x8000u) != 0) + v2 = grapple_beam_end_x_pos & 0xFFF0 | 7; + else + v2 = grapple_beam_end_x_pos & 0xFFF0 | 8; + grapple_beam_end_x_pos = v2; + if ((kSinCosTable8bit_Sext[v1] & 0x8000u) != 0) + v3 = grapple_beam_end_y_pos & 0xFFF0 | 7; + else + v3 = grapple_beam_end_y_pos & 0xFFF0 | 8; + grapple_beam_end_y_pos = v3; + } + WriteReg(WRMPYA, grapple_beam_tmpD84); + int v4 = v0 >> 1; + v5 = kSinCosTable8bit_Sext[v4 + 64]; + uint16 v6, v8; + if (v5 < 0) { + if (v5 == -256) { + v6 = grapple_beam_end_x_pos - grapple_beam_tmpD84; + } else { + uint16 prod = Mult8x8(grapple_beam_tmpD84, -(int8)v5); + v6 = grapple_beam_end_x_pos - (prod >> 8); + } + } else if (v5 == 256) { + v6 = grapple_beam_tmpD84 + grapple_beam_end_x_pos; + } else { + uint16 prod = Mult8x8(grapple_beam_tmpD84, kSinCosTable8bit_Sext[v4 + 64]); + v6 = grapple_beam_end_x_pos + (prod >> 8); + } + grapple_beam_grapple_start_x = v6; + grapple_beam_grapple_start_block_x = (uint8)(v6 >> 4); + v7 = kSinCosTable8bit_Sext[v4]; + if (v7 < 0) { + if (v7 == -256) { + v8 = grapple_beam_end_y_pos - grapple_beam_tmpD84; + } else { + uint16 prod = Mult8x8(grapple_beam_tmpD84, -v7); + v8 = grapple_beam_end_y_pos - (prod >> 8); + } + } else if (v7 == 256) { + v8 = grapple_beam_tmpD84 + grapple_beam_end_y_pos; + } else { + uint16 prod = Mult8x8(grapple_beam_tmpD84, kSinCosTable8bit_Sext[v4]); + v8 = grapple_beam_end_y_pos + (prod >> 8); + } + grapple_beam_grapple_start_y = v8; + grapple_beam_grapple_start_block_y = (uint8)(v8 >> 4); +} + +uint8 BlockReact_AA64(void) { // 0x94AA64 + static Func_U8 *const kBlockReactLut_AB90[16] = { + ClearCarry_10, + SetCarry_3, + BlockReact_AA64_SpikeAir, + ClearCarry_10, + ClearCarry_10, + BlockReact_HorizExt, + ClearCarry_10, + ClearCarry_10, + SetCarry_3, + SetCarry_3, + BlockReact_AA64_SpikeBlock, + SetCarry_3, + SetCarry_3, + BlockReact_VertExt, + SetCarry_3, + SetCarry_3, + }; + + uint16 v0 = grapple_beam_grapple_start_block_x; + uint16 RegWord = Mult8x8(grapple_beam_grapple_start_block_y, room_width_in_blocks); + cur_block_index = RegWord + v0; + uint8 rv; + do { + rv = kBlockReactLut_AB90[(level_data[cur_block_index] & 0xF000) >> 12](); + } while (rv & 0x80); + return rv; +} + +uint8 ClearCarry_10(void) { // 0x94AA9A + return 0; +} + +uint8 SetCarry_3(void) { // 0x94AA9C + return 1; +} + +static const uint16 g_word_94AAD7[16] = { // 0x94AA9E + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; +static const uint16 g_word_94AAF7[16] = { + 0, 0, 0x10, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +uint8 BlockReact_AA64_SpikeAir(void) { + int16 v0; + int16 v2; + + if (!samus_invincibility_timer) { + v0 = *(uint16 *)&BTS[cur_block_index]; + if (v0 >= 0) { + int v1 = v0; + if (g_word_94AAF7[v1] | g_word_94AAD7[v1]) { + v2 = (g_word_94AAD7[v1] + __PAIR32__(samus_periodic_damage, samus_periodic_subdamage)) >> 16; + samus_periodic_subdamage += g_word_94AAD7[v1]; + samus_periodic_damage = g_word_94AAF7[v1] + v2; + samus_invincibility_timer = 60; + samus_knockback_timer = 10; + } + } + } + return 0; +} + +static const uint16 g_word_94AB50[16] = { // 0x94AB17 + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; +static const uint16 g_word_94AB70[16] = { + 60, 16, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +uint8 BlockReact_AA64_SpikeBlock(void) { + int16 v0; + int16 v2; + + if (!samus_invincibility_timer) { + v0 = *(uint16 *)&BTS[cur_block_index]; + if (v0 >= 0) { + int v1 = v0; + if (g_word_94AB70[v1] | g_word_94AB50[v1]) { + v2 = (g_word_94AB50[v1] + __PAIR32__(samus_periodic_damage, samus_periodic_subdamage)) >> 16; + samus_periodic_subdamage += g_word_94AB50[v1]; + samus_periodic_damage = g_word_94AB70[v1] + v2; + samus_invincibility_timer = 60; + samus_knockback_timer = 10; + } + } + } + return 1; +} + +static Func_U8 *const kBlockReactLut_AB90[16] = { // 0x94ABB0 + ClearCarry_10, + SetCarry_3, + BlockReact_AA64_SpikeAir, + ClearCarry_10, + ClearCarry_10, + BlockReact_HorizExt, + ClearCarry_10, + ClearCarry_10, + SetCarry_3, + SetCarry_3, + BlockReact_AA64_SpikeBlock, + SetCarry_3, + SetCarry_3, + BlockReact_VertExt, + SetCarry_3, + SetCarry_3, +}; + +uint8 BlockFunc_ABB0(void) { + uint8 rv; + uint16 v0 = grapple_beam_grapple_start_block_x; + uint16 RegWord = Mult8x8(grapple_beam_grapple_start_block_y, room_width_in_blocks); + cur_block_index = RegWord + v0; + do { + rv = kBlockReactLut_AB90[(level_data[cur_block_index] & 0xF000) >> 12](); + } while (rv & 0x80); + return rv; +} + +uint8 BlockFunc_ABE6(void) { // 0x94ABE6 + uint8 v0; + g_word_7E0D98 = 6; + grapple_beam_tmpD84 = grapple_beam_length + 8; + while (1) { + BlockFunc_A957(); + v0 = BlockFunc_ABB0() & 1; + if (v0) + break; + grapple_beam_tmpD84 += 8; + if (!--g_word_7E0D98) + return 0; + } + return v0; +} + +void BlockFunc_AC11(void) { // 0x94AC11 + grapple_beam_tmpD82 = 2 * grapple_beam_end_angle; + grapple_beam_tmpD84 = grapple_beam_length; + BlockFunc_A957(); + x_pos_of_start_of_grapple_beam = grapple_beam_grapple_start_x; + y_pos_of_start_of_grapple_beam = grapple_beam_grapple_start_y; +} + +uint8 BlockFunc_AC31(void) { // 0x94AC31 + if (!grapple_beam_length_delta) + return 0; + if ((grapple_beam_length_delta & 0x8000u) != 0) { + uint16 v0 = grapple_beam_length_delta + grapple_beam_length; + if ((uint16)(grapple_beam_length_delta + grapple_beam_length) < 8u) { + grapple_beam_length_delta = 0; + v0 = 8; + } + grapple_beam_varD8C = v0; + grapple_beam_varD8E = 8; + grapple_beam_tmpD82 = 2 * grapple_beam_end_angle; + uint16 v1 = grapple_beam_length; + if (grapple_beam_length == grapple_beam_varD8C) { +LABEL_8: + grapple_beam_length = grapple_beam_varD8C; + return 0; + } + while (1) { + grapple_beam_tmpD8A = v1; + grapple_beam_tmpD84 = grapple_beam_varD8E + v1 - 1; + BlockFunc_A957(); + if (BlockReact_AA64() & 1) + goto LABEL_9; + v1 = --grapple_beam_tmpD8A; + if (grapple_beam_tmpD8A == grapple_beam_varD8C) + goto LABEL_8; + } + } + uint16 v3; + v3 = grapple_beam_length_delta + grapple_beam_length; + if ((uint16)(grapple_beam_length_delta + grapple_beam_length) >= 0x3Fu) { + grapple_beam_length_delta = 0; + v3 = 63; + } + grapple_beam_varD8C = v3; + grapple_beam_varD8E = 56; + grapple_beam_tmpD82 = 2 * grapple_beam_end_angle; + uint16 v4; + v4 = grapple_beam_length; + if (grapple_beam_length != grapple_beam_varD8C) { + while (1) { + grapple_beam_tmpD8A = v4; + grapple_beam_tmpD84 = grapple_beam_varD8E + v4 + 1; + BlockFunc_A957(); + if (BlockReact_AA64() & 1) + break; + v4 = ++grapple_beam_tmpD8A; + if (grapple_beam_tmpD8A == grapple_beam_varD8C) + goto LABEL_15; + } +LABEL_9: + grapple_beam_length = grapple_beam_tmpD8A; + return 1; + } +LABEL_15: + grapple_beam_length = grapple_beam_varD8C; + return 0; +} + +uint8 HandleMovementAndCollForSamusGrapple(void) { // 0x94ACFE + int16 v4; + int16 v7; + uint16 v3, v6; + + uint16 v0 = 256; + if ((grapple_beam_flags & 1) != 0) + v0 = 160; + uint16 v1 = grapple_beam_unkD2E + grapple_beam_unkD26; + if ((int16)(grapple_beam_unkD2E + grapple_beam_unkD26) >= 0) { + Multiply16x16(v1, v0); + if (!*(uint16 *)((char *)&mult_product_lo + 1)) + return 0; + g_word_7E0D9C = *(uint16 *)((char *)&mult_product_lo + 1); + grapple_beam_y_quarter_vel = 2 + * ((uint16)(*(uint16 *)&grapple_beam_end_subangle + + *(uint16 *)((char *)&mult_product_lo + 1)) >> 8); + grapple_beam_tmpD84 = grapple_beam_length; + uint16 v2; + v2 = 2 * grapple_beam_end_angle; + if (v2 != grapple_beam_y_quarter_vel) { + while (1) { + grapple_beam_y_quarter_subvel = v2; + grapple_beam_tmpD82 = (v2 + 2) & 0x1FF; + if (BlockFunc_ABE6() & 1) + break; + v2 = (grapple_beam_y_quarter_subvel + 2) & 0x1FF; + if (v2 == grapple_beam_y_quarter_vel) + goto LABEL_12; + } + LOBYTE(v4) = 0; + HIBYTE(v4) = grapple_beam_y_quarter_subvel >> 1; + *(uint16 *)&grapple_beam_end_subangle = v4 | 0x80; + grapple_beam_end_angles_mirror = v4 | 0x80; + if (g_word_7E0D98 != 6 && g_word_7E0D98 != 5 || grapple_beam_length != 8) + goto LABEL_39; +LABEL_23: + grapple_beam_unkD36 |= 0x8000u; + grapple_beam_unkD26 = 0; + grapple_beam_unkD2E = 0; + return 1; + } +LABEL_12: + *(uint16 *)&grapple_beam_end_subangle += g_word_7E0D9C; + grapple_beam_end_angles_mirror = *(uint16 *)&grapple_beam_end_subangle; + grapple_beam_unkD36 &= ~0x8000u; + if ((--grapple_beam_unkD30 & 0x8000u) != 0) + grapple_beam_unkD30 = 0; + if ((grapple_beam_unkD2E & 0x8000u) == 0) { + v3 = grapple_beam_unkD2E - 6; + if ((int16)(grapple_beam_unkD2E - 6) >= 0) { +LABEL_19: + grapple_beam_unkD2E = v3; + return 0; + } + } else { + v3 = grapple_beam_unkD2E + 6; + if ((int16)(grapple_beam_unkD2E + 6) < 0) + goto LABEL_19; + } + v3 = 0; + goto LABEL_19; + } + Multiply16x16(-v1, v0); + if (!*(uint16 *)((char *)&mult_product_lo + 1)) + return 0; + g_word_7E0D9C = -*(uint16 *)((char *)&mult_product_lo + 1); + grapple_beam_y_quarter_vel = 2 + * ((uint16)(*(uint16 *)&grapple_beam_end_subangle + - *(uint16 *)((char *)&mult_product_lo + 1)) >> 8); + grapple_beam_tmpD84 = grapple_beam_length; + uint16 v5; + v5 = 2 * grapple_beam_end_angle; + if (v5 == grapple_beam_y_quarter_vel) { +LABEL_28: + *(uint16 *)&grapple_beam_end_subangle += g_word_7E0D9C; + grapple_beam_end_angles_mirror = *(uint16 *)&grapple_beam_end_subangle; + grapple_beam_unkD36 &= ~0x8000u; + if ((--grapple_beam_unkD30 & 0x8000u) != 0) + grapple_beam_unkD30 = 0; + if ((grapple_beam_unkD2E & 0x8000u) == 0) { + v6 = grapple_beam_unkD2E - 6; + if ((int16)(grapple_beam_unkD2E - 6) >= 0) { +LABEL_35: + grapple_beam_unkD2E = v6; + return 0; + } + } else { + v6 = grapple_beam_unkD2E + 6; + if ((int16)(grapple_beam_unkD2E + 6) < 0) + goto LABEL_35; + } + v6 = 0; + goto LABEL_35; + } + while (1) { + grapple_beam_y_quarter_subvel = v5; + grapple_beam_tmpD82 = (v5 - 2) & 0x1FF; + if (BlockFunc_ABE6() & 1) + break; + v5 = (grapple_beam_y_quarter_subvel - 2) & 0x1FF; + if (v5 == grapple_beam_y_quarter_vel) + goto LABEL_28; + } + LOBYTE(v7) = 0; + HIBYTE(v7) = grapple_beam_y_quarter_subvel >> 1; + *(uint16 *)&grapple_beam_end_subangle = v7 | 0x80; + grapple_beam_end_angles_mirror = v7 | 0x80; + if ((g_word_7E0D98 == 6 || g_word_7E0D98 == 5) && grapple_beam_length == 8) + goto LABEL_23; +LABEL_39: + grapple_beam_unkD30 = 16; + grapple_beam_unkD26 = -((int16)grapple_beam_unkD26 >> 1); + grapple_beam_unkD2E = -((int16)grapple_beam_unkD2E >> 1); + return 1; +} + +uint8 BlockFunc_AEE3(void) { // 0x94AEE3 + if (((grapple_beam_unkD26 ^ *(uint16 *)&grapple_beam_end_subangle) & 0x8000u) != 0) { + grapple_beam_unkD38 = 0; + return 1; + } else { + if (++grapple_beam_unkD38 == 32) + grapple_beam_function = FUNC16(GrappleBeam_Func2); + grapple_beam_unkD26 = 0; + grapple_beam_unkD2E = 0; + return 1; + } +} + +uint8 ClearCarry_11(void) { // 0x94AF0B + return 0; +} + +void GrappleFunc_AF87(void) { // 0x94AF87 + for (int i = 30; i >= 0; i -= 8) { + int v1 = i >> 1; + grapple_segment_anim_instr_ptrs[v1] = addr_word_94B197; + grapple_segment_anim_instr_timers[v1 + 15] = addr_word_94B193; + grapple_segment_anim_instr_timers[v1 + 14] = addr_word_94B18F; + grapple_segment_anim_instr_timers[v1 + 13] = addr_word_94B18B; + grapple_segment_anim_instr_timers[v1] = 1; + *(uint16 *)((char *)&grapple_point_anim_ptr + i) = 1; + *(uint16 *)((char *)&grapple_point_anim_timer + i) = 1; + *(uint16 *)((char *)&grapple_beam_unkD3C + i) = 1; + } +} + +uint16 CallGrappleInstr(uint32 ea, uint16 j) { + switch (ea) { + case fnGrappleInstr_Goto: return GrappleInstr_Goto(j); // 0x94b0f4 + default: return Unreachable(); + } +} + +void HandleGrappleBeamGfx(void) { // 0x94AFBA + int16 RegWord; // dx + + R18_ = grapple_beam_end_x_pos - x_pos_of_start_of_grapple_beam_prevframe; + R20_ = grapple_beam_end_y_pos - y_pos_of_start_of_grapple_beam_prevframe; + uint16 v0 = 2 * CalculateAngleFromXY(); + R26_ = 0; + R28_ = 0; + int v1 = v0 >> 1; + uint16 v2 = 8 * kSinCosTable8bit_Sext[v1 + 64]; + if ((kSinCosTable8bit_Sext[v1 + 64] & 0x1000) != 0) + --R28_; + *(uint16 *)((char *)&R26_ + 1) = v2; + g_word_7E001E = 0; + R32 = 0; + uint16 v3 = 8 * kSinCosTable8bit_Sext[v1]; + if ((kSinCosTable8bit_Sext[v1] & 0x1000) != 0) + --R32; + *(uint16 *)((char *)&g_word_7E001E + 1) = v3; + R38 = (uint16)(*(uint16 *)&grapple_beam_end_subangle & 0x8000) >> 1; + R38 |= 2 * ((*(uint16 *)&grapple_beam_end_subangle ^ R38) & 0x4000 ^ 0x4000); + R20_ = x_pos_of_start_of_grapple_beam_prevframe - layer1_x_pos - 4; + R18_ = 0; + R24_ = y_pos_of_start_of_grapple_beam_prevframe - layer1_y_pos - 4; + R22_ = 0; + if ((grapple_beam_length & 0x8000u) == 0) { + RegWord = grapple_beam_length / 8; + if (RegWord >= 0) { + R40 = (RegWord & 0xF) - 1; + uint16 v5 = 30; + do { + int i, v6 = v5 >> 1; + uint16 v10; + if (grapple_segment_anim_instr_timers[v6]-- == 1) { + for (i = grapple_segment_anim_instr_ptrs[v6]; ; ) { + uint16 *v9 = (uint16 *)RomPtr_94(i); + v10 = *v9; + if ((*v9 & 0x8000u) == 0) + break; + R36 = *v9; + i = CallGrappleInstr(v10 | 0x940000, i + 2); + } + int v11 = v5 >> 1; + grapple_segment_anim_instr_timers[v11] = v10; + grapple_segment_anim_instr_ptrs[v11] = i + 4; + } + if (((R24_ | R20_) & 0xFF00) != 0) + break; + uint16 v12 = *(uint16 *)RomPtr_94(grapple_segment_anim_instr_ptrs[v5 >> 1] - 2); + DrawGrappleOams(v12); + v5 -= 2; + --R40; + } while ((R40 & 0x8000u) == 0); + if (samus_pose == kPose_B2_FaceR_Grapple_Air || samus_pose == kPose_B3_FaceL_Grapple_Air) + DrawGrappleOams3(); + else + DrawGrappleOams2(); + } + } +} + +void DrawGrappleOams(uint16 j) { // 0x94B0AA + OamEnt *v2; + unsigned int v3; // kr00_4 + unsigned int v4; // kr04_4 + + uint16 v1 = oam_next_ptr; + v2 = gOamEnt(oam_next_ptr); + *(uint16 *)&v2->xcoord = R20_; + v3 = __PAIR32__(R28_, R26_) + __PAIR32__(R20_, R18_); + R20_ = HIWORD(v3); + R18_ = v3; + *(uint16 *)&v2->ycoord = R24_; + v4 = __PAIR32__(R32, g_word_7E001E) + __PAIR32__(R24_, R22_); + R24_ = HIWORD(v4); + R22_ = v4; + *(uint16 *)&v2->charnum = R38 | j; + oam_next_ptr = v1 + 4; +} + +uint16 GrappleInstr_Goto(uint16 j) { // 0x94B0F4 + return *(uint16 *)RomPtr_94(j); +} + + +void DrawGrappleOams2(void) { // 0x94B0F9 + int16 v1; + OamEnt *v2; + int16 v4; + + if (((grapple_beam_end_y_pos - layer1_y_pos) & 0xFF00) == 0) { + uint16 v0 = oam_next_ptr; + v1 = grapple_beam_end_x_pos - layer1_x_pos - 4; + v2 = gOamEnt(oam_next_ptr); + *(uint16 *)&v2->xcoord = v1; + if ((v1 & 0x100) != 0) { + int v3 = v0 >> 1; + R34 = kOamExtra_Address_And_X8Large[v3]; + v4 = kOamExtra_X8Small_And_Large[v3] | *(uint16 *)RomPtr_RAM(R34); + *(uint16 *)RomPtr_RAM(R34) = v4; + } + *(uint16 *)&v2->ycoord = grapple_beam_end_y_pos - layer1_y_pos - 4; + *(uint16 *)&v2->charnum = 14880; + oam_next_ptr = v0 + 4; + } +} + +void DrawGrappleOams3(void) { // 0x94B14B + int16 v1; + OamEnt *v2; + int16 v4; + + uint16 v0 = oam_next_ptr; + v1 = grapple_beam_end_x_pos - layer1_x_pos - 4; + v2 = gOamEnt(oam_next_ptr); + *(uint16 *)&v2->xcoord = v1; + if ((v1 & 0x100) != 0) { + int v3 = v0 >> 1; + R34 = kOamExtra_Address_And_X8Large[v3]; + v4 = kOamExtra_X8Small_And_Large[v3] | *(uint16 *)RomPtr_RAM(R34); + *(uint16 *)RomPtr_RAM(R34) = v4; + } + *(uint16 *)&v2->ycoord = grapple_beam_end_y_pos - layer1_y_pos - 4; + *(uint16 *)&v2->charnum = 14880; + oam_next_ptr = v0 + 4; +} diff --git a/src/sm_9b.c b/src/sm_9b.c new file mode 100644 index 0000000..a42c057 --- /dev/null +++ b/src/sm_9b.c @@ -0,0 +1,1298 @@ +#include "sm_cpu_infra.h" +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" + +#define g_off_9BA4B3 ((uint16*)RomPtr(0x9ba4b3)) +#define g_off_9BA4CB ((uint16*)RomPtr(0x9ba4cb)) +#define g_off_9BA4E3 ((uint16*)RomPtr(0x9ba4e3)) +static const uint8 kDeathAnimationFrames[28] = { + 5, 5, 5, 5, 1, 5, 5, 0, 1, + 0, 5, 5, 5, 5, 5, 5, 5, 1, + 1, 1, 5, 5, 5, 5, 5, 5, 5, + 5, +}; +#define g_off_9BB5C8 ((uint16*)RomPtr(0x9bb5c8)) +#define g_byte_9BB823 ((uint8*)RomPtr(0x9bb823)) +#define g_off_9BB6D2 ((uint16*)RomPtr(0x9bb6d2)) + +#define kDeathSequencePals_PowerSuit ((uint16*)RomPtr(0x9bb7d3)) +#define kDeathSequencePals_VariaSuit ((uint16*)RomPtr(0x9bb7e7)) +#define kDeathSequencePals_GravitySuit ((uint16*)RomPtr(0x9bb7fb)) +#define kDeathSequencePals_Suitless ((uint16*)RomPtr(0x9bb80f)) +#define g_off_9BC3C6 ((uint16*)RomPtr(0x9bc3c6)) +#define g_off_9BC3EE ((uint16*)RomPtr(0x9bc3ee)) +#define g_off_9BC416 ((uint16*)RomPtr(0x9bc416)) +#define grapple_beam_special_angles ((GrappleBeamSpecialAngles*)RomPtr(0x9bc43e)) +static const uint16 g_word_9BC118 = 24; +static const uint16 g_word_9BC11A = 0xc; +static const uint16 g_word_9BC11C = 5; +static const uint16 g_word_9BC11E = 0x480; +static const uint16 g_word_9BC120 = 0x300; + +static const uint16 g_word_9BB7BF[5] = { 0x8400, 0x8800, 0x8c00, 0x9000, 0x8000 }; +static const uint16 g_word_9BB7C9[5] = { 0x6200, 0x6400, 0x6600, 0x6800, 0x6000 }; +static const uint16 kShadesOfWhite[22] = { + 0x421, 0xc63, 0x14a5, 0x1ce7, 0x2529, 0x2d6b, 0x35ad, 0x4210, + 0x4a52, 0x4e73, 0x5294, 0x56b5, 0x5ad6, 0x5ef7, 0x6318, 0x6739, + 0x6b5a, 0x6f7b, 0x739c, 0x77bd, 0x7bde, 0x7fff, +}; +static const uint8 kIsGrappleBannedForMovementType[28] = { + 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, + 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, + 1, 0, 0, 1, 1, 1, 0, 1, +}; +#define kGrappleBeam_SwingingData ((uint8*)RomPtr(0x9bc1c2)) +#define kGrappleBeam_SwingingData2 ((uint8*)RomPtr(0x9bc2c2)) +#define kGrappleBeam_SwingingData3 ((uint8*)RomPtr(0x9bc302)) +#define kGrappleBeam_OriginX_NoRun ((uint16*)RomPtr(0x9bc122)) +#define kGrappleBeam_OriginY_NoRun ((uint16*)RomPtr(0x9bc136)) +#define kGrappleBeam_0x0d1a_offs_NoRun ((uint16*)RomPtr(0x9bc14a)) +#define kGrappleBeam_0x0d1c_offs_NoRun ((uint16*)RomPtr(0x9bc15e)) +#define kGrappleBeam_OriginX_Run ((uint16*)RomPtr(0x9bc172)) +#define kGrappleBeam_OriginY_Run ((uint16*)RomPtr(0x9bc186)) +#define kGrappleBeam_0x0d1a_offs_Run ((uint16*)RomPtr(0x9bc19a)) +#define kGrappleBeam_0x0d1c_offs_Run ((uint16*)RomPtr(0x9bc1ae)) +#define g_off_9BC344 (*(uint16*)RomPtr(0x9bc344)) +#define g_off_9BC342 (*(uint16*)RomPtr(0x9bc342)) +#define g_off_9BC346 ((uint16*)RomPtr(0x9bc346)) +#define kFlareAnimDelays ((uint16*)RomPtr(0x90c481)) +#define kFlareAnimDelays_Main ((uint8*)RomPtr(0x90c487)) +#define kFlareAnimDelays_SlowSparks ((uint8*)RomPtr(0x90c4a7)) +#define kFlareAnimDelays_FastSparks ((uint8*)RomPtr(0x90c4ae)) +#define g_word_93A22B ((uint16*)RomPtr(0x93a22b)) +#define g_word_93A225 ((uint16*)RomPtr(0x93a225)) +#define g_byte_9BC9BA ((uint8*)RomPtr(0x9bc9ba)) +#define g_byte_9BC9C4 ((uint8*)RomPtr(0x9bc9c4)) +#define kGrappleBeam_Ext_Xvel ((uint16*)RomPtr(0x9bc0db)) +#define kGrappleBeam_Ext_Yvel ((uint16*)RomPtr(0x9bc0ef)) +#define kGrappleBeam_Init_EndAngle ((uint16*)RomPtr(0x9bc104)) + +void ProjectileTrail_Func5(uint16 k, uint16 j) { // 0x9BA3CC + ProjectileInsts_GetValue(k); + if ((ceres_status & 0x8000u) == 0) { + int v2 = k >> 1; + R18_ = projectile_x_pos[v2]; + R20_ = projectile_y_pos[v2]; + } else { + CalcExplosion_Mode7(k); + uint16 v10 = R18_; + R18_ = layer1_x_pos + R20_; + R20_ = layer1_y_pos + v10; + } + int v3 = k >> 1; + uint16 v4 = projectile_type[v3], v5; + if ((v4 & 0x20) != 0) { + v5 = g_off_9BA4E3[projectile_type[v3] & 0xF] + 2 * (projectile_dir[v3] & 0xF); + } else if ((v4 & 0x10) != 0) { + v5 = g_off_9BA4CB[projectile_type[v3] & 0xF] + 2 * (projectile_dir[v3] & 0xF); + } else { + v5 = g_off_9BA4B3[projectile_type[v3] & 0xF] + 2 * (projectile_dir[v3] & 0xF); + } + uint16 v6 = *(uint16 *)RomPtr_9B(v5) + 4 * R22_; + LOBYTE(v5) = HIBYTE(*(uint16 *)RomPtr_9B(v6)); + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + else + v5 = (uint8)v5; + int v7 = j >> 1; + projectiletrail_left_y_pos[v7] = R20_ + v5 - 4; + uint16 v8 = v6 - 1; + LOBYTE(v5) = HIBYTE(*(uint16 *)RomPtr_9B(v8)); + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + else + v5 = (uint8)v5; + projectiletrail_left_x_pos[v7] = R18_ + v5 - 4; + uint8 *v9 = RomPtr_9B(v8 + 1); + LOBYTE(v5) = HIBYTE(*((uint16 *)v9 + 1)); + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + else + v5 = (uint8)v5; + projectiletrail_right_y_pos[v7] = R20_ + v5 - 4; + LOBYTE(v5) = HIBYTE(*(uint16 *)(v9 + 1)); + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + else + v5 = (uint8)v5; + projectiletrail_right_x_pos[v7] = R18_ + v5 - 4; +} + +void StartSamusDeathAnimation(void) { // 0x9BB3A7 + uint16 v0 = samus_movement_type; + if (samus_movement_type == 3) + QueueSfx1_Max6(0x32u); + uint16 v1 = kDeathAnimationFrames[v0]; + if (samus_pose_x_dir == 4) + samus_pose = kPose_D8_FaceL_CrystalFlashEnd; + else + samus_pose = kPose_D7_FaceR_CrystalFlashEnd; + SamusFunc_F433(); + Samus_SetAnimationFrameIfPoseChanged(); + samus_last_different_pose = samus_prev_pose; + *(uint16 *)&samus_last_different_pose_x_dir = *(uint16 *)&samus_prev_pose_x_dir; + samus_prev_pose = samus_pose; + *(uint16 *)&samus_prev_pose_x_dir = *(uint16 *)&samus_pose_x_dir; + samus_anim_frame_skip = 0; + samus_anim_frame = v1; + samus_x_pos -= layer1_x_pos; + samus_y_pos -= layer1_y_pos; +} + +void DrawSamusStartingDeathAnim_(void) { // 0x9BB43C + Samus_DrawStartingDeathAnim(); +} + +uint16 HandleSamusDeathSequence(void) { // 0x9BB441 + if (sign16(g_word_7E0DE6 - 4)) + QueueTransferOfSamusDeathSequence(2 * g_word_7E0DE6); + if (sign16(++g_word_7E0DE6 - 60)) { + bool v0 = (--game_options_screen_index & 0x8000u) != 0; + if (!game_options_screen_index || v0) { + if (g_word_7E0DE4) { + g_word_7E0DE4 = 0; + game_options_screen_index = 3; + } else { + g_word_7E0DE4 = 1; + game_options_screen_index = 1; + } + CopyPalettesForSamusDeath(g_word_7E0DE4 * 2); + } + return 0; + } else { + HandleSamusDeathSequence_Helper2(); + substate = (joypad2_last & 0xB0) == (kButton_A | kButton_L | kButton_R); + return 1; + } +} + +void HandleSamusDeathSequence_Helper2(void) { // 0x9BB4B6 + uint16 *v0 = (uint16 *)RomPtr_9B(g_off_9BB5C8[samus_suit_palette_index >> 1]); + uint16 *v1 = (uint16 *)RomPtr_9B(*v0); + palette_buffer[192] = *v1; + palette_buffer[193] = v1[1]; + palette_buffer[194] = v1[2]; + palette_buffer[195] = v1[3]; + palette_buffer[196] = v1[4]; + palette_buffer[197] = v1[5]; + palette_buffer[198] = v1[6]; + palette_buffer[199] = v1[7]; + palette_buffer[200] = v1[8]; + palette_buffer[201] = v1[9]; + palette_buffer[202] = v1[10]; + palette_buffer[203] = v1[11]; + palette_buffer[204] = v1[12]; + palette_buffer[205] = v1[13]; + palette_buffer[206] = v1[14]; + palette_buffer[207] = v1[15]; + uint16 *v2 = (uint16 *)RomPtr_9B(0xA120); + palette_buffer[240] = *v2; + palette_buffer[241] = v2[1]; + palette_buffer[242] = v2[2]; + palette_buffer[243] = v2[3]; + palette_buffer[244] = v2[4]; + palette_buffer[245] = v2[5]; + palette_buffer[246] = v2[6]; + palette_buffer[247] = v2[7]; + palette_buffer[248] = v2[8]; + palette_buffer[249] = v2[9]; + palette_buffer[250] = v2[10]; + palette_buffer[251] = v2[11]; + palette_buffer[252] = v2[12]; + palette_buffer[253] = v2[13]; + palette_buffer[254] = v2[14]; + palette_buffer[255] = v2[15]; + QueueTransferOfSamusDeathSequence(8); + game_options_screen_index = g_byte_9BB823[0]; + g_word_7E0DE4 = 0; + g_word_7E0DE6 = 0; + GameState_24_SamusNoHealth_Explosion_2(); +} + +void CopyPalettesForSamusDeath(uint16 v0) { // 0x9BB5CE + R20_ = g_off_9BB6D2[samus_suit_palette_index >> 1]; + R18_ = kDeathSequencePals_Suitless[v0 >> 1]; + uint16 *v1 = (uint16 *)RomPtr_9B(R20_ + v0); + uint16 *v2 = (uint16 *)RomPtr_9B(*v1); + palette_buffer[192] = *v2; + palette_buffer[193] = v2[1]; + palette_buffer[194] = v2[2]; + palette_buffer[195] = v2[3]; + palette_buffer[196] = v2[4]; + palette_buffer[197] = v2[5]; + palette_buffer[198] = v2[6]; + palette_buffer[199] = v2[7]; + palette_buffer[200] = v2[8]; + palette_buffer[201] = v2[9]; + palette_buffer[202] = v2[10]; + palette_buffer[203] = v2[11]; + palette_buffer[204] = v2[12]; + palette_buffer[205] = v2[13]; + palette_buffer[206] = v2[14]; + palette_buffer[207] = v2[15]; + uint16 *v3 = (uint16 *)RomPtr_9B(R18_); + palette_buffer[240] = *v3; + palette_buffer[241] = v3[1]; + palette_buffer[242] = v3[2]; + palette_buffer[243] = v3[3]; + palette_buffer[244] = v3[4]; + palette_buffer[245] = v3[5]; + palette_buffer[246] = v3[6]; + palette_buffer[247] = v3[7]; + palette_buffer[248] = v3[8]; + palette_buffer[249] = v3[9]; + palette_buffer[250] = v3[10]; + palette_buffer[251] = v3[11]; + palette_buffer[252] = v3[12]; + palette_buffer[253] = v3[13]; + palette_buffer[254] = v3[14]; + palette_buffer[255] = v3[15]; +} + +void QueueTransferOfSamusDeathSequence(uint16 v0) { // 0x9BB6D8 + uint16 v1 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 1024; + v1 += 2; + int v2 = v0 >> 1; + gVramWriteEntry(v1)->size = g_word_9BB7BF[v2]; + v1 += 2; + LOBYTE(gVramWriteEntry(v1++)->size) = -101; + gVramWriteEntry(v1)->size = g_word_9BB7C9[v2]; + vram_write_queue_tail = v1 + 2; +} + +uint16 GameState_24_SamusNoHealth_Explosion_Helper(void) { // 0x9BB701 + GameState_24_SamusNoHealth_Explosion_1(); + return GameState_24_SamusNoHealth_Explosion_2(); +} + +void GameState_24_SamusNoHealth_Explosion_1(void) { // 0x9BB710 + *(VoidP *)((char *)&R0_.addr + 1) = 32256; + if (!substate && g_word_7E0DE4) { + uint16 v0 = 2 * g_word_7E0DE6; + R0_.addr = -16384; + uint16 v1 = 0; + do { + IndirWriteWord(&R0_, v1, kShadesOfWhite[v0 >> 1]); + v1 += 2; + } while ((int16)(v1 - 384) < 0); + uint16 v2 = 416; + do { + IndirWriteWord(&R0_, v2, kShadesOfWhite[v0 >> 1]); + v2 += 2; + } while ((int16)(v2 - 480) < 0); + if (sign16(g_word_7E0DE6 - 20)) + ++g_word_7E0DE6; + } +} + +uint16 GameState_24_SamusNoHealth_Explosion_2(void) { // 0x9BB758 + bool v0 = (--game_options_screen_index & 0x8000u) != 0; + if (!game_options_screen_index || v0) { + if (!sign16(++g_word_7E0DE4 - 9)) { + g_word_7E0DE6 = 21; + GameState_24_SamusNoHealth_Explosion_1(); + substate = 0; + return 1; + } + if (!substate || sign16(g_word_7E0DE4 - 2)) { + game_options_screen_index = g_byte_9BB823[(uint16)(2 * g_word_7E0DE4)]; + CopyPalettesForSamusDeath(2 * g_byte_9BB823[(uint16)(2 * g_word_7E0DE4) + 1]); + } else { + game_options_screen_index = g_byte_9BB823[(uint16)(2 * g_word_7E0DE4)]; + } + } + DrawSamusSuitExploding(); + return 0; +} + +void CancelGrappleBeamIfIncompatiblePose(void) { // 0x9BB861 + int16 v0; + + if (kIsGrappleBannedForMovementType[samus_movement_type]) { +LABEL_2: + if (grapple_beam_function != (uint16)FUNC16(GrappleBeamFunc_Inactive)) + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + return; + } + if (grapple_beam_function != (uint16)FUNC16(GrappleBeamFunc_Inactive) + && sign16(grapple_beam_function + 0x3882)) { + v0 = *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)); + if ((v0 & 0xF0) == 0) { + if (v0 == grapple_beam_direction) + return; + if (grapple_varCF6) { + QueueSfx1_Max6(7u); + grapple_beam_function = FUNC16(GrappleBeamFunc_FireGoToCancel); + return; + } + } + goto LABEL_2; + } +} + +void UNUSED_sub_9BB8D5(void) { // 0x9BB8D5 + int16 v0; + + v0 = *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)); + if ((v0 & 0xF0) == 0 && v0 != grapple_beam_direction) + grapple_beam_direction = *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)); +} + +uint8 CheckIfGrappleIsConnectedToBlock(void) { // 0x9BB8F1 + grapple_beam_extension_x_velocity = 0; + grapple_beam_extension_y_velocity = 0; + if ((BlockReactGrapple() & 1) == 0) + return 0; + samus_grapple_flags = 1; + return 1; +} + +int ProcessEnemyGrappleBeamColl(uint16 a) { // 0x9BB907 + int16 v1; + uint16 v3; + + v1 = 2 * a; + switch (v1) { + case 0: + case 4: + return -1; // clc + case 6: + return 1; + case 2: + case 8: + case 10: + return 0; + } + if (v1 != 12) { + Unreachable(); + while (1); + } + R18_ = *((uint16 *)RomPtr_A0(R18_) + 3); + if ((equipped_items & 0x20) != 0) { + R18_ >>= 1; + R18_ >>= 1; + v3 = R18_; + } else { + if (equipped_items & 1) + R18_ >>= 1; + v3 = R18_; + } + Samus_DealDamage(v3); + samus_invincibility_timer = 96; + samus_knockback_timer = 5; + knockback_x_dir = samus_pose_x_dir == 4; + return 1; +} + +void CallGrappleNextFunc(uint32 ea) { + switch (ea) { + case fnGrappleNext_SwingClockwise: GrappleNext_SwingClockwise(); return; + case fnGrappleNext_SwingAntiClockwise: GrappleNext_SwingAntiClockwise(); return; + case fnGrappleNext_StandAimRight: GrappleNext_StandAimRight(); return; + case fnGrappleNext_StandAimDownRight: GrappleNext_StandAimDownRight(); return; + case fnGrappleNext_StandAimDownLeft: GrappleNext_StandAimDownLeft(); return; + case fnGrappleNext_StandAimLeft: GrappleNext_StandAimLeft(); return; + case fnGrappleNext_CrouchAimRight: GrappleNext_CrouchAimRight(); return; + case fnGrappleNext_CrouchAimDownRight: GrappleNext_CrouchAimDownRight(); return; + case fnGrappleNext_CrouchAimDownLeft: GrappleNext_CrouchAimDownLeft(); return; + case fnGrappleNext_CrouchAimLeft: GrappleNext_CrouchAimLeft(); return; + default: Unreachable(); + } +} + +void HandleConnectingGrapple(void) { // 0x9BB97C + if (samus_movement_type == kMovementType_1A_GrabbedByDraygon) { + grapple_beam_function = FUNC16(GrappleBeamFunc_ConnectedLockedInPlace); + grapple_beam_length_delta = 0; + } else { + uint16 v0 = 4 * grapple_beam_direction; + if (samus_y_speed || samus_y_subspeed) { + int v2 = v0 >> 1; + grapple_beam_function = g_off_9BC3EE[v2]; + grapple_beam_tmpD82 = g_off_9BC3EE[v2 + 1]; + CallGrappleNextFunc(grapple_beam_tmpD82 | 0x9B0000); + } else { + int v1 = v0 >> 1; + if (samus_movement_type == 5) { + grapple_beam_function = g_off_9BC416[v1]; + grapple_beam_tmpD82 = g_off_9BC416[v1 + 1]; + } else { + grapple_beam_function = g_off_9BC3C6[v1]; + grapple_beam_tmpD82 = g_off_9BC3C6[v1 + 1]; + } + CallGrappleNextFunc(grapple_beam_tmpD82 | 0x9B0000); + } + } +} + +void GrappleNext_SwingClockwise(void) { // 0x9BB9D9 + samus_new_pose_interrupted = kPose_B2_FaceR_Grapple_Air; + HandleConnectingGrapple_Swinging(); +} + +void GrappleNext_SwingAntiClockwise(void) { // 0x9BB9E2 + samus_new_pose_interrupted = kPose_B3_FaceL_Grapple_Air; + HandleConnectingGrapple_Swinging(); +} + +void GrappleNext_StandAimRight(void) { // 0x9BB9EA + samus_new_pose_interrupted = kPose_A8_FaceR_Grappling; + HandleConnectingGrapple_StuckInPlace(); +} + +void GrappleNext_StandAimDownRight(void) { // 0x9BB9F3 + samus_new_pose_interrupted = kPose_AA_FaceR_Grappling_AimDR; + HandleConnectingGrapple_StuckInPlace(); +} + +void GrappleNext_StandAimDownLeft(void) { // 0x9BB9FC + samus_new_pose_interrupted = kPose_AB_FaceL_Grappling_AimDL; + HandleConnectingGrapple_StuckInPlace(); +} + +void GrappleNext_StandAimLeft(void) { // 0x9BBA05 + samus_new_pose_interrupted = kPose_A9_FaceL_Grappling; + HandleConnectingGrapple_StuckInPlace(); +} + +void GrappleNext_CrouchAimRight(void) { // 0x9BBA0E + samus_new_pose_interrupted = kPose_B4_FaceR_Grappling_Crouch; + HandleConnectingGrapple_StuckInPlace(); +} + +void GrappleNext_CrouchAimDownRight(void) { // 0x9BBA17 + samus_new_pose_interrupted = kPose_B6_FaceR_Grappling_Crouch_AimDR; + HandleConnectingGrapple_StuckInPlace(); +} + +void GrappleNext_CrouchAimDownLeft(void) { // 0x9BBA20 + samus_new_pose_interrupted = kPose_B7_FaceL_Grappling_Crouch_AimDL; + HandleConnectingGrapple_StuckInPlace(); +} + +void GrappleNext_CrouchAimLeft(void) { // 0x9BBA29 + samus_new_pose_interrupted = kPose_B5_FaceL_Grappling_Crouch; + HandleConnectingGrapple_StuckInPlace(); +} + +void UNUSED_sub_9BBA31(void) { // 0x9BBA31 + samus_new_pose_interrupted = 172; + HandleConnectingGrapple_StuckInPlace(); +} + +void HandleConnectingGrapple_Swinging(void) { // 0x9BBA61 + char v1; // t0 + + samus_special_transgfx_index = 9; + R18_ = samus_x_pos - grapple_beam_end_x_pos; + R20_ = samus_y_pos - grapple_beam_end_y_pos; + uint16 v0 = CalculateAngleFromXY(); + v1 = v0; + LOBYTE(v0) = HIBYTE(v0); + HIBYTE(v0) = v1; + *(uint16 *)&grapple_beam_end_subangle = v0; + grapple_beam_end_angles_mirror = v0; + grapple_beam_length_delta = 0; + if (!sign16(grapple_beam_length - 64)) + grapple_beam_length -= 24; + BlockFunc_AC11(); +} + +void HandleConnectingGrapple_StuckInPlace(void) { // 0x9BBA9B + char v1; // t0 + + samus_special_transgfx_index = 10; + R18_ = samus_x_pos - grapple_beam_end_x_pos; + R20_ = samus_y_pos - grapple_beam_end_y_pos; + uint16 v0 = CalculateAngleFromXY(); + v1 = v0; + LOBYTE(v0) = HIBYTE(v0); + HIBYTE(v0) = v1; + *(uint16 *)&grapple_beam_end_subangle = v0; + grapple_beam_end_angles_mirror = v0; + grapple_beam_length_delta = 0; + if (!sign16(grapple_beam_length - 64)) + grapple_beam_length -= 24; + BlockFunc_AC11(); +} + +uint8 HandleSpecialGrappleBeamAngles(void) { // 0x9BBAD5 + int16 v2; + int16 v3; + + uint16 v0 = 7; + while (*(uint16 *)&grapple_beam_end_subangle != grapple_beam_special_angles[v0].field_0) { + if ((--v0 & 0x8000u) != 0) + return 0; + } + samus_new_pose_interrupted = grapple_beam_special_angles[v0].field_2; + samus_x_pos = grapple_beam_end_x_pos + grapple_beam_special_angles[v0].field_4; + samus_y_pos = grapple_beam_end_y_pos + grapple_beam_special_angles[v0].field_6; + grapple_beam_function = grapple_beam_special_angles[v0].field_8; + samus_special_transgfx_index = 0; + slow_grabble_scrolling_flag = 0; + v2 = samus_x_pos - samus_prev_x_pos; + if ((int16)(samus_x_pos - samus_prev_x_pos) < 0) { + if (sign16(v2 + 12)) + samus_prev_x_pos = samus_x_pos + 12; + } else if (!sign16(v2 - 13)) { + samus_prev_x_pos = samus_x_pos - 12; + } + v3 = samus_y_pos - samus_prev_y_pos; + if ((int16)(samus_y_pos - samus_prev_y_pos) < 0) { + if (sign16(v3 + 12)) + samus_prev_y_pos = samus_y_pos + 12; + } else if (!sign16(v3 - 13)) { + samus_prev_y_pos = samus_y_pos - 12; + } + return 1; +} + +void GrappleBeamFunc_BB64(void) { // 0x9BBB64 + if ((joypad1_newkeys & kButton_Up) != 0) { + if (grapple_beam_length) + grapple_beam_length_delta = -2; + } else if ((joypad1_newkeys & kButton_Down) != 0) { + if (sign16(grapple_beam_length - 64)) + grapple_beam_length_delta = 2; + else + grapple_beam_length = 64; + } + if (sign16((grapple_beam_end_angle << 8) - 0x4000) || !sign16((grapple_beam_end_angle << 8) + 0x4000)) + goto LABEL_13; + if ((joypad1_lastkeys & 0x200) != 0) { + if (grapple_beam_end_angle << 8 == 0x8000 && !grapple_beam_unkD26) + grapple_beam_unkD26 = 256; + if (grapple_beam_flags && (grapple_beam_flags & 1) != 0) + grapple_beam_unkD2A = g_word_9BC11A >> 1; + else + grapple_beam_unkD2A = g_word_9BC11A; + } else { + if ((joypad1_lastkeys & 0x100) == 0) { +LABEL_13: + grapple_beam_unkD2A = 0; + return; + } + if (grapple_beam_end_angle << 8 == 0x8000 && !grapple_beam_unkD26) + grapple_beam_unkD26 = -256; + if (grapple_beam_flags && (grapple_beam_flags & 1) != 0) + grapple_beam_unkD2A = -(g_word_9BC11A >> 1); + else + grapple_beam_unkD2A = -g_word_9BC11A; + } +} + +void GrappleBeamFunc_BC1F(void) { // 0x9BBC1F + if ((*(uint16 *)&grapple_beam_end_subangle & 0xC000) == 0xC000) { + grapple_beam_unkD2C = -(g_word_9BC11C >> 2); + if (grapple_beam_flags && (grapple_beam_flags & 1) != 0) + grapple_beam_unkD28 = -(g_word_9BC118 >> 3); + else + grapple_beam_unkD28 = -(g_word_9BC118 >> 2); + } else if (*(int16 *)&grapple_beam_end_subangle < 0) { + if (grapple_beam_end_angle << 8 == 0x8000) { + grapple_beam_unkD28 = 0; + grapple_beam_unkD2C = 0; + uint16 v0 = grapple_beam_unkD26; + if ((grapple_beam_unkD26 & 0x8000u) != 0) + v0 = ~(grapple_beam_unkD26 - 1); + if (sign16(HIBYTE(v0) - 1)) + grapple_beam_unkD26 = 0; + } else { + grapple_beam_unkD2C = -g_word_9BC11C; + if (grapple_beam_flags && (grapple_beam_flags & 1) != 0) + grapple_beam_unkD28 = -(g_word_9BC118 >> 1); + else + grapple_beam_unkD28 = -g_word_9BC118; + } + } else if ((*(uint16 *)&grapple_beam_end_subangle & 0x4000) != 0) { + grapple_beam_unkD2C = g_word_9BC11C; + if (grapple_beam_flags && (grapple_beam_flags & 1) != 0) + grapple_beam_unkD28 = g_word_9BC118 >> 1; + else + grapple_beam_unkD28 = g_word_9BC118; + } else { + grapple_beam_unkD2C = g_word_9BC11C >> 2; + if (grapple_beam_flags && (grapple_beam_flags & 1) != 0) + grapple_beam_unkD28 = g_word_9BC118 >> 3; + else + grapple_beam_unkD28 = g_word_9BC118 >> 2; + } +} + +void GrappleBeamFunc_BCFF(void) { // 0x9BBCFF + grapple_beam_unkD26 += grapple_beam_unkD2A + grapple_beam_unkD28; + if (((grapple_beam_unkD26 ^ *(uint16 *)&grapple_beam_end_subangle) & 0x8000u) != 0) + grapple_beam_unkD26 += grapple_beam_unkD2C; + if ((grapple_beam_unkD26 & 0x8000u) == 0) { + if (grapple_beam_unkD26 >= g_word_9BC11E) + grapple_beam_unkD26 = g_word_9BC11E; + } else if ((uint16)-grapple_beam_unkD26 >= g_word_9BC11E) { + grapple_beam_unkD26 = -g_word_9BC11E; + } +} + +void GrappleBeamFunc_BD44(void) { // 0x9BBD44 + if (grapple_beam_unkD30 && (button_config_jump_a & joypad1_newkeys) != 0) { + if (grapple_beam_unkD26) { + if ((grapple_beam_unkD26 & 0x8000u) != 0) { + if (grapple_beam_flags && (grapple_beam_flags & 1) != 0) + grapple_beam_unkD2E = -(g_word_9BC120 >> 1); + else + grapple_beam_unkD2E = -g_word_9BC120; + } else if (grapple_beam_flags && (grapple_beam_flags & 1) != 0) { + grapple_beam_unkD2E = g_word_9BC120 >> 1; + } else { + grapple_beam_unkD2E = g_word_9BC120; + } + } else { + grapple_beam_unkD2E = 0; + } + } +} + +void GrappleBeamFunc_BD95(void) { // 0x9BBD95 + int16 v4; + int16 v5; + int16 v6; + + uint16 v0 = abs16(grapple_beam_unkD26); + uint16 v1; + + if (!sign16(v0 - 64)) { + slow_grabble_scrolling_flag = 1; +LABEL_7: + samus_anim_frame_timer = 15; + v1 = kGrappleBeam_SwingingData[HIBYTE(grapple_beam_end_angles_mirror)]; + samus_anim_frame = v1; + goto LABEL_8; + } + slow_grabble_scrolling_flag = 0; + if (grapple_beam_end_angle << 8 != 0x8000) + goto LABEL_7; + if (sign16(samus_anim_frame - 64)) { + samus_anim_frame_timer = 8; + samus_anim_frame = 64; + } + v1 = kGrappleBeam_SwingingData[HIBYTE(grapple_beam_end_angles_mirror)]; +LABEL_8:; + uint16 v2 = 2 * v1; + if ((abs16(grapple_beam_unkD2E) & 0xFF00) == 256) { + uint16 v3 = samus_anim_frame; + if (!sign16(samus_anim_frame - 64)) + v3 = 16; + samus_anim_frame = v3 + 32; + } + if (samus_pose_x_dir == 4) { + v6 = kGrappleBeam_SwingingData2[v2]; + if ((v6 & 0x80) != 0) + v6 |= 0xFF00u; + samus_x_pos = x_pos_of_start_of_grapple_beam + v6; + v5 = kGrappleBeam_SwingingData2[v2 + 1]; + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + } else { + v4 = kGrappleBeam_SwingingData3[v2]; + if ((v4 & 0x80) != 0) + v4 |= 0xFF00u; + samus_x_pos = x_pos_of_start_of_grapple_beam + v4; + v5 = kGrappleBeam_SwingingData3[v2 + 1]; + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + } + samus_y_pos = y_pos_of_start_of_grapple_beam + v5; + x_pos_of_start_of_grapple_beam_prevframe = x_pos_of_start_of_grapple_beam; + y_pos_of_start_of_grapple_beam_prevframe = y_pos_of_start_of_grapple_beam; + GrappleBeamFunc_BE98(); +} + +void GrappleBeamFunc_BE98(void) { // 0x9BBE98 + int16 v0; + int16 v1; + + v0 = samus_x_pos - samus_prev_x_pos; + if ((int16)(samus_x_pos - samus_prev_x_pos) < 0) { + if (sign16(v0 + 12)) + samus_prev_x_pos = samus_x_pos + 12; + } else if (!sign16(v0 - 13)) { + samus_prev_x_pos = samus_x_pos - 12; + } + v1 = samus_y_pos - samus_prev_y_pos; + if ((int16)(samus_y_pos - samus_prev_y_pos) < 0) { + if (sign16(v1 + 12)) + samus_prev_y_pos = samus_y_pos + 12; + } else if (!sign16(v1 - 13)) { + samus_prev_y_pos = samus_y_pos - 12; + } +} + +void GrappleBeamFunc_BEEB(void) { // 0x9BBEEB + int v0 = grapple_beam_direction; + samus_x_pos = x_pos_of_start_of_grapple_beam - kGrappleBeam_OriginX_NoRun[v0]; + x_pos_of_start_of_grapple_beam_prevframe = kGrappleBeam_0x0d1a_offs_NoRun[v0] + samus_x_pos; + samus_y_pos = y_pos_of_start_of_grapple_beam - kGrappleBeam_OriginY_NoRun[v0]; + y_pos_of_start_of_grapple_beam_prevframe = kGrappleBeam_0x0d1c_offs_NoRun[v0] + samus_y_pos; +} + +void GrappleBeamFunc_BF1B(void) { // 0x9BBF1B + R22_ = *(&kPoseParams[0].y_offset_to_gfx + (uint16)(8 * samus_pose)); + uint16 v0 = 2 * grapple_beam_direction; + if (samus_pose == kPose_49_FaceL_Moonwalk || samus_pose == kPose_4A_FaceR_Moonwalk || samus_movement_type != 1) { + int v1 = v0 >> 1; + x_pos_of_start_of_grapple_beam = kGrappleBeam_OriginX_NoRun[v1] + samus_x_pos; + x_pos_of_start_of_grapple_beam_prevframe = kGrappleBeam_0x0d1a_offs_NoRun[v1] + samus_x_pos; + y_pos_of_start_of_grapple_beam = kGrappleBeam_OriginY_NoRun[v1] + samus_y_pos - R22_; + y_pos_of_start_of_grapple_beam_prevframe = kGrappleBeam_0x0d1c_offs_NoRun[v1] + samus_y_pos - R22_; + } else { + int v2 = v0 >> 1; + x_pos_of_start_of_grapple_beam = kGrappleBeam_OriginX_Run[v2] + samus_x_pos; + x_pos_of_start_of_grapple_beam_prevframe = kGrappleBeam_0x0d1a_offs_Run[v2] + samus_x_pos; + y_pos_of_start_of_grapple_beam = kGrappleBeam_OriginY_Run[v2] + samus_y_pos - R22_; + y_pos_of_start_of_grapple_beam_prevframe = kGrappleBeam_0x0d1c_offs_Run[v2] + samus_y_pos - R22_; + } +} + +void UpdateGrappleBeamTilesAndIncrFlameCtr(void) { // 0x9BBFA5 + UpdateGrappleBeamTiles(); + if (sign16(flare_counter - 120)) + ++flare_counter; +} + +void UpdateGrappleBeamTiles(void) { // 0x9BBFBD + if ((--grapple_point_anim_timer & 0x8000u) != 0) { + grapple_point_anim_timer = 5; + grapple_point_anim_ptr += 512; + if ((int16)(grapple_point_anim_ptr - g_off_9BC344) >= 0) + grapple_point_anim_ptr = g_off_9BC342; + } + uint16 v0 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 32; + v0 += 2; + gVramWriteEntry(v0)->size = grapple_point_anim_ptr; + v0 += 2; + LOBYTE(gVramWriteEntry(v0++)->size) = -102; + gVramWriteEntry(v0)->size = 25088; + vram_write_queue_tail = v0 + 2; + uint16 v1 = (grapple_beam_end_angle >> 1) & 0xFE; + v0 += 2; + gVramWriteEntry(v0)->size = 128; + v0 += 2; + gVramWriteEntry(v0)->size = g_off_9BC346[v1 >> 1]; + v0 += 2; + LOBYTE(gVramWriteEntry(v0++)->size) = -102; + gVramWriteEntry(v0)->size = 25104; + vram_write_queue_tail = v0 + 2; +} + +void HandleGrappleBeamFlare(void) { // 0x9BC036 + if (flare_counter) { + if (flare_counter == 1) { + flare_animation_frame = 16; + flare_animation_timer = 3; + } + if ((--flare_animation_timer & 0x8000u) != 0) { + uint16 v0 = ++flare_animation_frame; + if (kFlareAnimDelays_Main[flare_animation_frame] == 254) { + R18_ = kFlareAnimDelays_Main[(uint16)(flare_animation_frame + 1)]; + flare_animation_frame -= R18_; + v0 = flare_animation_frame; + } + flare_animation_timer = kFlareAnimDelays_Main[v0]; + } + if (samus_pose_x_dir == 4) + R22_ = flare_animation_frame + g_word_93A22B[0]; + else + R22_ = flare_animation_frame + g_word_93A225[0]; + R20_ = x_pos_of_start_of_grapple_beam_prevframe - layer1_x_pos; + R18_ = y_pos_of_start_of_grapple_beam_prevframe - layer1_y_pos; + if (((y_pos_of_start_of_grapple_beam_prevframe - layer1_y_pos) & 0xFF00) != 0) + ; + else + DrawBeamGrappleSpritemap(R22_); + } +} + +void CallGrappleBeamFunc(uint32 ea) { + switch (ea) { + case fnGrappleBeamFunc_BB64: GrappleBeamFunc_BB64(); return; + case fnGrappleBeamFunc_BC1F: GrappleBeamFunc_BC1F(); return; + case fnGrappleBeamFunc_BCFF: GrappleBeamFunc_BCFF(); return; + case fnGrappleBeamFunc_BD44: GrappleBeamFunc_BD44(); return; + case fnGrappleBeamFunc_BD95: GrappleBeamFunc_BD95(); return; + case fnGrappleBeamFunc_BE98: GrappleBeamFunc_BE98(); return; + case fnGrappleBeamFunc_BEEB: GrappleBeamFunc_BEEB(); return; + case fnGrappleBeamFunc_BF1B: GrappleBeamFunc_BF1B(); return; + case fnGrappleBeamFunc_Inactive: GrappleBeamFunc_Inactive(); return; + case fnGrappleBeamFunc_FireGoToCancel: GrappleBeamFunc_FireGoToCancel(); return; + case fnGrappleBeamFunc_Firing: GrappleBeamFunc_Firing(); return; + case fnGrappleBeamFunc_ConnectedLockedInPlace: GrappleBeamFunc_ConnectedLockedInPlace(); return; + case fnGrappleBeamFunc_Connected_Swinging: GrappleBeamFunc_Connected_Swinging(); return; + case fnGrappleBeamFunc_Wallgrab: GrappleBeamFunc_Wallgrab(); return; + case fnGrappleBeamFunc_C832: GrappleBeamFunc_C832(); return; + case fnGrappleBeamFunc_Cancel: GrappleBeamFunc_Cancel(); return; + case fnGrappleBeamFunc_C9CE: GrappleBeamFunc_C9CE(); return; + case fnGrappleBeamFunc_ReleaseFromSwing: GrappleBeamFunc_ReleaseFromSwing(); return; + case fnGrappleBeam_Func2: GrappleBeam_Func2(); return; + default: Unreachable(); + } +} + +void GrappleBeamHandler(void) { // 0x9BC490 + if (grapple_varCF6) + --grapple_varCF6; + samus_grapple_flags &= ~1u; + CancelGrappleBeamIfIncompatiblePose(); + CallGrappleBeamFunc(grapple_beam_function | 0x9B0000); + if (grapple_beam_function != (uint16)FUNC16(GrappleBeamFunc_Inactive) + && sign16(grapple_beam_function + 0x37AA) + && (samus_suit_palette_index & 4) == 0 + && fx_type + && (Samus_GetTopBottomBoundary(), (fx_y_pos & 0x8000u) == 0) + && sign16(fx_y_pos - R18_)) { + grapple_beam_flags |= 1u; + } else { + grapple_beam_flags &= ~1u; + } +} + +void GrappleBeamFunc_Inactive(void) { // 0x9BC4F0 + if ((button_config_shoot_x & joypad1_newkeys) != 0 || (button_config_shoot_x & joypad1_newinput_samusfilter) != 0) { + GrappleBeamFunc_FireGoToCancel(); + } else if (flare_counter) { + flare_counter = 0; + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 0; + flare_slow_sparks_anim_timer = 0; + flare_fast_sparks_anim_timer = 0; + Samus_LoadSuitPalette(); + } +} + +void GrappleBeamFunc_FireGoToCancel(void) { // 0x9BC51E + int v0; + if (samus_pose == kPose_F0_FaceR_Draygon_Move || samus_pose == kPose_BE_FaceL_Draygon_Move) { + v0 = CheckBannedDraygonGrappleDirs(samus_pose); + if (!(v0 & 0x80000000)) + goto LABEL_4; + } else { + R22_ = *(&kPoseParams[0].y_offset_to_gfx + (uint16)(8 * samus_pose)); + v0 = *(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)); + if ((v0 & 0xF0) != 0) { +LABEL_4: + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + return; + } + } + grapple_beam_direction = v0; + int v1 = v0; + grapple_beam_extension_x_velocity = kGrappleBeam_Ext_Xvel[v1]; + grapple_beam_extension_y_velocity = kGrappleBeam_Ext_Yvel[v1]; + *(uint16 *)&grapple_beam_end_subangle = kGrappleBeam_Init_EndAngle[v1]; + grapple_beam_end_angles_mirror = *(uint16 *)&grapple_beam_end_subangle; + grapple_varCF6 = 10; + if (samus_pose == kPose_49_FaceL_Moonwalk || samus_pose == kPose_4A_FaceR_Moonwalk || samus_movement_type != 1) { + grapple_beam_origin_x_offset = kGrappleBeam_OriginX_NoRun[v1]; + grapple_beam_origin_y_offset = kGrappleBeam_OriginY_NoRun[v1] - R22_; + grapple_beam_end_x_pos = kGrappleBeam_OriginX_NoRun[v1] + samus_x_pos; + x_pos_of_start_of_grapple_beam = grapple_beam_end_x_pos; + x_pos_of_start_of_grapple_beam_prevframe = kGrappleBeam_0x0d1a_offs_NoRun[v1] + samus_x_pos; + grapple_beam_end_y_pos = kGrappleBeam_OriginY_NoRun[v1] + samus_y_pos - R22_; + y_pos_of_start_of_grapple_beam = grapple_beam_end_y_pos; + y_pos_of_start_of_grapple_beam_prevframe = kGrappleBeam_0x0d1c_offs_NoRun[v1] + samus_y_pos - R22_; + } else { + grapple_beam_origin_x_offset = kGrappleBeam_OriginX_Run[v1]; + grapple_beam_origin_y_offset = kGrappleBeam_OriginY_Run[v1] - R22_; + grapple_beam_end_x_pos = kGrappleBeam_OriginX_Run[v1] + samus_x_pos; + x_pos_of_start_of_grapple_beam = grapple_beam_end_x_pos; + x_pos_of_start_of_grapple_beam_prevframe = kGrappleBeam_0x0d1a_offs_Run[v1] + samus_x_pos; + grapple_beam_end_y_pos = kGrappleBeam_OriginY_Run[v1] + samus_y_pos - R22_; + y_pos_of_start_of_grapple_beam = grapple_beam_end_y_pos; + y_pos_of_start_of_grapple_beam_prevframe = kGrappleBeam_0x0d1c_offs_Run[v1] + samus_y_pos - R22_; + } + grapple_beam_end_x_subpos = 0; + grapple_beam_end_y_subpos = 0; + grapple_beam_end_x_suboffset = 0; + grapple_beam_end_x_offset = 0; + grapple_beam_end_y_suboffset = 0; + grapple_beam_end_y_offset = 0; + grapple_beam_flags = 0; + grapple_beam_length_delta = 12; + grapple_beam_length = 0; + grapple_beam_unkD26 = 0; + grapple_beam_unkD28 = 0; + grapple_beam_unkD2A = 0; + grapple_beam_unkD2C = 0; + grapple_beam_unkD2E = 0; + grapple_beam_unkD30 = 0; + grapple_beam_unkD1E = 0; + grapple_beam_unkD20 = 0; + grapple_beam_unkD3A = 2; + grapple_beam_unkD3C = 0; + grapple_point_anim_timer = 5; + grapple_point_anim_ptr = g_off_9BC342; + grapple_beam_tmpD82 = 0; + grapple_beam_tmpD84 = 0; + grapple_beam_y_quarter_subvel = 0; + grapple_beam_y_quarter_vel = 0; + grapple_beam_tmpD8A = 0; + grapple_beam_varD8C = 0; + grapple_beam_varD8E = 0; + grapple_beam_grapple_start_x = 0; + grapple_beam_unkD38 = 0; + grapple_beam_unkD36 = 0; + slow_grabble_scrolling_flag = 0; + GrappleFunc_AF87(); + samus_draw_handler = FUNC16(sub_90EB86); + grapple_walljump_timer = 0; + LoadProjectilePalette(2u); + palette_buffer[223] = 32657; + grapple_beam_function = FUNC16(GrappleBeamFunc_Firing); + QueueSfx1_Max1(5u); + flare_counter = 1; + play_resume_charging_beam_sfx = 0; + if (samus_movement_handler == FUNC16(Samus_MoveHandler_ReleaseFromGrapple)) + samus_movement_handler = FUNC16(Samus_MovementHandler_Normal); +} + +int CheckBannedDraygonGrappleDirs(uint16 a) { // 0x9BC6B2 + if (a == kPose_BE_FaceL_Draygon_Move) { + R22_ = 6; + if ((joypad1_lastkeys & kButton_Left) != 0) { + if ((joypad1_lastkeys & kButton_Down) != 0) + return -2147483642; + if ((joypad1_lastkeys & kButton_Up) != 0) + return -2147483640; + } + return -2147483641; + } + R22_ = 6; + if ((joypad1_lastkeys & kButton_Right) == 0) + return -2147483646; + if ((joypad1_lastkeys & kButton_Down) != 0) + return -2147483645; + if ((joypad1_lastkeys & kButton_Up) == 0) + return -2147483646; + return -2147483647; +} + +uint8 ClearCarry_12(void) { // 0x9BC701 + return 0; +} + +void GrappleBeamFunc_Firing(void) { // 0x9BC703 + if ((button_config_shoot_x & joypad1_lastkeys) == 0) { + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + return; + } + grapple_beam_length += grapple_beam_length_delta; + if (!sign16(grapple_beam_length - 128)) { + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + return; + } + int v1 = ProcessEnemyGrappleBeamColl(GrappleBeam_CollDetect_Enemy()); + if (v1 >= 0) { + if (v1) { + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + return; + } + } else { + uint8 v2 = BlockCollGrappleBeam(); + if ((v2 & 1) == 0) + return; + if ((v2 & 0x40) == 0) { + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + return; + } + } + QueueSfx1_Max6(6u); + HandleConnectingGrapple(); + grapple_beam_length_delta = -8; + samus_grapple_flags |= 1u; +} + +void UNUSED_sub_9BC759(void) { // 0x9BC759 + if ((button_config_shoot_x & joypad1_lastkeys) == 0 + || (grapple_beam_length -= grapple_beam_length_delta, sign16(grapple_beam_length - 13))) { + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + } else { + BlockCollGrappleBeam(); + } +} + +void GrappleBeamFunc_ConnectedLockedInPlace(void) { // 0x9BC77E + if ((button_config_shoot_x & joypad1_lastkeys) != 0 + && (GrappleBeam_CollDetect_Enemy() || CheckIfGrappleIsConnectedToBlock() & 1)) { + ClearCarry_11(); + } else { + grapple_beam_function = FUNC16(GrappleBeamFunc_Cancel); + } +} + +void GrappleBeamFunc_Connected_Swinging(void) { // 0x9BC79D + if ((button_config_shoot_x & joypad1_lastkeys) != 0) { + GrappleBeamFunc_BB64(); + if (grapple_beam_length_delta) + BlockFunc_AC31(); + GrappleBeamFunc_BC1F(); + GrappleBeamFunc_BCFF(); + GrappleBeamFunc_BD44(); + HandleMovementAndCollForSamusGrapple(); + if ((grapple_beam_unkD36 & 0x8000u) != 0 && HandleSpecialGrappleBeamAngles() & 1) { + ClearCarry_11(); + return; + } + if (GrappleBeam_CollDetect_Enemy()) { + grapple_beam_flags |= 0x8000u; + } else if (!(CheckIfGrappleIsConnectedToBlock() & 1)) { + goto LABEL_2; + } + BlockFunc_AC11(); + ClearCarry_11(); + GrappleBeamFunc_BD95(); + return; + } +LABEL_2: + if (grapple_beam_unkD26 || *(uint16 *)&grapple_beam_end_subangle != 0x8000) { + PropelSamusFromGrappleSwing(); + grapple_beam_function = FUNC16(GrappleBeamFunc_ReleaseFromSwing); + samus_movement_handler = FUNC16(Samus_MoveHandler_ReleaseFromGrapple); + } else { + grapple_beam_function = FUNC16(GrappleBeam_Func2); + } +} + +void GrappleBeamFunc_Wallgrab(void) { // 0x9BC814 + if ((button_config_shoot_x & joypad1_lastkeys) != 0 && CheckIfGrappleIsConnectedToBlock() & 1) { + ClearCarry_11(); + } else { + grapple_walljump_timer = 30; + grapple_beam_function = FUNC16(GrappleBeamFunc_C832); + } +} + +void GrappleBeamFunc_C832(void) { // 0x9BC832 + if ((--grapple_walljump_timer & 0x8000u) == 0) { + R18_ = 16; + R20_ = 0; + if (Samus_GrappleWallJumpCheck() & 1) + grapple_beam_function = FUNC16(GrappleBeamFunc_C9CE); + } else { + grapple_beam_function = FUNC16(GrappleBeam_Func2); + } +} + +void GrappleBeamFunc_Cancel(void) { // 0x9BC856 + QueueSfx1_Max15(7u); + if (samus_movement_type == kMovementType_16_Grappling) + Samus_Pose_CancelGrapple(); + else + CallSomeSamusCode(0x1Cu); + grapple_beam_unkD1E = 0; + grapple_beam_unkD20 = 0; + grapple_beam_direction = 0; + grapple_beam_unkD36 = 0; + grapple_walljump_timer = 0; + slow_grabble_scrolling_flag = 0; + grapple_varCF6 = 0; + grapple_beam_flags = 0; + flare_counter = 0; + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 0; + flare_slow_sparks_anim_timer = 0; + flare_fast_sparks_anim_timer = 0; + LoadProjectilePalette(equipped_beams); + grapple_beam_function = FUNC16(GrappleBeamFunc_Inactive); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + Samus_PostGrappleCollisionDetect(); + if (samus_auto_cancel_hud_item_index) { + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + } +} + +void GrappleBeam_Func2(void) { // 0x9BC8C5 + QueueSfx1_Max15(7u); + if (samus_pose == kPose_B2_FaceR_Grapple_Air) + goto LABEL_5; + if (samus_pose == kPose_B3_FaceL_Grapple_Air) { +LABEL_6: + samus_new_pose_transitional = kPose_02_FaceL_Normal; + goto LABEL_15; + } + if (sign16(samus_y_radius - 17)) { + if ((*(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)) & 0xF0) != 0) { + if (samus_pose_x_dir == 4) + samus_new_pose_transitional = kPose_28_FaceL_Crouch; + else + samus_new_pose_transitional = kPose_27_FaceR_Crouch; + } else { + samus_new_pose_transitional = g_byte_9BC9C4[*(&kPoseParams[0].direction_shots_fired + + (uint16)(8 * samus_pose))]; + } + goto LABEL_15; + } + if ((*(&kPoseParams[0].direction_shots_fired + (uint16)(8 * samus_pose)) & 0xF0) != 0) { + if (samus_pose_x_dir != 4) { +LABEL_5: + samus_new_pose_transitional = kPose_01_FaceR_Normal; + goto LABEL_15; + } + goto LABEL_6; + } + samus_new_pose_transitional = g_byte_9BC9BA[*(&kPoseParams[0].direction_shots_fired + + (uint16)(8 * samus_pose))]; +LABEL_15: + samus_hurt_switch_index = 0; + input_to_pose_calc = 1; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + grapple_beam_unkD1E = 0; + grapple_beam_unkD20 = 0; + grapple_beam_direction = 0; + grapple_beam_unkD36 = 0; + grapple_walljump_timer = 0; + slow_grabble_scrolling_flag = 0; + grapple_varCF6 = 0; + grapple_beam_flags = 0; + flare_counter = 0; + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 0; + flare_slow_sparks_anim_timer = 0; + flare_fast_sparks_anim_timer = 0; + LoadProjectilePalette(equipped_beams); + grapple_beam_function = FUNC16(GrappleBeamFunc_Inactive); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + Samus_PostGrappleCollisionDetect(); + if (samus_auto_cancel_hud_item_index) { + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + } +} + +void GrappleBeamFunc_C9CE(void) { // 0x9BC9CE + QueueSfx1_Max15(7u); + if (samus_pose_x_dir == 8) + samus_new_pose_transitional = kPose_84_FaceL_Walljump; + else + samus_new_pose_transitional = kPose_83_FaceR_Walljump; + samus_hurt_switch_index = 6; + samus_x_accel_mode = 0; + samus_collides_with_solid_enemy = 0; + samus_is_falling_flag = 0; + UNUSED_word_7E0B1A = 0; + UNUSED_word_7E0B2A = 0; + samus_y_subspeed = 0; + samus_y_speed = 0; + samus_y_dir = 0; + UNUSED_word_7E0B38 = 0; + samus_x_base_speed = 0; + samus_x_base_subspeed = 0; + grapple_beam_unkD1E = 0; + grapple_beam_unkD20 = 0; + grapple_beam_direction = 0; + grapple_beam_unkD36 = 0; + grapple_walljump_timer = 0; + slow_grabble_scrolling_flag = 0; + grapple_varCF6 = 0; + grapple_beam_flags = 0; + flare_counter = 0; + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 0; + flare_slow_sparks_anim_timer = 0; + flare_fast_sparks_anim_timer = 0; + LoadProjectilePalette(equipped_beams); + grapple_beam_function = FUNC16(GrappleBeamFunc_Inactive); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + Samus_PostGrappleCollisionDetect(); + if (samus_auto_cancel_hud_item_index) { + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + } +} + +void PropelSamusFromGrappleSwing(void) { // 0x9BCA65 + int16 v1; + int16 v2; + uint16 v0; + + if ((grapple_beam_unkD26 & 0x8000u) == 0) { + v0 = 2 * grapple_beam_unkD26; + v2 = kSinCosTable8bit_Sext[((uint16)(2 * HIBYTE(*(uint16 *)&grapple_beam_end_subangle)) >> 1) + 64]; + if (v2 >= 0) { + Multiply16x16(v2, v0); + samus_y_subspeed = mult_product_lo; + samus_y_speed = mult_product_hi; + samus_y_dir = 2; + } else { + Multiply16x16(-v2, v0); + samus_y_subspeed = mult_product_lo; + samus_y_speed = mult_product_hi; + samus_y_dir = 1; + } + } else { + v0 = -2 * grapple_beam_unkD26; + v1 = kSinCosTable8bit_Sext[((uint16)(2 * HIBYTE(*(uint16 *)&grapple_beam_end_subangle)) >> 1) + 64]; + if (v1 < 0) { + Multiply16x16(-v1, v0); + samus_y_subspeed = mult_product_lo; + samus_y_speed = mult_product_hi; + samus_y_dir = 2; + } else { + Multiply16x16(v1, v0); + samus_y_subspeed = mult_product_lo; + samus_y_speed = mult_product_hi; + samus_y_dir = 1; + } + } + samus_x_accel_mode = 2; + R18_ = 3 * (v0 >> 9); + R18_ = 64 - R18_; + uint16 v3 = abs16(kSinCosTable8bit_Sext[((uint16)(2 * (uint8)(grapple_beam_end_angle - R18_)) >> 1) + 64]); + Multiply16x16(v3, v0); + samus_x_base_subspeed = mult_product_lo; + samus_x_base_speed = mult_product_hi; +} + +void GrappleBeamFunc_ReleaseFromSwing(void) { // 0x9BCB8B + QueueSfx1_Max15(7u); + if ((grapple_beam_unkD26 & 0x8000u) == 0) + samus_new_pose_transitional = kPose_52_FaceL_Jump_NoAim_MoveF; + else + samus_new_pose_transitional = kPose_51_FaceR_Jump_NoAim_MoveF; + samus_hurt_switch_index = 7; + grapple_beam_unkD1E = 0; + grapple_beam_unkD20 = 0; + grapple_beam_direction = 0; + grapple_beam_unkD36 = 0; + grapple_walljump_timer = 0; + slow_grabble_scrolling_flag = 0; + grapple_varCF6 = 0; + grapple_beam_flags = 0; + flare_counter = 0; + flare_animation_frame = 0; + flare_slow_sparks_anim_frame = 0; + flare_fast_sparks_anim_frame = 0; + flare_animation_timer = 0; + flare_slow_sparks_anim_timer = 0; + flare_fast_sparks_anim_timer = 0; + LoadProjectilePalette(equipped_beams); + grapple_beam_function = FUNC16(GrappleBeamFunc_Inactive); + samus_draw_handler = FUNC16(SamusDrawHandler_Default); + Samus_PostGrappleCollisionDetect(); + if (samus_auto_cancel_hud_item_index) { + hud_item_index = 0; + samus_auto_cancel_hud_item_index = 0; + } +} diff --git a/src/sm_a0.c b/src/sm_a0.c new file mode 100644 index 0000000..ac07077 --- /dev/null +++ b/src/sm_a0.c @@ -0,0 +1,4718 @@ +// Enemies +#include "sm_rtl.h" +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" + +#define kEnemyLayerToQueuePtr ((uint16*)RomPtr(0xa0b133)) + +void Enemy_GrappleReact_NoInteract_A0(void) { // 0xA08000 + SwitchEnemyAiToMainAi(); +} + +void Enemy_GrappleReact_SamusLatchesOn_A0(void) { // 0xA08005 + SamusLatchesOnWithGrapple(); +} + +void Enemy_GrappleReact_KillEnemy_A0(void) { // 0xA0800A + EnemyGrappleDeath(); +} + +void Enemy_GrappleReact_CancelBeam_A0(void) { // 0xA0800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_GrappleReact_SamusLatchesNoInvinc_A0(void) { // 0xA08014 + SamusLatchesOnWithGrappleNoInvinc(); +} + +void Enemy_GrappleReact_SamusLatchesParalyze_A0(void) { // 0xA08019 + SamusLatchesOnWithGrappleParalyze(); +} + +void Enemy_GrappleReact_HurtSamus_A0(void) { // 0xA0801E + SamusHurtFromGrapple(); +} + +void Enemy_NormalTouchAI_A0(void) { // 0xA08023 + NormalEnemyTouchAi(); +} + +void Enemy_NormalTouchAI_SkipDeathAnim_A0(void) { // 0xA08028 + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); +} + +void Enemy_NormalShotAI_A0(void) { // 0xA0802D + NormalEnemyShotAi(); +} + +void Enemy_NormalShotAI_SkipSomeParts_A0(void) { // 0xA08032 + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); +} + +void Enemy_NormalPowerBombAI_A0(void) { // 0xA08037 + NormalEnemyPowerBombAi(); +} + +void Enemy_NormalPowerBombAI_SkipDeathAnim_A0(void) { // 0xA0803C + NormalEnemyPowerBombAiSkipDeathAnim_CurEnemy(); +} + +void Enemy_NormalFrozenAI(void) { // 0xA08041 + NormalEnemyFrozenAI(); +} + +void CreateADudShot(void) { // 0xA08046 + CreateDudShot(); +} + +void func_nullsub_169(void) { + ; +} + +void func_nullsub_170(void) { + ; +} + +uint16 EnemyInstr_SetAiPreInstr(uint16 k, uint16 j) { // 0xA0806B + uint16 v2 = *(uint16 *)RomPtr_A0(j); + gEnemyData(k)->ai_preinstr = v2; + return j + 2; +} + +uint16 EnemyInstr_ClearAiPreInstr(uint16 k, uint16 j) { // 0xA08074 + gEnemyData(k)->ai_preinstr = FUNC16(nullsub_171); + return j; +} + +void func_nullsub_171(void) { + ; +} + +uint16 EnemyInstr_StopScript(uint16 k, uint16 j) { // 0xA0807C + EnemyData *v2 = gEnemyData(k); + v2->properties |= kEnemyProps_Deleted; + return 0; +} + +uint16 EnemyInstr_Goto(uint16 k, uint16 j) { // 0xA080ED + return *(uint16 *)RomPtr_A0(j); +} + +uint16 EnemyInstr_GotoRel(uint16 k, uint16 j) { // 0xA080F2 + int16 v2; + + R18_ = j; + LOBYTE(v2) = HIBYTE(*(uint16 *)RomPtr_A0(j - 1)); + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + else + v2 = (uint8)v2; + return R18_ + v2; +} + +uint16 EnemyInstr_DecTimerAndGoto(uint16 k, uint16 j) { // 0xA08108 + EnemyData *v2 = gEnemyData(k); + if (v2->timer-- == 1) + return j + 2; + else + return EnemyInstr_Goto(k, j); +} + +uint16 EnemyInstr_DecTimerAndGoto2(uint16 k, uint16 j) { // 0xA08110 + EnemyData *v2 = gEnemyData(k); + if (v2->timer-- == 1) + return j + 2; + else + return EnemyInstr_Goto(k, j); +} + +uint16 EnemyInstr_DecTimerAndGotoRel(uint16 k, uint16 j) { // 0xA08118 + EnemyData *v2 = gEnemyData(k); + if (LOBYTE(v2->timer)-- == 1) + return j + 1; + else + return EnemyInstr_GotoRel(k, j); +} + +uint16 EnemyInstr_SetTimer(uint16 k, uint16 j) { // 0xA08123 + uint16 v2 = *(uint16 *)RomPtr_A0(j); + gEnemyData(k)->timer = v2; + return j + 2; +} + +uint16 EnemyInstr_Skip2bytes(uint16 k, uint16 j) { // 0xA0812C + return j + 2; +} + +uint16 EnemyInstr_Sleep(uint16 k, uint16 j) { // 0xA0812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + +uint16 EnemyInstr_WaitNframes(uint16 k, uint16 j) { // 0xA0813A + uint16 v2 = *(uint16 *)RomPtr_A0(j); + EnemyData *v3 = gEnemyData(k); + v3->instruction_timer = v2; + v3->current_instruction = j + 2; + return 0; +} + +uint16 EnemyInstr_CopyToVram(uint16 k, uint16 j) { // 0xA0814B + VramWriteEntry *v4; + + uint16 v2 = vram_write_queue_tail; + uint8 *v3 = RomPtr_A0(j); + v4 = gVramWriteEntry(vram_write_queue_tail); + v4->size = *(uint16 *)v3; + v4->src.addr = *((uint16 *)v3 + 1); + *(VoidP *)((char *)&v4->src.addr + 1) = *(uint16 *)(v3 + 3); + v4->vram_dst = *(uint16 *)(v3 + 5); + vram_write_queue_tail = v2 + 7; + return j + 7; +} + +uint16 EnemyInstr_EnableOffScreenProcessing(uint16 k, uint16 j) { // 0xA08173 + EnemyData *v2 = gEnemyData(k); + v2->properties |= 0x800u; + return j; +} + +uint16 EnemyInstr_DisableOffScreenProcessing(uint16 k, uint16 j) { // 0xA0817D + EnemyData *v2 = gEnemyData(k); + v2->properties &= ~0x800u; + return j; +} + +static const uint16 kRoomShakes[144] = { // 0xA08687 + 1, 0, 0, 0, + 0, 1, 0, 0, + 1, 1, 0, 0, + 2, 0, 0, 0, + 0, 2, 0, 0, + 2, 2, 0, 0, + 3, 0, 0, 0, + 0, 3, 0, 0, + 3, 3, 0, 0, + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 1, 1, 1, + 2, 0, 2, 0, + 0, 2, 0, 2, + 2, 2, 2, 2, + 3, 0, 3, 0, + 0, 3, 0, 3, + 3, 3, 3, 3, + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 1, 1, 1, + 2, 0, 2, 0, + 0, 2, 0, 2, + 2, 2, 2, 2, + 3, 0, 3, 0, + 0, 3, 0, 3, + 3, 3, 3, 3, + 0, 0, 1, 0, + 0, 0, 0, 1, + 0, 0, 1, 1, + 0, 0, 2, 0, + 0, 0, 0, 2, + 0, 0, 2, 2, + 0, 0, 3, 0, + 0, 0, 0, 3, + 0, 0, 3, 3, +}; + +void HandleRoomShaking(void) { + + if (earthquake_timer && !time_is_frozen_flag && sign16(earthquake_type - 36)) { + int v0 = (uint16)(8 * earthquake_type) >> 1; + if ((earthquake_timer & 2) != 0) { + reg_BG1HOFS -= kRoomShakes[v0]; + reg_BG1VOFS -= kRoomShakes[v0 + 1]; + reg_BG2HOFS -= kRoomShakes[v0 + 2]; + reg_BG2VOFS -= kRoomShakes[v0 + 3]; + } else { + reg_BG1HOFS += kRoomShakes[v0]; + reg_BG1VOFS += kRoomShakes[v0 + 1]; + reg_BG2HOFS += kRoomShakes[v0 + 2]; + reg_BG2VOFS += kRoomShakes[v0 + 3]; + } + --earthquake_timer; + if (!sign16(earthquake_type - 18)) + SetAllEnemiesToShakeFor2Frames(); + } + ++frame_counter_every_frame; +} + +void SetAllEnemiesToShakeFor2Frames(void) { // 0xA08712 + for (int i = 0; ; i += 2) { + int v1 = i >> 1; + if (active_enemy_indexes[v1] == 0xFFFF) + break; + gEnemyData(active_enemy_indexes[v1])->shake_timer = 2; + } +} + +void CallEnemyGfxDrawHook(uint32 ea) { + switch (ea) { + case fnnullsub_170: return; // 0xa0804c + case fnReflec_Func_1: Reflec_Func_1(); return; // 0xa3db0c + case fnDraygon_Func_36: Draygon_Func_36(); return; // 0xa59342 + case fnRidley_A2F2: Ridley_A2F2(); return; // 0xa6a2f2 + case fnnullsub_170_A8: return; // 0xa8804c + case fnNorfairLavaMan_Func_6: NorfairLavaMan_Func_6(); return; // 0xa8b0b2 + case fnWreckedShipRobot_Func_1: WreckedShipRobot_Func_1(); return; // 0xa8cc67 + case fnBlueBrinstarFaceBlock_Func_1: BlueBrinstarFaceBlock_Func_1(); return; // 0xa8e86e + case fnnullsub_264: return; // 0xa98786 + case fnMotherBrain_DrawBrainNeck_EnemyGfxDrawHook: MotherBrain_DrawBrainNeck_EnemyGfxDrawHook(); return; // 0xa987c9 + case fnMotherBrainsBrain_GfxDrawHook: MotherBrainsBrain_GfxDrawHook(); return; // 0xa987dd + case fnDeadTorizo_MainGfxHook: DeadTorizo_MainGfxHook(); return; // 0xa9d39a + default: Unreachable(); + } +} + +void DrawSamusEnemiesAndProjectiles(void) { // 0xA0884D + DrawSpriteObjects(); + DrawBombAndProjectileExplosions(); + DrawLowPriorityEnemyProjectiles(); + for (draw_enemy_layer = 0; draw_enemy_layer != 8; ++draw_enemy_layer) { + if (draw_enemy_layer == 3) { + DrawSamusAndProjectiles(); + } else if (draw_enemy_layer == 6) { + DrawHighPriorityEnemyProjectiles(); + } + int v0 = draw_enemy_layer; + if (enemy_drawing_queue_sizes[v0]) { + loop_index_end = enemy_drawing_queue_sizes[v0]; + enemy_drawing_queue_base = kEnemyLayerToQueuePtr[v0]; + uint16 v1 = 0; + enemy_drawing_queue_sizes[v0] = 0; + do { + loop_index = v1; + uint8 *v2 = RomPtr_RAM(enemy_drawing_queue_base + v1); + uint16 v3 = *(uint16 *)v2; + *(uint16 *)v2 = 0; + cur_enemy_index = v3; + WriteEnemyOams(); + v1 = loop_index + 2; + } while (loop_index + 2 != loop_index_end); + } + } + CallEnemyGfxDrawHook(Load24(&enemy_gfx_drawn_hook)); +} + +void RecordEnemySpawnData(uint16 j) { // 0xA088D0 + EnemySpawnData *v2; + EnemySpawnData *v5; + + EnemyData *v1 = gEnemyData(j); + v2 = gEnemySpawnData(j); + v2->id = v1->enemy_ptr; + v2->x_pos = v1->x_pos; + v2->y_pos = v1->y_pos; + v2->init_param = v1->current_instruction; + v2->properties = v1->properties; + v2->extra_properties = v1->extra_properties; + v2->param_1 = v1->parameter_1; + v2->param_2 = v1->parameter_2; + R18_ = 0; + R20_ = 0; + R22_ = 0; + R24_ = 0; + R26_ = 0; + R28_ = 0; + uint16 name_ptr = get_EnemyDef_A2(v1->enemy_ptr)->name_ptr; + if (name_ptr) { + uint16 *v4 = (uint16 *)RomPtr_B4(name_ptr); + R18_ = *v4; + R20_ = v4[1]; + R22_ = v4[2]; + R24_ = v4[3]; + R26_ = v4[4]; + R28_ = v4[6]; + } + v5 = gEnemySpawnData(j); + *(uint16 *)v5->name = R18_; + *(uint16 *)&v5->name[2] = R20_; + *(uint16 *)&v5->name[4] = R22_; + *(uint16 *)&v5->name[6] = R24_; + *(uint16 *)&v5->name[8] = R26_; + *(uint16 *)&v5->name[10] = R28_; +} + +void DebugLoadEnemySetData(void) { // 0xA0896F + int16 v1; + + uint16 v0 = 0; + v1 = 160; + do { + *(uint16 *)&debug_enemy_set_name[v0] = 0; + v0 += 2; + v1 -= 2; + } while (v1); + uint8 *v2 = RomPtr_B4(room_enemy_tilesets_ptr - 7); + *(uint16 *)debug_enemy_set_name = *(uint16 *)v2; + *(uint16 *)&debug_enemy_set_name[2] = *((uint16 *)v2 + 1); + *(uint16 *)&debug_enemy_set_name[4] = *((uint16 *)v2 + 2); + *(uint16 *)&debug_enemy_set_name[6] = *((uint16 *)v2 + 3); + uint16 v3 = 7; + for (int i = room_enemy_tilesets_ptr; ; i += 4) { + uint16 v5 = *(uint16 *)RomPtr_B4(i); + if (v5 == 0xFFFF) + break; + uint16 v6 = *((uint16 *)RomPtr_A0(v5) + 31); + if (!v6) + v6 = addr_asc_B4DD89; + uint16 *v7 = (uint16 *)RomPtr_B4(v6); + R18_ = *v7; + R20_ = v7[1]; + R22_ = v7[2]; + R24_ = v7[3]; + R26_ = v7[4]; + *(uint16 *)&debug_enemy_set_name[v3] = R18_; + *(uint16 *)&debug_enemy_set_name[v3 + 2] = R20_; + *(uint16 *)&debug_enemy_set_name[v3 + 4] = R22_; + *(uint16 *)&debug_enemy_set_name[v3 + 6] = R24_; + *(uint16 *)&debug_enemy_set_data[v3] = R26_; + *(uint16 *)&debug_enemy_set_data[v3 + 2] = *((uint16 *)RomPtr_B4(i) + 1); + v3 += 12; + } +} + +void LoadEnemies(void) { // 0xA08A1E + // DebugLoadEnemySetData(); + debug_time_frozen_for_enemies = 0; + *(uint16 *)&enemy_gfx_drawn_hook.bank = 160; + enemy_gfx_drawn_hook.addr = FUNC16(nullsub_170); + *(uint16 *)&set_to_rtl_when_loading_enemies_unused.bank = 160; + set_to_rtl_when_loading_enemies_unused.addr = FUNC16(nullsub_170); + enemy_bg2_tilemap_size = 2048; + UNUSED_word_7E179E = 0; + UNUSED_word_7E17A0 = 0; + boss_id = 0; + ClearEnemyDataAndProcessEnemySet(); + LoadEnemyTileData(); + enemy_tile_vram_src = 0; + flag_disable_projectile_interaction = 0; + ClearSpriteObjects(); +} + +void ClearEnemyDataAndProcessEnemySet(void) { // 0xA08A6D + int16 v0; + + v0 = 2048; + uint16 v1 = 0; + do { + gEnemyData(v1)->enemy_ptr = 0; + v1 += 2; + v0 -= 2; + } while (v0); + if (*(uint16 *)RomPtr_A1(room_enemy_population_ptr) != 0xFFFF) + ProcessEnemyTilesets(); +} + +void InitializeEnemies(void) { // 0xA08A9E + int16 v0; + uint16 j; + EnemyPopulation *v9; + EnemyDef_A2 *v10; + EnemyPopulation *EnemyPopulation; + EnemyDef_A2 *EnemyDef_A2; + + v0 = 5120; + uint16 v1 = 0; + do { + gEnemySpawnData(v1)->some_flag = 0; + v1 += 2; + --v0; + } while (v0); + num_enemies_in_room = 0; + num_enemies_killed_in_room = 0; + flag_process_all_enemies = 0; + for (int i = 286; i >= 0; i -= 2) + enemy_projectile_flags[i >> 1] = 0; + for (j = 34; (j & 0x8000u) == 0; j -= 2) + enemy_projectile_killed_enemy_index[j >> 1] = -1; + uint16 v4 = room_enemy_population_ptr; + if (get_EnemyPopulation(0xa1, room_enemy_population_ptr)->enemy_ptr != 0xFFFF) { + UNUSED_word_7E0E48 = 0; + uint16 v5 = 0; + do { + LoadEnemyGfxIndexes(v4, v5); + uint16 v13 = v4; + EnemyPopulation = get_EnemyPopulation(0xa1, v4); + EnemyDef_A2 = get_EnemyDef_A2(EnemyPopulation->enemy_ptr); + uint16 *v8 = (uint16 *)gEnemyData(v5); + v8[5] = EnemyDef_A2->x_radius; + v8[6] = EnemyDef_A2->y_radius; + v8[10] = EnemyDef_A2->health; + v8[17] = EnemyDef_A2->layer; + v8[23] = *(uint16 *)&EnemyDef_A2->bank; + if (EnemyDef_A2->boss_fight_value) + boss_id = EnemyDef_A2->boss_fight_value; + v9 = get_EnemyPopulation(0xa1, v4); + *v8 = v9->enemy_ptr; + v8[1] = v9->x_pos; + v8[3] = v9->y_pos; + v8[13] = v9->init_param; + v8[7] = v9->properties; + v8[8] = v9->extra_properties; + v8[30] = v9->parameter1; + v8[31] = v9->parameter2; + v8[22] = 0; + v8[12] = 0; + v8[14] = 1; + v8[22] = 0; + RecordEnemySpawnData(v5); + cur_enemy_index = v5; + v10 = get_EnemyDef_A2(*v8); + enemy_ai_pointer.addr = v10->ai_init; + *(uint16 *)&enemy_ai_pointer.bank = *(uint16 *)&v10->bank; + CallEnemyAi(Load24(&enemy_ai_pointer)); + EnemyData *v11 = gEnemyData(v5); + v11->spritemap_pointer = 0; + if ((v11->properties & 0x2000) != 0) { + uint16 v12 = addr_kSpritemap_Nothing_A4; + if ((v11->extra_properties & 4) != 0) + v12 = addr_kExtendedSpritemap_Nothing_A4; + v11->spritemap_pointer = v12; + v4 = v13; + } + v5 += 64; + v4 += 16; + } while (get_EnemyPopulation(0xa1, v4)->enemy_ptr != 0xFFFF); + first_free_enemy_index = v5; + num_enemies_in_room = v5 >> 6; + num_enemy_deaths_left_to_clear = RomPtr_A1(v4)[2]; + } +} + +void LoadEnemyGfxIndexes(uint16 k, uint16 j) { // 0xA08BF3 + VoidP enemy_ptr; + EnemyTileset *EnemyTileset; + EnemySpawnData *v6; + EnemySpawnData *v10; + + R18_ = k; + R20_ = j; + R28_ = room_enemy_tilesets_ptr; + g_word_7E001E = 0; + while (1) { + enemy_ptr = get_EnemyPopulation(0xa1, R18_)->enemy_ptr; + EnemyTileset = get_EnemyTileset(R28_); + if (enemy_ptr == EnemyTileset->enemy_def) + break; + if (EnemyTileset->enemy_def == 0xFFFF) { + uint16 v4 = R20_; + EnemyData *v5 = gEnemyData(R20_); + v5->vram_tiles_index = 0; + v6 = gEnemySpawnData(v4); + v6->vram_tiles_index = 0; + v5->palette_index = 2560; + v6->palette_index = 2560; + return; + } + g_word_7E001E += get_EnemyDef_A2(EnemyTileset->enemy_def)->tile_data_size >> 5; + R28_ += 4; + } + uint16 v7 = (get_EnemyTileset(R28_)->vram_dst & 0xF) << 9; + uint16 v8 = R20_; + EnemyData *v9 = gEnemyData(R20_); + v9->palette_index = v7; + v10 = gEnemySpawnData(v8); + v10->palette_index = v7; + uint16 v11 = g_word_7E001E; + v9->vram_tiles_index = g_word_7E001E; + v10->vram_tiles_index = v11; +} +#define kStandardSpriteTiles ((uint16*)RomPtr(0x9ad200)) +void LoadEnemyTileData(void) { // 0xA08C6C + for (int i = 510; i >= 0; i -= 2) + gEnemySpawnData(i)->some_flag = kStandardSpriteTiles[(i >> 1) + 3072]; + if (enemy_tile_load_data_write_pos) { + uint16 v1 = 0; + do { + EnemyTileLoadData *load_data = (EnemyTileLoadData *)((char *)enemy_tile_load_data + v1); + uint16 v2 = load_data->tile_data_ptr.addr; + R18_ = load_data->tile_data_size + v2; + uint16 v3 = load_data->offset_into_ram; + uint8 db = load_data->tile_data_ptr.bank; + do { + memcpy(&g_ram[0x7000 + v3], RomPtrWithBank(db, v2), 8); + v3 += 8; + v2 += 8; + } while (v2 != R18_); + v1 += 7; + } while (v1 != enemy_tile_load_data_write_pos); + enemy_tile_load_data_write_pos = 0; + } +} + +void TransferEnemyTilesToVramAndInit(void) { // 0xA08CD7 + VramWriteEntry *v2; + + uint16 v0 = enemy_tile_vram_src; + if (!enemy_tile_vram_src) { + v0 = ADDR16_OF_RAM(*enemy_spawn_data); + enemy_tile_vram_src = ADDR16_OF_RAM(*enemy_spawn_data); + enemy_tile_vram_dst = 0x6c00; + } + if (v0 != 0xFFFF) { + if (v0 == 0xFFFE) { + InitializeEnemies(); + enemy_tile_vram_src = -1; + } else if (v0 == 0x9800) { + enemy_tile_vram_src = -2; + } else { + uint16 v1 = vram_write_queue_tail; + v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 2048; + uint16 v3 = enemy_tile_vram_src; + v2->src.addr = enemy_tile_vram_src; + enemy_tile_vram_src = v3 + 2048; + *(uint16 *)&v2->src.bank = 126; + uint16 v4 = enemy_tile_vram_dst; + v2->vram_dst = enemy_tile_vram_dst; + enemy_tile_vram_dst = v4 + 1024; + vram_write_queue_tail = v1 + 7; + } + } +} + +void ProcessEnemyTilesets(void) { // 0xA08D64 + int16 v6; + EnemyTileset *v7; + EnemyDef_A2 *v8; + EnemyTileset *v12; + EnemyTileset *EnemyTileset; + + enemy_tile_load_data_write_pos = 0; + g_word_7E001E = 2048; + enemy_def_ptr[0] = 0; + enemy_def_ptr[1] = 0; + enemy_def_ptr[2] = 0; + enemy_def_ptr[3] = 0; + enemy_gfxdata_tiles_index[0] = 0; + enemy_gfxdata_tiles_index[1] = 0; + enemy_gfxdata_tiles_index[2] = 0; + enemy_gfxdata_tiles_index[3] = 0; + enemy_gfxdata_vram_ptr[0] = 0; + enemy_gfxdata_vram_ptr[1] = 0; + enemy_gfxdata_vram_ptr[2] = 0; + enemy_gfxdata_vram_ptr[3] = 0; + enemy_gfx_data_write_ptr = 0; + next_enemy_tiles_index = 0; + uint16 v0 = room_enemy_tilesets_ptr; + for (R28_ = room_enemy_tilesets_ptr; ; R28_ += 4) { + uint16 enemy_def = get_EnemyTileset(v0)->enemy_def; + if (enemy_def == 0xFFFF) + break; + uint16 *EnemyDef_A2 = (uint16 *)get_EnemyDef_A2(enemy_def); + R18_ = *EnemyDef_A2; + R20_ = EnemyDef_A2[1]; + enemy_population_ptr = EnemyDef_A2[6]; + EnemyTileset = get_EnemyTileset(R28_); + R22_ = Mult32(LOBYTE(EnemyTileset->vram_dst) + 8) - 15872; + uint8 v13 = enemy_population_ptr; + varE2E = 16; + uint16 v4 = R22_; + uint16 v5 = R20_; + do { + v6 = *(uint16 *)RomPtrWithBank(v13, v5); + *(uint16 *)RomPtr_7E(v4) = v6; + v4 += 2; + v5 += 2; + --varE2E; + } while (varE2E); + v7 = get_EnemyTileset(R28_); + v8 = get_EnemyDef_A2(v7->enemy_def); + R22_ = v8->tile_data.addr; + R26_ = v8->tile_data.bank; + uint16 v9 = enemy_tile_load_data_write_pos; + *(uint16 *)((char *)&enemy_tile_load_data[0].tile_data_size + enemy_tile_load_data_write_pos) = R18_ & 0x7FFF; + *(VoidP *)((char *)&enemy_tile_load_data[0].tile_data_ptr.addr + enemy_tile_load_data_write_pos) = R22_; + uint16 v10 = g_word_7E001E; + if ((R18_ & 0x8000u) != 0) + v10 = (uint16)(get_EnemyTileset(R28_)->vram_dst & 0x3000) >> 3; + *(uint16 *)((char *)&enemy_tile_load_data[0].offset_into_ram + v9) = v10; + *(&enemy_tile_load_data[0].tile_data_ptr.bank + v9) = R26_; + enemy_tile_load_data_write_pos += 7; + uint16 v11 = enemy_gfx_data_write_ptr; + enemy_gfxdata_tiles_index[enemy_gfx_data_write_ptr >> 1] = next_enemy_tiles_index; + enemy_def_ptr[v11 >> 1] = get_EnemyTileset(R28_)->enemy_def; + enemy_gfxdata_vram_ptr[v11 >> 1] = get_EnemyTileset(R28_)->vram_dst; + enemy_gfx_data_write_ptr += 2; + next_enemy_tiles_index += R18_ >> 5; + v12 = get_EnemyTileset(R28_); + g_word_7E001E += get_EnemyDef_A2(v12->enemy_def)->tile_data_size; + v0 = R28_ + 4; + } +} + +void DetermineWhichEnemiesToProcess(void) { // 0xA08EB6 + ++UNUSED_word_7E0E46; + cur_enemy_index = 0; + active_enemy_indexes_write_ptr = 0; + interactive_enemy_indexes_write_ptr = 0; + if (flag_process_all_enemies) { + do { + uint16 v5 = cur_enemy_index; + EnemyData *v6 = gEnemyData(cur_enemy_index); + if (v6->enemy_ptr && v6->enemy_ptr != (uint16)addr_kEnemyDef_DAFF) { + if ((v6->properties & 0x200) != 0) { + v6->enemy_ptr = 0; + } else { + uint16 v7 = active_enemy_indexes_write_ptr; + int v8 = active_enemy_indexes_write_ptr >> 1; + active_enemy_indexes[v8] = cur_enemy_index; + interactive_enemy_indexes[v8] = v5; + active_enemy_indexes_write_ptr = v7 + 2; + if ((v6->properties & 0x400) == 0) { + uint16 v9 = interactive_enemy_indexes_write_ptr; + interactive_enemy_indexes[interactive_enemy_indexes_write_ptr >> 1] = v5; + interactive_enemy_indexes_write_ptr = v9 + 2; + } + } + } + cur_enemy_index += 64; + } while (sign16(cur_enemy_index - 2048)); + active_enemy_indexes[active_enemy_indexes_write_ptr >> 1] = -1; + interactive_enemy_indexes[interactive_enemy_indexes_write_ptr >> 1] = -1; + } else { + do { + uint16 v0 = cur_enemy_index; + EnemyData *v1 = gEnemyData(cur_enemy_index); + if (v1->enemy_ptr && v1->enemy_ptr != (uint16)addr_kEnemyDef_DAFF) { + uint16 properties = v1->properties; + if ((properties & 0x200) != 0) { + v1->enemy_ptr = 0; + } else if ((properties & 0x800) != 0 + || (v1->ai_handler_bits & 4) != 0 + || (int16)(v1->x_width + v1->x_pos - layer1_x_pos) >= 0 + && (int16)(v1->x_width + layer1_x_pos + 256 - v1->x_pos) >= 0 + && (int16)(v1->y_pos + 8 - layer1_y_pos) >= 0 + && (int16)(layer1_y_pos + 248 - v1->y_pos) >= 0) { + uint16 v3 = active_enemy_indexes_write_ptr; + active_enemy_indexes[active_enemy_indexes_write_ptr >> 1] = cur_enemy_index; + active_enemy_indexes_write_ptr = v3 + 2; + if ((v1->properties & 0x400) == 0) { + uint16 v4 = interactive_enemy_indexes_write_ptr; + interactive_enemy_indexes[interactive_enemy_indexes_write_ptr >> 1] = v0; + interactive_enemy_indexes_write_ptr = v4 + 2; + } + } + } + cur_enemy_index += 64; + } while (sign16(cur_enemy_index - 2048)); + active_enemy_indexes[active_enemy_indexes_write_ptr >> 1] = -1; + interactive_enemy_indexes[interactive_enemy_indexes_write_ptr >> 1] = -1; + } +} + +void CallEnemyAi(uint32 ea) { + switch (ea) { + case fnEnemy_GrappleReact_SamusLatchesOn_A2: Enemy_GrappleReact_SamusLatchesOn_A2(); return; + case fnEnemy_GrappleReact_KillEnemy_A2: Enemy_GrappleReact_KillEnemy_A2(); return; + case fnEnemy_GrappleReact_CancelBeam_A2: Enemy_GrappleReact_CancelBeam_A2(); return; + case fnEnemy_NormalTouchAI_A2: Enemy_NormalTouchAI_A2(); return; + case fnEnemy_NormalShotAI_A2: Enemy_NormalShotAI_A2(); return; + case fnEnemy_NormalFrozenAI_A2: Enemy_NormalFrozenAI_A2(); return; + case fnnullsub_170_A2: return; + case fnBouncingGoofball_Init: BouncingGoofball_Init(); return; + case fnBouncingGoofball_Main: BouncingGoofball_Main(); return; + case fnMiniCrocomire_Init: MiniCrocomire_Init(); return; + case fnMiniCrocomire_Main: MiniCrocomire_Main(); return; + case fnMaridiaBeybladeTurtle_Init: MaridiaBeybladeTurtle_Init(); return; + case fnMiniMaridiaBeybladeTurtle_Init: MiniMaridiaBeybladeTurtle_Init(); return; + case fnMaridiaBeybladeTurtle_Main: MaridiaBeybladeTurtle_Main(); return; + case fnMiniMaridiaBeybladeTurtle_Main: MiniMaridiaBeybladeTurtle_Main(); return; + case fnMaridiaBeybladeTurtle_Touch: MaridiaBeybladeTurtle_Touch(); return; + case fnMiniMaridiaBeybladeTurtle_Touch: MiniMaridiaBeybladeTurtle_Touch(); return; + case fnMiniMaridiaBeybladeTurtle_Shot: MiniMaridiaBeybladeTurtle_Shot(); return; + case fnThinHoppingBlobs_Init: ThinHoppingBlobs_Init(); return; + case fnThinHoppingBlobs_Main: ThinHoppingBlobs_Main(); return; + case fnSpikeShootingPlant_Init: SpikeShootingPlant_Init(); return; + case fnSpikeShootingPlant_Main: SpikeShootingPlant_Main(); return; + case fnMaridiaSpikeyShell_Init: MaridiaSpikeyShell_Init(); return; + case fnMaridiaSpikeyShell_Main: MaridiaSpikeyShell_Main(); return; + case fnMaridiaSpikeyShell_Shot: MaridiaSpikeyShell_Shot(); return; + case fnGunshipTop_Init: GunshipTop_Init(); return; + case fnGunshipBottom_Init: GunshipBottom_Init(); return; + case fnGunshipTop_Main: GunshipTop_Main(); return; + case fnFlies_Init: Flies_Init(); return; + case fnFlies_Main: Flies_Main(); return; + case fnNorfairErraticFireball_Init: NorfairErraticFireball_Init(); return; + case fnNorfairErraticFireball_Main: NorfairErraticFireball_Main(); return; + case fnLavaquakeRocks_Init: LavaquakeRocks_Init(); return; + case fnLavaquakeRocks_Main: LavaquakeRocks_Main(); return; + case fnRinka_Init: Rinka_Init(); return; + case fnRinka_Main: Rinka_Main(); return; + case fnRinka_Frozen: Rinka_Frozen(cur_enemy_index); return; + case fnRinka_Touch: Rinka_Touch(); return; + case fnRinka_Shot: Rinka_Shot(); return; + case fnRinka_Powerbomb: Rinka_Powerbomb(cur_enemy_index); return; + case fnRio_Init: Rio_Init(); return; + case fnRio_Main: Rio_Main(); return; + case fnNorfairLavajumpingEnemy_Init: NorfairLavajumpingEnemy_Init(); return; + case fnNorfairLavajumpingEnemy_Main: NorfairLavajumpingEnemy_Main(); return; + case fnNorfairRio_Init: NorfairRio_Init(); return; + case fnNorfairRio_Main: NorfairRio_Main(); return; + case fnLowerNorfairRio_Init: LowerNorfairRio_Init(); return; + case fnLowerNorfairRio_Main: LowerNorfairRio_Main(); return; + case fnMaridiaLargeSnail_Init: MaridiaLargeSnail_Init(); return; + case fnMaridiaLargeSnail_Main: MaridiaLargeSnail_Main(); return; + case fnMaridiaLargeSnail_Touch: MaridiaLargeSnail_Touch(cur_enemy_index); return; + case fnMaridiaLargeSnail_Shot: MaridiaLargeSnail_Shot(); return; + case fnHirisingSlowfalling_Init: HirisingSlowfalling_Init(); return; + case fnHirisingSlowfalling_Main: HirisingSlowfalling_Main(); return; + case fnGripper_Init: Gripper_Init(); return; + case fnGripper_Main: Gripper_Main(); return; + case fnJetPowerRipper_Init: JetPowerRipper_Init(); return; + case fnJetPowerRipper_Main: JetPowerRipper_Main(); return; + case fnJetPowerRipper_Shot: JetPowerRipper_Shot(); return; + case fnRipper_Init: Ripper_Init(); return; + case fnRipper_Main: Ripper_Main(); return; + case fnLavaSeahorse_Init: LavaSeahorse_Init(); return; + case fnLavaSeahorse_Main: LavaSeahorse_Main(); return; + case fnLavaSeahorse_Touch: LavaSeahorse_Touch(); return; + case fnLavaSeahorse_Shot: LavaSeahorse_Shot(); return; + case fnLavaSeahorse_Powerbomb: LavaSeahorse_Powerbomb(); return; + case fnTimedShutter_Init: TimedShutter_Init(); return; + case fnTimedShutter_Main: TimedShutter_Main(); return; + case fnRisingFallingPlatform_Init: RisingFallingPlatform_Init(); return; + case fnShootableShutter_Init: ShootableShutter_Init(); return; + case fnRisingFallingPlatform_Main: RisingFallingPlatform_Main(); return; + case fnRisingFallingPlatform_Touch: RisingFallingPlatform_Touch(); return; + case fnRisingFallingPlatform_Shot: RisingFallingPlatform_Shot(); return; + case fnShootableShutter_Shot: ShootableShutter_Shot(); return; + case fnRisingFallingPlatform_Powerbomb: RisingFallingPlatform_Powerbomb(); return; + case fnHorizontalShootableShutter_Init: HorizontalShootableShutter_Init(); return; + case fnHorizontalShootableShutter_Main: HorizontalShootableShutter_Main(); return; + case fnHorizontalShootableShutter_Touch: HorizontalShootableShutter_Touch(); return; + case fnHorizontalShootableShutter_Shot: HorizontalShootableShutter_Shot(); return; + case fnHorizontalShootableShutter_Powerbomb: HorizontalShootableShutter_Powerbomb(); return; + case fnEnemy_GrappleReact_NoInteract_A3: Enemy_GrappleReact_NoInteract_A3(); return; + case fnEnemy_GrappleReact_KillEnemy_A3: Enemy_GrappleReact_KillEnemy_A3(); return; + case fnEnemy_GrappleReact_CancelBeam_A3: Enemy_GrappleReact_CancelBeam_A3(); return; + case fnEnemy_NormalTouchAI_A3: Enemy_NormalTouchAI_A3(); return; + case fnEnemy_NormalShotAI_A3: Enemy_NormalShotAI_A3(); return; + case fnEnemy_NormalFrozenAI_A3: Enemy_NormalFrozenAI_A3(); return; + case fnnullsub_170_A3: return; + case fnWaver_Init: Waver_Init(); return; + case fnWaver_Main: Waver_Main(); return; + case fnMetalee_Init: Metalee_Init(); return; + case fnMetalee_Main: Metalee_Main(); return; + case fnMetalee_Shot: Metalee_Shot(); return; + case fnFireflea_Init: Fireflea_Init(); return; + case fnFireflea_Main: Fireflea_Main(); return; + case fnFireflea_Touch: Fireflea_Touch(cur_enemy_index); return; + case fnFireflea_Powerbomb: Fireflea_Powerbomb(); return; + case fnFireflea_Shot: Fireflea_Shot(); return; + case fnMaridiaFish_Init: MaridiaFish_Init(); return; + case fnMaridiaFish_Main: MaridiaFish_Main(); return; + case fnElevator_Init: Elevator_Init(); return; + case fnElevator_Frozen: Elevator_Frozen(); return; + case fnCrab_Init: Crab_Init(); return; + case fnSlug_Init: Slug_Init(); return; + case fnPlatformThatFallsWithSamus_Init: PlatformThatFallsWithSamus_Init(); return; + case fnFastMovingSlowSinkingPlatform_Init: FastMovingSlowSinkingPlatform_Init(); return; + case fnPlatformThatFallsWithSamus_Main: PlatformThatFallsWithSamus_Main(); return; + case fnnullsub_32: return; + case fnFastMovingSlowSinkingPlatform_Shot: FastMovingSlowSinkingPlatform_Shot(); return; + case fnRoach_Init: Roach_Init(); return; + case fnRoach_Main: Roach_Main(); return; + case fnMochtroid_Init: Mochtroid_Init(); return; + case fnMochtroid_Main: Mochtroid_Main(); return; + case fnMochtroid_Touch: Mochtroid_Touch(); return; + case fnMochtroid_Shot: Mochtroid_Shot(); return; + case fnSidehopper_Init: Sidehopper_Init(); return; + case fnSidehopper_Main: Sidehopper_Main(); return; + case fnMaridiaRefillCandy_Init: MaridiaRefillCandy_Init(); return; + case fnMaridiaRefillCandy_Main: MaridiaRefillCandy_Main(); return; + case fnNorfairSlowFireball_Init: NorfairSlowFireball_Init(); return; + case fnBang_Init: Bang_Init(); return; + case fnBang_Main: Bang_Main(); return; + case fnBang_Shot: Bang_Shot(); return; + case fnSkree_Init: Skree_Init(); return; + case fnSkree_Main: Skree_Main(); return; + case fnSkree_Shot: Skree_Shot(); return; + case fnMaridiaSnail_Init: MaridiaSnail_Init(); return; + case fnMaridiaSnail_Main: MaridiaSnail_Main(); return; + case fnMaridiaSnail_Touch: MaridiaSnail_Touch(); return; + case fnMaridiaSnail_Shot: MaridiaSnail_Shot(); return; + case fnReflec_Init: Reflec_Init(); return; + case fnnullsub_33: return; + case fnReflec_Shot: Reflec_Shot(); return; + case fnWreckedShipOrangeZoomer_Init: WreckedShipOrangeZoomer_Init(); return; + case fnWreckedShipOrangeZoomer_Main: WreckedShipOrangeZoomer_Main(); return; + case fnBigEyeBugs_Init: BigEyeBugs_Init(); return; + case fnFireZoomer_Init: FireZoomer_Init(); return; + case fnStoneZoomer_Init: StoneZoomer_Init(); return; + case fnStoneZoomer_Main: StoneZoomer_Main(); return; + case fnMetroid_Init: Metroid_Init(); return; + case fnMetroid_Frozen: Metroid_Frozen(); return; + case fnMetroid_Hurt: Metroid_Hurt(); return; + case fnMetroid_Main: Metroid_Main(); return; + case fnMetroid_Touch: Metroid_Touch(); return; + case fnMetroid_Shot: Metroid_Shot(); return; + case fnMetroid_Powerbomb: Metroid_Powerbomb(cur_enemy_index); return; + case fnEnemy_GrappleReact_SamusLatchesOn_A4: Enemy_GrappleReact_SamusLatchesOn_A4(); return; + case fnEnemy_NormalTouchAI_A4: Enemy_NormalTouchAI_A4(); return; + case fnEnemy_NormalShotAI_A4: Enemy_NormalShotAI_A4(); return; + case fnEnemy_NormalFrozenAI_A4: Enemy_NormalFrozenAI_A4(); return; + case fnnullsub_170_A4: return; + case fnCrocomire_Hurt: Crocomire_Hurt(); return; + case fnCrocomire_Init: Crocomire_Init(); return; + case fnCrocomire_Main: Crocomire_Main(); return; + case fnnullsub_34: return; + case fnCrocomire_Powerbomb: Crocomire_Powerbomb(); return; + case fnCrocomireTongue_Init: CrocomireTongue_Init(); return; + case fnCrocomireTongue_Main: CrocomireTongue_Main(); return; + case fnEnemy_GrappleReact_NoInteract_A5: Enemy_GrappleReact_NoInteract_A5(); return; + case fnEnemy_GrappleReact_CancelBeam_A5: Enemy_GrappleReact_CancelBeam_A5(); return; + case fnEnemy_NormalTouchAI_A5: Enemy_NormalTouchAI_A5(); return; + case fnEnemy_NormalShotAI_A5: Enemy_NormalShotAI_A5(); return; + case fnEnemy_NormalFrozenAI_A5: Enemy_NormalFrozenAI_A5(); return; + case fnnullsub_170_A5: return; + case fnDraygon_Init: Draygon_Init(); return; + case fnDraygon_Main: Draygon_Main(); return; + case fnDraygon_Hurt: Draygon_Hurt(); return; + case fnDraygon_Touch: Draygon_Touch(); return; + case fnDraygon_Shot: Draygon_Shot(); return; + case fnDraygon_Powerbomb: Draygon_Powerbomb(); return; + case fnDraygonsEye_Init: DraygonsEye_Init(); return; + case fnDraygonsEye_Main: DraygonsEye_Main(); return; + case fnDraygonsTail_Init: DraygonsTail_Init(); return; + case fnnullsub_37: return; + case fnDraygonsArms_Init: DraygonsArms_Init(); return; + case fnnullsub_38: return; + case fnSporeSpawn_Init: SporeSpawn_Init(); return; + case fnSporeSpawn_Main: SporeSpawn_Main(); return; + case fnSporeSpawn_Shot: SporeSpawn_Shot(); return; + case fnSporeSpawn_Touch: SporeSpawn_Touch(); return; + case fnnullsub_39: return; + case fnEnemy_GrappleReact_NoInteract_A6: Enemy_GrappleReact_NoInteract_A6(); return; + case fnEnemy_GrappleReact_CancelBeam_A6: Enemy_GrappleReact_CancelBeam_A6(); return; + case fnEnemy_NormalTouchAI_A6: Enemy_NormalTouchAI_A6(); return; + case fnEnemy_NormalShotAI_A6: Enemy_NormalShotAI_A6(); return; + case fnEnemy_NormalFrozenAI_A6: Enemy_NormalFrozenAI_A6(); return; + case fnnullsub_170_A6: return; + case fnBoulder_Init: Boulder_Init(); return; + case fnBoulder_Main: Boulder_Main(); return; + case fnSpikeyPlatform_Init: SpikeyPlatform_Init(); return; + case fnSpikeyPlatform2ndEnemy_Init: SpikeyPlatform2ndEnemy_Init(); return; + case fnSpikeyPlatform2ndEnemy_Main: SpikeyPlatform2ndEnemy_Main(); return; + case fnSpikeyPlatform_Main: SpikeyPlatform_Main(); return; + case fnFireGeyser_Init: FireGeyser_Init(); return; + case fnFireGeyser_Main: FireGeyser_Main(); return; + case fnNuclearWaffle_Init: NuclearWaffle_Init(); return; + case fnNuclearWaffle_Main: NuclearWaffle_Main(); return; + case fnFakeKraid_Init: FakeKraid_Init(); return; + case fnFakeKraid_Main: FakeKraid_Main(); return; + case fnFakeKraid_Touch: FakeKraid_Touch(); return; + case fnFakeKraid_Shot: FakeKraid_Shot(); return; + case fnCeresRidley_Init: CeresRidley_Init(); return; + case fnCeresRidley_Main: CeresRidley_Main(); return; + case fnCeresRidley_Hurt: CeresRidley_Hurt(); return; + case fnRidley_Main: Ridley_Main(); return; + case fnRidley_Func_2: Ridley_Func_2(); return; + case fnRidley_Hurt: Ridley_Hurt(); return; + case fnRidleysExplosion_Init: RidleysExplosion_Init(); return; + case fnRidleysExplosion_Main: RidleysExplosion_Main(); return; + case fnRidley_Shot: Ridley_Shot(); return; + case fnRidley_Powerbomb: Ridley_Powerbomb(); return; + case fnCeresSteam_Init: CeresSteam_Init(); return; + case fnCeresSteam_Main: CeresSteam_Main(); return; + case fnCeresSteam_Touch: CeresSteam_Touch(); return; + case fnCeresDoor_Init: CeresDoor_Init(); return; + case fnCeresDoor_Main: CeresDoor_Main(); return; + case fnnullsub_41: return; + case fnZebetites_Init: Zebetites_Init(); return; + case fnZebetites_Main: Zebetites_Main(); return; + case fnZebetites_Touch: Zebetites_Touch(); return; + case fnZebetites_Shot: Zebetites_Shot(); return; + case fnEnemy_GrappleReact_NoInteract_A7: Enemy_GrappleReact_NoInteract_A7(); return; + case fnEnemy_GrappleReact_CancelBeam_A7: Enemy_GrappleReact_CancelBeam_A7(); return; + case fnEnemy_NormalShotAI_A7: Enemy_NormalShotAI_A7(); return; + case fnEnemy_NormalPowerBombAI_SkipDeathAnim_A7: Enemy_NormalPowerBombAI_SkipDeathAnim_A7(); return; + case fnEnemy_NormalFrozenAI_A7: Enemy_NormalFrozenAI_A7(); return; + case fnnullsub_170_A7: return; + case fnnullsub_44: return; + case fnKraidsArm_Touch: KraidsArm_Touch(); return; + case fnKraid_Touch: Kraid_Touch(); return; + case fnnullsub_43: return; + case fnKraid_Init: Kraid_Init(); return; + case fnKraidsArm_Init: KraidsArm_Init(); return; + case fnKraidsTopLint_Init: KraidsTopLint_Init(); return; + case fnKraidsMiddleLint_Init: KraidsMiddleLint_Init(); return; + case fnKraidsBottomLint_Init: KraidsBottomLint_Init(); return; + case fnKraidsFoot_Init: KraidsFoot_Init(); return; + case fnKraid_Main: Kraid_Main(); return; + case fnKraidsArm_Main: KraidsArm_Main(); return; + case fnKraidsTopLint_Main: KraidsTopLint_Main(); return; + case fnKraidsMiddleLint_Main: KraidsMiddleLint_Main(); return; + case fnKraidsBottomLint_Main: KraidsBottomLint_Main(); return; + case fnKraidsFoot_Main: KraidsFoot_Main(); return; + case fnKraidsGoodFingernail_Touch: KraidsGoodFingernail_Touch(); return; + case fnKraidsBadFingernail_Touch: KraidsBadFingernail_Touch(); return; + case fnKraidsGoodFingernail_Init: KraidsGoodFingernail_Init(); return; + case fnKraidsBadFingernail_Init: KraidsBadFingernail_Init(); return; + case fnKraidsGoodFingernail_Main: KraidsGoodFingernail_Main(); return; + case fnKraidsBadFingernail_Main: KraidsBadFingernail_Main(); return; + case fnPhantoon_Init: Phantoon_Init(); return; + case fnPhantoon2_Init: Phantoon2_Init(); return; + case fnPhantoon_Main: Phantoon_Main(); return; + case fnPhantoon_Hurt: Phantoon_Hurt(); return; + case fnPhantoon_Touch: Phantoon_Touch(); return; + case fnnullsub_358: return; + case fnPhantoon_Shot: Phantoon_Shot(); return; + case fnnullsub_45: return; + case fnEtecoon_Init: Etecoon_Init(); return; + case fnEtecoon_Main: Etecoon_Main(); return; + case fnDachora_Init: Dachora_Init(); return; + case fnDachora_Main: Dachora_Main(); return; + case fnEnemy_GrappleReact_NoInteract_A8: Enemy_GrappleReact_NoInteract_A8(); return; + case fnEnemy_GrappleReact_KillEnemy_A8: Enemy_GrappleReact_KillEnemy_A8(); return; + case fnEnemy_GrappleReact_CancelBeam_A8: Enemy_GrappleReact_CancelBeam_A8(); return; + case fnEnemy_GrappleReact_SamusLatchesNoInvinc_A8: Enemy_GrappleReact_SamusLatchesNoInvinc_A8(); return; + case fnEnemy_GrappleReact_HurtSamus_A8: Enemy_GrappleReact_HurtSamus_A8(); return; + case fnEnemy_NormalTouchAI_A8: Enemy_NormalTouchAI_A8(); return; + case fnEnemy_NormalShotAI_A8: Enemy_NormalShotAI_A8(); return; + case fnEnemy_NormalFrozenAI_A8: Enemy_NormalFrozenAI_A8(); return; + case fnnullsub_170_A8: return; + case fnMiniDraygon_Init: MiniDraygon_Init(); return; + case fnEvirProjectile_Init: EvirProjectile_Init(); return; + case fnMiniDraygon_Main: MiniDraygon_Main(); return; + case fnEvirProjectile_Main: EvirProjectile_Main(); return; + case fnMiniDraygon_Touch: MiniDraygon_Touch(); return; + case fnMiniDraygon_Powerbomb: MiniDraygon_Powerbomb(); return; + case fnMiniDraygon_Shot: MiniDraygon_Shot(); return; + case fnMorphBallEye_Init: MorphBallEye_Init(); return; + case fnMorphBallEye_Main: MorphBallEye_Main(); return; + case fnFune_Init: Fune_Init(); return; + case fnFune_Main: Fune_Main(); return; + case fnWreckedShipGhost_Init: WreckedShipGhost_Init(); return; + case fnWreckedShipGhost_Main: WreckedShipGhost_Main(); return; + case fnYappingMaw_Init: YappingMaw_Init(); return; + case fnYappingMaw_Main: YappingMaw_Main(); return; + case fnYappingMaw_Touch: YappingMaw_Touch(); return; + case fnYappingMaw_Shot: YappingMaw_Shot(); return; + case fnYappingMaw_Frozen: YappingMaw_Frozen(); return; + case fnKago_Init: Kago_Init(); return; + case fnKago_Main: Kago_Main(); return; + case fnKago_Shot: Kago_Shot(); return; + case fnNorfairLavaMan_Init: NorfairLavaMan_Init(); return; + case fnNorfairLavaMan_Main: NorfairLavaMan_Main(); return; + case fnNorfairLavaMan_Powerbomb: NorfairLavaMan_Powerbomb(); return; + case fnNorfairLavaMan_Touch: NorfairLavaMan_Touch(); return; + case fnNorfairLavaMan_Shot: NorfairLavaMan_Shot(); return; + case fnBeetom_Init: Beetom_Init(); return; + case fnBeetom_Main: Beetom_Main(); return; + case fnBeetom_Touch: Beetom_Touch(); return; + case fnBeetom_Shot: Beetom_Shot(); return; + case fnMaridiaFloater_Init: MaridiaFloater_Init(); return; + case fnMaridiaFloater_Main: MaridiaFloater_Main(); return; + case fnMaridiaFloater_Touch: MaridiaFloater_Touch(); return; + case fnMaridiaFloater_Shot: MaridiaFloater_Shot(); return; + case fnMaridiaFloater_Powerbomb: MaridiaFloater_Powerbomb(); return; + case fnWreckedShipRobot_Init: WreckedShipRobot_Init(); return; + case fnWreckedShipRobotDeactivated_Init: WreckedShipRobotDeactivated_Init(); return; + case fnWreckedShipRobot_Main: WreckedShipRobot_Main(); return; + case fnnullsub_342: return; + case fnWreckedShipRobotDeactivated_Touch: WreckedShipRobotDeactivated_Touch(); return; + case fnWreckedShipRobotDeactivated_Shot: WreckedShipRobotDeactivated_Shot(); return; + case fnWreckedShipRobot_Shot: WreckedShipRobot_Shot(); return; + case fnMaridiaPuffer_Init: MaridiaPuffer_Init(); return; + case fnMaridiaPuffer_Main: MaridiaPuffer_Main(); return; + case fnMaridiaPuffer_Shot: MaridiaPuffer_Shot(); return; + case fnWalkingLavaSeahorse_Init: WalkingLavaSeahorse_Init(); return; + case fnWalkingLavaSeahorse_Main: WalkingLavaSeahorse_Main(); return; + case fnWreckedShipOrbs_Init: WreckedShipOrbs_Init(); return; + case fnWreckedShipOrbs_Main: WreckedShipOrbs_Main(); return; + case fnWreckedShipSpark_Init: WreckedShipSpark_Init(); return; + case fnWreckedShipSpark_Main: WreckedShipSpark_Main(); return; + case fnWreckedShipSpark_Shot: WreckedShipSpark_Shot(); return; + case fnBlueBrinstarFaceBlock_Init: BlueBrinstarFaceBlock_Init(); return; + case fnBlueBrinstarFaceBlock_Main: BlueBrinstarFaceBlock_Main(); return; + case fnBlueBrinstarFaceBlock_Shot: BlueBrinstarFaceBlock_Shot(); return; + case fnKiHunter_Init: KiHunter_Init(); return; + case fnKiHunterWings_Init: KiHunterWings_Init(); return; + case fnKiHunter_Main: KiHunter_Main(); return; + case fnKiHunterWings_Main: KiHunterWings_Main(); return; + case fnKiHunter_Shot: KiHunter_Shot(); return; + case fnEnemy_GrappleReact_CancelBeam_A9: Enemy_GrappleReact_CancelBeam_A9(); return; + case fnEnemy_NormalFrozenAI_A9: Enemy_NormalFrozenAI_A9(); return; + case fnnullsub_170_A9: return; + case fnMotherBrainsBody_Init: MotherBrainsBody_Init(); return; + case fnMotherBrainsBrain_Init: MotherBrainsBrain_Init(); return; + case fnMotherBrainsBody_Hurt: MotherBrainsBody_Hurt(); return; + case fnMotherBrainsBody_Powerbomb: MotherBrainsBody_Powerbomb(); return; + case fnMotherBrainsBrain_Hurt: MotherBrainsBrain_Hurt(); return; + case fnMotherBrainsTubesFalling_Init: MotherBrainsTubesFalling_Init(); return; + case fnMotherBrainsTubesFalling_Main: MotherBrainsTubesFalling_Main(cur_enemy_index); return; + case fnMotherBrainsBody_Shot: MotherBrainsBody_Shot(); return; + case fnMotherBrainsBrain_Shot: MotherBrainsBrain_Shot(); return; + case fnnullsub_47: return; + case fnMotherBrainsBrain_Touch: MotherBrainsBrain_Touch(); return; + case fnShitroidInCutscene_Init: ShitroidInCutscene_Init(); return; + case fnShitroidInCutscene_Main: ShitroidInCutscene_Main(); return; + case fnShitroidInCutscene_Touch: ShitroidInCutscene_Touch(); return; + case fnDeadTorizo_Init: DeadTorizo_Init(); return; + case fnDeadTorizo_Main: DeadTorizo_Main(); return; + case fnDeadTorizo_Powerbomb: DeadTorizo_Powerbomb(); return; + case fnDeadTorizo_Shot: DeadTorizo_Shot(); return; + case fnDeadSidehopper_Init: DeadSidehopper_Init(); return; + case fnDeadZoomer_Init: DeadZoomer_Init(); return; + case fnDeadRipper_Init: DeadRipper_Init(); return; + case fnDeadSkree_Init: DeadSkree_Init(); return; + case fnDeadSidehopper_Powerbomb: DeadSidehopper_Powerbomb(); return; + case fnDeadSidehopper_Main: DeadSidehopper_Main(); return; + case fnDeadZoomer_Powerbomb: DeadZoomer_Powerbomb(); return; + case fnDeadZoomer_Shot: DeadZoomer_Shot(); return; + case fnDeadRipper_Powerbomb: DeadRipper_Powerbomb(); return; + case fnDeadRipper_Shot: DeadRipper_Shot(); return; + case fnDeadSkree_Powerbomb: DeadSkree_Powerbomb(); return; + case fnDeadSkree_Shot: DeadSkree_Shot(); return; + case fnDeadSidehopper_Shot: DeadSidehopper_Shot(); return; + case fnDeadSidehopper_Touch: DeadSidehopper_Touch(); return; + case fnShitroid_Init: Shitroid_Init(); return; + case fnShitroid_Powerbomb: Shitroid_Powerbomb(); return; + case fnShitroid_Main: Shitroid_Main(); return; + case fnShitroid_Touch: Shitroid_Touch(); return; + case fnShitroid_Shot: Shitroid_Shot(); return; + case fnEnemy_GrappleReact_CancelBeam_AA: Enemy_GrappleReact_CancelBeam_AA(); return; + case fnEnemy_NormalFrozenAI_AA: Enemy_NormalFrozenAI_AA(); return; + case fnnullsub_170_AA: return; + case fnTorizo_Hurt: Torizo_Hurt(); return; + case fnTorizo_Main: Torizo_Main(); return; + case fnTorizo_Init: Torizo_Init(); return; + case fnGoldTorizo_Touch: GoldTorizo_Touch(); return; + case fnTorizo_Shot: Torizo_Shot(); return; + case fnGoldTorizo_Main: GoldTorizo_Main(); return; + case fnGoldTorizo_Hurt: GoldTorizo_Hurt(); return; + case fnGoldTorizo_Shot: GoldTorizo_Shot(); return; + case fnnullsub_49: return; + case fnTourianEntranceStatue_Init: TourianEntranceStatue_Init(); return; + case fnShaktool_Hurt: Shaktool_Hurt(); return; + case fnShaktool_Init: Shaktool_Init(); return; + case fnShaktool_Touch: Shaktool_Touch(); return; + case fnShaktool_Shot: Shaktool_Shot(); return; + case fnN00bTubeCracks_Init: N00bTubeCracks_Init(); return; + case fnChozoStatue_Init: ChozoStatue_Init(); return; + case fnChozoStatue_Main: ChozoStatue_Main(); return; + case fnnullsub_51: return; + case fnnullsub_52: return; + case fnEnemy_GrappleReact_CancelBeam_B2: Enemy_GrappleReact_CancelBeam_B2(); return; + case fnEnemy_NormalFrozenAI_B2: Enemy_NormalFrozenAI_B2(); return; + case fnnullsub_170_B2: return; + case fnWalkingSpacePirates_Powerbomb: WalkingSpacePirates_Powerbomb(); return; + case fnWalkingSpacePirates_Touch: WalkingSpacePirates_Touch(); return; + case fnWalkingSpacePirates_Shot: WalkingSpacePirates_Shot(); return; + case fnWallSpacePirates_Init: WallSpacePirates_Init(); return; + case fnWallSpacePirates_Main: WallSpacePirates_Main(); return; + case fnNinjaSpacePirates_Init: NinjaSpacePirates_Init(); return; + case fnNinjaSpacePirates_Main: NinjaSpacePirates_Main(); return; + case fnWalkingSpacePirates_Init: WalkingSpacePirates_Init(); return; + case fnWalkingSpacePirates_Main: WalkingSpacePirates_Main(); return; + case fnEnemy_GrappleReact_NoInteract_B3: Enemy_GrappleReact_NoInteract_B3(); return; + case fnEnemy_GrappleReact_KillEnemy_B3: Enemy_GrappleReact_KillEnemy_B3(); return; + case fnEnemy_GrappleReact_CancelBeam_B3: Enemy_GrappleReact_CancelBeam_B3(); return; + case fnEnemy_NormalTouchAI_B3: Enemy_NormalTouchAI_B3(); return; + case fnEnemy_NormalShotAI_B3: Enemy_NormalShotAI_B3(); return; + case fnEnemy_NormalFrozenAI_B3: Enemy_NormalFrozenAI_B3(); return; + case fnnullsub_170_B3: return; + case fnUnusedSpinningTurtleEye_Init: UnusedSpinningTurtleEye_Init(); return; + case fnUnusedSpinningTurtleEye_Main: UnusedSpinningTurtleEye_Main(); return; + case fnBrinstarPipeBug_Init: BrinstarPipeBug_Init(); return; + case fnBrinstarPipeBug_Main: BrinstarPipeBug_Main(); return; + case fnNorfairPipeBug_Init: NorfairPipeBug_Init(); return; + case fnNorfairPipeBug_Main: NorfairPipeBug_Main(); return; + case fnBrinstarYellowPipeBug_Init: BrinstarYellowPipeBug_Init(); return; + case fnBrinstarYellowPipeBug_Main: BrinstarYellowPipeBug_Main(); return; + case fnBotwoon_Init: Botwoon_Init(); return; + case fnBotwoon_Main: Botwoon_Main(); return; + case fnBotwoon_Touch: Botwoon_Touch(); return; + case fnBotwoon_Shot: Botwoon_Shot(); return; + case fnBotwoon_Powerbomb: Botwoon_Powerbomb(); return; + case fnEscapeEtecoon_Main: EscapeEtecoon_Main(); return; + case fnEscapeEtecoon_Init: EscapeEtecoon_Init(); return; + case fnEscapeDachora_Init: EscapeDachora_Init(); return; + case fnnullsub_54: return; + case fnEnemy_NormalPowerBombAI_A0: + case fnEnemy_NormalPowerBombAI_A2: + case fnEnemy_NormalPowerBombAI_A3: + case fnEnemy_NormalPowerBombAI_A4: + case fnEnemy_NormalPowerBombAI_A5: + case fnEnemy_NormalPowerBombAI_A6: + case fnEnemy_NormalPowerBombAI_A7: + case fnEnemy_NormalPowerBombAI_A8: + case fnEnemy_NormalPowerBombAI_A9: + case fnEnemy_NormalPowerBombAI_AA: + case fnEnemy_NormalPowerBombAI_B2: + case fnEnemy_NormalPowerBombAI_B3: NormalEnemyPowerBombAi(); return; + default: Unreachable(); + } +} +void CallEnemyPreInstr(uint32 ea) { + uint16 k = cur_enemy_index; + switch (ea) { + case fnnullsub_171: return; // 0xa0807b + case fnnullsub_171_A2: return; // 0xa2807b + case fnMiniCrocomire_PreInstr5: MiniCrocomire_PreInstr5(k); return; // 0xa28a43 + case fnMiniCrocomire_PreInstr6: MiniCrocomire_PreInstr6(k); return; // 0xa28a5c + case fnnullsub_175: return; // 0xa28a75 + case fnSpikeShootingPlant_2: SpikeShootingPlant_2(k); return; // 0xa29fba + case fnSpikeShootingPlant_3: SpikeShootingPlant_3(k); return; // 0xa29fec + case fnnullsub_182: return; // 0xa2a01b + case fnnullsub_187: return; // 0xa2a7d7 + case fnGunshipTop_3: GunshipTop_3(k); return; // 0xa2a80c + case fnGunshipTop_4: GunshipTop_4(k); return; // 0xa2a8d0 + case fnGunshipTop_5: GunshipTop_5(k); return; // 0xa2a942 + case fnGunshipTop_6: GunshipTop_6(k); return; // 0xa2a950 + case fnGunshipTop_7: GunshipTop_7(k); return; // 0xa2a987 + case fnGunshipTop_8: GunshipTop_8(k); return; // 0xa2a9bd + case fnGunshipTop_9: GunshipTop_9(k); return; // 0xa2aa4f + case fnGunshipTop_10: GunshipTop_10(k); return; // 0xa2aa5d + case fnGunshipTop_11: GunshipTop_11(k); return; // 0xa2aa94 + case fnGunshipTop_12: GunshipTop_12(k); return; // 0xa2aaa2 + case fnGunshipTop_13: GunshipTop_13(k); return; // 0xa2ab1f + case fnGunshipTop_14: GunshipTop_14(k); return; // 0xa2ab60 + case fnGunshipTop_15: GunshipTop_15(k); return; // 0xa2ab6e + case fnGunshipTop_16: GunshipTop_16(k); return; // 0xa2aba5 + case fnGunshipTop_17: GunshipTop_17(k); return; // 0xa2abc7 + case fnGunshipTop_18: GunshipTop_18(k); return; // 0xa2ac1b + case fnGunshipTop_19: GunshipTop_19(k); return; // 0xa2acd7 + case fnGunshipTop_20: GunshipTop_20(k); return; // 0xa2ad0e + case fnGunshipTop_21: GunshipTop_21(k); return; // 0xa2ad2d + case fnFlies_4: Flies_4(k); return; // 0xa2b14e + case fnFlies_5: Flies_5(k); return; // 0xa2b17c + case fnFlies_6: Flies_6(k); return; // 0xa2b1aa + case fnFlies_7: Flies_7(k); return; // 0xa2b1d2 + case fnNorfairLavajumpingEnemy_Func_1: NorfairLavajumpingEnemy_Func_1(k); return; // 0xa2bedc + case fnNorfairLavajumpingEnemy_Func_2: NorfairLavajumpingEnemy_Func_2(k); return; // 0xa2bf1a + case fnNorfairLavajumpingEnemy_Func_3: NorfairLavajumpingEnemy_Func_3(k); return; // 0xa2bf3e + case fnNorfairLavajumpingEnemy_Func_4: NorfairLavajumpingEnemy_Func_4(k); return; // 0xa2bf7c + case fnNorfairLavajumpingEnemy_Func_5: NorfairLavajumpingEnemy_Func_5(k); return; // 0xa2bfbc + case fnNorfairRio_Func_1: NorfairRio_Func_1(k); return; // 0xa2c281 + case fnNorfairRio_Func_2: NorfairRio_Func_2(k); return; // 0xa2c2e7 + case fnNorfairRio_Func_3: NorfairRio_Func_3(k); return; // 0xa2c33f + case fnNorfairRio_Func_4: NorfairRio_Func_4(k); return; // 0xa2c361 + case fnNorfairRio_Func_5: NorfairRio_Func_5(k); return; // 0xa2c3b1 + case fnNorfairRio_Func_6: NorfairRio_Func_6(k); return; // 0xa2c406 + case fnLowerNorfairRio_Func_1: LowerNorfairRio_Func_1(k); return; // 0xa2c72e + case fnLowerNorfairRio_Func_2: LowerNorfairRio_Func_2(k); return; // 0xa2c771 + case fnLowerNorfairRio_Func_3: LowerNorfairRio_Func_3(k); return; // 0xa2c7bb + case fnLowerNorfairRio_Func_4: LowerNorfairRio_Func_4(k); return; // 0xa2c7d6 + case fnLowerNorfairRio_Func_5: LowerNorfairRio_Func_5(k); return; // 0xa2c82d + case fnLowerNorfairRio_Func_6: LowerNorfairRio_Func_6(k); return; // 0xa2c888 + case fnMaridiaLargeSnail_Func_7: MaridiaLargeSnail_Func_7(k); return; // 0xa2cf66 + case fnMaridiaLargeSnail_Func_8: MaridiaLargeSnail_Func_8(k); return; // 0xa2cfa9 + case fnLavaSeahorse_Func_1: LavaSeahorse_Func_1(k); return; // 0xa2e654 + case fnLavaSeahorse_Func_2: LavaSeahorse_Func_2(k); return; // 0xa2e6ad + case fnLavaSeahorse_Func_3: LavaSeahorse_Func_3(k); return; // 0xa2e6f1 + case fnLavaSeahorse_Func_4: LavaSeahorse_Func_4(k); return; // 0xa2e734 + case fnLavaSeahorse_Func_5: LavaSeahorse_Func_5(k); return; // 0xa2e749 + case fnnullsub_196: return; // 0xa2e781 + case fnBang_Func_6: Bang_Func_6(k); return; // 0xa3bca5 + case fnBang_Func_7: Bang_Func_7(k); return; // 0xa3bcc1 + case fnBang_Func_8: Bang_Func_8(k); return; // 0xa3bcc5 + case fnBang_Func_10: Bang_Func_10(k); return; // 0xa3bd1c + case fnBang_Func_11: Bang_Func_11(k); return; // 0xa3bd2c + case fnnullsub_215: return; // 0xa3cf5f + case fnMaridiaSnail_Func_15: MaridiaSnail_Func_15(k); return; // 0xa3d1b3 + case fnnullsub_343: return; // 0xa3e08a + case fnnullsub_304: return; // 0xa3e6c1 + case fnFireZoomer_Func_1: FireZoomer_Func_1(k); return; // 0xa3e6c8 + case fnFireZoomer_Func_2: FireZoomer_Func_2(k); return; // 0xa3e785 + case fnFireZoomer_Func_3: FireZoomer_Func_3(k); return; // 0xa3e7f2 + case fnnullsub_237: return; // 0xa7d4a8 + case fnPhantoon_Spawn8FireballsInCircleAtStart: Phantoon_Spawn8FireballsInCircleAtStart(k); return; // 0xa7d4a9 + case fnPhantoon_WaitBetweenSpawningAndSpinningFireballs: Phantoon_WaitBetweenSpawningAndSpinningFireballs(k); return; // 0xa7d4ee + case fnPhantoon_SpawnFireballsBeforeFight: Phantoon_SpawnFireballsBeforeFight(k); return; // 0xa7d508 + case fnPhantoon_WavyFadeIn: Phantoon_WavyFadeIn(k); return; // 0xa7d54a + case fnPhantoon_PickPatternForRound1: Phantoon_PickPatternForRound1(k); return; // 0xa7d596 + case fnPhantoon_MovePhantoonInFigure8ThenOpenEye: Phantoon_MovePhantoonInFigure8ThenOpenEye(k); return; // 0xa7d5e7 + case fnPhantoon_EyeFollowsSamusUntilTimerRunsOut: Phantoon_EyeFollowsSamusUntilTimerRunsOut(k); return; // 0xa7d60d + case fnPhantoon_BecomesSolidAndBodyVuln: Phantoon_BecomesSolidAndBodyVuln(k); return; // 0xa7d65c + case fnPhantoon_IsSwooping: Phantoon_IsSwooping(k); return; // 0xa7d678 + case fnPhantoon_FadeoutWithSwoop: Phantoon_FadeoutWithSwoop(k); return; // 0xa7d6b9 + case fnPhantoon_WaitAfterFadeOut: Phantoon_WaitAfterFadeOut(k); return; // 0xa7d6d4 + case fnPhantoon_MoveLeftOrRightAndPickEyeOpenPatt: Phantoon_MoveLeftOrRightAndPickEyeOpenPatt(k); return; // 0xa7d6e2 + case fnPhantoon_FadeInBeforeFigure8: Phantoon_FadeInBeforeFigure8(k); return; // 0xa7d72d + case fnPhantoon_BecomeSolidAfterRainingFireballs: Phantoon_BecomeSolidAfterRainingFireballs(k); return; // 0xa7d73f + case fnPhantoon_FadeInDuringFireballRain: Phantoon_FadeInDuringFireballRain(k); return; // 0xa7d767 + case fnPhantoon_FollowSamusWithEyeDuringFireballRain: Phantoon_FollowSamusWithEyeDuringFireballRain(k); return; // 0xa7d788 + case fnPhantoon_FadeOutDuringFireballRain: Phantoon_FadeOutDuringFireballRain(k); return; // 0xa7d7d5 + case fnPhantoon_SpawnRainingFireballs: Phantoon_SpawnRainingFireballs(k); return; // 0xa7d7f7 + case fnPhantoon_FadeOutBeforeFirstFireballRain: Phantoon_FadeOutBeforeFirstFireballRain(k); return; // 0xa7d82a + case fnPhantoon_FadeOutBeforeEnrage: Phantoon_FadeOutBeforeEnrage(k); return; // 0xa7d85c + case fnPhantoon_MoveEnragedPhantoonToTopCenter: Phantoon_MoveEnragedPhantoonToTopCenter(k); return; // 0xa7d874 + case fnPhantoon_FadeInEnragedPhantoon: Phantoon_FadeInEnragedPhantoon(k); return; // 0xa7d891 + case fnPhantoon_Enraged: Phantoon_Enraged(k); return; // 0xa7d8ac + case fnPhantoon_FadeoutAfterEnrage: Phantoon_FadeoutAfterEnrage(k); return; // 0xa7d916 + case fnPhantoon_CompleteSwoopAfterFatalShot: Phantoon_CompleteSwoopAfterFatalShot(k); return; // 0xa7d92e + case fnPhantoon_DyingPhantoonFadeInOut: Phantoon_DyingPhantoonFadeInOut(k); return; // 0xa7d948 + case fnPhantoon_DyingPhantoonExplosions: Phantoon_DyingPhantoonExplosions(k); return; // 0xa7d98b + case fnPhantoon_WavyDyingPhantoonAndCry: Phantoon_WavyDyingPhantoonAndCry(k); return; // 0xa7da51 + case fnPhantoon_DyingFadeOut: Phantoon_DyingFadeOut(k); return; // 0xa7da86 + case fnPhantoon_AlmostDead: Phantoon_AlmostDead(k); return; // 0xa7dad7 + case fnPhantoon_Dead: Phantoon_Dead(k); return; // 0xa7db3d + case fnEtecoon_Func_4: Etecoon_Func_4(k); return; // 0xa7e9af + case fnEtecoon_Func_5: Etecoon_Func_5(k); return; // 0xa7ea00 + case fnEtecoon_Func_6: Etecoon_Func_6(k); return; // 0xa7ea37 + case fnEtecoon_Func_7: Etecoon_Func_7(k); return; // 0xa7eab5 + case fnEtecoon_Func_8: Etecoon_Func_8(k); return; // 0xa7eb02 + case fnEtecoon_Func_9: Etecoon_Func_9(k); return; // 0xa7eb2c + case fnEtecoon_Func_10: Etecoon_Func_10(k); return; // 0xa7eb50 + case fnEtecoon_Func_11: Etecoon_Func_11(k); return; // 0xa7ebcd + case fnEtecoon_Func_12: Etecoon_Func_12(k); return; // 0xa7ec1b + case fnEtecoon_Func_16: Etecoon_Func_16(k); return; // 0xa7ec97 + case fnEtecoon_Func_17: Etecoon_Func_17(k); return; // 0xa7ecbb + case fnEtecoon_Func_18: Etecoon_Func_18(k); return; // 0xa7ecdf + case fnEtecoon_Func_19: Etecoon_Func_19(k); return; // 0xa7ed09 + case fnEtecoon_Func_20: Etecoon_Func_20(k); return; // 0xa7ed2a + case fnEtecoon_Func_21: Etecoon_Func_21(k); return; // 0xa7ed54 + case fnEtecoon_Func_22: Etecoon_Func_22(k); return; // 0xa7ed75 + case fnEtecoon_Func_23: Etecoon_Func_23(k); return; // 0xa7edc7 + case fnEtecoon_Func_24: Etecoon_Func_24(k); return; // 0xa7ee3e + case fnEtecoon_Func_25: Etecoon_Func_25(k); return; // 0xa7ee9a + case fnEtecoon_Func_26: Etecoon_Func_26(k); return; // 0xa7eeb8 + case fnDachora_Func_2: Dachora_Func_2(k); return; // 0xa7f570 + case fnDachora_Func_3: Dachora_Func_3(k); return; // 0xa7f5bc + case fnDachora_Func_4: Dachora_Func_4(k); return; // 0xa7f5ed + case fnDachora_Func_5: Dachora_Func_5(k); return; // 0xa7f65e + case fnDachora_Func_7: Dachora_Func_7(k); return; // 0xa7f78f + case fnDachora_Func_8: Dachora_Func_8(k); return; // 0xa7f806 + case fnDachora_Func_11: Dachora_Func_11(k); return; // 0xa7f935 + case fnDachora_Func_12: Dachora_Func_12(k); return; // 0xa7f98c + case fnMorphBallEye_Func_1: MorphBallEye_Func_1(k); return; // 0xa890f1 + case fnMorphBallEye_Func_2: MorphBallEye_Func_2(k); return; // 0xa8912e + case fnMorphBallEye_Func_3: MorphBallEye_Func_3(k); return; // 0xa89160 + case fnMorphBallEye_Func_4: MorphBallEye_Func_4(k); return; // 0xa891ce + case fnnullsub_244: return; // 0xa891dc + case fnNorfairLavaMan_Func_7: NorfairLavaMan_Func_7(k); return; // 0xa8b11a + case fnNorfairLavaMan_Func_8: NorfairLavaMan_Func_8(k); return; // 0xa8b175 + case fnsub_A8B193: sub_A8B193(k); return; // 0xa8b193 + case fnNorfairLavaMan_Func_9: NorfairLavaMan_Func_9(k); return; // 0xa8b1b8 + case fnNorfairLavaMan_Func_10: NorfairLavaMan_Func_10(k); return; // 0xa8b1dd + case fnNorfairLavaMan_Func_11: NorfairLavaMan_Func_11(k); return; // 0xa8b204 + case fnsub_A8B291: sub_A8B291(k); return; // 0xa8b291 + case fnNorfairLavaMan_Func_13: NorfairLavaMan_Func_13(); return; + case fnNorfairLavaMan_Func_15: NorfairLavaMan_Func_15(k); return; // 0xa8b30d + case fnNorfairLavaMan_Func_16: NorfairLavaMan_Func_16(k); return; // 0xa8b31f + case fnNorfairLavaMan_Func_17: NorfairLavaMan_Func_17(k); return; // 0xa8b356 + case fnNorfairLavaMan_Func_18: NorfairLavaMan_Func_18(k); return; // 0xa8b3a7 + case fnMaridiaFloater_Func_3: MaridiaFloater_Func_3(k); return; // 0xa8c283 + case fnMaridiaFloater_Func_4: MaridiaFloater_Func_4(k); return; // 0xa8c2a6 + case fnMaridiaFloater_Func_5: MaridiaFloater_Func_5(k); return; // 0xa8c2cf + case fnMaridiaFloater_Func_6: MaridiaFloater_Func_6(k); return; // 0xa8c36b + case fnMaridiaFloater_Func_7: MaridiaFloater_Func_7(k); return; // 0xa8c3e1 + case fnMaridiaFloater_Func_8: MaridiaFloater_Func_8(k); return; // 0xa8c469 + case fnMaridiaFloater_Func_9: MaridiaFloater_Func_9(k); return; // 0xa8c4dc + case fnMaridiaFloater_Func_10: MaridiaFloater_Func_10(k); return; // 0xa8c500 + case fnMaridiaFloater_Func_11: MaridiaFloater_Func_11(k); return; // 0xa8c51d + case fnnullsub_256: return; // 0xa8c568 + case fnMaridiaFloater_Func_12: MaridiaFloater_Func_12(k); return; // 0xa8c569 + case fnMaridiaFloater_Func_13: MaridiaFloater_Func_13(k); return; // 0xa8c59f + case fnnullsub_344: return; // 0xaac95e + case fnnullsub_274: return; // 0xaadcaa + case fnnullsub_276: return; // 0xaae7a6 + case fnnullsub_171_AA: return; // 0xaa807b + case fnnullsub_171_B3: return; // 0xb3807b + case fnBrinstarPipeBug_PreInstr_1: BrinstarPipeBug_PreInstr_1(k); return; // 0xb38880 + case fnBrinstarPipeBug_PreInstr_2: BrinstarPipeBug_PreInstr_2(k); return; // 0xb38890 + case fnBrinstarPipeBug_PreInstr_3: BrinstarPipeBug_PreInstr_3(k); return; // 0xb388e3 + case fnBrinstarPipeBug_PreInstr_4: BrinstarPipeBug_PreInstr_4(k); return; // 0xb3891c + case fnBrinstarPipeBug_PreInstr_5: BrinstarPipeBug_PreInstr_5(k); return; // 0xb3897e + case fnNorfairPipeBug_Func_5: NorfairPipeBug_Func_5(k); return; // 0xb38cff + case fnBotwoon_Func_26: Botwoon_Func_26(k); return; // 0xb39dc0 + case fnBotwoon_Func_27: Botwoon_Func_27(k); return; // 0xb39e7d + case fnBotwoon_Func_28: Botwoon_Func_28(k); return; // 0xb39ee0 + case fnBotwoon_Func_29: Botwoon_Func_29(k); return; // 0xb39f34 + case fnBotwoon_Func_30: Botwoon_Func_30(k); return; // 0xb39f7a + case fnTorizo_Func_5: Torizo_Func_5(k); return; + case fnTorizo_Func_6: Torizo_Func_6(k); return; + case fnTorizo_Func_7: Torizo_Func_7(k); return; + case fnTorizo_D5ED: Torizo_D5ED(k); return; + case fnTorizo_D5F1: Torizo_D5F1(k); return; + case fnsub_AAE445: sub_AAE445(k); return; + case fnShaktool_PreInstr_0: Shaktool_PreInstr_0(k); return; + case fnnullsub_277: return; + case fnEscapeEtecoon_E65C: EscapeEtecoon_E65C(k); return; + case fnsub_A3E168: sub_A3E168(k); return; + case fnMaridiaSnail_Func_7: MaridiaSnail_Func_7(k); return; + case fnMaridiaSnail_Func_9: MaridiaSnail_Func_9(k); return; + case fnMaridiaSnail_CFB7: MaridiaSnail_CFB7(k); return; + case fnMaridiaSnail_CFBD: MaridiaSnail_CFBD(k); return; + case fnMaridiaSnail_CFCE: MaridiaSnail_CFCE(k); return; + case fnMaridiaSnail_CFD4: MaridiaSnail_CFD4(k); return; + case fnMaridiaSnail_CFE5: MaridiaSnail_CFE5(k); return; + case fnMaridiaSnail_CFEB: MaridiaSnail_CFEB(k); return; + case fnMaridiaSnail_CFFC: MaridiaSnail_CFFC(k); return; + case fnnullsub_275: return; + case fnShaktool_DCAC: Shaktool_DCAC(k); return; + case fnShaktool_DCD7: Shaktool_DCD7(k); return; + case fnShaktool_DD25: Shaktool_DD25(k); return; + default: Unreachable(); + } +} + +uint16 CallEnemyInstr(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnEnemyInstr_Goto_A2: return EnemyInstr_Goto_A2(k, j); + case fnEnemyInstr_DecTimerAndGoto2_A2: return EnemyInstr_DecTimerAndGoto2_A2(k, j); + case fnEnemyInstr_SetTimer_A2: return EnemyInstr_SetTimer_A2(k, j); + case fnEnemyInstr_Sleep_A2: return EnemyInstr_Sleep_A2(k, j); + case fnEnemyInstr_EnableOffScreenProcessing_A2: return EnemyInstr_EnableOffScreenProcessing_A2(k, j); + case fnEnemyInstr_DisableOffScreenProcessing_A2: return EnemyInstr_DisableOffScreenProcessing_A2(k, j); + case fnBouncingGoofball_Instr_88C5: return BouncingGoofball_Instr_88C5(k, j); + case fnBouncingGoofball_Instr_88C6: return BouncingGoofball_Instr_88C6(k, j); + case fnMiniCrocomire_Instr_897E: return MiniCrocomire_Instr_897E(k, j); + case fnMiniCrocomire_Instr_8990: return MiniCrocomire_Instr_8990(k, j); + case fnMiniCrocomire_Instr_899D: return MiniCrocomire_Instr_899D(k, j); + case fnMaridiaBeybladeTurtle_Instr_9381: return MaridiaBeybladeTurtle_Instr_9381(k, j); + case fnMaridiaBeybladeTurtle_Instr_9412: return MaridiaBeybladeTurtle_Instr_9412(k, j); + case fnMaridiaBeybladeTurtle_Instr_9447: return MaridiaBeybladeTurtle_Instr_9447(k, j); + case fnMaridiaBeybladeTurtle_Instr_9451: return MaridiaBeybladeTurtle_Instr_9451(k, j); + case fnMaridiaBeybladeTurtle_Instr_946B: return MaridiaBeybladeTurtle_Instr_946B(k, j); + case fnMaridiaBeybladeTurtle_Instr_9485: return MaridiaBeybladeTurtle_Instr_9485(k, j); + case fnMaridiaBeybladeTurtle_Instr_94A1: return MaridiaBeybladeTurtle_Instr_94A1(k, j); + case fnMaridiaBeybladeTurtle_Instr_94C7: return MaridiaBeybladeTurtle_Instr_94C7(k, j); + case fnMaridiaBeybladeTurtle_Instr_94D1: return MaridiaBeybladeTurtle_Instr_94D1(k, j); + case fnSpikeShootingPlant_Instr_9F2A: return SpikeShootingPlant_Instr_9F2A(k, j); + case fnSpikeShootingPlant_Instr_A095: return SpikeShootingPlant_Instr_A095(k, j); + case fnSpikeShootingPlant_Instr_A0A7: return SpikeShootingPlant_Instr_A0A7(k, j); + case fnMaridiaSpikeyShell_Instr_A56D: return MaridiaSpikeyShell_Instr_A56D(k, j); + case fnMaridiaSpikeyShell_Instr_A571: return MaridiaSpikeyShell_Instr_A571(k, j); + case fnRinka_Instr_B9B3: return Rinka_Instr_B9B3(k, j); + case fnRinka_Instr_B9BD: return Rinka_Instr_B9BD(k, j); + case fnRinka_Instr_B9C7: return Rinka_Instr_B9C7(k, j); + case fnEnemyInstr_Rio_Instr_1: return EnemyInstr_Rio_Instr_1(k, j); + case fnNorfairLavajumpingEnemy_Instr_BE8E: return NorfairLavajumpingEnemy_Instr_BE8E(k, j); + case fnNorfairRio_Instr_C1C9: return NorfairRio_Instr_C1C9(k, j); + case fnNorfairRio_Instr_C1D4: return NorfairRio_Instr_C1D4(k, j); + case fnNorfairRio_Instr_C1DF: return NorfairRio_Instr_C1DF(k, j); + case fnNorfairRio_Instr_C1EA: return NorfairRio_Instr_C1EA(k, j); + case fnNorfairRio_Instr_C1F5: return NorfairRio_Instr_C1F5(k, j); + case fnNorfairRio_Instr_C200: return NorfairRio_Instr_C200(k, j); + case fnNorfairRio_Instr_C20B: return NorfairRio_Instr_C20B(k, j); + case fnNorfairRio_Instr_C216: return NorfairRio_Instr_C216(k, j); + case fnNorfairRio_Instr_C221: return NorfairRio_Instr_C221(k, j); + case fnNorfairRio_Instr_C22C: return NorfairRio_Instr_C22C(k, j); + case fnNorfairRio_Instr_C237: return NorfairRio_Instr_C237(k, j); + case fnLowerNorfairRio_Instr_C6D2: return LowerNorfairRio_Instr_C6D2(k, j); + case fnLowerNorfairRio_Instr_C6DD: return LowerNorfairRio_Instr_C6DD(k, j); + case fnLowerNorfairRio_Instr_C6E8: return LowerNorfairRio_Instr_C6E8(k, j); + case fnMaridiaLargeSnail_Instr_CB6B: return MaridiaLargeSnail_Instr_CB6B(k, j); + case fnMaridiaLargeSnail_Instr_CCB3: return MaridiaLargeSnail_Instr_CCB3(k, j); + case fnMaridiaLargeSnail_Instr_CCBE: return MaridiaLargeSnail_Instr_CCBE(k, j); + case fnMaridiaLargeSnail_Instr_CCC9: return MaridiaLargeSnail_Instr_CCC9(k, j); + case fnLavaSeahorse_Instr_E5FB: return LavaSeahorse_Instr_E5FB(k, j); + case fnEnemyInstr_Goto_A3: return EnemyInstr_Goto_A3(k, j); + case fnEnemyInstr_Sleep_A3: return EnemyInstr_Sleep_A3(k, j); + case fnEnemyInstr_EnableOffScreenProcessing_A3: return EnemyInstr_EnableOffScreenProcessing_A3(k, j); + case fnEnemyInstr_DisableOffScreenProcessing_A3: return EnemyInstr_DisableOffScreenProcessing_A3(k, j); + case fnWaver_Instr_1: return Waver_Instr_1(k, j); + case fnMetalee_Instr_1: return Metalee_Instr_1(k, j); + case fnMaridiaFish_Instr_3: return MaridiaFish_Instr_3(k, j); + case fnMaridiaFish_Instr_1: return MaridiaFish_Instr_1(k, j); + case fnMaridiaFish_Instr_2: return MaridiaFish_Instr_2(k, j); + case fnPlatformThatFallsWithSamus_Instr_3: return PlatformThatFallsWithSamus_Instr_3(k, j); + case fnPlatformThatFallsWithSamus_Instr_4: return PlatformThatFallsWithSamus_Instr_4(k, j); + case fnPlatformThatFallsWithSamus_Instr_1: return PlatformThatFallsWithSamus_Instr_1(k, j); + case fnPlatformThatFallsWithSamus_Instr_2: return PlatformThatFallsWithSamus_Instr_2(k, j); + case fnSidehopper_Func_1: return Sidehopper_Func_1(k, j); + case fnSidehopper_Instr_1: return Sidehopper_Instr_1(k, j); + case fnMaridiaRefillCandy_Instr_1: return MaridiaRefillCandy_Instr_1(k, j); + case fnMaridiaRefillCandy_Instr_2: return MaridiaRefillCandy_Instr_2(k, j); + case fnMaridiaRefillCandy_Instr_3: return MaridiaRefillCandy_Instr_3(k, j); + case fnBang_Instr_1: return Bang_Instr_1(k, j); + case fnBang_Instr_2: return Bang_Instr_2(k, j); + case fnSkree_Instr_1: return Skree_Instr_1(k, j); + case fnMaridiaSnail_Instr_1: return MaridiaSnail_Instr_1(k, j); + case fnMaridiaSnail_Instr_2: return MaridiaSnail_Instr_2(k, j); + case fnMaridiaSnail_Instr_4: return MaridiaSnail_Instr_4(k, j); + case fnMaridiaSnail_Instr_3: return MaridiaSnail_Instr_3(k, j); + case fnMaridiaSnail_Instr_5: return MaridiaSnail_Instr_5(k, j); + case fnReflec_Instr_1: return Reflec_Instr_1(k, j); + case fnWreckedShipOrangeZoomer_Func_1: return WreckedShipOrangeZoomer_Func_1(k, j); + case fnZoomer_Instr_SetPreinstr: return Zoomer_Instr_SetPreinstr(k, j); + case fnMetroid_Instr_2: return Metroid_Instr_2(k, j); + case fnMetroid_Instr_1: return Metroid_Instr_1(k, j); + case fnEnemyInstr_Goto_A4: return EnemyInstr_Goto_A4(k, j); + case fnEnemyInstr_Sleep_A4: return EnemyInstr_Sleep_A4(k, j); + case fnCrocomire_Instr_1: return Crocomire_Instr_1(k, j); + case fnCrocomire_Instr_14: return Crocomire_Instr_14(k, j); + case fnCrocomire_Instr_11: return Crocomire_Instr_11(k, j); + case fnCrocomire_Instr_7: return Crocomire_Instr_7(k, j); + case fnCrocomire_Instr_19: return Crocomire_Instr_19(k, j); + case fnCrocomire_Instr_2: return Crocomire_Instr_2(k, j); + case fnCrocomire_Instr_4: return Crocomire_Instr_4(k, j); + case fnCrocomire_Instr_3: return Crocomire_Instr_3(k, j); + case fnCrocomire_Instr_15: return Crocomire_Instr_15(k, j); + case fnCrocomire_Instr_16: return Crocomire_Instr_16(k, j); + case fnCrocomire_Instr_13: return Crocomire_Instr_13(k, j); + case fnCrocomire_Instr_18: return Crocomire_Instr_18(k, j); + case fnCrocomire_Instr_12: return Crocomire_Instr_12(k, j); + case fnCrocomire_Instr_17: return Crocomire_Instr_17(k, j); + case fnCrocomire_Instr_8: return Crocomire_Instr_8(k, j); + case fnCrocomire_Instr_6: return Crocomire_Instr_6(k, j); + case fnCrocomire_Instr_9: return Crocomire_Instr_9(k, j); + case fnCrocomire_Instr_5: return Crocomire_Instr_5(k, j); + case fnCrocomire_Instr_20: return Crocomire_Instr_20(k, j); + case fnCrocomire_Instr_21: return Crocomire_Instr_21(k, j); + case fnCrocomire_Instr_22: return Crocomire_Instr_22(k, j); + case fnCrocomire_Instr_23: return Crocomire_Instr_23(k, j); + case fnCrocomire_Instr_24: return Crocomire_Instr_24(k, j); + case fnCrocomire_Instr_10: return Crocomire_Instr_10(k, j); + case fnCrocomire_Instr_25: return Crocomire_Instr_25(k, j); + case fnCrocomire_Instr_26: return Crocomire_Instr_26(k, j); + case fnCrocomire_Instr_27: return Crocomire_Instr_27(k, j); + case fnEnemyInstr_StopScript_A5: return EnemyInstr_StopScript_A5(k, j); + case fnEnemyInstr_Goto_A5: return EnemyInstr_Goto_A5(k, j); + case fnEnemyInstr_DecTimerAndGoto2_A5: return EnemyInstr_DecTimerAndGoto2_A5(k, j); + case fnEnemyInstr_SetTimer_A5: return EnemyInstr_SetTimer_A5(k, j); + case fnEnemyInstr_Sleep_A5: return EnemyInstr_Sleep_A5(k, j); + case fnEnemyInstr_WaitNframes_A5: return EnemyInstr_WaitNframes_A5(k, j); + case fnDraygon_Instr_1: return Draygon_Instr_1(k, j); + case fnDraygon_Instr_13: return Draygon_Instr_13(k, j); + case fnDraygon_Instr_8: return Draygon_Instr_8(k, j); + case fnDraygon_Instr_7: return Draygon_Instr_7(k, j); + case fnDraygon_Instr_6: return Draygon_Instr_6(k, j); + case fnDraygon_Instr_9: return Draygon_Instr_9(k, j); + case fnDraygon_Instr_2: return Draygon_Instr_2(k, j); + case fnDraygon_Instr_11: return Draygon_Instr_11(k, j); + case fnDraygon_Instr_5: return Draygon_Instr_5(k, j); + case fnDraygon_Instr_15: return Draygon_Instr_15(k, j); + case fnDraygon_Instr_17: return Draygon_Instr_17(k, j); + case fnDraygon_Instr_14: return Draygon_Instr_14(k, j); + case fnDraygon_Instr_16: return Draygon_Instr_16(k, j); + case fnDraygon_Instr_10: return Draygon_Instr_10(k, j); + case fnDraygon_Instr_4: return Draygon_Instr_4(k, j); + case fnDraygon_Instr_12: return Draygon_Instr_12(k, j); + case fnDraygon_Instr_18: return Draygon_Instr_18(k, j); + case fnDraygon_Instr_3: return Draygon_Instr_3(k, j); + case fnDraygon_Instr_25: return Draygon_Instr_25(k, j); + case fnDraygon_Instr_24: return Draygon_Instr_24(k, j); + case fnDraygon_Instr_21: return Draygon_Instr_21(k, j); + case fnDraygon_Instr_22: return Draygon_Instr_22(k, j); + case fnDraygon_Instr_27: return Draygon_Instr_27(k, j); + case fnDraygon_Instr_23: return Draygon_Instr_23(k, j); + case fnDraygon_Instr_30: return Draygon_Instr_30(k, j); + case fnDraygon_Instr_20: return Draygon_Instr_20(k, j); + case fnDraygon_Instr_29: return Draygon_Instr_29(k, j); + case fnDraygon_Instr_19: return Draygon_Instr_19(k, j); + case fnDraygon_Instr_28: return Draygon_Instr_28(k, j); + case fnDraygon_Instr_26: return Draygon_Instr_26(k, j); + case fnEnemyInstr_Goto_A6: return EnemyInstr_Goto_A6(k, j); + case fnEnemyInstr_Sleep_A6: return EnemyInstr_Sleep_A6(k, j); + case fnFireGeyser_Instr_1: return FireGeyser_Instr_1(k, j); + case fnFireGeyser_Instr_2: return FireGeyser_Instr_2(k, j); + case fnFireGeyser_Instr_3: return FireGeyser_Instr_3(k, j); + case fnFireGeyser_Instr_4: return FireGeyser_Instr_4(k, j); + case fnFireGeyser_Instr_5: return FireGeyser_Instr_5(k, j); + case fnFireGeyser_Instr_6: return FireGeyser_Instr_6(k, j); + case fnFireGeyser_Instr_7: return FireGeyser_Instr_7(k, j); + case fnFireGeyser_Instr_8: return FireGeyser_Instr_8(k, j); + case fnFireGeyser_Instr_9: return FireGeyser_Instr_9(k, j); + case fnFireGeyser_Instr_10: return FireGeyser_Instr_10(k, j); + case fnFireGeyser_Instr_11: return FireGeyser_Instr_11(k, j); + case fnFireGeyser_Instr_12: return FireGeyser_Instr_12(k, j); + case fnFireGeyser_Instr_13: return FireGeyser_Instr_13(k, j); + case fnFireGeyser_Instr_14: return FireGeyser_Instr_14(k, j); + case fnFireGeyser_Instr_15: return FireGeyser_Instr_15(k, j); + case fnFireGeyser_Instr_16: return FireGeyser_Instr_16(k, j); + case fnFireGeyser_Instr_17: return FireGeyser_Instr_17(k, j); + case fnFireGeyser_Instr_18: return FireGeyser_Instr_18(k, j); + case fnFireGeyser_Instr_19: return FireGeyser_Instr_19(k, j); + case fnFireGeyser_Instr_20: return FireGeyser_Instr_20(k, j); + case fnFireGeyser_Instr_21: return FireGeyser_Instr_21(k, j); + case fnFireGeyser_Instr_22: return FireGeyser_Instr_22(k, j); + case fnFireGeyser_Instr_23: return FireGeyser_Instr_23(k, j); + case fnFireGeyser_Instr_24: return FireGeyser_Instr_24(k, j); + case fnFakeKraid_Instr_2: return FakeKraid_Instr_2(k, j); + case fnFakeKraid_Instr_1: return FakeKraid_Instr_1(k, j); + case fnFakeKraid_Instr_3: return FakeKraid_Instr_3(k, j); + case fnFakeKraid_Instr_4: return FakeKraid_Instr_4(k, j); + case fnFakeKraid_Instr_5: return FakeKraid_Instr_5(k, j); + case fnRidley_Instr_5: return Ridley_Instr_5(k, j); + case fnRidley_Instr_6: return Ridley_Instr_6(k, j); + case fnRidley_Instr_10: return Ridley_Instr_10(k, j); + case fnRidley_Instr_4: return Ridley_Instr_4(k, j); + case fnRidley_Instr_3: return Ridley_Instr_3(k, j); + case fnRidley_Instr_2: return Ridley_Instr_2(k, j); + case fnRidley_Instr_1: return Ridley_Instr_1(k, j); + case fnRidley_Instr_14: return Ridley_Instr_14(k, j); + case fnRidley_Instr_9: return Ridley_Instr_9(k, j); + case fnRidley_Instr_7: return Ridley_Instr_7(k, j); + case fnRidley_Instr_8: return Ridley_Instr_8(k, j); + case fnRidley_Instr_11: return Ridley_Instr_11(k, j); + case fnRidley_Instr_12: return Ridley_Instr_12(k, j); + case fnRidley_Instr_13: return Ridley_Instr_13(k, j); + case fnRidley_Instr_15: return Ridley_Instr_15(k, j); + case fnRidley_Instr_16: return Ridley_Instr_16(k, j); + case fnCeresSteam_Instr_1: return CeresSteam_Instr_1(k, j); + case fnCeresSteam_Instr_2: return CeresSteam_Instr_2(k, j); + case fnCeresSteam_Instr_3: return CeresSteam_Instr_3(k, j); + case fnCeresDoor_Instr_6: return CeresDoor_Instr_6(k, j); + case fnCeresDoor_Instr_4: return CeresDoor_Instr_4(k, j); + case fnCeresDoor_Instr_8: return CeresDoor_Instr_8(k, j); + case fnCeresSteam_Instr_4: return CeresSteam_Instr_4(k, j); + case fnCeresDoor_Instr_1: return CeresDoor_Instr_1(k, j); + case fnCeresDoor_Instr_3: return CeresDoor_Instr_3(k, j); + case fnCeresSteam_Instr_5: return CeresSteam_Instr_5(k, j); + case fnCeresDoor_Instr_5: return CeresDoor_Instr_5(k, j); + case fnCeresDoor_Instr_2: return CeresDoor_Instr_2(k, j); + case fnCeresDoor_Instr_7: return CeresDoor_Instr_7(k, j); + case fnEnemyInstr_Call_A7: return EnemyInstr_Call_A7(k, j); + case fnEnemyInstr_Goto_A7: return EnemyInstr_Goto_A7(k, j); + case fnEnemyInstr_DecTimerAndGoto2_A7: return EnemyInstr_DecTimerAndGoto2_A7(k, j); + case fnEnemyInstr_SetTimer_A7: return EnemyInstr_SetTimer_A7(k, j); + case fnEnemyInstr_Sleep_A7: return EnemyInstr_Sleep_A7(k, j); + case fnKraid_Instr_9: return Kraid_Instr_9(k, j); + case fnKraid_Instr_1: return Kraid_Instr_1(k, j); + case fnKraid_Instr_DecYpos: return Kraid_Instr_DecYpos(k, j); + case fnKraid_Instr_IncrYpos_Shake: return Kraid_Instr_IncrYpos_Shake(k, j); + case fnKraid_Instr_PlaySound_0x76: return Kraid_Instr_PlaySound_0x76(k, j); + case fnKraid_Instr_XposMinus3: return Kraid_Instr_XposMinus3(k, j); + case fnKraid_Instr_XposMinus3b: return Kraid_Instr_XposMinus3b(k, j); + case fnKraid_Instr_XposPlus3: return Kraid_Instr_XposPlus3(k, j); + case fnKraid_Instr_MoveHimRight: return Kraid_Instr_MoveHimRight(k, j); + case fnEnemyInstr_Goto_A8: return EnemyInstr_Goto_A8(k, j); + case fnEnemyInstr_DecTimerAndGoto2_A8: return EnemyInstr_DecTimerAndGoto2_A8(k, j); + case fnEnemyInstr_SetTimer_A8: return EnemyInstr_SetTimer_A8(k, j); + case fnEnemyInstr_Sleep_A8: return EnemyInstr_Sleep_A8(k, j); + case fnEnemyInstr_EnableOffScreenProcessing_A8: return EnemyInstr_EnableOffScreenProcessing_A8(k, j); + case fnEnemyInstr_DisableOffScreenProcessing_A8: return EnemyInstr_DisableOffScreenProcessing_A8(k, j); + case fnMiniDraygon_Instr_2: return MiniDraygon_Instr_2(k, j); + case fnMiniDraygon_Instr_1: return MiniDraygon_Instr_1(k, j); + case fnMiniDraygon_Instr_3: return MiniDraygon_Instr_3(k, j); + case fnMiniDraygon_Instr_4: return MiniDraygon_Instr_4(k, j); + case fnFune_Instr_2: return Fune_Instr_2(k, j); + case fnFune_Instr_6: return Fune_Instr_6(k, j); + case fnFune_Instr_7: return Fune_Instr_7(k, j); + case fnFune_Instr_1: return Fune_Instr_1(k, j); + case fnFune_Instr_4: return Fune_Instr_4(k, j); + case fnFune_Instr_3: return Fune_Instr_3(k, j); + case fnFune_Instr_5: return Fune_Instr_5(k, j); + case fnYappingMaw_Instr_2: return YappingMaw_Instr_2(k, j); + case fnYappingMaw_Instr_4: return YappingMaw_Instr_4(k, j); + case fnYappingMaw_Instr_5: return YappingMaw_Instr_5(k, j); + case fnYappingMaw_Instr_7: return YappingMaw_Instr_7(k, j); + case fnYappingMaw_Instr_3: return YappingMaw_Instr_3(k, j); + case fnYappingMaw_Instr_6: return YappingMaw_Instr_6(k, j); + case fnYappingMaw_Instr_1: return YappingMaw_Instr_1(k, j); + case fnNorfairLavaMan_Instr_1: return NorfairLavaMan_Instr_1(k, j); + case fnNorfairLavaMan_Instr_8: return NorfairLavaMan_Instr_8(k, j); + case fnNorfairLavaMan_Instr_14: return NorfairLavaMan_Instr_14(k, j); + case fnNorfairLavaMan_Instr_2: return NorfairLavaMan_Instr_2(k, j); + case fnNorfairLavaMan_Instr_7: return NorfairLavaMan_Instr_7(k, j); + case fnNorfairLavaMan_Instr_10: return NorfairLavaMan_Instr_10(k, j); + case fnNorfairLavaMan_Instr_12: return NorfairLavaMan_Instr_12(k, j); + case fnNorfairLavaMan_Instr_9: return NorfairLavaMan_Instr_9(k, j); + case fnNorfairLavaMan_Instr_11: return NorfairLavaMan_Instr_11(k, j); + case fnNorfairLavaMan_Instr_13: return NorfairLavaMan_Instr_13(k, j); + case fnNorfairLavaMan_Instr_5: return NorfairLavaMan_Instr_5(k, j); + case fnNorfairLavaMan_Instr_15: return NorfairLavaMan_Instr_15(k, j); + case fnNorfairLavaMan_Instr_4: return NorfairLavaMan_Instr_4(k, j); + case fnNorfairLavaMan_Instr_16: return NorfairLavaMan_Instr_16(k, j); + case fnNorfairLavaMan_Instr_6: return NorfairLavaMan_Instr_6(k, j); + case fnNorfairLavaMan_Instr_3: return NorfairLavaMan_Instr_3(k, j); + case fnBeetom_Instr_1: return Beetom_Instr_1(k, j); + case fnWreckedShipRobot_Instr_4: return WreckedShipRobot_Instr_4(k, j); + case fnWreckedShipRobot_Instr_9: return WreckedShipRobot_Instr_9(k, j); + case fnWreckedShipRobot_Instr_6: return WreckedShipRobot_Instr_6(k, j); + case fnWreckedShipRobot_Instr_8: return WreckedShipRobot_Instr_8(k, j); + case fnWreckedShipRobot_Instr_7: return WreckedShipRobot_Instr_7(k, j); + case fnWreckedShipRobot_Instr_15: return WreckedShipRobot_Instr_15(k, j); + case fnWreckedShipRobot_Instr_18: return WreckedShipRobot_Instr_18(k, j); + case fnWreckedShipRobot_Instr_16: return WreckedShipRobot_Instr_16(k, j); + case fnWreckedShipRobot_Instr_17: return WreckedShipRobot_Instr_17(k, j); + case fnWreckedShipRobot_Instr_3: return WreckedShipRobot_Instr_3(k, j); + case fnWreckedShipRobot_Instr_10: return WreckedShipRobot_Instr_10(k, j); + case fnWreckedShipRobot_Instr_14: return WreckedShipRobot_Instr_14(k, j); + case fnWreckedShipRobot_Instr_2: return WreckedShipRobot_Instr_2(k, j); + case fnWreckedShipRobot_Instr_13: return WreckedShipRobot_Instr_13(k, j); + case fnWreckedShipRobot_Instr_1: return WreckedShipRobot_Instr_1(k, j); + case fnWreckedShipRobot_Instr_12: return WreckedShipRobot_Instr_12(k, j); + case fnWreckedShipRobot_Instr_5: return WreckedShipRobot_Instr_5(k, j); + case fnWreckedShipRobot_Instr_11: return WreckedShipRobot_Instr_11(k, j); + case fnWalkingLavaSeahorse_Instr_4: return WalkingLavaSeahorse_Instr_4(k, j); + case fnWalkingLavaSeahorse_Instr_3: return WalkingLavaSeahorse_Instr_3(k, j); + case fnWalkingLavaSeahorse_Instr_5: return WalkingLavaSeahorse_Instr_5(k, j); + case fnWalkingLavaSeahorse_Instr_6: return WalkingLavaSeahorse_Instr_6(k, j); + case fnWalkingLavaSeahorse_Instr_2: return WalkingLavaSeahorse_Instr_2(k, j); + case fnWalkingLavaSeahorse_Instr_1: return WalkingLavaSeahorse_Instr_1(k, j); + case fnWreckedShipSpark_Instr_2: return WreckedShipSpark_Instr_2(k, j); + case fnWreckedShipSpark_Instr_1: return WreckedShipSpark_Instr_1(k, j); + case fnKiHunter_Instr_1: return KiHunter_Instr_1(k, j); + case fnKiHunter_Instr_2: return KiHunter_Instr_2(k, j); + case fnKiHunter_Instr_3: return KiHunter_Instr_3(k, j); + case fnKiHunter_Instr_4: return KiHunter_Instr_4(k, j); + case fnKiHunter_Instr_5: return KiHunter_Instr_5(k, j); + case fnEnemyInstr_Sleep_A9: return EnemyInstr_Sleep_A9(k, j); + case fnShitroid_Instr_1: return Shitroid_Instr_1(k, j); + case fnShitroid_Instr_2: return Shitroid_Instr_2(k, j); + case fnsub_A9ECD0: return sub_A9ECD0(k, j); + case fnShitroid_Instr_3: return Shitroid_Instr_3(k, j); + case fnShitroid_Instr_4: return Shitroid_Instr_4(k, j); + case fnShitroid_Instr_6: return Shitroid_Instr_6(k, j); + case fnShitroid_Instr_5: return Shitroid_Instr_5(k, j); + case fnEnemy_SetAiPreInstr_AA: return Enemy_SetAiPreInstr_AA(k, j); + case fnEnemy_ClearAiPreInstr_AA: return Enemy_ClearAiPreInstr_AA(k, j); + case fnEnemyInstr_StopScript_AA: return EnemyInstr_StopScript_AA(k, j); + case fnEnemyInstr_Goto_AA: return EnemyInstr_Goto_AA(k, j); + case fnEnemyInstr_DecTimerAndGoto2_AA: return EnemyInstr_DecTimerAndGoto2_AA(k, j); + case fnEnemyInstr_SetTimer_AA: return EnemyInstr_SetTimer_AA(k, j); + case fnEnemyInstr_Sleep_AA: return EnemyInstr_Sleep_AA(k, j); + case fnEnemyInstr_WaitNframes_AA: return EnemyInstr_WaitNframes_AA(k, j); + case fnEnemyInstr_CopyToVram_AA: return EnemyInstr_CopyToVram_AA(k, j); + case fnTorizo_Instr_3: return Torizo_Instr_3(k, j); + case fnTorizo_Instr_31: return Torizo_Instr_31(k, j); + case fnTorizo_Instr_33: return Torizo_Instr_33(k, j); + case fnTorizo_Instr_36: return Torizo_Instr_36(k, j); + case fnTorizo_Instr_37: return Torizo_Instr_37(k, j); + case fnTorizo_Instr_35: return Torizo_Instr_35(k, j); + case fnTorizo_Instr_38: return Torizo_Instr_38(k, j); + case fnTorizo_Instr_6: return Torizo_Instr_6(k, j); + case fnTorizo_Instr_5: return Torizo_Instr_5(k, j); + case fnTorizo_Instr_9: return Torizo_Instr_9(k, j); + case fnTorizo_Instr_7: return Torizo_Instr_7(k, j); + case fnTorizo_Instr_2: return Torizo_Instr_2(k, j); + case fnTorizo_Instr_8: return Torizo_Instr_8(k, j); + case fnTorizo_Instr_25: return Torizo_Instr_25(k, j); + case fnTorizo_Instr_22: return Torizo_Instr_22(k, j); + case fnTorizo_Instr_19: return Torizo_Instr_19(k, j); + case fnTorizo_Instr_32: return Torizo_Instr_32(k, j); + case fnTorizo_Instr_30: return Torizo_Instr_30(k, j); + case fnTorizo_Instr_34: return Torizo_Instr_34(k, j); + case fnTorizo_Instr_24: return Torizo_Instr_24(k, j); + case fnTorizo_Instr_12: return Torizo_Instr_12(k, j); + case fnTorizo_Instr_10: return Torizo_Instr_10(k, j); + case fnTorizo_Instr_11: return Torizo_Instr_11(k, j); + case fnTorizo_Instr_29: return Torizo_Instr_29(k, j); + case fnTorizo_Instr_1: return Torizo_Instr_1(k, j); + case fnTorizo_Instr_28: return Torizo_Instr_28(k, j); + case fnTorizo_Instr_4: return Torizo_Instr_4(k, j); + case fnTorizo_Instr_40: return Torizo_Instr_40(k, j); + case fnTorizo_Instr_16: return Torizo_Instr_16(k, j); + case fnTorizo_Instr_27: return Torizo_Instr_27(k, j); + case fnTorizo_Instr_23: return Torizo_Instr_23(k, j); + case fnTorizo_Instr_14: return Torizo_Instr_14(k, j); + case fnTorizo_Instr_15: return Torizo_Instr_15(k, j); + case fnTorizo_Instr_26: return Torizo_Instr_26(k, j); + case fnTorizo_Instr_18: return Torizo_Instr_18(k, j); + case fnTorizo_Instr_20: return Torizo_Instr_20(k, j); + case fnTorizo_Instr_44: return Torizo_Instr_44(k, j); + case fnTorizo_Instr_21: return Torizo_Instr_21(k, j); + case fnTorizo_Instr_17: return Torizo_Instr_17(k, j); + case fnTorizo_Instr_13: return Torizo_Instr_13(k, j); + case fnTorizo_Instr_39: return Torizo_Instr_39(k, j); + case fnTorizo_Instr_41: return Torizo_Instr_41(k, j); + case fnTorizo_Instr_42: return Torizo_Instr_42(k, j); + case fnTorizo_Instr_48: return Torizo_Instr_48(k, j); + case fnTorizo_Instr_57: return Torizo_Instr_57(k, j); + case fnTorizo_Instr_58: return Torizo_Instr_58(k, j); + case fnTorizo_Instr_59: return Torizo_Instr_59(k, j); + case fnTorizo_Instr_62: return Torizo_Instr_62(k, j); + case fnTorizo_Instr_63: return Torizo_Instr_63(k, j); + case fnTorizo_Instr_56: return Torizo_Instr_56(k, j); + case fnTorizo_Instr_60: return Torizo_Instr_60(k, j); + case fnTorizo_Instr_46: return Torizo_Instr_46(k, j); + case fnTorizo_Instr_47: return Torizo_Instr_47(k, j); + case fnTorizo_Instr_49: return Torizo_Instr_49(k, j); + case fnTorizo_Instr_61: return Torizo_Instr_61(k, j); + case fnTorizo_Instr_53: return Torizo_Instr_53(k, j); + case fnTorizo_Instr_55: return Torizo_Instr_55(k, j); + case fnTorizo_Instr_52: return Torizo_Instr_52(k, j); + case fnTorizo_Instr_50: return Torizo_Instr_50(k, j); + case fnTorizo_Instr_43: return Torizo_Instr_43(k, j); + case fnTorizo_Instr_51: return Torizo_Instr_51(k, j); + case fnTorizo_Instr_45: return Torizo_Instr_45(k, j); + case fnTorizo_Instr_54: return Torizo_Instr_54(k, j); + case fnShaktool_Instr_2: return Shaktool_Instr_2(k, j); + case fnShaktool_Instr_3: return Shaktool_Instr_3(k, j); + case fnShaktool_Instr_4: return Shaktool_Instr_4(k, j); + case fnShaktool_Instr_5: return Shaktool_Instr_5(k, j); + case fnShaktool_Instr_6: return Shaktool_Instr_6(k, j); + case fnShaktool_Instr_1: return Shaktool_Instr_1(k, j); + case fnShaktool_Instr_9: return Shaktool_Instr_9(k, j); + case fnShaktool_Instr_11: return Shaktool_Instr_11(k, j); + case fnShaktool_Instr_10: return Shaktool_Instr_10(k, j); + case fnShaktool_Instr_8: return Shaktool_Instr_8(k, j); + case fnShaktool_Instr_13: return Shaktool_Instr_13(k, j); + case fnShaktool_Instr_12: return Shaktool_Instr_12(k, j); + case fnShaktool_Instr_7: return Shaktool_Instr_7(k, j); + case fnShaktool_Instr_14: return Shaktool_Instr_14(k, j); + case fnEnemyInstr_Goto_B2: return EnemyInstr_Goto_B2(k, j); + case fnEnemyInstr_DecTimerAndGoto2_B2: return EnemyInstr_DecTimerAndGoto2_B2(k, j); + case fnEnemyInstr_SetTimer_B2: return EnemyInstr_SetTimer_B2(k, j); + case fnEnemyInstr_Sleep_B2: return EnemyInstr_Sleep_B2(k, j); + case fnEnemyInstr_WaitNframes_B2: return EnemyInstr_WaitNframes_B2(k, j); + case fnSpacePirates_Instr_MovePixelsDownAndChangeDirFaceRight: return SpacePirates_Instr_MovePixelsDownAndChangeDirFaceRight(k, j); + case fnSpacePirates_Instr_MovePixelsDownAndChangeDirFaceLeft: return SpacePirates_Instr_MovePixelsDownAndChangeDirFaceLeft(k, j); + case fnSpacePirates_Instr_RandomNewDirFaceR: return SpacePirates_Instr_RandomNewDirFaceR(k, j); + case fnSpacePirates_Instr_RandomNewDirFaceL: return SpacePirates_Instr_RandomNewDirFaceL(k, j); + case fnSpacePirates_Instr_PrepareWallJumpR: return SpacePirates_Instr_PrepareWallJumpR(k, j); + case fnSpacePirates_Instr_PrepareWallJumpL: return SpacePirates_Instr_PrepareWallJumpL(k, j); + case fnSpacePirates_Instr_FireLaserL: return SpacePirates_Instr_FireLaserL(k, j); + case fnSpacePirates_Instr_FireLaserR: return SpacePirates_Instr_FireLaserR(k, j); + case fnSpacePirates_Instr_SetEnemyFunc: return SpacePirates_Instr_SetEnemyFunc(k, j); + case fnSpacePirates_Instr_PlaySfx: return SpacePirates_Instr_PlaySfx(k, j); + case fnSpacePirates_Instr_20: return SpacePirates_Instr_20(k, j); + case fnSpacePirates_Instr_16: return SpacePirates_Instr_16(k, j); + case fnSpacePirates_Instr_15: return SpacePirates_Instr_15(k, j); + case fnSpacePirates_Instr_18: return SpacePirates_Instr_18(k, j); + case fnSpacePirates_Instr_17: return SpacePirates_Instr_17(k, j); + case fnSpacePirates_Instr_19: return SpacePirates_Instr_19(k, j); + case fnSpacePirates_Instr_21: return SpacePirates_Instr_21(k, j); + case fnSpacePirates_Instr_12: return SpacePirates_Instr_12(k, j); + case fnSpacePirates_Instr_14: return SpacePirates_Instr_14(k, j); + case fnSpacePirates_Instr_11: return SpacePirates_Instr_11(k, j); + case fnSpacePirates_Instr_13: return SpacePirates_Instr_13(k, j); + case fnEnemy_SetAiPreInstr_B3: return Enemy_SetAiPreInstr_B3(k, j); + case fnEnemy_ClearAiPreInstr_B3: return Enemy_ClearAiPreInstr_B3(k, j); + case fnEnemyInstr_Goto_B3: return EnemyInstr_Goto_B3(k, j); + case fnEnemyInstr_DecTimerAndGoto2_B3: return EnemyInstr_DecTimerAndGoto2_B3(k, j); + case fnEnemyInstr_SetTimer_B3: return EnemyInstr_SetTimer_B3(k, j); + case fnEnemyInstr_Sleep_B3: return EnemyInstr_Sleep_B3(k, j); + case fnBotwoon_Instr_1: return Botwoon_Instr_1(k, j); + case fnBotwoon_Instr_2: return Botwoon_Instr_2(k, j); + case fnBotwoon_Instr_3: return Botwoon_Instr_3(k, j); + case fnBotwoon_Instr_4: return Botwoon_Instr_4(k, j); + case fnBotwoon_Instr_5: return Botwoon_Instr_5(k, j); + case fnBotwoon_Instr_6: return Botwoon_Instr_6(k, j); + case fnBotwoon_Instr_7: return Botwoon_Instr_7(k, j); + case fnBotwoon_Instr_8: return Botwoon_Instr_8(k, j); + case fnBotwoon_Instr_9: return Botwoon_Instr_9(k, j); + case fnBotwoon_Instr_10: return Botwoon_Instr_10(k, j); + case fnBotwoon_Instr_SetSpitting: return Botwoon_Instr_SetSpitting(k, j); + case fnBotwoon_Instr_QueueSpitSfx: return Botwoon_Instr_QueueSpitSfx(k, j); + case fnEscapeEtecoon_Instr_1: return EscapeEtecoon_Instr_1(k, j); + case fnEscapeEtecoon_Instr_2: return EscapeEtecoon_Instr_2(k, j); + case fnEscapeDachora_Instr_2: return EscapeDachora_Instr_2(k, j); + case fnEscapeDachora_Instr_3: return EscapeDachora_Instr_3(k, j); + case fnEscapeDachora_Instr_1: return EscapeDachora_Instr_1(k, j); + case fnEscapeDachora_Instr_4: return EscapeDachora_Instr_4(k, j); + case fnMotherBrain_Instr_MoveBodyUp10Left4: return MotherBrain_Instr_MoveBodyUp10Left4(k, j); + case fnMotherBrain_Instr_MoveBodyUp16Left4: return MotherBrain_Instr_MoveBodyUp16Left4(k, j); + case fnMotherBrain_Instr_MoveBodyUp12Right2: return MotherBrain_Instr_MoveBodyUp12Right2(k, j); + case fnMotherBrain_Instr_MoveDown12Left4: return MotherBrain_Instr_MoveDown12Left4(k, j); + case fnMotherBrain_Instr_MoveDown16Right2: return MotherBrain_Instr_MoveDown16Right2(k, j); + case fnMotherBrain_Instr_MoveDown10Right2: return MotherBrain_Instr_MoveDown10Right2(k, j); + case fnMotherBrain_Instr_MoveUp2Right1: return MotherBrain_Instr_MoveUp2Right1(k, j); + case fnMotherBrain_Instr_MoveRight2: return MotherBrain_Instr_MoveRight2(k, j); + case fnMotherBrain_Instr_MoveUp1: return MotherBrain_Instr_MoveUp1(k, j); + case fnMotherBrain_Instr_MoveUp1Right3_Sfx: return MotherBrain_Instr_MoveUp1Right3_Sfx(k, j); + case fnMotherBrain_Instr_Down2Right15: return MotherBrain_Instr_Down2Right15(k, j); + case fnMotherBrain_Instr_Down4Right6: return MotherBrain_Instr_Down4Right6(k, j); + case fnMotherBrain_Instr_Up4Left2: return MotherBrain_Instr_Up4Left2(k, j); + case fnMotherBrain_Instr_Up2Left1_Sfx: return MotherBrain_Instr_Up2Left1_Sfx(k, j); + case fnMotherBrain_Instr_Up2Left1_Sfx2: return MotherBrain_Instr_Up2Left1_Sfx2(k, j); + case fnMotherBrain_Instr_MoveLeft2: return MotherBrain_Instr_MoveLeft2(k, j); + case fnMotherBrain_Instr_MoveDown1: return MotherBrain_Instr_MoveDown1(k, j); + case fnMotherBrain_Instr_MoveDown1Left3: return MotherBrain_Instr_MoveDown1Left3(k, j); + case fnMotherBrain_Instr_MoveUp2Left15_Sfx: return MotherBrain_Instr_MoveUp2Left15_Sfx(k, j); + case fnMotherBrain_Instr_MoveUp4Left6: return MotherBrain_Instr_MoveUp4Left6(k, j); + case fnMotherBrain_Instr_MoveDown4Right2: return MotherBrain_Instr_MoveDown4Right2(k, j); + case fnMotherBrain_Instr_MoveDown2Right1: return MotherBrain_Instr_MoveDown2Right1(k, j); + case fnMotherBrain_Instr_SetPose_Standing: return MotherBrain_Instr_SetPose_Standing(k, j); + case fnMotherBrain_Instr_SetPose_Walking: return MotherBrain_Instr_SetPose_Walking(k, j); + case fnMotherBrain_Instr_SetPose_Crouched: return MotherBrain_Instr_SetPose_Crouched(k, j); + case fnMotherBrain_Instr_SetPose_CrouchedTrans: return MotherBrain_Instr_SetPose_CrouchedTrans(k, j); + case fnMotherBrain_Instr_SetPose_DeathBeamMode: return MotherBrain_Instr_SetPose_DeathBeamMode(k, j); + case fnMotherBrain_Instr_SetPose_LeaningDown: return MotherBrain_Instr_SetPose_LeaningDown(k, j); + case fnMotherBrain_Instr_SpawnEprojToOffset: return MotherBrain_Instr_SpawnEprojToOffset(k, j); + case fnMotherBrain_Instr_SpawnDeathBeamEproj: return MotherBrain_Instr_SpawnDeathBeamEproj(k, j); + case fnMotherBrain_Instr_IncrBeamAttackPhase: return MotherBrain_Instr_IncrBeamAttackPhase(k, j); + + default: return Unreachable(); + } +} + +void EnemyMain(void) { // 0xA08FD4 + EnemyDef_A2 *EnemyDef_A2; + int16 v6; + char v8; // cf + + if (first_free_enemy_index) { + if (enemy_index_to_shake != 0xFFFF) { + gEnemyData(enemy_index_to_shake)->shake_timer = 64; + enemy_index_to_shake = -1; + } + interactive_enemy_indexes_index = 0; + for (active_enemy_indexes_index = 0; ; ++active_enemy_indexes_index) { + int v0 = active_enemy_indexes_index >> 1; + uint16 v1 = active_enemy_indexes[v0]; + if (v1 == 0xFFFF) + break; + cur_enemy_index = active_enemy_indexes[v0]; + uint16 v2 = v1; + enemy_data_ptr = v1 + 3960; + EnemyData *v3 = gEnemyData(v1); + *(uint16 *)&enemy_ai_pointer.bank = *(uint16 *)&v3->bank; + if ((v3->properties & 0x400) == 0) { + if (v3->invincibility_timer) { + --v3->invincibility_timer; + } else if (!debug_disable_sprite_interact) { + if (!(debug_time_frozen_for_enemies | time_is_frozen_flag)) { + EnemyCollisionHandler(); + if (!gEnemyData(cur_enemy_index)->enemy_ptr) + goto LABEL_32; + } + v2 = cur_enemy_index; + if ((gEnemyData(cur_enemy_index)->extra_properties & 1) != 0) + goto LABEL_23; + } + } + UNUSED_word_7E17A2 = 0; + if (!(debug_time_frozen_for_enemies | time_is_frozen_flag)) { + v6 = 0; + uint16 ai_handler_bits = gEnemyData(cur_enemy_index)->ai_handler_bits; + if (ai_handler_bits) { + do { + ++v6; + v8 = ai_handler_bits & 1; + ai_handler_bits >>= 1; + } while (!v8); + } + EnemyData *v9 = gEnemyData(cur_enemy_index); + enemy_ai_pointer.addr = get_EnemyDef_A2(v9->enemy_ptr + 2 * v6)->main_ai; + goto LABEL_20; + } + EnemyData *v4; + v4 = gEnemyData(v2); + EnemyDef_A2 = get_EnemyDef_A2(v4->enemy_ptr); + if (EnemyDef_A2->time_is_frozen_ai) { + enemy_ai_pointer.addr = EnemyDef_A2->time_is_frozen_ai; +LABEL_20: + enemy_ai_pointer.bank = gEnemyData(cur_enemy_index)->bank; + CallEnemyAi(Load24(&enemy_ai_pointer)); + if (!(debug_time_frozen_for_enemies | time_is_frozen_flag)) { + EnemyData *v10 = gEnemyData(cur_enemy_index); + ++v10->frame_counter; + if ((v10->properties & 0x2000) != 0) { + enemy_processing_stage = 2; + ProcessEnemyInstructions(); + } + } + } +LABEL_23:; + uint16 v11; + v11 = cur_enemy_index; + EnemyData *v12; + v12 = gEnemyData(cur_enemy_index); + if ((v12->extra_properties & 1) != 0 && (v12->flash_timer == 1 || v12->frozen_timer == 1)) { + gEnemySpawnData(cur_enemy_index)->cause_of_death = 0; + EnemyDeathAnimation(v11, 0); + } + if (((gEnemyData(cur_enemy_index)->extra_properties & 4) != 0 || !EnemyWithNormalSpritesIsOffScreen()) + && (gEnemyData(cur_enemy_index)->properties & 0x300) == 0 + && (UNUSED_word_7E17A2 & 1) == 0) { + DrawOneEnemy(); + } +LABEL_32:; + EnemyData *v13 = gEnemyData(cur_enemy_index); + if (v13->flash_timer && !(debug_time_frozen_for_enemies | time_is_frozen_flag)) { + if (sign16(--v13->flash_timer - 8)) + v13->ai_handler_bits &= ~2u; + } + ++active_enemy_indexes_index; + } + } + HandleSpriteObjects(); + ++enemy_damage_routine_exec_count; + enemy_index_colliding_dirs[0] = -1; + enemy_index_colliding_dirs[1] = -1; + enemy_index_colliding_dirs[2] = -1; + enemy_index_colliding_dirs[3] = -1; + distance_to_enemy_colliding_dirs[0] = 0; + distance_to_enemy_colliding_dirs[1] = 0; + distance_to_enemy_colliding_dirs[2] = 0; + distance_to_enemy_colliding_dirs[3] = 0; +} + +void DecrementSamusTimers(void) { // 0xA09169 + if (samus_invincibility_timer) + --samus_invincibility_timer; + if (samus_knockback_timer) + --samus_knockback_timer; + if (projectile_invincibility_timer) + --projectile_invincibility_timer; + interactive_enemy_indexes[0] = -1; + active_enemy_indexes[0] = -1; +} + +void SpawnEnemyDrops(uint16 a, uint16 k) { // 0xA0920E + varE24 = a; + SpawnEnemyProjectileWithGfx(enemy_population_ptr, k, addr_kEproj_Pickup); +} + +void DeleteEnemyAndConnectedEnemies(void) { // 0xA0922B + EnemyData *v0 = gEnemyData(cur_enemy_index); + uint16 num_parts = get_EnemyDef_A2(v0->enemy_ptr)->num_parts; + if (!num_parts) + num_parts = 1; + uint16 v2 = num_parts; + do { + gEnemyData(cur_enemy_index)->enemy_ptr = 0; + cur_enemy_index += 64; + --v2; + } while (v2); +} + +uint16 SpawnEnemy(uint8 db, uint16 k) { // 0xA09275 + int16 v3; + VoidP v7; + int16 v12; + EnemyPopulation *v13; + EnemyPopulation *v16; + EnemyDef_A2 *v17; + EnemyDef_A2 *EnemyDef_A2; + EnemyPopulation *EnemyPopulation; + + uint8 v19 = db; + enemy_population_ptr = k; + cur_enemy_index_backup = cur_enemy_index; + enemy_ai_pointer_backup.addr = enemy_ai_pointer.addr; + *(uint16 *)&enemy_ai_pointer_backup.bank = *(uint16 *)&enemy_ai_pointer.bank; + uint16 enemy_ptr = get_EnemyPopulation(db, k)->enemy_ptr; + v3 = get_EnemyDef_A2(enemy_ptr)->num_parts - 1; + if (v3 < 0) + v3 = 0; + draw_oam_x_offset = v3; + varE26 = v3; + new_enemy_index = 0; + do { + uint16 v4 = new_enemy_index; + if (!gEnemyData(new_enemy_index)->enemy_ptr) { + while (!gEnemyData(v4)->enemy_ptr) { + if (!draw_oam_x_offset) { + while (1) { + uint16 v5 = new_enemy_index; + EnemyPopulation = get_EnemyPopulation(v19, enemy_population_ptr); + v7 = EnemyPopulation->enemy_ptr; + uint16 v8 = 0; + if (EnemyPopulation->enemy_ptr == enemy_def_ptr[0] + || (v8 = 2, v7 == enemy_def_ptr[1]) + || (v8 = 4, v7 == enemy_def_ptr[2]) + || (v8 = 6, v7 == enemy_def_ptr[3])) { + int v10 = v8 >> 1; + EnemyData *v11 = gEnemyData(new_enemy_index); + v11->vram_tiles_index = enemy_gfxdata_tiles_index[v10]; + LOBYTE(v12) = HIBYTE(enemy_gfxdata_vram_ptr[v10]); + HIBYTE(v12) = enemy_gfxdata_vram_ptr[v10]; + v11->palette_index = 2 * v12; + } else { + EnemyData *v9 = gEnemyData(new_enemy_index); + v9->vram_tiles_index = 0; + v9->palette_index = 0; + } + v13 = get_EnemyPopulation(v19, enemy_population_ptr); + EnemyDef_A2 = get_EnemyDef_A2(v13->enemy_ptr); + EnemyData *v15 = gEnemyData(v5); + v15->x_width = EnemyDef_A2->x_radius; + v15->y_height = EnemyDef_A2->y_radius; + v15->health = EnemyDef_A2->health; + v15->layer = EnemyDef_A2->layer; + *(uint16 *)&v15->bank = *(uint16 *)&EnemyDef_A2->bank; + v16 = get_EnemyPopulation(v19, enemy_population_ptr); + v15->enemy_ptr = v16->enemy_ptr; + v15->x_pos = v16->x_pos; + v15->y_pos = v16->y_pos; + v15->current_instruction = v16->init_param; + v15->properties = v16->properties; + v15->extra_properties = v16->extra_properties; + v15->parameter_1 = v16->parameter1; + v15->parameter_2 = v16->parameter2; + v15->frame_counter = 0; + v15->timer = 0; + v15->ai_var_A = 0; + v15->ai_var_B = 0; + v15->ai_var_C = 0; + v15->ai_var_D = 0; + v15->ai_var_E = 0; + v15->ai_preinstr = 0; + v15->instruction_timer = 1; + v15->frame_counter = 0; + RecordEnemySpawnData(v5); + cur_enemy_index = v5; + v17 = get_EnemyDef_A2(v15->enemy_ptr); + if (!sign16(v17->ai_init + 0x8000)) { + enemy_ai_pointer.addr = v17->ai_init; + *(uint16 *)&enemy_ai_pointer.bank = *(uint16 *)&v17->bank; + CallEnemyAi(Load24(&enemy_ai_pointer)); + } + EnemyData *v18 = gEnemyData(v5); + if ((v18->properties & 0x2000) != 0) + v18->spritemap_pointer = addr_kSpritemap_Nothing_A0; + if (!varE26) + break; + if (!--varE26) + break; + new_enemy_index += 64; + enemy_population_ptr += 16; + } + enemy_ai_pointer.addr = enemy_ai_pointer_backup.addr; + *(uint16 *)&enemy_ai_pointer.bank = *(uint16 *)&enemy_ai_pointer_backup.bank; + cur_enemy_index = cur_enemy_index_backup; + return new_enemy_index; + } + --draw_oam_x_offset; + v4 += 64; + if ((int16)(v4 - 2048) >= 0) + return 0xffff; + } + } + new_enemy_index += 64; + } while (sign16(new_enemy_index - 2048)); + return 0xffff; +} + +void DrawOneEnemy(void) { // 0xA09423 + enemy_drawing_queue_index = 2 * gEnemyData(cur_enemy_index)->layer; + *(uint16 *)RomPtr_RAM( + enemy_drawing_queue_sizes[enemy_drawing_queue_index >> 1] + + kEnemyLayerToQueuePtr[enemy_drawing_queue_index >> 1]) = cur_enemy_index; + int v0 = enemy_drawing_queue_index >> 1; + ++enemy_drawing_queue_sizes[v0]; + ++enemy_drawing_queue_sizes[v0]; +} + +void WriteEnemyOams(void) { // 0xA0944A + EnemySpawnData *v1; + VoidP palette_index; + ExtendedSpriteMap *ExtendedSpriteMap; + + uint8 db = gEnemyData(cur_enemy_index)->bank; + EnemyData *v0 = gEnemyData(cur_enemy_index); + v1 = gEnemySpawnData(cur_enemy_index); + draw_oam_x_offset = v1->xpos2 + v0->x_pos - layer1_x_pos; + R20_ = draw_oam_x_offset; + enemy_population_ptr = v1->ypos2 + v0->y_pos - layer1_y_pos; + R18_ = enemy_population_ptr; + if (v0->shake_timer) { + if ((v0->frame_counter & 2) != 0) { + --R20_; + --draw_oam_x_offset; + } else { + ++R20_; + ++draw_oam_x_offset; + } + --v0->shake_timer; + } + if (v0->flash_timer && (enemy_damage_routine_exec_count & 2) != 0) { + palette_index = 0; + } else { + uint16 frozen_timer = v0->frozen_timer; + if (frozen_timer && (frozen_timer >= 0x5Au || (frozen_timer & 2) != 0)) + palette_index = 3072; + else + palette_index = v0->palette_index; + } + R3_.addr = palette_index; + R0_.addr = v0->vram_tiles_index; + if ((v0->extra_properties & 4) != 0) { + while ((int16)(v0->spritemap_pointer + 0x8000) < 0) + ; + uint16 spritemap_pointer = v0->spritemap_pointer; + remaining_enemy_spritemap_entries = *RomPtrWithBank(db, spritemap_pointer); + uint16 v5 = spritemap_pointer + 2; + do { + ExtendedSpriteMap = get_ExtendedSpriteMap(db, v5); + R22_ = ExtendedSpriteMap->spritemap; + if (*(uint16 *)RomPtrWithBank(db, R22_) == 0xFFFE) { + R20_ = draw_oam_x_offset + ExtendedSpriteMap->xpos; + R18_ = enemy_population_ptr + ExtendedSpriteMap->ypos; + if ((gEnemyData(cur_enemy_index)->extra_properties & 0x8000u) != 0) + ProcessExtendedTilemap(db); + } else { + R20_ = draw_oam_x_offset + ExtendedSpriteMap->xpos; + if (((R20_ + 128) & 0xFE00) == 0) { + uint16 ypos = ExtendedSpriteMap->ypos; + R18_ = enemy_population_ptr + ypos; + if (((R18_ + 128) & 0xFE00) == 0) { + if (HIBYTE(R18_)) + DrawSpritemapWithBaseTileOffscreen(db, R22_); + else + DrawSpritemapWithBaseTile2(db, R22_); + } + } + } + v5 += 8; + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); + } else { + g_word_7EF37E = v0->enemy_ptr; + g_word_7EF37A = v0->current_instruction; + g_word_7EF37C = cur_enemy_index; + enemy_processing_stage = 1; + DrawSpritemapWithBaseTile(db, v0->spritemap_pointer); + } +} + +void NormalEnemyFrozenAI(void) { // 0xA0957E + EnemyData *v0 = gEnemyData(cur_enemy_index); + v0->flash_timer = 0; + if (!v0->frozen_timer || (--v0->frozen_timer, (equipped_beams & 2) == 0)) { + uint16 v1 = v0->ai_handler_bits & 0xFFFB; + v0->ai_handler_bits = v1; + v0->frozen_timer = v1; + } +} + +void ProcessExtendedTilemap(uint8 db) { // 0xA096CA + int16 v3; + + uint16 v0 = R22_ + 2; + while (1) { + uint8 *v1 = RomPtrWithBank(db, v0); + if (*(uint16 *)v1 == 0xFFFF) + break; + uint16 v2 = *(uint16 *)v1; + remaining_enemy_hitbox_entries = *((uint16 *)v1 + 1); + v0 += 4; + if (remaining_enemy_hitbox_entries & 1) { + do { + v3 = *(uint16 *)RomPtrWithBank(db, v0); + *(uint16 *)RomPtr_7E(v2) = v3; + v2 += 2; + v0 += 2; + --remaining_enemy_hitbox_entries; + } while (remaining_enemy_hitbox_entries); + } else { + do { + uint8 *v4 = RomPtrWithBank(db, v0); + uint8 *v5 = RomPtr_7E(v2); + *(uint16 *)v5 = *(uint16 *)v4; + *((uint16 *)v5 + 1) = *((uint16 *)v4 + 1); + v2 += 4; + v0 += 4; + while ((int16)(v2 - 10240) >= 0) + ; + --remaining_enemy_hitbox_entries; + --remaining_enemy_hitbox_entries; + } while (remaining_enemy_hitbox_entries); + } + } + ++nmi_flag_bg2_enemy_vram_transfer; +} + +void QueueEnemyBG2TilemapTransfers(void) { // 0xA09726 + VramWriteEntry *v0; + + if (nmi_flag_bg2_enemy_vram_transfer && !(debug_time_frozen_for_enemies | time_is_frozen_flag)) { + v0 = gVramWriteEntry(vram_write_queue_tail); + v0->size = enemy_bg2_tilemap_size; + v0->src.addr = ADDR16_OF_RAM(*tilemap_stuff); + *(uint16 *)&v0->src.bank = 126; + v0->vram_dst = addr_unk_604800; + vram_write_queue_tail += 7; + } + nmi_flag_bg2_enemy_vram_transfer = 0; +} + +void EnemyCollisionHandler(void) { // 0xA09758 + if ((gEnemyData(cur_enemy_index)->extra_properties & 4) != 0) { + EnemyProjectileCollHandler_Multibox(); + EnemyBombCollHandler_Multibox(); + EnemySamusCollHandler_Multibox(); + } else { + EnemyProjectileCollHandler(); + EnemyBombCollHandler(); + EnemySamusCollHandler(); + } +} + +void func_nullsub_4(void) { + ; +} + +void SamusProjectileInteractionHandler(void) { // 0xA09785 + int16 v2; + + enemy_processing_stage = 10; + if (!flag_disable_projectile_interaction) { + num_projs_to_check = 5; + if (bomb_counter) { + num_projs_to_check = 10; + } else if (!projectile_counter) { + return; + } + if (!projectile_invincibility_timer && !samus_contact_damage_index) { + collision_detection_index = 0; + do { + int v1 = collision_detection_index; + if (projectile_damage[v1]) { + v2 = projectile_type[v1]; + if (v2 >= 0) { + if (sign16((v2 & 0xF00) - 1792)) { + int v3 = collision_detection_index; + if ((projectile_dir[v3] & 0x10) == 0) { + uint16 v4 = abs16(projectile_x_pos[v3] - samus_x_pos); + bool v5 = v4 < projectile_x_radius[v3]; + uint16 v6 = v4 - projectile_x_radius[v3]; + if (v5 || v6 < samus_x_radius) { + uint16 v7 = abs16(projectile_y_pos[v3] - samus_y_pos); + v5 = v7 < projectile_y_radius[v3]; + uint16 v8 = v7 - projectile_y_radius[v3]; + if (v5 || v8 < samus_y_radius) { + if ((projectile_type[v3] & 0xFF00) != 768 && (projectile_type[v3] & 0xFF00) != 1280) { + projectile_dir[v3] |= 0x10u; + uint16 v10 = SuitDamageDivision(projectile_damage[v3]); + Samus_DealDamage(v10); + samus_invincibility_timer = 96; + samus_knockback_timer = 5; + assert(0); + uint16 v0 = 0; + knockback_x_dir = (int16)(samus_x_pos - enemy_projectile_x_pos[v0 >> 1]) >= 0; + return; + } + if (projectile_variables[v3] == 8) { + uint16 v9; + if (samus_x_pos == projectile_x_pos[v3]) { + v9 = 2; + } else if ((int16)(samus_x_pos - projectile_x_pos[v3]) < 0) { + v9 = 1; + } else { + v9 = 3; + } + bomb_jump_dir = v9; + } + } + } + } + } + } + } + ++collision_detection_index; + } while (collision_detection_index != num_projs_to_check); + } + } +} + +void EprojSamusCollDetect(void) { // 0xA09894 + enemy_processing_stage = 11; + if (!samus_invincibility_timer && !samus_contact_damage_index) { + collision_detection_index = 34; + do { + if (*(uint16 *)((char *)enemy_projectile_id + collision_detection_index)) { + int v0 = collision_detection_index >> 1; + if ((enemy_projectile_properties[v0] & 0x2000) == 0) { + if (LOBYTE(enemy_projectile_radius[v0])) { + enemy_population_ptr = LOBYTE(enemy_projectile_radius[v0]); + if (HIBYTE(enemy_projectile_radius[v0])) { + draw_oam_x_offset = HIBYTE(enemy_projectile_radius[v0]); + uint16 v1 = abs16(samus_x_pos - enemy_projectile_x_pos[v0]); + bool v2 = v1 < samus_x_radius; + uint16 v3 = v1 - samus_x_radius; + if (v2 || v3 < enemy_population_ptr) { + uint16 v4 = abs16(samus_y_pos - enemy_projectile_y_pos[v0]); + v2 = v4 < samus_y_radius; + uint16 v5 = v4 - samus_y_radius; + if (v2 || v5 < draw_oam_x_offset) + HandleEprojCollWithSamus(collision_detection_index); + } + } + } + } + } + --collision_detection_index; + --collision_detection_index; + } while ((collision_detection_index & 0x8000u) == 0); + } +} + +void HandleEprojCollWithSamus(uint16 k) { // 0xA09923 + samus_invincibility_timer = 96; + samus_knockback_timer = 5; + uint16 v1 = *((uint16 *)RomPtr_86(*(uint16 *)((char *)enemy_projectile_id + k)) + 5); + if (v1) { + int v2 = k >> 1; + enemy_projectile_instr_list_ptr[v2] = v1; + enemy_projectile_instr_timers[v2] = 1; + } + int v3 = k >> 1; + if ((enemy_projectile_properties[v3] & 0x4000) == 0) + *(uint16 *)((char *)enemy_projectile_id + k) = 0; + uint16 v4 = SuitDamageDivision(enemy_projectile_properties[v3] & 0xFFF); + Samus_DealDamage(v4); + knockback_x_dir = (int16)(samus_x_pos - enemy_projectile_x_pos[v3]) >= 0; +} + +void EprojProjCollDet(void) { // 0xA0996C + int16 v5; + + enemy_processing_stage = 12; + if (projectile_counter) { + collision_detection_index = 34; + do { + uint16 v0 = collision_detection_index; + if (*(uint16 *)((char *)enemy_projectile_id + collision_detection_index) + && (enemy_projectile_properties[collision_detection_index >> 1] & 0x8000u) != 0) { + uint16 v1 = 0; + do { + int v2 = v0 >> 1; + if (enemy_projectile_flags[v2] == 2) + break; + int v3 = v1 >> 1; + uint16 v4 = projectile_type[v3]; + if (v4) { + v5 = v4 & 0xF00; + if (v5 != 768 && v5 != 1280) { + if (sign16(v5 - 1792)) { + R18_ = projectile_x_pos[v3] & 0xFFE0; + if ((enemy_projectile_x_pos[v2] & 0xFFE0) == R18_) { + R18_ = projectile_y_pos[v3] & 0xFFE0; + if ((enemy_projectile_y_pos[v2] & 0xFFE0) == R18_) + HandleEprojCollWithProj(v0, v1); + } + } + } + } + v1 += 2; + } while ((int16)(v1 - 10) < 0); + } + --collision_detection_index; + --collision_detection_index; + } while ((collision_detection_index & 0x8000u) == 0); + } +} + +void HandleEprojCollWithProj(uint16 k, uint16 j) { // 0xA099F9 + int v2 = j >> 1; + if ((projectile_type[v2] & 8) == 0) + projectile_dir[v2] |= 0x10u; + if (enemy_projectile_flags[k >> 1] == 1) { + int v4 = k >> 1; + R18_ = projectile_x_pos[v4]; + R20_ = projectile_y_pos[v4]; + R22_ = 6; + R24_ = 0; + CreateSpriteAtPos(); + QueueSfx1_Max6(0x3Du); + } else { + int v3 = k >> 1; + enemy_projectile_G[v3] = projectile_type[v2]; + enemy_projectile_instr_list_ptr[v3] = get_EnemyProjectileDef(*(uint16 *)((char *)enemy_projectile_id + k))->shot_instruction_list; + enemy_projectile_instr_timers[v3] = 1; + enemy_projectile_pre_instr[v3] = FUNC16(EprojPreInstr_nullsub_83); + enemy_projectile_properties[v3] &= 0xFFFu; + } +} + +void CallHitboxTouch(uint32 ea) { + switch (ea) { + case fnEnemy_NormalTouchAI_A0: Enemy_NormalTouchAI_A0(); return; // 0xa08023 + case fnMaridiaLargeSnail_Func_12: MaridiaLargeSnail_Func_12(); return; // 0xa2d388 + case fnMaridiaLargeSnail_Touch: MaridiaLargeSnail_Touch(cur_enemy_index); return; // 0xa2d38c + case fnEnemy_NormalTouchAI_A4: Enemy_NormalTouchAI_A4(); return; // 0xa48023 + case fnCrocomire_Func_92: Crocomire_Func_92(); return; // 0xa4b93d + case fnnullsub_34: return; // 0xa4b950 + case fnnullsub_170_A5: return; // 0xa5804c + case fnDraygon_Touch: Draygon_Touch(); return; // 0xa595ea + case fnSporeSpawn_Touch: SporeSpawn_Touch(); return; // 0xa5edec + case fnsub_A6DF59: sub_A6DF59(); return; // 0xa6df59 + case fnCeresSteam_Touch: CeresSteam_Touch(); return; // 0xa6f03f + case fnnullsub_170_A7: return; // 0xa7804c + case fnKraid_Touch_ArmFoot: Kraid_Touch_ArmFoot(); return; // 0xa7948b + case fnKraidsArm_Touch: KraidsArm_Touch(); return; // 0xa79490 + case fnPhantoon_Touch: Phantoon_Touch(); return; // 0xa7dd95 + case fnnullsub_47: return; // 0xa9b5c5 + case fnMotherBrainsBrain_Touch: MotherBrainsBrain_Touch(); return; // 0xa9b5c6 + case fnGoldTorizo_Touch: GoldTorizo_Touch(); return; // 0xaac977 + case fnWalkingSpacePirates_Touch: WalkingSpacePirates_Touch(); return; // 0xb2876c + default: Unreachable(); + } +} +void CallHitboxShot(uint32 ea, uint16 j) { // 0xA09D17 + switch (ea) { + case fnEnemy_NormalShotAI_A0: Enemy_NormalShotAI_A0(); return; // 0xa0802d + case fnnullsub_170_A2: return; // 0xa2804c + case fnMaridiaLargeSnail_Shot: MaridiaLargeSnail_Shot(); return; // 0xa2d3b4 + case fnEnemy_NormalShotAI_A4: Enemy_NormalShotAI_A4(); return; // 0xa4802d + case fnCrocomire_Func_93: Crocomire_Func_93(); return; // 0xa4b951 + case fnCrocomire_Func_94: Crocomire_Func_94(); return; // 0xa4b968 + case fnCrocomire_Func_95: Crocomire_Func_95(); return; // 0xa4ba05 + case fnCrocomire_Func_1: Crocomire_Func_1(); return; // 0xa4bab4 + case fnEnemy_NormalShotAI_A5: Enemy_NormalShotAI_A5(); return; // 0xa5802d + case fnCreateADudShot_A5: CreateADudShot(); return; // 0xa58046 + case fnnullsub_170_A5: return; // 0xa5804c + case fnDraygon_Shot: Draygon_Shot(); return; // 0xa595f0 + case fnSporeSpawn_Shot: SporeSpawn_Shot(); return; // 0xa5ed5a + case fnnullsub_170_A6: return; // 0xa6804c + case fnRidley_Shot: Ridley_Shot(); return; // 0xa6df8a + case fnnullsub_170_A7: return; // 0xa7804c + case fnnullsub_43: return; // 0xa794b5 + case fnKraid_Arm_Shot: Kraid_Arm_Shot(j); return; // 0xa794b6 + case fnPhantoon_Shot: Phantoon_Shot(); return; // 0xa7dd9b + case fnMotherBrainsBody_Shot: MotherBrainsBody_Shot(); return; // 0xa9b503 + case fnMotherBrainsBrain_Shot: MotherBrainsBrain_Shot(); return; // 0xa9b507 + case fnTorizo_Shot: Torizo_Shot(); return; // 0xaac97c + case fnnullsub_271: return; // 0xaac9c1 + case fnTorizo_Func_8: Torizo_Func_8(); return; // 0xaac9c2 + case fnWalkingSpacePirates_Shot: WalkingSpacePirates_Shot(); return; // 0xb28779 + case fnWalkingSpacePirates_87C8: WalkingSpacePirates_87C8(); return; // 0xb287c8 + case fnWalkingSpacePirates_883E: WalkingSpacePirates_883E(); return; // 0xb2883e + default: Unreachable(); + } +} + +void EnemySamusCollHandler_Multibox(void) { // 0xA09A5A + VoidP touch_ai; + ExtendedSpriteMap *ExtendedSpriteMap; + VoidP hitbox_ptr_; + Hitbox *Hitbox; + + uint16 *v0 = (uint16 *)gEnemyData(cur_enemy_index); + *(uint16 *)&enemy_ai_pointer.bank = v0[23]; + enemy_processing_stage = 6; + if (v0[11]) { + touch_ai = get_EnemyDef_A2(*v0)->touch_ai; + if (touch_ai != (uint16)FUNC16(nullsub_170) && touch_ai != (uint16)FUNC16(nullsub_169)) { + if (samus_contact_damage_index) { + samus_invincibility_timer = 0; + } else if (samus_invincibility_timer) { + return; + } + EnemyData *v2 = gEnemyData(cur_enemy_index); + if (!sign16(v2->spritemap_pointer + 0x8000)) { + samus_right_border_coll = samus_x_radius + samus_x_pos; + samus_left_border_coll = samus_x_pos - samus_x_radius; + samus_bottom_border_coll = samus_y_radius + samus_y_pos; + samus_top_border_coll = samus_y_pos - samus_y_radius; + uint16 spritemap_pointer = v2->spritemap_pointer; + remaining_enemy_spritemap_entries = *RomPtrWithBank(enemy_ai_pointer.bank, spritemap_pointer); + enemy_spritemap_entry_pointer = spritemap_pointer + 2; + uint16 *v7; + while (1) { + EnemyData *v4; + v4 = gEnemyData(cur_enemy_index); + ExtendedSpriteMap = get_ExtendedSpriteMap(enemy_ai_pointer.bank, enemy_spritemap_entry_pointer); + enemy_spritemap_entry_coll_x_pos = ExtendedSpriteMap->xpos + v4->x_pos; + num_projs_to_check = ExtendedSpriteMap->ypos + v4->y_pos; + hitbox_ptr_ = ExtendedSpriteMap->hitbox_ptr_; + v7 = (uint16 *)RomPtrWithBank(enemy_ai_pointer.bank, hitbox_ptr_); + if (*v7) + break; +LABEL_18: + enemy_spritemap_entry_pointer += 8; + if ((int16)--remaining_enemy_spritemap_entries <= 0) + return; + } + remaining_enemy_hitbox_entries = *v7; + hitbox_ptr = hitbox_ptr_ + 2; + while (1) { + Hitbox = get_Hitbox(enemy_ai_pointer.bank, hitbox_ptr); + if ((int16)(Hitbox->left + enemy_spritemap_entry_coll_x_pos - samus_right_border_coll) < 0 + && (int16)(Hitbox->right + enemy_spritemap_entry_coll_x_pos - samus_left_border_coll) >= 0 + && (int16)(Hitbox->top + num_projs_to_check - samus_bottom_border_coll) < 0 + && (int16)(Hitbox->bottom + num_projs_to_check - samus_top_border_coll) >= 0) { + break; + } + hitbox_ptr += 12; + if ((int16)--remaining_enemy_hitbox_entries <= 0) + goto LABEL_18; + } + enemy_ai_pointer.addr = get_Hitbox(enemy_ai_pointer.bank, hitbox_ptr)->func_ptr; + CallHitboxTouch(Load24(&enemy_ai_pointer)); + } + } + } +} + +void EnemyProjectileCollHandler_Multibox(void) { // 0xA09B7F + VoidP shot_ai; + int16 v5; + Hitbox *v11; + Hitbox *v12; + Hitbox *Hitbox; + + *(uint16 *)&enemy_ai_pointer.bank = *(uint16 *)&gEnemyData(cur_enemy_index)->bank; + enemy_processing_stage = 3; + if (projectile_counter) { + num_projectiles_to_check_enemy_coll = projectile_counter; + EnemyData *v0 = gEnemyData(cur_enemy_index); + uint16 spritemap_pointer = v0->spritemap_pointer; + if (spritemap_pointer) { + if (spritemap_pointer != (uint16)addr_kExtendedSpritemap_Nothing_A0) { + shot_ai = get_EnemyDef_A2(v0->enemy_ptr)->shot_ai; + if (shot_ai != (uint16)FUNC16(nullsub_170) && shot_ai != (uint16)FUNC16(nullsub_169)) { + EnemyData *v3 = gEnemyData(cur_enemy_index); + if ((v3->properties & 0x400) == 0 + && !v3->invincibility_timer + && v3->enemy_ptr != (uint16)addr_kEnemyDef_DAFF) { + collision_detection_index = 0; + while (1) { + uint16 v4; + v4 = projectile_type[collision_detection_index]; + if (v4) { + v5 = v4 & 0xF00; + if (v5 != 768 && v5 != 1280 && sign16(v5 - 1792)) + break; + } +LABEL_37: + if (!sign16(++collision_detection_index - 5)) + return; + } + EnemyData *v6 = gEnemyData(cur_enemy_index); + while ((int16)(v6->spritemap_pointer + 0x8000) < 0) + ; + uint16 v7 = v6->spritemap_pointer; + uint16 bottom; + remaining_enemy_spritemap_entries = *RomPtrWithBank(enemy_ai_pointer.bank, v7); + enemy_spritemap_entry_pointer = v7 + 2; + while (1) { + EnemyData *v8; + v8 = gEnemyData(cur_enemy_index); + Hitbox = get_Hitbox(enemy_ai_pointer.bank, enemy_spritemap_entry_pointer); + enemy_spritemap_entry_coll_x_pos = Hitbox->left + v8->x_pos; + num_projs_to_check = Hitbox->top + v8->y_pos; + bottom = Hitbox->bottom; + v11 = get_Hitbox(enemy_ai_pointer.bank, bottom); + if (v11->left) + break; +LABEL_34: + enemy_spritemap_entry_pointer += 8; + bool v15 = (--remaining_enemy_spritemap_entries & 0x8000u) != 0; + if (!remaining_enemy_spritemap_entries || v15) + goto LABEL_37; + } + remaining_enemy_hitbox_entries = v11->left; + hitbox_ptr = bottom + 2; + int v13; + while (1) { + v12 = get_Hitbox(enemy_ai_pointer.bank, hitbox_ptr); + enemy_left_border_collision = enemy_spritemap_entry_coll_x_pos + v12->left; + v13 = collision_detection_index; + if ((int16)(projectile_x_radius[v13] + projectile_x_pos[v13] - enemy_left_border_collision) >= 0) { + enemy_right_border_collision = enemy_spritemap_entry_coll_x_pos + v12->right; + if ((int16)(projectile_x_pos[v13] - projectile_x_radius[v13] - enemy_right_border_collision) < 0) { + enemy_bottom_border_collision = num_projs_to_check + v12->top; + if ((int16)(projectile_y_radius[v13] + projectile_y_pos[v13] - enemy_bottom_border_collision) >= 0) { + enemy_top_border_collision = num_projs_to_check + v12->bottom; + if ((int16)(projectile_y_pos[v13] - projectile_y_radius[v13] - enemy_top_border_collision) < 0) + break; + } + } + } + hitbox_ptr += 12; + bool v14 = (--remaining_enemy_hitbox_entries & 0x8000u) != 0; + if (!remaining_enemy_hitbox_entries || v14) + goto LABEL_34; + } + if ((projectile_type[v13] & 0xF00) == 512) { + earthquake_timer = 30; + earthquake_type = 18; + } + if ((gEnemyData(cur_enemy_index)->properties & 0x1000) != 0 || (projectile_type[v13] & 8) == 0) + projectile_dir[v13] |= 0x10u; + enemy_ai_pointer.addr = get_Hitbox(enemy_ai_pointer.bank, hitbox_ptr)->func_ptrA; + CallHitboxShot(Load24(&enemy_ai_pointer), collision_detection_index * 2); + } + } + } + } + } +} + +void EnemyBombCollHandler_Multibox(void) { // 0xA09D23 + VoidP shot_ai; + Hitbox *v11; + ExtendedSpriteMap *ExtendedSpriteMap; + Hitbox *Hitbox; + + *(uint16 *)&enemy_ai_pointer.bank = *(uint16 *)&gEnemyData(cur_enemy_index)->bank; + enemy_processing_stage = 4; + if (gEnemyData(cur_enemy_index)->spritemap_pointer) { + EnemyData *v0 = gEnemyData(cur_enemy_index); + if ((v0->properties & 0x400) == 0 && !v0->invincibility_timer) { + uint16 enemy_ptr = gEnemyData(cur_enemy_index)->enemy_ptr; + shot_ai = get_EnemyDef_A2(enemy_ptr)->shot_ai; + if (shot_ai != (uint16)FUNC16(nullsub_170) + && shot_ai != (uint16)FUNC16(nullsub_169) + && bomb_counter) { + collision_detection_index = 5; + while (1) { + int v3; + v3 = collision_detection_index; + if (projectile_x_pos[v3]) { + uint16 v4 = projectile_type[v3]; + if (v4) { + if ((v4 & 0xF00) == 1280 && !projectile_variables[v3]) + break; + } + } +LABEL_26: + if (++collision_detection_index == 10) + return; + } + EnemyData *v5 = gEnemyData(cur_enemy_index); + while ((int16)(v5->spritemap_pointer + 0x8000) < 0) + ; + uint16 spritemap_pointer = v5->spritemap_pointer; + remaining_enemy_spritemap_entries = *RomPtrWithBank(enemy_ai_pointer.bank, spritemap_pointer); + enemy_spritemap_entry_pointer = spritemap_pointer + 2; + uint16 hitbox_ptr_; + while (1) { + EnemyData *v7; + v7 = gEnemyData(cur_enemy_index); + ExtendedSpriteMap = get_ExtendedSpriteMap(enemy_ai_pointer.bank, enemy_spritemap_entry_pointer); + enemy_spritemap_entry_coll_x_pos = ExtendedSpriteMap->xpos + v7->x_pos; + num_projs_to_check = ExtendedSpriteMap->ypos + v7->y_pos; + hitbox_ptr_ = ExtendedSpriteMap->hitbox_ptr_; + Hitbox = get_Hitbox(enemy_ai_pointer.bank, hitbox_ptr_); + if (Hitbox->left) + break; +LABEL_25: + enemy_spritemap_entry_pointer += 8; + if ((int16)--remaining_enemy_spritemap_entries <= 0) + goto LABEL_26; + } + remaining_enemy_hitbox_entries = Hitbox->left; + hitbox_ptr = hitbox_ptr_ + 2; + int v12; + while (1) { + v11 = get_Hitbox(enemy_ai_pointer.bank, hitbox_ptr); + enemy_left_border_collision = enemy_spritemap_entry_coll_x_pos + v11->left; + v12 = collision_detection_index; + if ((int16)(projectile_x_radius[v12] + projectile_x_pos[v12] - enemy_left_border_collision) >= 0) { + enemy_right_border_collision = enemy_spritemap_entry_coll_x_pos + v11->right; + if ((int16)(projectile_x_pos[v12] - projectile_x_radius[v12] - enemy_right_border_collision) < 0) { + enemy_bottom_border_collision = num_projs_to_check + v11->top; + if ((int16)(projectile_y_radius[v12] + projectile_y_pos[v12] - enemy_bottom_border_collision) >= 0) { + enemy_top_border_collision = num_projs_to_check + v11->bottom; + if ((int16)(projectile_y_pos[v12] - projectile_y_radius[v12] - enemy_top_border_collision) < 0) + break; + } + } + } + hitbox_ptr += 12; + if ((int16)--remaining_enemy_hitbox_entries <= 0) + goto LABEL_25; + } + projectile_dir[v12] |= 0x10u; + enemy_ai_pointer.addr = get_Hitbox(enemy_ai_pointer.bank, hitbox_ptr)->func_ptrA; + CallHitboxShot(Load24(&enemy_ai_pointer), collision_detection_index * 2); + } + } + } +} + +uint16 GrappleBeam_CollDetect_Enemy(void) { // 0xA09E9A + VoidP grapple_ai; + EnemyData *v4; + + CallSomeSamusCode(0xDu); + collision_detection_index = 0; + for (interactive_enemy_indexes_index = 0; ; ++interactive_enemy_indexes_index) { + uint16 v2 = interactive_enemy_indexes[interactive_enemy_indexes_index >> 1]; + cur_enemy_index = v2; + if (v2 == 0xFFFF) { + R18_ = 0; + return 0; + } + v4 = gEnemyData(v2); + if (!v4->invincibility_timer) { + uint16 v5 = abs16(v4->x_pos - grapple_beam_end_x_pos); + bool v6 = v5 < v4->x_width; + uint16 v7 = v5 - v4->x_width; + if (v6 || v7 < 8u) { + uint16 v8 = abs16(v4->y_pos - grapple_beam_end_y_pos); + v6 = v8 < v4->y_height; + uint16 v9 = v8 - v4->y_height; + if (v6 || v9 < 8u) + break; + } + } + ++interactive_enemy_indexes_index; + } + v4->ai_handler_bits = 1; + uint16 v0 = 0; + uint16 enemy_ptr = v4->enemy_ptr; + grapple_ai = get_EnemyDef_A2(v4->enemy_ptr)->grapple_ai; + if (grapple_ai + (uint16)FUNC16(Enemy_GrappleReact_NoInteract_A0)) { + v0 = 1; + if (grapple_ai != (uint16)FUNC16(Enemy_GrappleReact_SamusLatchesOn_A0)) { + v0 = 2; + if (grapple_ai != (uint16)FUNC16(Enemy_GrappleReact_KillEnemy_A0)) { + v0 = 3; + if (grapple_ai != (uint16)FUNC16(Enemy_GrappleReact_CancelBeam_A0)) { + v0 = 4; + if (grapple_ai != (uint16)FUNC16(Enemy_GrappleReact_SamusLatchesNoInvinc_A0)) { + v0 = 5; + if (grapple_ai != (uint16)FUNC16(Enemy_GrappleReact_SamusLatchesParalyze_A0)) { + v0 = 6; + if (grapple_ai != (uint16)FUNC16(Enemy_GrappleReact_HurtSamus_A0)) + v0 = 0; + } + } + } + } + } + } + R18_ = enemy_ptr; + uint16 result = v0; + if (v0 == 1 || v0 == 4 || v0 == 5) { + EnemyData *v11 = gEnemyData(cur_enemy_index); + grapple_beam_end_x_pos = v11->x_pos; + grapple_beam_end_y_pos = v11->y_pos; + return v0; + } + return result; +} + +void SwitchEnemyAiToMainAi(void) { // 0xA09F6D + EnemyData *v0 = gEnemyData(cur_enemy_index); + v0->ai_handler_bits = 0; + v0->invincibility_timer = 0; + v0->frozen_timer = 0; + v0->shake_timer = 0; +} + +void SamusLatchesOnWithGrapple(void) { // 0xA09F7D + EnemyDef_A2 *EnemyDef_A2; + + EnemyData *v0 = gEnemyData(cur_enemy_index); + grapple_beam_end_x_pos = v0->x_pos; + grapple_beam_end_y_pos = v0->y_pos; + if (v0->frozen_timer) { + gEnemyData(cur_enemy_index)->ai_handler_bits = 4; + } else { + EnemyData *v1 = gEnemyData(cur_enemy_index); + EnemyDef_A2 = get_EnemyDef_A2(v1->enemy_ptr); + uint16 hurt_ai_time = EnemyDef_A2->hurt_ai_time; + if (!EnemyDef_A2->hurt_ai_time) + hurt_ai_time = 4; + gEnemyData(cur_enemy_index)->flash_timer = hurt_ai_time; + gEnemyData(cur_enemy_index)->ai_handler_bits = 0; + } +} + +void EnemyGrappleDeath(void) { // 0xA09FC4 + gEnemySpawnData(cur_enemy_index)->cause_of_death = 4; + EnemyDeathAnimation(cur_enemy_index, 0); + gEnemyData(cur_enemy_index)->ai_handler_bits = 0; +} + +void Enemy_SwitchToFrozenAi(void) { // 0xA09FDF + gEnemyData(cur_enemy_index)->ai_handler_bits = 4; +} + +void SamusLatchesOnWithGrappleNoInvinc(void) { // 0xA09FE9 + EnemyData *v0; + + if (gEnemyData(cur_enemy_index)->frozen_timer) { + v0 = gEnemyData(cur_enemy_index); + grapple_beam_end_x_pos = v0->x_pos; + grapple_beam_end_y_pos = v0->y_pos; + v0->ai_handler_bits = 4; + } else { + v0 = gEnemyData(cur_enemy_index); + enemy_ai_pointer.addr = get_EnemyDef_A2(v0->enemy_ptr)->main_ai; + *(uint16 *)&enemy_ai_pointer.bank = *(uint16 *)&gEnemyData(cur_enemy_index)->bank; + CallEnemyAi(Load24(&enemy_ai_pointer)); + EnemyData *v1 = gEnemyData(cur_enemy_index); + grapple_beam_end_x_pos = v1->x_pos; + grapple_beam_end_y_pos = v1->y_pos; + v1->ai_handler_bits = 0; + } +} + +void SamusLatchesOnWithGrappleParalyze(void) { // 0xA0A03E + EnemyDef_A2 *EnemyDef_A2; + + EnemyData *v0 = gEnemyData(cur_enemy_index); + EnemyDef_A2 = get_EnemyDef_A2(v0->enemy_ptr); + uint16 hurt_ai_time = EnemyDef_A2->hurt_ai_time; + if (!EnemyDef_A2->hurt_ai_time) + hurt_ai_time = 4; + gEnemyData(cur_enemy_index)->flash_timer = hurt_ai_time; + gEnemyData(cur_enemy_index)->ai_handler_bits = 0; + EnemyData *v3 = gEnemyData(cur_enemy_index); + v3->extra_properties |= 1u; +} + +void SamusHurtFromGrapple(void) { // 0xA0A070 + gEnemyData(cur_enemy_index)->ai_handler_bits = 4; +} + +void EnemySamusCollHandler(void) { // 0xA0A07A + VoidP touch_ai; + + enemy_processing_stage = 9; + if (gEnemyData(cur_enemy_index)->spritemap_pointer) { + if (samus_contact_damage_index) { + samus_invincibility_timer = 0; + } else if (samus_invincibility_timer) { + if (gEnemyData(cur_enemy_index)->enemy_ptr != (uint16)addr_kEnemyDef_DAFF) + return; + uint16 some_flag = gEnemySpawnData(cur_enemy_index)->some_flag; + if (!some_flag || some_flag == 8) + return; + } + uint16 enemy_ptr = gEnemyData(cur_enemy_index)->enemy_ptr; + touch_ai = get_EnemyDef_A2(enemy_ptr)->touch_ai; + if (touch_ai != (uint16)FUNC16(nullsub_170) && touch_ai != (uint16)FUNC16(nullsub_169)) { + EnemyData *v3 = gEnemyData(cur_enemy_index); + uint16 v4 = abs16(samus_x_pos - v3->x_pos); + bool v5 = v4 < samus_x_radius; + uint16 v6 = v4 - samus_x_radius; + if (v5 || v6 < v3->x_width) { + uint16 v7 = abs16(samus_y_pos - v3->y_pos); + v5 = v7 < samus_y_radius; + uint16 v8 = v7 - samus_y_radius; + if (v5 || v8 < v3->y_height) { + R20_ = 2 * gEnemyData(cur_enemy_index)->spritemap_pointer; + if (gEnemyData(cur_enemy_index)->enemy_ptr == (uint16)addr_kEnemyDef_DAFF + || !gEnemyData(cur_enemy_index)->frozen_timer) { + enemy_ptr = gEnemyData(cur_enemy_index)->enemy_ptr; + enemy_ai_pointer.addr = get_EnemyDef_A2(enemy_ptr)->touch_ai; + enemy_ai_pointer.bank = gEnemyData(cur_enemy_index)->bank; + CallEnemyAi(Load24(&enemy_ai_pointer)); + } + } + } + } + } +} + +void EnemyProjectileCollHandler(void) { // 0xA0A143 + int16 v4; + + *(uint16 *)&enemy_ai_pointer.bank = *(uint16 *)&gEnemyData(cur_enemy_index)->bank; + enemy_processing_stage = 7; + if (projectile_counter) { + EnemyData *v0 = gEnemyData(cur_enemy_index); + uint16 spritemap_pointer = v0->spritemap_pointer; + if (spritemap_pointer) { + if (spritemap_pointer != (uint16)addr_kSpritemap_Nothing_A0 + && (v0->properties & 0x400) == 0 + && v0->enemy_ptr != (uint16)addr_kEnemyDef_DAFF + && !v0->invincibility_timer) { + collision_detection_index = 0; + int v2; + while (1) { + v2 = collision_detection_index; + uint16 v3 = projectile_type[v2]; + if (v3) { + v4 = v3 & 0xF00; + if (v4 != 768 && v4 != 1280) { + if (sign16(v4 - 1792)) { + EnemyData *v5 = gEnemyData(cur_enemy_index); + uint16 v6 = abs16(projectile_x_pos[v2] - v5->x_pos); + bool v7 = v6 < projectile_x_radius[v2]; + uint16 v8 = v6 - projectile_x_radius[v2]; + if (v7 || v8 < v5->x_width) { + uint16 v9 = abs16(projectile_y_pos[v2] - v5->y_pos); + v7 = v9 < projectile_y_radius[v2]; + uint16 v10 = v9 - projectile_y_radius[v2]; + if (v7 || v10 < v5->y_height) + break; + } + } + } + } + if (++collision_detection_index == 5) + return; + } + if ((projectile_type[v2] & 0xF00) == 512) { + earthquake_timer = 30; + earthquake_type = 18; + } + uint16 v11 = 2 * collision_detection_index; + if ((gEnemyData(cur_enemy_index)->properties & 0x1000) != 0 || (projectile_type[v11 >> 1] & 8) == 0) + projectile_dir[v11 >> 1] |= 0x10u; + uint16 enemy_ptr; + enemy_ptr = gEnemyData(cur_enemy_index)->enemy_ptr; + enemy_ai_pointer.addr = get_EnemyDef_A2(enemy_ptr)->shot_ai; + CallEnemyAi(Load24(&enemy_ai_pointer)); + } + } + } +} + +void EnemyBombCollHandler(void) { // 0xA0A236 + int v8; + *(uint16 *)&enemy_ai_pointer.bank = *(uint16 *)&gEnemyData(cur_enemy_index)->bank; + enemy_processing_stage = 8; + if (bomb_counter) { + if (gEnemyData(cur_enemy_index)->spritemap_pointer) { + EnemyData *v0 = gEnemyData(cur_enemy_index); + if (!v0->invincibility_timer && v0->enemy_ptr != (uint16)addr_kEnemyDef_DAFF) { + collision_detection_index = 5; + while (1) { + int v1 = collision_detection_index; + if (projectile_type[v1] + && !projectile_variables[v1] + && ((projectile_type[v1] & 0xF00) == 1280 || (projectile_type[v1] & 0x8000u) != 0)) { + EnemyData *v2 = gEnemyData(cur_enemy_index); + uint16 v3 = abs16(projectile_x_pos[v1] - v2->x_pos); + bool v4 = v3 < projectile_x_radius[v1]; + uint16 v5 = v3 - projectile_x_radius[v1]; + if (v4 || v5 < v2->x_width) { + uint16 v6 = abs16(projectile_y_pos[v1] - v2->y_pos); + v4 = v6 < projectile_y_radius[v1]; + uint16 v7 = v6 - projectile_y_radius[v1]; + if (v4 || v7 < v2->y_height) { + v8 = collision_detection_index; + if (!projectile_variables[v8]) + break; + } + } + } + if (++collision_detection_index == 10) + return; + } + projectile_dir[v8] |= 0x10u; + uint16 enemy_ptr = gEnemyData(cur_enemy_index)->enemy_ptr; + enemy_ai_pointer.addr = get_EnemyDef_A2(enemy_ptr)->shot_ai; + CallEnemyAi(Load24(&enemy_ai_pointer)); + } + } + } +} + +void ProcessEnemyPowerBombInteraction(void) { // 0xA0A306 + VoidP powerbomb_reaction; + + enemy_processing_stage = 5; + R18_ = HIBYTE(power_bomb_explosion_radius); + if (HIBYTE(power_bomb_explosion_radius)) { + R20_ = (uint16)(R18_ + (HIBYTE(power_bomb_explosion_radius) & 1) + (power_bomb_explosion_radius >> 9)) >> 1; + cur_enemy_index = 1984; + do { + EnemyData *v0 = gEnemyData(cur_enemy_index); + if (!v0->invincibility_timer) { + uint16 enemy_ptr = v0->enemy_ptr; + if (v0->enemy_ptr) { + if (enemy_ptr != (uint16)addr_kEnemyDef_DAFF) { + uint16 vulnerability_ptr = get_EnemyDef_A2(enemy_ptr)->vulnerability_ptr; + if (!vulnerability_ptr) + vulnerability_ptr = addr_stru_B4EC1C; + if ((get_Vulnerability(vulnerability_ptr)->power_bomb & 0x7F) != 0) { + EnemyData *v3 = gEnemyData(cur_enemy_index); + if (abs16(power_bomb_explosion_x_pos - v3->x_pos) < R18_ + && abs16(power_bomb_explosion_y_pos - v3->y_pos) < R20_) { + powerbomb_reaction = get_EnemyDef_A2(v3->enemy_ptr)->powerbomb_reaction; + if (!powerbomb_reaction) + powerbomb_reaction = FUNC16(Enemy_NormalPowerBombAI_A0); + enemy_ai_pointer.addr = powerbomb_reaction; + *(uint16 *)&enemy_ai_pointer.bank = *(uint16 *)&gEnemyData(cur_enemy_index)->bank; + CallEnemyAi(Load24(&enemy_ai_pointer)); + EnemyData *v5 = gEnemyData(cur_enemy_index); + v5->properties |= 0x800u; + } + } + } + } + } + cur_enemy_index -= 64; + } while ((cur_enemy_index & 0x8000u) == 0); + } +} + +void EnemyDeathAnimation(uint16 k, uint16 a) { // 0xA0A3AF + int16 v3; + + if (gEnemyData(k)->ai_handler_bits == 1) + grapple_beam_function = FUNC16(GrappleBeam_Func2); + if (!sign16(a - 5)) + a = 0; + enemy_population_ptr = a; + SpawnEnemyProjectileWithGfx(a, cur_enemy_index, addr_kEproj_EnemyDeathExplosion); + R18_ = gEnemyData(cur_enemy_index)->properties & 0x4000; + v3 = 62; + int v4 = cur_enemy_index; + do { + gEnemyData(v4)->enemy_ptr = 0; + v4 += 2; + v3 -= 2; + } while (v3 >= 0); + if (R18_) { + EnemyData *v5 = gEnemyData(cur_enemy_index); + v5->enemy_ptr = addr_kEnemyDef_DAFF; + *(uint16 *)&v5->bank = 0xa3; + } + ++num_enemies_killed_in_room; +} + +void RinkasDeathAnimation(uint16 a) { // 0xA0A410 + int16 v2; + + if (!sign16(a - 3)) + a = 0; + enemy_population_ptr = a; + SpawnEnemyProjectileWithGfx(a, cur_enemy_index, addr_kEproj_EnemyDeathExplosion); + R18_ = gEnemyData(cur_enemy_index)->properties & 0x4000; + v2 = 62; + int v4 = cur_enemy_index; + do { + gEnemyData(v4)->enemy_ptr = 0; + v4 += 2; + v2 -= 2; + } while (v2 >= 0); + if (R18_) { + EnemyData *v4 = gEnemyData(cur_enemy_index); + v4->enemy_ptr = addr_kEnemyDef_DAFF; + *(uint16 *)&v4->bank = 163; + } +} + +uint16 SuitDamageDivision(uint16 a) { // 0xA0A45E + R18_ = a; + if ((equipped_items & 0x20) != 0) { + R18_ >>= 1; + R18_ >>= 1; + return R18_; + } else { + if (equipped_items & 1) + R18_ >>= 1; + return R18_; + } +} + +void NormalEnemyTouchAi(void) { // 0xA0A477 + + NormalEnemyTouchAiSkipDeathAnim(); + if (!gEnemyData(cur_enemy_index)->health) { + gEnemySpawnData(cur_enemy_index)->cause_of_death = 6; + EnemyDeathAnimation(cur_enemy_index, 1u); + } +} + +void NormalEnemyTouchAiSkipDeathAnim_CurEnemy(void) { // 0xA0A497 + NormalEnemyTouchAiSkipDeathAnim(); +} + +void NormalEnemyTouchAiSkipDeathAnim(void) { // 0xA0A4A1 + VoidP vulnerability_ptr; + int16 hurt_ai_time; + int16 v7; + EnemyDef_A2 *v9; + EnemyDef_A2 *EnemyDef_A2; + + if (samus_contact_damage_index) { + R20_ = samus_contact_damage_index + 15; + uint16 v0 = 500; + if (samus_contact_damage_index != 1) { + v0 = 300; + if (samus_contact_damage_index != 2) { + v0 = 2000; + if (samus_contact_damage_index != 3) { + ++R20_; + v0 = 200; + if (samus_contact_damage_index == 4) + CallSomeSamusCode(4u); + else + v0 = 200; + } + } + } + R22_ = v0; + EnemyData *v1 = gEnemyData(cur_enemy_index); + vulnerability_ptr = get_EnemyDef_A2(v1->enemy_ptr)->vulnerability_ptr; + if (!vulnerability_ptr) + vulnerability_ptr = addr_stru_B4EC1C; + enemy_damage_multiplier = *(uint16 *)&get_Vulnerability(R20_ + vulnerability_ptr)->power; + draw_enemy_layer = enemy_damage_multiplier & 0x7F; + if ((enemy_damage_multiplier & 0x7F) != 0) { + R40 = draw_enemy_layer; + R38 = R22_ >> 1; + Mult32bit(); + if (R42) { + R18_ = R42; + EnemyData *v3 = gEnemyData(cur_enemy_index); + EnemyDef_A2 = get_EnemyDef_A2(v3->enemy_ptr); + hurt_ai_time = EnemyDef_A2->hurt_ai_time; + if (!EnemyDef_A2->hurt_ai_time) + hurt_ai_time = 4; + EnemyData *v6 = gEnemyData(cur_enemy_index); + v6->flash_timer = hurt_ai_time; + v6->ai_handler_bits |= 2u; + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + v7 = v6->health - R18_; + if (v7 < 0) + v7 = 0; + v6->health = v7; + QueueSfx2_Max1(0xBu); + } + } + } else { + EnemyData *v8 = gEnemyData(cur_enemy_index); + v9 = get_EnemyDef_A2(v8->enemy_ptr); + uint16 v10 = SuitDamageDivision(v9->damage); + Samus_DealDamage(v10); + samus_invincibility_timer = 96; + samus_knockback_timer = 5; + knockback_x_dir = (int16)(samus_x_pos - gEnemyData(cur_enemy_index)->x_pos) >= 0; + } +} +// 72078: conditional instruction was optimized away because ax.2<80u + +void NormalEnemyPowerBombAi(void) { // 0xA0A597 + NormalEnemyPowerBombAiSkipDeathAnim(); + if (!gEnemyData(cur_enemy_index)->health) { + gEnemySpawnData(cur_enemy_index)->cause_of_death = 3; + EnemyDeathAnimation(cur_enemy_index, 0); + } +} + +void NormalEnemyPowerBombAiSkipDeathAnim_CurEnemy(void) { // 0xA0A5B7 + NormalEnemyPowerBombAiSkipDeathAnim(); +} + +void NormalEnemyPowerBombAiSkipDeathAnim(void) { // 0xA0A5C1 + EnemyDef_A2 *EnemyDef_A2; + int16 hurt_ai_time; + + EnemyData *v0 = gEnemyData(cur_enemy_index); + uint16 vulnerability_ptr = get_EnemyDef_A2(v0->enemy_ptr)->vulnerability_ptr; + if (!vulnerability_ptr) + vulnerability_ptr = -5092; + uint8 power_bomb = get_Vulnerability(vulnerability_ptr)->power_bomb; + if (power_bomb != 255) { + draw_enemy_layer = power_bomb & 0x7F; + if ((power_bomb & 0x7F) != 0) { + R38 = 100; + R40 = draw_enemy_layer; + Mult32bit(); + enemy_spritemap_entry_coll_x_pos = R42; + if (R42) { + gEnemyData(cur_enemy_index)->invincibility_timer = 48; + EnemyData *v3 = gEnemyData(cur_enemy_index); + EnemyDef_A2 = get_EnemyDef_A2(v3->enemy_ptr); + hurt_ai_time = EnemyDef_A2->hurt_ai_time; + if (!EnemyDef_A2->hurt_ai_time) + hurt_ai_time = 4; + EnemyData *v6 = gEnemyData(cur_enemy_index); + v6->flash_timer = hurt_ai_time + 8; + v6->ai_handler_bits |= 2u; + uint16 health = v6->health; + bool v9 = health < enemy_spritemap_entry_coll_x_pos; + uint16 v8 = health - enemy_spritemap_entry_coll_x_pos; + v9 = !v9; + if (!v8 || !v9) + v8 = 0; + v6->health = v8; + } + } + } +} + +void NormalEnemyShotAi(void) { // 0xA0A63D + EnemyDef_A2 *EnemyDef_A2; + + varE2E = 0; + NormalEnemyShotAiSkipDeathAnim(); + if (varE2E) { + EnemyData *v1 = gEnemyData(cur_enemy_index); + R18_ = v1->x_pos; + R20_ = v1->y_pos; + R22_ = 55; + R24_ = 0; + CreateSpriteAtPos(); + } + EnemyData *v2 = gEnemyData(cur_enemy_index); + if (!v2->health) { + uint16 v3 = HIBYTE(projectile_type[collision_detection_index]) & 0xF; + gEnemySpawnData(cur_enemy_index)->cause_of_death = v3; + uint16 death_anim = 2; + uint16 enemy_ptr; + if (v3 == 2) { + enemy_ptr = gEnemyData(cur_enemy_index)->enemy_ptr; + EnemyDef_A2 = get_EnemyDef_A2(enemy_ptr); + if (!sign16(EnemyDef_A2->death_anim - 3)) + death_anim = EnemyDef_A2->death_anim; + } else { + enemy_ptr = v2->enemy_ptr; + death_anim = get_EnemyDef_A2(v2->enemy_ptr)->death_anim; + } + EnemyDeathAnimation(enemy_ptr, death_anim); + } +} + +void NormalEnemyShotAiSkipDeathAnim_CurEnemy(void) { // 0xA0A6A7 + varE2E = 0; + NormalEnemyShotAiSkipDeathAnim(); +} + +void EnemyFunc_A6B4_UsedBySporeSpawn(void) { // 0xA0A6B4 + varE2E = 0; + NormalEnemyShotAiSkipDeathAnim(); + if (varE2E) { + EnemyData *v0 = gEnemyData(cur_enemy_index); + R18_ = v0->x_pos; + R20_ = v0->y_pos; + R22_ = 55; + R24_ = 0; + CreateSpriteAtPos(); + } +} + +void NormalEnemyShotAiSkipDeathAnim(void) { // 0xA0A6DE + int16 v5; + int16 v6; + int16 v9; + EnemyDef_A2 *EnemyDef_A2; + int16 hurt_ai_time; + int16 v20; + + int v0 = collision_detection_index; + enemy_spritemap_entry_coll_x_pos = projectile_damage[v0]; + R18_ = projectile_type[v0]; + EnemyData *v1 = gEnemyData(cur_enemy_index); + uint16 vulnerability_ptr = get_EnemyDef_A2(v1->enemy_ptr)->vulnerability_ptr; + if (!vulnerability_ptr) + vulnerability_ptr = addr_stru_B4EC1C; + R20_ = vulnerability_ptr; + if ((R18_ & 0xF00) != 0) { + v5 = R18_ & 0xF00; + if ((R18_ & 0xF00) == 256 || v5 == 512) { + LOBYTE(v6) = (uint16)(R18_ & 0xF00) >> 8; + HIBYTE(v6) = 0; + draw_enemy_layer = get_Vulnerability(R20_ + v6)->plasma_ice_wave & 0x7F; + } else if (v5 == 1280) { + draw_enemy_layer = get_Vulnerability(R20_)->bomb & 0x7F; + } else { + if (v5 != 768) + goto LABEL_18; + draw_enemy_layer = get_Vulnerability(R20_)->power_bomb & 0x7F; + } +LABEL_9: + R38 = enemy_spritemap_entry_coll_x_pos >> 1; + R40 = draw_enemy_layer; + Mult32bit(); + if (R42) { + enemy_spritemap_entry_coll_x_pos = R42; + EnemyData *v10 = gEnemyData(cur_enemy_index); + EnemyDef_A2 = get_EnemyDef_A2(v10->enemy_ptr); + hurt_ai_time = EnemyDef_A2->hurt_ai_time; + if (!EnemyDef_A2->hurt_ai_time) + hurt_ai_time = 4; + EnemyData *v13 = gEnemyData(cur_enemy_index); + v13->flash_timer = hurt_ai_time + 8; + v13->ai_handler_bits |= 2u; + if (!v13->frozen_timer) { + uint16 hurt_sfx = get_EnemyDef_A2(v13->enemy_ptr)->hurt_sfx; + if (hurt_sfx) + QueueSfx2_Max3(hurt_sfx); + ++varE2E; + } + uint16 v15 = cur_enemy_index; + if ((projectile_type[collision_detection_index] & 8) != 0) + gEnemyData(cur_enemy_index)->invincibility_timer = 16; + EnemyData *v16 = gEnemyData(v15); + uint16 health = v16->health; + bool v19 = health < enemy_spritemap_entry_coll_x_pos; + uint16 v18 = health - enemy_spritemap_entry_coll_x_pos; + v19 = !v19; + if (!v18 || !v19) { + if ((projectile_type[collision_detection_index] & 2) != 0 + && (enemy_damage_multiplier & 0xF0) != 128 + && !v16->frozen_timer) { + v20 = 400; + if (area_index == 2) + v20 = 300; + v16->frozen_timer = v20; + v16->ai_handler_bits |= 4u; + v16->invincibility_timer = 10; + QueueSfx3_Max3(0xAu); + return; + } + v18 = 0; + } + v16->health = v18; + return; + } +LABEL_18:; + int v7 = collision_detection_index; + projectile_dir[v7] |= 0x10u; + R18_ = projectile_x_pos[v7]; + R20_ = projectile_y_pos[v7]; + R22_ = 6; + R24_ = 0; + CreateSpriteAtPos(); + QueueSfx1_Max3(0x3Du); + return; + } + enemy_damage_multiplier = get_Vulnerability(R20_ + ((uint8)R18_ & 0xFu))->power; + draw_enemy_layer = enemy_damage_multiplier & 0x7F; + if (enemy_damage_multiplier != 255) { + if ((R18_ & 0x10) != 0) { + uint8 charged_beam = get_Vulnerability(R20_)->charged_beam; + if (charged_beam == 255) + goto LABEL_18; + uint16 v4 = charged_beam & 0xF; + if (!v4) + goto LABEL_18; + draw_enemy_layer = v4; + } + goto LABEL_9; + } + EnemyData *v8 = gEnemyData(cur_enemy_index); + if (!v8->frozen_timer) + QueueSfx3_Max3(0xAu); + v9 = 400; + if (area_index == 2) + v9 = 300; + v8->frozen_timer = v9; + v8->ai_handler_bits |= 4u; + v8->invincibility_timer = 10; +} + +void CreateDudShot(void) { // 0xA0A8BC + int v0 = collision_detection_index; + R18_ = projectile_x_pos[v0]; + R20_ = projectile_y_pos[v0]; + R22_ = 6; + R24_ = 0; + CreateSpriteAtPos(); + QueueSfx1_Max3(0x3Du); + projectile_dir[collision_detection_index] |= 0x10u; +} + +uint16 Samus_CheckSolidEnemyColl(void) { // 0xA0A8F0 + int16 v1; + int16 v16; + int16 v18; + + if (!interactive_enemy_indexes_write_ptr) + return 0; + v1 = 2 * (samus_collision_direction & 3); + if (v1) { + switch (v1) { + case 2: { + samus_target_x_pos = samus_x_pos + R18_; + bool v3 = samus_x_subpos + R20_ == 0; + if (__CFADD__uint16(samus_x_subpos, R20_)) + v3 = samus_target_x_pos++ == 0xFFFF; + if (!v3) + ++samus_target_x_pos; + samus_target_y_pos = samus_y_pos; + samus_target_y_subpos = samus_y_subpos; + break; + } + case 4: { + samus_target_y_pos = samus_y_pos - R18_; + bool v4 = samus_y_subpos == R20_; + if (samus_y_subpos < R20_) + v4 = samus_target_y_pos-- == 1; + if (!v4) + --samus_target_y_pos; + samus_target_x_pos = samus_x_pos; + samus_target_x_subpos = samus_x_subpos; + break; + } + case 6: { + samus_target_y_pos = samus_y_pos + R18_; + bool v5 = samus_y_subpos + R20_ == 0; + if (__CFADD__uint16(samus_y_subpos, R20_)) + v5 = samus_target_y_pos++ == 0xFFFF; + if (!v5) + ++samus_target_y_pos; + samus_target_x_pos = samus_x_pos; + samus_target_x_subpos = samus_x_subpos; + break; + } + default: + Unreachable(); + while (1) + ; + } + } else { + samus_target_x_pos = samus_x_pos - R18_; + bool v2 = samus_x_subpos == R20_; + if (samus_x_subpos < R20_) + v2 = samus_target_x_pos-- == 1; + if (!v2) + --samus_target_x_pos; + samus_target_y_pos = samus_y_pos; + samus_target_y_subpos = samus_y_subpos; + } + samus_x_radius_mirror = samus_x_radius; + samus_y_radius_mirror = samus_y_radius; + collision_detection_index = 0; + for (interactive_enemy_indexes_index = 0; ; ++interactive_enemy_indexes_index) { + int v6 = interactive_enemy_indexes_index >> 1; + uint16 v7 = interactive_enemy_indexes[v6]; + if (v7 == 0xFFFF) + break; + collision_detection_index = interactive_enemy_indexes[v6]; + EnemyData *v8 = gEnemyData(v7); + if (v8->frozen_timer || (v8->properties & 0x8000u) != 0) { + uint8 *v9 = RomPtr_7E(v7 + 3962); + uint8 *v10 = (uint8*)&samus_target_x_pos; + uint16 v11 = abs16(*(uint16 *)v9 - *(uint16 *)v10); + bool v12 = v11 < *((uint16 *)v9 + 4); + uint16 v13 = v11 - *((uint16 *)v9 + 4); + if (v12 || v13 < *((uint16 *)v10 + 4)) { + uint16 v14 = abs16(*((uint16 *)v9 + 2) - *((uint16 *)v10 + 2)); + v12 = v14 < *((uint16 *)v9 + 5); + uint16 v15 = v14 - *((uint16 *)v9 + 5); + if (v12 || v15 < *((uint16 *)v10 + 5)) { + v16 = 2 * (samus_collision_direction & 3); + if (v16) { + switch (v16) { + case 2: { + draw_enemy_layer = samus_x_radius + samus_x_pos; + EnemyData *v19 = gEnemyData(collision_detection_index); + v18 = v19->x_pos - v19->x_width - (samus_x_radius + samus_x_pos); + if (!v18) + goto LABEL_57; + if (v18 >= 0) + goto LABEL_58; + break; + } + case 4: { + EnemyData *v20 = gEnemyData(collision_detection_index); + draw_enemy_layer = v20->y_height + v20->y_pos; + v18 = samus_y_pos - samus_y_radius - draw_enemy_layer; + if (samus_y_pos - samus_y_radius == draw_enemy_layer) + goto LABEL_57; + if ((int16)(samus_y_pos - samus_y_radius - draw_enemy_layer) >= 0) + goto LABEL_58; + break; + } + case 6: { + draw_enemy_layer = samus_y_radius + samus_y_pos; + EnemyData *v21; + v21 = gEnemyData(collision_detection_index); + v18 = v21->y_pos - v21->y_height - (samus_y_radius + samus_y_pos); + if (!v18) { +LABEL_57: + samus_y_subpos = 0; + samus_x_pos_colliding_solid = samus_x_pos; + samus_x_subpos_colliding_solid = samus_x_subpos; + EnemyData *v22 = gEnemyData(collision_detection_index); + enemy_x_pos_colliding_solid = v22->x_pos; + enemy_x_subpos_colliding_solid = v22->x_subpos; + samus_pos_delta_colliding_solid = R18_; + samus_subpos_delta_colliding_solid = R20_; + samus_y_pos_colliding_solid = samus_y_pos; + samus_y_subpos_colliding_solid = 0; + solid_enemy_collision_type = 1; + R18_ = 0; + R20_ = 0; + R22_ = collision_detection_index; + int v23 = samus_collision_direction & 3; + enemy_index_colliding_dirs[v23] = collision_detection_index; + distance_to_enemy_colliding_dirs[v23] = 0; + return -1; + } + if (v18 >= 0) { +LABEL_58: + samus_x_pos_colliding_solid = samus_x_pos; + samus_x_subpos_colliding_solid = samus_x_subpos; + EnemyData *v24 = gEnemyData(collision_detection_index); + enemy_x_pos_colliding_solid = v24->x_pos; + enemy_x_subpos_colliding_solid = v24->x_subpos; + samus_pos_delta_colliding_solid = R18_; + samus_subpos_delta_colliding_solid = R20_; + samus_y_pos_colliding_solid = samus_y_pos; + samus_y_subpos_colliding_solid = samus_y_subpos; + solid_enemy_collision_type = 2; + R18_ = v18; + int v25 = samus_collision_direction & 3; + distance_to_enemy_colliding_dirs[v25] = v18; + R20_ = 0; + R22_ = collision_detection_index; + enemy_index_colliding_dirs[v25] = collision_detection_index; + return -1; + } + break; + } + default: + Unreachable(); + while (1) + ; + } + } else { + EnemyData *v17 = gEnemyData(collision_detection_index); + draw_enemy_layer = v17->x_width + v17->x_pos; + v18 = samus_x_pos - samus_x_radius - draw_enemy_layer; + if (samus_x_pos - samus_x_radius == draw_enemy_layer) + goto LABEL_57; + if ((int16)(samus_x_pos - samus_x_radius - draw_enemy_layer) >= 0) + goto LABEL_58; + } + } + } + } + ++interactive_enemy_indexes_index; + } + return 0; +} + +uint16 CheckIfEnemyTouchesSamus(uint16 k) { // 0xA0ABE7 + EnemyData *v1 = gEnemyData(k); + uint16 v2 = abs16(samus_x_pos - v1->x_pos); + bool v3 = v2 < samus_x_radius; + uint16 v4 = v2 - samus_x_radius; + if (!v3 && v4 >= v1->x_width) + return 0; + if ((int16)(samus_y_pos + 3 - v1->y_pos) < 0) { + uint16 v6 = v1->y_pos - (samus_y_pos + 3); + v3 = v6 < samus_y_radius; + uint16 v7 = v6 - samus_y_radius; + if (v3 || v7 == v1->y_height || v7 < v1->y_height) + return -1; + } + return 0; +} + +uint16 EnemyFunc_AC67(uint16 k) { // 0xA0AC67 + EnemyData *v1 = gEnemyData(k); + uint16 v2 = abs16(samus_x_pos - v1->x_pos); + bool v3 = v2 < samus_x_radius; + uint16 v4 = v2 - samus_x_radius; + if (!v3 && v4 >= v1->x_width && v4 >= 8u) + return 0; + uint16 v6 = abs16(samus_y_pos - v1->y_pos); + v3 = v6 < samus_y_radius; + uint16 v7 = v6 - samus_y_radius; + if (v3 || v7 < v1->y_height) + return -1; + else + return 0; +} + +uint16 EnemyFunc_ACA8(void) { // 0xA0ACA8 + int16 v1; + int16 v2; + + g_word_7E0E3C = loop_index_end - draw_enemy_layer; + uint16 result = abs16(loop_index_end - draw_enemy_layer); + if (sign16(result - 255)) { + R18_ = result; + enemy_population_ptr = result; + g_word_7E0E3E = loop_index - enemy_drawing_queue_index; + result = abs16(loop_index - enemy_drawing_queue_index); + if (sign16(result - 255)) { + R20_ = result; + draw_oam_x_offset = result; + varE24 = CalculateAngleFromXY(); + draw_enemy_layer = enemy_population_ptr; + v1 = SineMult8bitNegative(varE24); + if (v1 < 0) + v1 = -v1; + varE26 = v1; + draw_enemy_layer = draw_oam_x_offset; + v2 = CosineMult8bit(varE24); + if (v2 < 0) + v2 = -v2; + uint16 v3 = varE26 + v2; + R18_ = g_word_7E0E3C; + R20_ = g_word_7E0E3E; + enemy_drawing_queue_base = CalculateAngleFromXY(); + return v3; + } + } + return result; +} + +uint16 CheckIfEnemyIsOnScreen(void) { // 0xA0AD70 + EnemyData *v0 = gEnemyData(cur_enemy_index); + return (int16)(v0->x_pos - layer1_x_pos) < 0 + || (int16)(layer1_x_pos + 256 - v0->x_pos) < 0 + || (int16)(v0->y_pos - layer1_y_pos) < 0 + || (int16)(layer1_y_pos + 256 - v0->y_pos) < 0; +} + +uint16 EnemyFunc_ADA3(uint16 a) { // 0xA0ADA3 + R18_ = a; + EnemyData *v1 = gEnemyData(cur_enemy_index); + return (int16)(a + v1->x_pos - layer1_x_pos) < 0 + || (int16)(R18_ + layer1_x_pos + 256 - v1->x_pos) < 0 + || (int16)(R18_ + v1->y_pos - layer1_y_pos) < 0 + || (int16)(R18_ + layer1_y_pos + 256 - v1->y_pos) < 0; +} + +uint16 EnemyWithNormalSpritesIsOffScreen(void) { // 0xA0ADE7 + EnemyData *v0 = gEnemyData(cur_enemy_index); + return (int16)(v0->x_width + v0->x_pos - layer1_x_pos) < 0 + || (int16)(v0->x_width + layer1_x_pos + 256 - v0->x_pos) < 0 + || (int16)(v0->y_pos + 8 - layer1_y_pos) < 0 + || (int16)(layer1_y_pos + 248 - v0->y_pos) < 0; +} + +uint16 DetermineDirectionOfSamusFromEnemy(void) { // 0xA0AE29 + if (IsSamusWithinEnemy_Y(cur_enemy_index, 0x20u)) { + uint16 v1 = 2; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) != 0) + return 7; + return v1; + } else if (IsSamusWithinEnemy_X(cur_enemy_index, 0x20u)) { + uint16 v3 = 4; + if ((GetSamusEnemyDelta_Y(cur_enemy_index) & 0x8000u) != 0) + return 0; + return v3; + } else if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) != 0) { + uint16 v5 = 6; + if ((GetSamusEnemyDelta_Y(cur_enemy_index) & 0x8000u) != 0) + return 8; + return v5; + } else { + uint16 v4 = 3; + if ((GetSamusEnemyDelta_Y(cur_enemy_index) & 0x8000u) != 0) + return 1; + return v4; + } +} + + +uint16 GetSamusEnemyDelta_Y(uint16 k) { // 0xA0AEDD + return samus_y_pos - gEnemyData(k)->y_pos; +} + +uint16 GetSamusEnemyDelta_X(uint16 k) { // 0xA0AEE5 + return samus_x_pos - gEnemyData(k)->x_pos; +} + +uint16 IsSamusWithinEnemy_Y(uint16 k, uint16 a) { // 0xA0AEED + enemy_population_ptr = a; + EnemyData *v2 = gEnemyData(k); + return (int16)(SubtractThenAbs16(v2->y_pos, samus_y_pos) - a) < 0; +} + +uint16 IsSamusWithinEnemy_X(uint16 k, uint16 a) { // 0xA0AF0B + enemy_population_ptr = a; + EnemyData *v2 = gEnemyData(k); + return (int16)(SubtractThenAbs16(v2->x_pos, samus_x_pos) - a) < 0; +} + +void Enemy_SubPos_X(uint16 k) { // 0xA0AF5A + EnemyData *v1 = gEnemyData(k); + uint16 x_subpos = v1->x_subpos; + bool v3 = x_subpos < R18_; + v1->x_subpos = x_subpos - R18_; + v1->x_pos -= v3 + R20_; +} + +void Enemy_AddPos_X(uint16 k) { // 0xA0AF6C + EnemyData *v1 = gEnemyData(k); + uint16 x_subpos = v1->x_subpos; + bool v3 = __CFADD__uint16(R18_, x_subpos); + v1->x_subpos = R18_ + x_subpos; + v1->x_pos += R20_ + v3; +} + +void Enemy_SubPos_Y(uint16 k) { // 0xA0AF7E + EnemyData *v1 = gEnemyData(k); + uint16 y_subpos = v1->y_subpos; + bool v3 = y_subpos < R18_; + v1->y_subpos = y_subpos - R18_; + v1->y_pos -= v3 + R20_; +} + +void Enemy_AddPos_Y(uint16 k) { // 0xA0AF90 + EnemyData *v1 = gEnemyData(k); + uint16 y_subpos = v1->y_subpos; + bool v3 = __CFADD__uint16(R18_, y_subpos); + v1->y_subpos = R18_ + y_subpos; + v1->y_pos += R20_ + v3; +} + +uint16 SignExtend8(uint16 a) { // 0xA0AFEA + draw_enemy_layer = a; + if ((a & 0x80) != 0) + return (uint8)draw_enemy_layer | 0xFF00; + else + return draw_enemy_layer; +} + +uint16 Mult32(uint16 a) { // 0xA0B002 + return 32 * a; +} + +uint16 Abs16(uint16 a) { // 0xA0B067 + draw_enemy_layer = a; + if ((a & 0x8000) != 0) + draw_enemy_layer = -draw_enemy_layer; + return draw_enemy_layer; +} + +uint16 SubtractThenAbs16(uint16 k, uint16 j) { // 0xA0B07D + draw_enemy_layer = k; + enemy_drawing_queue_index = j - k; + if ((int16)(j - k) < 0) + enemy_drawing_queue_index = -enemy_drawing_queue_index; + return enemy_drawing_queue_index; +} + +uint16 CosineMult8bit(uint16 a) { // 0xA0B0B2 + enemy_drawing_queue_index = (uint8)(a + 64); + return SineMult8bit(); +} + +uint16 SineMult8bitNegative(uint16 a) { // 0xA0B0C6 + enemy_drawing_queue_index = (uint8)(a + 0x80); + return SineMult8bit(); +} + +#define kSine8bit ((uint8*)RomPtr(0xa0b143)) +#define kEquationForQuarterCircle ((uint16*)RomPtr(0xa0b7ee)) + +uint16 SineMult8bit(void) { // 0xA0B0DA + int16 v1; + + uint16 RegWord = Mult8x8(kSine8bit[enemy_drawing_queue_index & 0x7F], draw_enemy_layer); + LOBYTE(v1) = HIBYTE(RegWord); + HIBYTE(v1) = RegWord; + loop_index_end = HIBYTE(RegWord); + loop_index = v1 & 0xFF00; + if ((enemy_drawing_queue_index & 0x80) != 0) { + loop_index_end = -loop_index_end; + loop_index = -loop_index; + } + return loop_index_end; +} + +void ConvertAngleToXy(void) { // 0xA0B643 + R38 = kEquationForQuarterCircle[((uint8)R18_ + 0x80) & 0x7F]; + R40 = R20_; + Mult32bit(); + R26_ = R44; + R28_ = R42; + R38 = kEquationForQuarterCircle[((uint8)R18_ + 64) & 0x7F]; + R40 = R20_; + Mult32bit(); + R22_ = R44; + R24_ = R42; +} + +void EnemyFunc_B691(void) { // 0xA0B691 + EnemyData *v1 = gEnemyData(cur_enemy_index); + uint16 x_subpos = v1->x_subpos; + if (((enemy_population_ptr + 64) & 0x80) != 0) { + bool v3 = x_subpos < varE26; + v1->x_subpos = x_subpos - varE26; + v1->x_pos -= v3 + varE24; + } else { + bool v3 = __CFADD__uint16(varE26, x_subpos); + v1->x_subpos = varE26 + x_subpos; + v1->x_pos += varE24 + v3; + } + EnemyData *v4 = gEnemyData(cur_enemy_index); + uint16 y_subpos = v4->y_subpos; + if (((enemy_population_ptr + 128) & 0x80) != 0) { + bool v3 = y_subpos < varE2A; + v4->y_subpos = y_subpos - varE2A; + v4->y_pos -= v3 + varE28; + } else { + bool v3 = __CFADD__uint16(varE2A, y_subpos); + v4->y_subpos = varE2A + y_subpos; + v4->y_pos += varE28 + v3; + } +} + +void Mult32bit(void) { // 0xA0B6FF + uint32 t = (uint32)R38 * (uint32)R40; + R42 = t; + R44 = t >> 16; +} + +void EnemyFunc_B761(void) { // 0xA0B761 + int16 v0; + unsigned int v1; // kr00_4 + + R40 = 0; + R38 = 0; + if (__PAIR32__(R48, R46)) { + v0 = 33; + uint8 carry = 0, carry2; + + while (1) { + carry2 = R44 >> 15; + R44 = (R44 << 1) | (R42 >> 15); + R42 = (R42 << 1) | carry; + if (!--v0) + break; + carry = R38 >> 15; + R40 = (R40 << 1) | (R38 >> 15); + R38 = (R38 << 1) | carry2; + + if (__PAIR32__(R40, R38)) { + carry = 0; + v1 = __PAIR32__(R40, R38) - __PAIR32__(R48, R46); + if (__PAIR32__(R40, R38) >= __PAIR32__(R48, R46)) { + R40 = v1 >> 16; + R38 = v1; + carry = 1; + } + } + } + } else { + R44 = 0; + R42 = 0; + } +} + +void EnemyFunc_B7A1(void) { // 0xA0B7A1 + int16 v1; + int16 v3; + + R18_ = samus_y_pos - samus_prev_y_pos; + uint16 v0 = Abs16(samus_y_pos - samus_prev_y_pos); + if (!sign16(v0 - 12)) { + v1 = -12; + if ((R18_ & 0x8000u) == 0) + v1 = 12; + samus_prev_y_pos = samus_y_pos + v1; + } + R18_ = samus_x_pos - samus_prev_x_pos; + uint16 v2 = Abs16(samus_x_pos - samus_prev_x_pos); + if (!sign16(v2 - 12)) { + v3 = -12; + if ((R18_ & 0x8000u) == 0) + v3 = 12; + samus_prev_x_pos = samus_x_pos + v3; + } +} + +void Enemy_ItemDrop_MiniKraid(uint16 k) { // 0xA0B8EE + remaining_enemy_spritemap_entries = 4; + do { + R18_ = special_death_item_drop_x_origin_pos + (NextRandom() & 0x1F) - 16; + R20_ = special_death_item_drop_y_origin_pos + ((uint16)(random_number & 0x1F00) >> 8) - 16; + SpawnEnemyDrops(addr_kEnemyDef_E0FF, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_LowerNorfairSpacePirate(uint16 k) { // 0xA0B92B + remaining_enemy_spritemap_entries = 5; + do { + R18_ = special_death_item_drop_x_origin_pos + (NextRandom() & 0x1F) - 16; + R20_ = special_death_item_drop_y_origin_pos + ((uint16)(random_number & 0x1F00) >> 8) - 16; + SpawnEnemyDrops(addr_kEnemyDef_F593, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_Metroid(uint16 k) { // 0xA0B968 + remaining_enemy_spritemap_entries = 5; + do { + R18_ = special_death_item_drop_x_origin_pos + (NextRandom() & 0x1F) - 16; + R20_ = special_death_item_drop_y_origin_pos + ((uint16)(random_number & 0x1F00) >> 8) - 16; + SpawnEnemyDrops(addr_kEnemyDef_DD7F, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_Ridley(uint16 k) { // 0xA0B9A5 + remaining_enemy_spritemap_entries = 16; + do { + R18_ = (NextRandom() & 0x7F) + 64; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) + 320; + SpawnEnemyDrops(addr_kEnemyDef_E17F, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_Crocomire(uint16 k) { // 0xA0B9D8 + remaining_enemy_spritemap_entries = 16; + do { + R18_ = (NextRandom() & 0x7F) + 576; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) + 96; + SpawnEnemyDrops(addr_kEnemyDef_DDBF, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_Phantoon(uint16 k) { // 0xA0BA0B + remaining_enemy_spritemap_entries = 16; + do { + R18_ = (NextRandom() & 0x7F) + 64; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) + 96; + SpawnEnemyDrops(addr_kEnemyDef_E4BF, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_Botwoon(uint16 k) { // 0xA0BA3E + remaining_enemy_spritemap_entries = 16; + do { + R18_ = (NextRandom() & 0x7F) + 64; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) + 128; + SpawnEnemyDrops(addr_kEnemyDef_F293, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_Kraid(uint16 k) { // 0xA0BA71 + remaining_enemy_spritemap_entries = 16; + do { + R18_ = (uint8)NextRandom() + 128; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) + 352; + SpawnEnemyDrops(addr_kEnemyDef_E2BF, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_BombTorizo(uint16 k) { // 0xA0BAA4 + remaining_enemy_spritemap_entries = 16; + do { + R18_ = (NextRandom() & 0x7F) + 64; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) + 96; + SpawnEnemyDrops(addr_kEnemyDef_EEFF, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_GoldenTorizo(uint16 k) { // 0xA0BAD7 + remaining_enemy_spritemap_entries = 16; + do { + R18_ = (uint8)NextRandom() + 128; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) + 288; + SpawnEnemyDrops(addr_kEnemyDef_EEFF, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_SporeSpawn(uint16 k) { // 0xA0BB0A + remaining_enemy_spritemap_entries = 16; + do { + R18_ = (NextRandom() & 0x7F) + 64; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) + 528; + SpawnEnemyDrops(addr_kEnemyDef_DF3F, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +void Enemy_ItemDrop_Draygon(uint16 k) { // 0xA0BB3D + remaining_enemy_spritemap_entries = 16; + do { + R18_ = (uint8)NextRandom() + 128; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) + 352; + SpawnEnemyDrops(addr_kEnemyDef_DE3F, k); + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); +} + +uint8 CompareDistToSamus_X(uint16 k, uint16 a) { // 0xA0BB9B + EnemyData *v2 = gEnemyData(k); + return abs16(samus_x_pos - v2->x_pos) >= a; +} + +uint8 CompareDistToSamus_Y(uint16 k, uint16 a) { // 0xA0BBAD + EnemyData *v2 = gEnemyData(k); + return abs16(samus_y_pos - v2->y_pos) >= a; +} + +uint8 EnemyFunc_BBBF(uint16 k) { // 0xA0BBBF + int16 v7; + int16 v8; + int16 v11; + + EnemyData *v1 = gEnemyData(k); + R26_ = (v1->y_pos - v1->y_height) & 0xFFF0; + R26_ = (uint16)(v1->y_height + v1->y_pos - 1 - R26_) >> 4; + uint16 prod = Mult8x8((uint16)(v1->y_pos - v1->y_height) >> 4, room_width_in_blocks); + uint16 v2 = (__PAIR32__(R20_, R18_) + __PAIR32__(v1->x_pos, v1->x_subpos)) >> 16; + uint16 v3; + R22_ = R18_ + v1->x_subpos; + R24_ = v2; + if ((R20_ & 0x8000u) != 0) + v3 = v2 - v1->x_width; + else + v3 = v1->x_width + v2 - 1; + R34 = v3; + uint16 v4 = 2 * (prod + (v3 >> 4)); + while ((level_data[v4 >> 1] & 0x8000u) == 0) { + v4 += room_width_in_blocks + room_width_in_blocks; + if ((--R26_ & 0x8000u) != 0) + return 0; + } + R18_ = 0; + if ((R20_ & 0x8000u) != 0) { + v8 = R34 | 0xF; + EnemyData *v9 = gEnemyData(k); + v11 = v9->x_width + 1 + v8 - v9->x_pos; + if (v11 >= 0) + v11 = 0; + R20_ = -v11; + return 1; + } else { + EnemyData *v6 = gEnemyData(k); + v7 = (R34 & 0xFFF0) - v6->x_width - v6->x_pos; + if (v7 < 0) + v7 = 0; + R20_ = v7; + return 1; + } +} + +uint8 EnemyFunc_BC76(uint16 k) { // 0xA0BC76 + int16 v4; + int16 v8; + int16 v9; + int16 v12; + + EnemyData *v1 = gEnemyData(k); + R26_ = (v1->x_pos - v1->x_width) & 0xFFF0; + R26_ = (uint16)(v1->x_width + v1->x_pos - 1 - R26_) >> 4; + uint16 v2 = (__PAIR32__(R20_, R18_) + __PAIR32__(v1->y_pos, v1->y_subpos)) >> 16; + uint16 v3; + R22_ = R18_ + v1->y_subpos; + R24_ = v2; + if ((R20_ & 0x8000u) != 0) + v3 = v2 - v1->y_height; + else + v3 = v1->y_height + v2 - 1; + R34 = v3; + uint16 prod = Mult8x8(v3 >> 4, room_width_in_blocks); + v4 = (uint16)(v1->x_pos - v1->x_width) >> 4; + for (int i = 2 * (prod + v4); (level_data[i >> 1] & 0x8000u) == 0; i += 2) { + if ((--R26_ & 0x8000u) != 0) + return 0; + } + R18_ = 0; + if ((R20_ & 0x8000u) != 0) { + v9 = R34 | 0xF; + EnemyData *v10 = gEnemyData(k); + v12 = v10->y_height + 1 + v9 - v10->y_pos; + if (v12 >= 0) + v12 = 0; + R20_ = -v12; + return 1; + } else { + EnemyData *v7 = gEnemyData(k); + v8 = (R34 & 0xFFF0) - v7->y_height - v7->y_pos; + if (v8 < 0) + v8 = 0; + R20_ = v8; + return 1; + } +} + +uint8 EnemyFunc_BF8A(uint16 k, uint16 a) { // 0xA0BF8A + int16 v6; + int16 v10; + int16 v13; + uint16 v4; + + R28_ = a; + EnemyData *v2 = gEnemyData(k); + R26_ = (v2->x_pos - v2->x_width) & 0xFFF0; + R26_ = (uint16)(v2->x_width + v2->x_pos - 1 - R26_) >> 4; + + if (a & 1) { + uint16 v3 = (__PAIR32__(R20_, R18_) + __PAIR32__(v2->y_pos, v2->y_subpos)) >> 16; + R22_ = R18_ + v2->y_subpos; + R24_ = v3; + v4 = v2->y_height + v3 - 1; + } else { + uint16 v5 = (__PAIR32__(v2->y_pos, v2->y_subpos) - __PAIR32__(R20_, R18_)) >> 16; + R22_ = v2->y_subpos - R18_; + R24_ = v5; + v4 = v5 - v2->y_height; + } + R34 = v4; + uint16 prod = Mult8x8(v4 >> 4, room_width_in_blocks); + v6 = (uint16)(v2->x_pos - v2->x_width) >> 4; + for (int i = 2 * (prod + v6); (level_data[i >> 1] & 0x8000u) == 0; i += 2) { + if ((--R26_ & 0x8000u) != 0) + return 0; + } + R18_ = 0; + if (R28_ & 1) { + EnemyData *v9 = gEnemyData(k); + v10 = (__PAIR32__((R34 & 0xFFF0) - v9->y_height, R34 & 0xFFF0) - __PAIR32__(v9->y_pos, v9->y_height)) >> 16; + if (v10 < 0) + v10 = 0; + R20_ = v10; + return 1; + } else { + EnemyData *v11 = gEnemyData(k); + v13 = v11->y_height + 1 + (R34 | 0xF) - v11->y_pos; + if (v13 >= 0) + v13 = 0; + R20_ = -v13; + return 1; + } +} + +uint16 CalculateAngleOfSamusFromEproj(uint16 k) { // 0xA0C04E + int v1 = k >> 1; + R18_ = samus_x_pos - enemy_projectile_x_pos[v1]; + R20_ = samus_y_pos - enemy_projectile_y_pos[v1]; + return CalculateAngleFromXY_(); +} + +uint16 CalculateAngleOfSamusFromEnemy(uint16 k) { // 0xA0C066 + EnemyData *v1 = gEnemyData(k); + R18_ = samus_x_pos - v1->x_pos; + R20_ = samus_y_pos - v1->y_pos; + return CalculateAngleFromXY_(); +} + +uint16 CalculateAngleOfEnemyXfromEnemyY(uint16 k, uint16 j) { // 0xA0C096 + EnemyData *v2 = gEnemyData(k); + EnemyData *v3 = gEnemyData(j); + R18_ = v2->x_pos - v3->x_pos; + R20_ = v2->y_pos - v3->y_pos; + return CalculateAngleFromXY_(); +} + +uint16 CalculateAngleFromXY(void) { // 0xA0C0AE + return CalculateAngleFromXY_(); +} + +static Func_Y_Y *const funcs_758EE[4] = { CalculateAngleFromXY_1, CalculateAngleFromXY_2, CalculateAngleFromXY_4, CalculateAngleFromXY_7 }; +static Func_Y_Y *const funcs_7587D[4] = { CalculateAngleFromXY_0, CalculateAngleFromXY_3, CalculateAngleFromXY_5, CalculateAngleFromXY_6 }; +uint16 CalculateAngleFromXY_(void) { // 0xA0C0B1 + uint16 v0 = 0; + uint16 v1 = R18_; + uint16 r; + + if ((R18_ & 0x8000u) != 0) { + v0 = 4; + v1 = -R18_; + } + R18_ = v1; + uint16 v2 = R20_; + if ((R20_ & 0x8000u) != 0) { + v0 += 2; + v2 = -R20_; + } + R20_ = v2; + if (v2 < R18_) { + uint16 div = SnesDivide(R20_ << 8, R18_); + r = funcs_7587D[v0 >> 1](div); + } else { + uint16 div = SnesDivide(R18_ << 8, R20_); + r = funcs_758EE[v0 >> 1](div); + } + + return r; +} + +uint16 CalculateAngleFromXY_0(uint16 div) { // 0xA0C112 + return (uint8)((div >> 3) + 64); +} + +uint16 CalculateAngleFromXY_1(uint16 div) { // 0xA0C120 + R18_ = div >> 3; + return (uint8)(0x80 - R18_); +} + +uint16 CalculateAngleFromXY_2(uint16 div) { // 0xA0C132 + return (uint8)(div >> 3); +} + +uint16 CalculateAngleFromXY_3(uint16 div) { // 0xA0C13C + R18_ = div >> 3; + return (uint8)(64 - R18_); +} + +uint16 CalculateAngleFromXY_4(uint16 div) { // 0xA0C14E + return (div >> 3) + 0x80 & 0xff; +} + +uint16 CalculateAngleFromXY_5(uint16 div) { // 0xA0C15C + R18_ = div >> 3; + return (uint8)(-64 - R18_); +} + +uint16 CalculateAngleFromXY_6(uint16 div) { // 0xA0C16E + return (uint8)((div >> 3) - 64); +} + +uint16 CalculateAngleFromXY_7(uint16 div) { // 0xA0C17C + R18_ = div >> 3; + return (uint8)-(int8)R18_; +} + +uint8 IsEnemyLeavingScreen(uint16 k) { // 0xA0C18E + int16 x_pos; + int16 v3; + + EnemyData *v1 = gEnemyData(k); + x_pos = v1->x_pos; + uint8 result = 1; + if (x_pos >= 0) { + v3 = v1->x_width + x_pos - layer1_x_pos; + if (v3 >= 0 && (int16)(v3 - 256 - v1->x_width) < 0) + return 0; + } + return result; +} + +void ProcessEnemyInstructions(void) { // 0xA0C26A + VoidP *v4; + int16 v5; + + EnemyData *v1 = gEnemyData(cur_enemy_index); + if ((v1->ai_handler_bits & 4) == 0) { + if (v1->instruction_timer-- == 1) { + uint8 bank = v1->bank; + uint16 current_instruction = v1->current_instruction; + while (1) { + v4 = (VoidP *)RomPtrWithBank(bank, current_instruction); + v5 = *v4; + if ((*v4 & 0x8000u) == 0) + break; + enemy_ai_pointer.addr = *v4; + current_instruction = CallEnemyInstr(Load24(&enemy_ai_pointer), cur_enemy_index, current_instruction + 2); + if (!current_instruction) + return; + } + EnemyData *v6 = gEnemyData(cur_enemy_index); + v6->instruction_timer = v5; + v6->spritemap_pointer = *((uint16 *)RomPtrWithBank(bank, current_instruction) + 1); + v6->current_instruction = current_instruction + 4; + v6->extra_properties |= 0x8000u; + } else { + EnemyData *v7 = gEnemyData(cur_enemy_index); + v7->extra_properties &= ~0x8000u; + } + } +} + +uint8 ClearCarry_13(void) { // 0xA0C2BC + return 0; +} + +uint8 SetCarry_4(void) { // 0xA0C2BE + return 1; +} + +#define g_off_A0C2DA ((uint16*)RomPtr(0xa0c2da)) + +uint8 EnemyBlockCollReact_Spike(void) { // 0xA0C2C0 + uint16 v0 = g_off_A0C2DA[BTS[cur_block_index] & 0x7F]; + if (!v0) + return 1; + SpawnPLM(v0); + return 0; +} + +uint8 EnemyBlockCollHorizReact_Slope(void) { // 0xA0C2FA + if ((BTS[cur_block_index] & 0x1Fu) >= 5) { + uint16 v0 = BTS[cur_block_index]; + current_slope_bts = v0; + return EnemyBlockCollHorizReact_Slope_NonSquare(); + } else { + return EnemyBlockCollHorizReact_Slope_Square(cur_block_index, BTS[cur_block_index] & 0x1F); + } +} + +uint8 EnemyBlockCollVertReact_Slope(void) { // 0xA0C319 + uint16 v0 = BTS[cur_block_index] & 0x1F; + if (v0 >= 5u) + return EnemyBlockCollVertReact_Slope_NonSquare(); + else + return EnemyBlockCollVertReact_Slope_Square(v0, cur_block_index); +} + +static const uint8 byte_A0C435[20] = { // 0xA0C32E + 0, 1, 0x82, 0x83, + 0, 0x81, 2, 0x83, + 0, 1, 2, 0x83, + 0, 0x81, 0x82, 0x83, + 0x80, 0x81, 0x82, 0x83, +}; + +#define CHECK_locret_A0C434(i) (byte_A0C435[i] & 0x80 ? -1 : 0) + +uint8 EnemyBlockCollHorizReact_Slope_Square(uint16 k, uint16 a) { + EnemyData *v4; + + temp_collision_DD4 = 4 * a; + temp_collision_DD6 = BTS[k] >> 6; + uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R26_ & 8) >> 3)); + if (!R28_) { + EnemyData *v3 = gEnemyData(cur_enemy_index); + if (((LOBYTE(v3->y_height) + LOBYTE(v3->y_pos) - 1) & 8) == 0) + return CHECK_locret_A0C434(v2) < 0; + goto LABEL_7; + } + if (R28_ != g_word_7E001E || (v4 = gEnemyData(cur_enemy_index), ((v4->y_pos - v4->y_height) & 8) == 0)) { +LABEL_7: + if (CHECK_locret_A0C434(v2) < 0) + return 1; + } + return CHECK_locret_A0C434(v2 ^ 2) < 0; +} + +void Enemy_SetXpos_Aligned(uint16 j) { // 0xA0C390 + EnemyData *v1 = gEnemyData(j); + uint16 v2; + v1->x_subpos = 0; + if ((R20_ & 0x8000u) != 0) + v2 = v1->x_width + (R26_ | 7) + 1; + else + v2 = (R26_ & 0xFFF8) - v1->x_width; + v1->x_pos = v2; +} + +uint8 EnemyBlockCollVertReact_Slope_Square(uint16 a, uint16 k) { // 0xA0C3B2 + EnemyData *v4; + + temp_collision_DD4 = 4 * a; + temp_collision_DD6 = BTS[k] >> 6; + uint16 v2 = 4 * a + (temp_collision_DD6 ^ ((uint8)(R26_ & 8) >> 2)); + if (!R28_) { + EnemyData *v3 = gEnemyData(cur_enemy_index); + if (((LOBYTE(v3->x_width) + LOBYTE(v3->x_pos) - 1) & 8) == 0) + return CHECK_locret_A0C434(v2) < 0; + goto LABEL_7; + } + if (R28_ != g_word_7E001E || (v4 = gEnemyData(cur_enemy_index), ((v4->x_pos - v4->x_width) & 8) == 0)) { +LABEL_7: + if (CHECK_locret_A0C434(v2) < 0) + return 1; + } + return CHECK_locret_A0C434(v2 ^ 1) < 0; +} + +uint8 Enemy_SetYpos_Aligned(uint16 j) { // 0xA0C413 + EnemyData *v1 = gEnemyData(j); + uint16 v2; + v1->y_subpos = 0; + if ((R20_ & 0x8000u) != 0) + v2 = v1->y_height + (R26_ | 7) + 1; + else + v2 = (R26_ & 0xFFF8) - v1->y_height; + v1->y_pos = v2; + return 1; +} +#define g_word_A0C49F ((uint16*)RomPtr(0xa0c49f)) +uint8 EnemyBlockCollHorizReact_Slope_NonSquare(void) { // 0xA0C449 + if ((R32 & 0x8000u) == 0) + return (R32 & 0x4000) != 0; + uint16 v2 = 4 * (current_slope_bts & 0x1F); + if ((R20_ & 0x8000u) == 0) { + Multiply16x16(*(uint16 *)((char *)&R18_ + 1), g_word_A0C49F[(v2 >> 1) + 1]); + R18_ = mult_product_lo; + R20_ = mult_product_hi; + } else { + Multiply16x16(-*(uint16 *)((char *)&R18_ + 1), g_word_A0C49F[(v2 >> 1) + 1]); + Negate32(&mult_product_hi, &mult_product_lo, &R20_, &R18_); + } + return 0; +} + +#define kAlignYPos_Tab0 ((uint8*)RomPtr(0x948b2b)) + +uint8 EnemyBlockCollVertReact_Slope_NonSquare(void) { // 0xA0C51F + int16 v3; + int16 v5; + int16 v6; + uint16 v7; + int16 v8; + int16 v11; + int16 v12; + int16 x_pos; + uint16 v14; + int16 v15; + + if ((R20_ & 0x8000u) != 0) { + uint16 v9 = cur_block_index; + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + EnemyData *v10 = gEnemyData(cur_enemy_index); + v11 = v10->x_pos >> 4; + if (v11 == mod) { + temp_collision_DD4 = (R24_ - v10->y_height) & 0xF ^ 0xF; + temp_collision_DD6 = 16 * (BTS[v9] & 0x1F); + v12 = BTS[v9] << 8; + if (v12 < 0 + && ((v12 & 0x4000) != 0 ? (x_pos = v10->x_pos ^ 0xF) : (x_pos = v10->x_pos), + (v14 = temp_collision_DD6 + (x_pos & 0xF), + v15 = (kAlignYPos_Tab0[v14] & 0x1F) - temp_collision_DD4 - 1, + (kAlignYPos_Tab0[v14] & 0x1F) - temp_collision_DD4 == 1) + || v15 < 0)) { + v10->y_pos = R24_ - v15; + v10->y_subpos = 0; + return 1; + } else { + return 0; + } + } else { + return 0; + } + } else { + uint16 v1 = cur_block_index; + uint16 mod = SnesModulus(cur_block_index, room_width_in_blocks); + EnemyData *v2 = gEnemyData(cur_enemy_index); + v3 = v2->x_pos >> 4; + if (v3 == mod) { + temp_collision_DD4 = (LOBYTE(v2->y_height) + (uint8)R24_ - 1) & 0xF; + temp_collision_DD6 = 16 * (BTS[v1] & 0x1F); + v5 = BTS[v1] << 8; + if (v5 >= 0 + && ((v5 & 0x4000) != 0 ? (v6 = v2->x_pos ^ 0xF) : (v6 = v2->x_pos), + (v7 = temp_collision_DD6 + (v6 & 0xF), + v8 = (kAlignYPos_Tab0[v7] & 0x1F) - temp_collision_DD4 - 1, + (kAlignYPos_Tab0[v7] & 0x1F) - temp_collision_DD4 == 1) + || v8 < 0)) { + v2->y_pos = R24_ + v8; + v2->y_subpos = -1; + return 1; + } else { + return 0; + } + } else { + return 0; + } + } +} + +uint8 EnemyBlockCollReact_HorizExt(void) { // 0xA0C619 + int16 v0; + + LOBYTE(v0) = BTS[cur_block_index]; + if ((uint8)v0) { + if ((BTS[cur_block_index] & 0x80) != 0) + v0 |= 0xFF00u; + else + v0 = (uint8)v0; + cur_block_index += v0; + return 0xff; + } + return 0; +} + +uint8 EnemyBlockCollReact_VertExt(void) { // 0xA0C64F + uint16 v0; + if (BTS[cur_block_index]) { + if ((BTS[cur_block_index] & 0x80) != 0) { + temp_collision_DD4 = BTS[cur_block_index] | 0xFF00; + v0 = cur_block_index; + do { + v0 -= room_width_in_blocks; + ++temp_collision_DD4; + } while (temp_collision_DD4); + } else { + temp_collision_DD4 = BTS[cur_block_index]; + v0 = cur_block_index; + do { + v0 += room_width_in_blocks; + --temp_collision_DD4; + } while (temp_collision_DD4); + } + cur_block_index = v0; + return 0xff; + } + return 0; +} + +uint8 Enemy_MoveRight_SlopesAsWalls(uint16 k) { // 0xA0C69D + R32 = 0x4000; + return Enemy_MoveRight_IgnoreSlopes_Inner(k); +} + +uint8 Enemy_MoveRight_ProcessSlopes(uint16 k) { // 0xA0C6A4 + R32 = 0x8000; + return Enemy_MoveRight_IgnoreSlopes_Inner(k); +} + +uint8 Enemy_MoveRight_IgnoreSlopes(uint16 k) { // 0xA0C6AB + R32 = 0; + return Enemy_MoveRight_IgnoreSlopes_Inner(k); +} + +uint8 Enemy_MoveRight_IgnoreSlopes_Inner(uint16 k) { // 0xA0C6AD + if (!__PAIR32__(R20_, R18_)) + return 0; + EnemyData *v3 = gEnemyData(k); + R28_ = (v3->y_pos - v3->y_height) & 0xFFF0; + R28_ = (uint16)(v3->y_height + v3->y_pos - 1 - R28_) >> 4; + g_word_7E001E = R28_; + uint16 prod = Mult8x8((uint16)(v3->y_pos - v3->y_height) >> 4, room_width_in_blocks); + uint16 v4 = (__PAIR32__(R20_, R18_) + __PAIR32__(v3->x_pos, v3->x_subpos)) >> 16; + R22_ = R18_ + v3->x_subpos; + R24_ = v4; + uint16 v5; + if ((R20_ & 0x8000u) != 0) + v5 = v4 - v3->x_width; + else + v5 = v3->x_width + v4 - 1; + R26_ = v5; + uint16 v6 = 2 * (prod + (v5 >> 4)); + while (!(EnemyBlockCollReact_Horiz(v6) & 1)) { + v6 += room_width_in_blocks + room_width_in_blocks; + if ((--R28_ & 0x8000u) != 0) { + EnemyData *v7 = gEnemyData(k); + bool v8 = __CFADD__uint16(v7->x_subpos, R18_); + v7->x_subpos += R18_; + v7->x_pos += v8 + R20_; + return 0; + } + } + if ((R20_ & 0x8000u) != 0) { + EnemyData *v11 = gEnemyData(k); + uint16 v12 = v11->x_width + 1 + (R26_ | 0xF); + if (v12 == v11->x_pos || v12 < v11->x_pos) + v11->x_pos = v12; + v11->x_subpos = 0; + return 1; + } else { + EnemyData *v9 = gEnemyData(k); + uint16 v10 = (R26_ & 0xFFF0) - v9->x_width; + if (v10 >= v9->x_pos) + v9->x_pos = v10; + v9->x_subpos = -1; + return 1; + } +} + +uint8 Enemy_MoveDown(uint16 k) { // 0xA0C786 + R32 = 0; + return Enemy_MoveDownInner(k); +} + +uint8 Enemy_MoveDownInner(uint16 k) { // 0xA0C788 + int16 v6; + uint16 v5; + + if (!__PAIR32__(R20_, R18_)) + return 0; + EnemyData *v3 = gEnemyData(k); + R28_ = (v3->x_pos - v3->x_width) & 0xFFF0; + R28_ = (uint16)(v3->x_width + v3->x_pos - 1 - R28_) >> 4; + g_word_7E001E = R28_; + uint16 v4 = (__PAIR32__(R20_, R18_) + __PAIR32__(v3->y_pos, v3->y_subpos)) >> 16; + R22_ = R18_ + v3->y_subpos; + R24_ = v4; + if ((R20_ & 0x8000u) != 0) + v5 = v4 - v3->y_height; + else + v5 = v3->y_height + v4 - 1; + R26_ = v5; + uint16 prod = Mult8x8(v5 >> 4, room_width_in_blocks); + v6 = (uint16)(v3->x_pos - v3->x_width) >> 4; + for (int i = 2 * (prod + v6); !(EnemyBlockCollReact_Vert(i) & 1); i += 2) { + if ((--R28_ & 0x8000u) != 0) { + EnemyData *v8 = gEnemyData(k); + v8->y_subpos = R22_; + v8->y_pos = R24_; + return 0; + } + } + if ((R20_ & 0x8000u) != 0) { + EnemyData *v11 = gEnemyData(k); + uint16 v13 = v11->y_height + 1 + (R26_ | 0xF); + if (v13 == v11->y_pos || v13 < v11->y_pos) + v11->y_pos = v13; + v11->y_subpos = 0; + return 1; + } else { + EnemyData *v9 = gEnemyData(k); + uint16 v10 = (R26_ & 0xFFF0) - v9->y_height; + if (v10 >= v9->y_pos) + v9->y_pos = v10; + v9->y_subpos = -1; + return 1; + } +} + +static Func_U8 *const off_A0C859[16] = { // 0xA0C845 + ClearCarry_13, + EnemyBlockCollHorizReact_Slope, + ClearCarry_13, + ClearCarry_13, + ClearCarry_13, + EnemyBlockCollReact_HorizExt, + ClearCarry_13, + ClearCarry_13, + SetCarry_4, + SetCarry_4, + EnemyBlockCollReact_Spike, + SetCarry_4, + SetCarry_4, + EnemyBlockCollReact_VertExt, + SetCarry_4, + SetCarry_4, +}; + +uint8 EnemyBlockCollReact_Horiz(uint16 k) { + cur_block_index = k >> 1; + uint8 rv = 0; + do { + rv = off_A0C859[(level_data[cur_block_index] & 0xf000) >> 12](); + } while (rv & 0x80); + return rv; +} + +static Func_U8 *const off_A0C88D[16] = { // 0xA0C879 + ClearCarry_13, + EnemyBlockCollVertReact_Slope, + ClearCarry_13, + ClearCarry_13, + ClearCarry_13, + EnemyBlockCollReact_HorizExt, + ClearCarry_13, + ClearCarry_13, + SetCarry_4, + SetCarry_4, + EnemyBlockCollReact_Spike, + SetCarry_4, + SetCarry_4, + EnemyBlockCollReact_VertExt, + SetCarry_4, + SetCarry_4, +}; + +uint8 EnemyBlockCollReact_Vert(uint16 k) { + cur_block_index = k >> 1; + uint8 rv = 0; + do { + rv = off_A0C88D[(level_data[cur_block_index] & 0xf000) >> 12](); + } while (rv & 0x80); + return rv; +} + +void CalculateBlockContainingPixelPos(uint16 xpos, uint16 ypos) { + uint16 prod = Mult8x8(ypos >> 4, room_width_in_blocks); + cur_block_index = prod + (xpos >> 4); +} + +uint8 EnemyFunc_C8AD(uint16 k) { // 0xA0C8AD + int16 v2; + int16 v3; + int16 v4; + int16 v5; + int16 x_pos; + int16 v7; + + uint8 result = 0; + + EnemyData *v1 = gEnemyData(k); + CalculateBlockContainingPixelPos(v1->x_pos, v1->y_pos + v1->y_height - 1); + if ((level_data[cur_block_index] & 0xF000) == 4096 + && (BTS[cur_block_index] & 0x1Fu) >= 5) { + result = 1; + temp_collision_DD4 = (LOBYTE(v1->y_height) + LOBYTE(v1->y_pos) - 1) & 0xF; + temp_collision_DD6 = 16 * (BTS[cur_block_index] & 0x1F); + v2 = BTS[cur_block_index] << 8; + if (v2 >= 0) { + v3 = (v2 & 0x4000) != 0 ? v1->x_pos ^ 0xF : v1->x_pos; + v4 = (kAlignYPos_Tab0[(uint16)(temp_collision_DD6 + (v3 & 0xF))] & 0x1F) - temp_collision_DD4 - 1; + if (v4 < 0) + v1->y_pos += v4; + } + } + CalculateBlockContainingPixelPos(v1->x_pos, v1->y_pos - v1->y_height); + if ((level_data[cur_block_index] & 0xF000) == 4096 + && (BTS[cur_block_index] & 0x1Fu) >= 5) { + result = 1; + temp_collision_DD4 = (v1->y_pos - v1->y_height) & 0xF ^ 0xF; + temp_collision_DD6 = 16 * (BTS[cur_block_index] & 0x1F); + v5 = BTS[cur_block_index] << 8; + if (v5 < 0) { + if ((v5 & 0x4000) != 0) + x_pos = v1->x_pos ^ 0xF; + else + x_pos = v1->x_pos; + v7 = (kAlignYPos_Tab0[(uint16)(temp_collision_DD6 + (x_pos & 0xF))] & 0x1F) - temp_collision_DD4 - 1; + if (v7 <= 0) + v1->y_pos -= v7; + } + } + return result; +} diff --git a/src/sm_a2.c b/src/sm_a2.c new file mode 100644 index 0000000..8a59376 --- /dev/null +++ b/src/sm_a2.c @@ -0,0 +1,4506 @@ +// Enemy AI - inc. gunship & shutters +#include "ida_types.h" +#include "sm_rtl.h" +#include "funcs.h" +#include "enemy_types.h" +#include "variables.h" + +#define kEnemyInit_BouncingGoofball_Tab0 ((uint16*)RomPtr(0xa286df)) +#define kEnemyInit_BouncingGoofball_Tab1 ((uint16*)RomPtr(0xa286ef)) +#define kBouncingGoofball_Tab0 ((uint8*)RomPtr(0xa28701)) +#define g_word_A28D56 (*(uint16*)RomPtr(0xa28d56)) +#define g_word_A28D58 (*(uint16*)RomPtr(0xa28d58)) + +static const uint16 g_word_A28D50 = 0x30; +static const uint16 g_word_A28D52 = 1; +static const uint16 g_word_A28D5E = 3; +static const uint16 g_word_A28D54 = 0x20; +static const uint16 g_word_A28D60 = 0x1e8; +static const uint16 g_word_A28D62 = 7; +static const uint16 g_word_A28D64 = 0x1e; +static const uint16 g_word_A28D66 = 4; +static const uint16 g_word_A28D68 = 0xfffd; +static const uint16 g_word_A28D6A = 3; + +static const int16 g_word_A28E80[48] = { + -16, -16, -16, -16, -15, -15, -15, -15, + -15, -14, -13, -13, -12, -11, -10, -9, + -8, -7, -6, -5, -4, -4, 0, 0, + -16, -16, -16, -15, -15, -15, -14, -13, + -12, -11, -10, -9, -8, -7, -6, -5, + -4, -3, -3, -2, 0, 0, 0, 0, +}; +#define g_word_A29A07 (*(uint16*)RomPtr(0xa29a07)) +#define g_word_A29A09 (*(uint16*)RomPtr(0xa29a09)) +#define g_word_A29A0B (*(uint16*)RomPtr(0xa29a0b)) +#define g_word_A29A0D (*(uint16*)RomPtr(0xa29a0d)) +#define g_word_A29F36 ((uint16*)RomPtr(0xa29f36)) +#define g_off_A29F42 ((uint16*)RomPtr(0xa29f42)) +#define g_word_A2A3DD ((uint16*)RomPtr(0xa2a3dd)) +#define g_word_A2A3ED ((uint16*)RomPtr(0xa2a3ed)) +#define g_byte_A2A7CF ((uint8*)RomPtr(0xa2a7cf)) +#define g_word_A2A622 ((uint16*)RomPtr(0xa2a622)) +#define g_word_A2AC07 ((uint16*)RomPtr(0xa2ac07)) +#define g_word_A2AC11 ((uint16*)RomPtr(0xa2ac11)) +#define g_word_A2B520 ((uint16*)RomPtr(0xa2b520)) +#define g_word_A2B530 ((uint16*)RomPtr(0xa2b530)) +#define g_word_A2B550 ((uint16*)RomPtr(0xa2b550)) +#define g_word_A2B75B ((uint16*)RomPtr(0xa2b75b)) +#define g_word_A2BBBB (*(uint16*)RomPtr(0xa2bbbb)) +#define g_word_A2BBBF (*(uint16*)RomPtr(0xa2bbbf)) +#define g_word_A2BE86 ((uint16*)RomPtr(0xa2be86)) +#define g_word_A2C1C1 ((uint16*)RomPtr(0xa2c1c1)) +#define g_word_A2C1C5 (*(uint16*)RomPtr(0xa2c1c5)) +#define g_word_A2C6CA (*(uint16*)RomPtr(0xa2c6ca)) +#define g_word_A2C6CE (*(uint16*)RomPtr(0xa2c6ce)) +#define g_off_A2CB77 ((uint16*)RomPtr(0xa2cb77)) +#define g_off_A2DF5E ((uint16*)RomPtr(0xa2df5e)) +#define g_off_A2DF6A ((uint16*)RomPtr(0xa2df6a)) +#define g_off_A2E5EF ((uint16*)RomPtr(0xa2e5ef)) +#define g_word_A2EA56 ((uint16*)RomPtr(0xa2ea56)) +#define g_off_A2EA4E ((uint16*)RomPtr(0xa2ea4e)) +#define g_off_A2EC3A ((uint16*)RomPtr(0xa2ec3a)) +#define g_off_A2EDFB ((uint16*)RomPtr(0xa2edfb)) +#define g_off_A2F107 ((uint16*)RomPtr(0xa2f107)) + +uint16 EnemyInstr_DecTimerAndGoto2_A2(uint16 k, uint16 j) { // 0xA28110 + EnemyData *v2 = gEnemyData(k); + if (v2->timer-- == 1) + return j + 2; + else + return EnemyInstr_Goto_A2(k, j); +} + +uint16 EnemyInstr_DisableOffScreenProcessing_A2(uint16 k, uint16 j) { // 0xA2817D + EnemyData *v2 = gEnemyData(k); + v2->properties &= ~kEnemyProps_ProcessedOffscreen; + return j; +} + +uint16 EnemyInstr_EnableOffScreenProcessing_A2(uint16 k, uint16 j) { // 0xA28173 + EnemyData *v2 = gEnemyData(k); + v2->properties |= kEnemyProps_ProcessedOffscreen; + return j; +} + +uint16 EnemyInstr_Goto_A2(uint16 k, uint16 j) { // 0xA280ED + return *(uint16 *)RomPtr_A2(j); +} + +uint16 EnemyInstr_SetTimer_A2(uint16 k, uint16 j) { // 0xA28123 + uint16 v2 = *(uint16 *)RomPtr_A2(j); + gEnemyData(k)->timer = v2; + return j + 2; +} + +uint16 EnemyInstr_Sleep_A2(uint16 k, uint16 j) { // 0xA2812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + +void Enemy_GrappleReact_CancelBeam_A2(void) { // 0xA2800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_GrappleReact_KillEnemy_A2(void) { // 0xA2800A + EnemyGrappleDeath(); +} + +void Enemy_GrappleReact_SamusLatchesOn_A2(void) { // 0xA28005 + SamusLatchesOnWithGrapple(); +} + +void Enemy_NormalFrozenAI_A2(void) { // 0xA28041 + NormalEnemyFrozenAI(); +} + +void Enemy_NormalPowerBombAI_A2(void) { // 0xA28037 + NormalEnemyPowerBombAi(); +} + +void Enemy_NormalTouchAI_A2(void) { // 0xA28023 + NormalEnemyTouchAi(); +} + +void Enemy_NormalShotAI_A2(void) { // 0xA2802D + NormalEnemyShotAi(); +} + +void BouncingGoofball_Init(void) { // 0xA2871C + Enemy_BouncingGoofball *E = Get_BouncingGoofball(cur_enemy_index); + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A2; + BouncingGoofball_Func2(); + E->bgl_var_01 = 1; + E->bgl_var_A = kEnemyInit_BouncingGoofball_Tab0[(uint16)(2 + * LOBYTE(E->bgl_parameter_1)) >> 1]; + E->bgl_var_C = kEnemyInit_BouncingGoofball_Tab1[(uint16)(2 + * HIBYTE(E->bgl_parameter_1)) >> 1]; + E->bgl_var_D = 0; + E->bgl_var_E = 0; + E->bgl_var_F = 0; +} + +void BouncingGoofball_Func1(uint16 k) { // 0xA28755 + Enemy_BouncingGoofball *E = Get_BouncingGoofball(k); + uint16 v5; + do { + uint16 bgl_var_E = E->bgl_var_E; + uint8 v3 = kBouncingGoofball_Tab0[bgl_var_E]; + if ((int16)(bgl_var_E - 23) >= 0) + v3 = -1; + uint16 prod = Mult8x8(v3, E->bgl_var_A); + uint16 RegWord = prod; + E->bgl_var_B = RegWord; + v5 = E->bgl_var_D + RegWord; + E->bgl_var_D = v5; + ++E->bgl_var_E; + } while ((int16)(v5 - E->bgl_var_C) < 0); + E->bgl_var_00 = E->bgl_var_E; + E->bgl_var_02 = 1; + E->bgl_var_04 = 1; +} + +static Func_V *const off_A28718[2] = { BouncingGoofball_State0, BouncingGoofball_State1 }; + +void BouncingGoofball_Main(void) { // 0xA2879C + Enemy_BouncingGoofball *E = Get_BouncingGoofball(cur_enemy_index); + if (!E->bgl_var_05) { + BouncingGoofball_Func1(cur_enemy_index); + E->bgl_var_05 = 1; + return; + } + E->bgl_var_03 = E->bgl_var_A; + if (BouncingGoofball_SamusCloseX()) { + E->bgl_var_02 = 0; + E->bgl_var_04 = 0; + if (!E->bgl_var_F) { + E->bgl_var_F = 1; + BouncingGoofball_Func3(); + } + goto LABEL_9; + } + if (!E->bgl_var_02) { +LABEL_9: + E->bgl_var_A = E->bgl_var_03; + off_A28718[E->bgl_var_01](); + return; + } + if (!E->bgl_var_04) { + E->bgl_var_04 = 1; + BouncingGoofball_Func2(); + } +} + +void BouncingGoofball_State0(void) { // 0xA28801 + Enemy_BouncingGoofball *E = Get_BouncingGoofball(cur_enemy_index); + uint16 v1 = ++E->bgl_var_E; + uint8 v2 = kBouncingGoofball_Tab0[v1]; + if ((int16)(v1 - 23) >= 0) + v2 = -1; + uint16 RegWord = Mult8x8(v2, E->bgl_var_A); + E->bgl_var_B = RegWord; + E->base.y_pos += HIBYTE(RegWord); + if ((int16)(E->bgl_var_E - E->bgl_var_00) >= 0) { + E->bgl_var_01 = 1; + E->bgl_var_02 = 1; + E->bgl_var_F = 0; + } +} + +void BouncingGoofball_State1(void) { // 0xA28850 + Enemy_BouncingGoofball *E = Get_BouncingGoofball(cur_enemy_index); + uint16 bgl_var_E = E->bgl_var_E; + uint8 v2 = kBouncingGoofball_Tab0[bgl_var_E]; + if ((int16)(bgl_var_E - 23) >= 0) + v2 = -1; + uint16 RegWord = Mult8x8(v2, E->bgl_var_A); + E->bgl_var_B = RegWord; + E->base.y_pos -= HIBYTE(RegWord); + if ((--E->bgl_var_E & 0x8000u) != 0) + E->bgl_var_01 = 0; +} + +uint16 BouncingGoofball_SamusCloseX(void) { // 0xA28894 + Enemy_BouncingGoofball *E = Get_BouncingGoofball(cur_enemy_index); + return IsSamusWithinEnemy_X(cur_enemy_index, E->bgl_parameter_2); +} + +void BouncingGoofball_Func2(void) { // 0xA2889F + Enemy_BouncingGoofball *E = Get_BouncingGoofball(cur_enemy_index); + E->base.current_instruction = addr_kBouncingGoofball_Ilist_86A7; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void BouncingGoofball_Func3(void) { // 0xA288B2 + Enemy_BouncingGoofball *E = Get_BouncingGoofball(cur_enemy_index); + E->base.current_instruction = addr_kBouncingGoofball_Ilist_86BF; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +uint16 BouncingGoofball_Instr_88C5(uint16 k, uint16 j) { // 0xA288C5 + return j; +} + +uint16 BouncingGoofball_Instr_88C6(uint16 k, uint16 j) { // 0xA288C6 + Get_BouncingGoofball(cur_enemy_index)->bgl_var_02 = 0; + QueueSfx2_Max6(0xEu); + return j; +} + +uint16 MiniCrocomire_Instr_897E(uint16 k, uint16 j) { // 0xA2897E + uint16 *v2 = (uint16 *)RomPtr_A2(j); + SpawnEnemyProjectileWithGfx(*v2, cur_enemy_index, addr_Eproj_DBF2); + return j + 2; +} + +uint16 MiniCrocomire_Instr_8990(uint16 k, uint16 j) { // 0xA28990 + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + E->mce_var_F = FUNC16(MiniCrocomire_PreInstr5); + E->mce_var_E = 0; + return j; +} + +uint16 MiniCrocomire_Instr_899D(uint16 k, uint16 j) { // 0xA2899D + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + E->mce_var_F = FUNC16(MiniCrocomire_PreInstr6); + E->mce_var_E = 1; + return j; +} + +void MiniCrocomire_Init(void) { // 0xA289AD + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A2; + int v1 = (uint16)(8 * E->mce_parameter_2) >> 1; + E->mce_var_B = kCommonEnemySpeeds_Linear[v1]; + E->mce_var_A = kCommonEnemySpeeds_Linear[v1 + 1]; + E->mce_var_D = kCommonEnemySpeeds_Linear[v1 + 2]; + E->mce_var_C = kCommonEnemySpeeds_Linear[v1 + 3]; + MiniCrocomire_Func1(); + E->mce_var_F = FUNC16(MiniCrocomire_PreInstr5); + uint16 mce_parameter_1 = E->mce_parameter_1; + E->mce_var_E = mce_parameter_1; + if (mce_parameter_1) { + MiniCrocomire_Func3(); + E->mce_var_F = FUNC16(MiniCrocomire_PreInstr6); + } +} + +void MiniCrocomire_Main(void) { // 0xA289F0 + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + CallEnemyPreInstr(E->mce_var_F | 0xA20000); +} + +void MiniCrocomire_Func1(void) { // 0xA289F7 + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMiniCrocomire_Ilist_8932; +} + +void MiniCrocomire_Func2(void) { // 0xA28A0A + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMiniCrocomire_Ilist_8948; +} + +void MiniCrocomire_Func3(void) { // 0xA28A1D + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMiniCrocomire_Ilist_8958; +} + +void MiniCrocomire_Func4(void) { // 0xA28A30 + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMiniCrocomire_Ilist_896E; +} + +void MiniCrocomire_PreInstr5(uint16 k) { // 0xA28A43 + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + R20_ = E->mce_var_D; + R18_ = E->mce_var_C; + MiniCrocomire_Func7(); + if (MiniCrocomire_Func9() & 1) + MiniCrocomire_Func2(); +} + +void MiniCrocomire_PreInstr6(uint16 k) { // 0xA28A5C + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + R20_ = E->mce_var_B; + R18_ = E->mce_var_A; + MiniCrocomire_Func7(); + if (MiniCrocomire_Func9() & 1) + MiniCrocomire_Func4(); +} + +void MiniCrocomire_Func7(void) { // 0xA28A76 + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1 || (R20_ = 2, R18_ = 0, !(EnemyFunc_BC76(cur_enemy_index) & 1))) + MiniCrocomire_Func8(); +} + +void MiniCrocomire_Func8(void) { // 0xA28A95 + MiniCrocomire_Func1(); + if (Get_MiniCrocomire(cur_enemy_index)->mce_var_E != 1) + MiniCrocomire_Func3(); +} + +uint8 MiniCrocomire_Func9(void) { // 0xA28AA7 + NextRandom(); + Enemy_MiniCrocomire *E = Get_MiniCrocomire(cur_enemy_index); + if (sign16((uint8)(LOBYTE(E->base.frame_counter) + random_number) - 2)) { + E->mce_var_F = FUNC16(nullsub_175); + return 1; + } + return 0; +} + +void MaridiaBeybladeTurtle_Init(void) { // 0xA28D6C + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A2; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.y_height = 0; + E->base.current_instruction = addr_kMaridiaBeybladeTurtle_Ilist_8C44; + E->mbte_var_A = FUNC16(MaridiaBeybladeTurtle_Func1); + E->mbte_var_F = g_word_A28D52; +} + +void MiniMaridiaBeybladeTurtle_Init(void) { // 0xA28D9D + int16 mmbte_parameter_1; + + Enemy_MiniMaridiaBeybladeTurtle *E = Get_MiniMaridiaBeybladeTurtle(cur_enemy_index); + E->mmbte_var_C = E->base.x_pos; + E->mmbte_var_D = E->base.y_pos + - E->base.y_height; + E->mmbte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func1); + E->base.instruction_timer = 1; + E->base.timer = 0; + uint16 v1 = addr_kMaridiaBeybladeTurtle_Ilist_8B80; + mmbte_parameter_1 = E->mmbte_parameter_1; + E->mmbte_var_E = mmbte_parameter_1; + if (mmbte_parameter_1 >= 0) + v1 = addr_kMaridiaBeybladeTurtle_Ilist_8C72; + E->base.current_instruction = v1; +} + +void CallMaridiaBeybladeTurtleFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnMaridiaBeybladeTurtle_Func1: MaridiaBeybladeTurtle_Func1(k); return; + case fnMaridiaBeybladeTurtle_Func2: MaridiaBeybladeTurtle_Func2(k); return; + case fnMaridiaBeybladeTurtle_Func3: MaridiaBeybladeTurtle_Func3(k); return; + case fnMaridiaBeybladeTurtle_Func5: MaridiaBeybladeTurtle_Func5(k); return; + case fnMaridiaBeybladeTurtle_Func7: MaridiaBeybladeTurtle_Func7(k); return; + case fnMaridiaBeybladeTurtle_Func8: MaridiaBeybladeTurtle_Func8(k); return; + case fnMaridiaBeybladeTurtle_Func9: MaridiaBeybladeTurtle_Func9(k); return; + case fnMaridiaBeybladeTurtle_Func10: MaridiaBeybladeTurtle_Func10(k); return; + case fnMaridiaBeybladeTurtle_Func11: MaridiaBeybladeTurtle_Func11(k); return; + case fnnullsub_360: return; + case fnMiniMaridiaBeybladeTurtle_Func1: MiniMaridiaBeybladeTurtle_Func1(k); return; + case fnMiniMaridiaBeybladeTurtle_Func2: MiniMaridiaBeybladeTurtle_Func2(k); return; + case fnMiniMaridiaBeybladeTurtle_Func3: MiniMaridiaBeybladeTurtle_Func3(k); return; + case fnMiniMaridiaBeybladeTurtle_Func4: MiniMaridiaBeybladeTurtle_Func4(k); return; + case fnMiniMaridiaBeybladeTurtle_Func6: MiniMaridiaBeybladeTurtle_Func6(k); return; + case fnMiniMaridiaBeybladeTurtle_Func7: MiniMaridiaBeybladeTurtle_Func7(); return; + default: Unreachable(); + } +} + +void MaridiaBeybladeTurtle_Main(void) { // 0xA28DD2 + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(cur_enemy_index); + CallMaridiaBeybladeTurtleFunc(E->mbte_var_A | 0xA20000, cur_enemy_index); +} + +void MaridiaBeybladeTurtle_Func1(uint16 k) { // 0xA28DD8 + uint16 palette_index = Get_MaridiaBeybladeTurtle(k)->base.palette_index; + Get_MaridiaBeybladeTurtle(k + 64)->base.palette_index = palette_index; + Get_MaridiaBeybladeTurtle(k + 128)->base.palette_index = palette_index; + Get_MaridiaBeybladeTurtle(k + 192)->base.palette_index = palette_index; + Get_MaridiaBeybladeTurtle(k + 256)->base.palette_index = palette_index; + uint16 vram_tiles_index = Get_MaridiaBeybladeTurtle(k)->base.vram_tiles_index; + Enemy_MaridiaBeybladeTurtle *E1 = Get_MaridiaBeybladeTurtle(k + 64); + E1->base.vram_tiles_index = vram_tiles_index; + Enemy_MaridiaBeybladeTurtle *E2 = Get_MaridiaBeybladeTurtle(k + 128); + E2->base.vram_tiles_index = vram_tiles_index; + Enemy_MaridiaBeybladeTurtle *E3 = Get_MaridiaBeybladeTurtle(k + 192); + E3->base.vram_tiles_index = vram_tiles_index; + Enemy_MaridiaBeybladeTurtle *E4 = Get_MaridiaBeybladeTurtle(k + 256); + E4->base.vram_tiles_index = vram_tiles_index; + E1->mbte_var_B = k; + E2->mbte_var_B = k; + E3->mbte_var_B = k; + E4->mbte_var_B = k; + Get_MaridiaBeybladeTurtle(k)->mbte_var_A = FUNC16(MaridiaBeybladeTurtle_Func2); +} + +void MaridiaBeybladeTurtle_Func2(uint16 k) { // 0xA28E0A + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(k); + if (E->mbte_var_F) { + E->base.y_height = 0; + uint16 xd = E->base.x_pos - samus_x_pos; + uint16 v2 = abs16(xd); + if (sign16(v2 - 24)) { + if (sign16(xd)) + v2 += 24; + uint16 v3 = cur_enemy_index; + E->base.y_height = -g_word_A28E80[v2]; + E->base.properties |= 0x8000u; + if (CheckIfEnemyTouchesSamus(v3)) { + R18_ = E->base.y_pos - E->base.y_height; + if ((int16)(samus_y_radius + samus_y_pos - R18_) >= 0) + extra_samus_y_displacement += R18_ - (samus_y_radius + samus_y_pos); + } + } + } else { + E->mbte_var_A = FUNC16(MaridiaBeybladeTurtle_Func3); + E->base.properties &= ~kEnemyProps_Tangible; + } +} + +void MaridiaBeybladeTurtle_Func3(uint16 k) { // 0xA28EE0 + MaridiaBeybladeTurtle_Func4(); + if ((nmi_frame_counter_byte & 1) == 0) { + if (CheckIfEnemyTouchesSamus(k)) + --extra_samus_x_displacement; + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(k); + --E->base.y_pos; + R18_ = 0; + E->base.y_height = 16; + if ((E->base.y_pos & 1) != 0) + --E->base.x_pos; + else + ++E->base.x_pos; + R20_ = 1; + if (!(Enemy_MoveRight_IgnoreSlopes(k) & 1)) { + E->base.current_instruction = addr_kMaridiaBeybladeTurtle_Ilist_8C4A; + E->base.instruction_timer = 1; + //*((uint16 *)RomPtr_A2(k) + 3) = g_word_A28D54; // WTF? + E->mbte_var_A = addr_locret_A28E09; + } + } +} + +void MaridiaBeybladeTurtle_Func5(uint16 k) { // 0xA28F3F + uint16 v1 = addr_kMaridiaBeybladeTurtle_Ilist_8C1C; + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(k); + if ((int16)(E->base.x_pos - samus_x_pos) < 0) + v1 = addr_kMaridiaBeybladeTurtle_Ilist_8D00; + E->base.current_instruction = v1; + E->base.instruction_timer = 1; + E->mbte_var_A = addr_locret_A28E09; +} + +void MaridiaBeybladeTurtle_Func6(uint16 k) { // 0xA28F5F + if (CheckIfEnemyTouchesSamus(k)) { + Enemy_MaridiaTurtle *E = Get_MaridiaTurtle(k); + E->mte_var_A = FUNC16(MaridiaBeybladeTurtle_Func9); + uint16 v2 = (__PAIR32__(extra_samus_x_displacement, extra_samus_x_subdisplacement) + - __PAIR32__(E->mte_var_E, E->mte_var_03)) >> 16; + extra_samus_x_subdisplacement -= E->mte_var_03; + if (sign16(v2 + 16)) + v2 = -16; + extra_samus_x_displacement = v2; + } +} + +void MaridiaBeybladeTurtle_Func7(uint16 k) { // 0xA28F8D + MaridiaBeybladeTurtle_Func4(); + R20_ = -1; + R18_ = 0; + if (!(Enemy_MoveDown(k) & 1)) { + if (CheckIfEnemyTouchesSamus(k)) + --extra_samus_y_displacement; + Enemy_MaridiaTurtle *E = Get_MaridiaTurtle(k); + uint16 v2 = E->mte_var_00 - 1; + E->mte_var_00 = v2; + if (!v2) { + uint16 v3 = 0; + if ((int16)(E->base.x_pos - samus_x_pos) < 0) + v3 = 4; + E->mte_var_01 = *(uint16 *)((char *)&g_word_A28D56 + v3); + E->mte_var_02 = *(uint16 *)((char *)&g_word_A28D58 + v3); + E->mte_var_E = 0; + E->mte_var_03 = 0; + E->mte_var_A = FUNC16(MaridiaBeybladeTurtle_Func8); + } + } +} + +void MaridiaBeybladeTurtle_Func8(uint16 k) { // 0xA28FEB + MaridiaBeybladeTurtle_Func4(); + Enemy_MaridiaTurtle *E = Get_MaridiaTurtle(k); + R20_ = E->mte_var_E; + R18_ = E->mte_var_03; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + Negate32(&E->mte_var_E, &E->mte_var_03, + &E->mte_var_E, &E->mte_var_03); + Negate32(&E->mte_var_02, &E->mte_var_01, + &E->mte_var_02, &E->mte_var_01); + earthquake_type = 0; + earthquake_timer = 16; + QueueSfx2_Max6(0x1Bu); + } else { + MaridiaBeybladeTurtle_Func6(k); + uint16 mte_var_03 = E->mte_var_03; + bool v3 = __CFADD__uint16(E->mte_var_01, mte_var_03); + E->mte_var_03 = E->mte_var_01 + mte_var_03; + uint16 v5 = E->mte_var_02 + v3 + E->mte_var_E; + if ((int16)(abs16(v5) - g_word_A28D5E) >= 0) { + uint16 v4 = g_word_A28D5E; + if ((E->mte_var_E & 0x8000u) != 0) + v4 = -g_word_A28D5E; + v5 = v4; + } + E->mte_var_E = v5; + } +} + +void MaridiaBeybladeTurtle_Func9(uint16 k) { // 0xA29083 + Enemy_MaridiaTurtle *E = Get_MaridiaTurtle(k); + uint16 v2; + MaridiaBeybladeTurtle_Func4(); + if ((int16)(E->base.y_pos - g_word_A28D60) < 0) { + E->mte_var_00 = g_word_A28D64; + v2 = FUNC16(MaridiaBeybladeTurtle_Func10); + } else { + if (CheckIfEnemyTouchesSamus(k)) { + E->base.y_pos -= g_word_A28D62; + extra_samus_y_displacement -= g_word_A28D62; + return; + } + v2 = FUNC16(MaridiaBeybladeTurtle_Func11); + } + E->mte_var_A = v2; + E->mte_var_07 = 0; + E->mte_var_04 = 0; +} + +void MaridiaBeybladeTurtle_Func10(uint16 k) { // 0xA290CC + MaridiaBeybladeTurtle_Func4(); + Enemy_MaridiaTurtle *E = Get_MaridiaTurtle(k); + uint16 v2 = E->mte_var_00 - 1; + E->mte_var_00 = v2; + if (!v2) + E->mte_var_A = FUNC16(MaridiaBeybladeTurtle_Func11); +} + +void MaridiaBeybladeTurtle_Func11(uint16 k) { // 0xA290E1 + MaridiaBeybladeTurtle_Func4(); + Enemy_MaridiaTurtle *E = Get_MaridiaTurtle(k); + if ((int16)(Get_MaridiaTurtle(0)->mte_var_04 - g_word_A28D66) < 0) { + uint16 mte_var_07 = E->mte_var_07; + E->mte_var_07 = mte_var_07 + 0x2000; + E->mte_var_04 += __CFADD__uint16(mte_var_07, 0x2000); + } + R18_ = 0; + R20_ = E->mte_var_04; + if (Enemy_MoveDown(k) & 1) { + uint16 v4 = addr_kMaridiaBeybladeTurtle_Ilist_8C4A; + if ((E->mte_var_E & 0x8000u) == 0) + v4 = addr_kMaridiaBeybladeTurtle_Ilist_8D28; + E->base.current_instruction = v4; + E->base.instruction_timer = 1; + E->mte_var_A = addr_locret_A28E09; + } +} + +void MiniMaridiaBeybladeTurtle_Main(void) { // 0xA2912E + Enemy_MiniMaridiaTurtle *E = Get_MiniMaridiaTurtle(cur_enemy_index); + Get_MiniMaridiaTurtle(E->mmte_var_B)->mmte_var_06 = 0; + CallMaridiaBeybladeTurtleFunc(E->mmte_var_A | 0xA20000, cur_enemy_index); +} + +void MiniMaridiaBeybladeTurtle_Func1(uint16 k) { // 0xA29142 + if (CheckIfEnemyTouchesSamus(k)) { + Enemy_MiniMaridiaTurtle *E = Get_MiniMaridiaTurtle(k); + E->mmte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func2); + E->mmte_var_05 = 4; + uint16 v2 = addr_kMaridiaBeybladeTurtle_Ilist_8C30; + if ((E->mmte_var_E & 0x8000u) == 0) + v2 = addr_kMaridiaBeybladeTurtle_Ilist_8D14; + E->base.current_instruction = v2; + E->base.instruction_timer = 1; + } +} + +void MiniMaridiaBeybladeTurtle_Func2(uint16 k) { // 0xA2916E + Enemy_MiniMaridiaTurtle *E = Get_MiniMaridiaTurtle(k); + if (CheckIfEnemyTouchesSamus(k)) { + E->mmte_var_05 = 4; + } else { + uint16 v2 = E->mmte_var_05 - 1; + E->mmte_var_05 = v2; + if (!v2) { + E->mmte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func3); + E->mmte_var_00 = 60; + } + } +} + +void MiniMaridiaBeybladeTurtle_Func3(uint16 k) { // 0xA29198 + Enemy_MiniMaridiaTurtle *E = Get_MiniMaridiaTurtle(k); + if (CheckIfEnemyTouchesSamus(k)) { + E->mmte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func4); + E->base.current_instruction = addr_kMaridiaBeybladeTurtle_Ilist_8BD2; + E->base.instruction_timer = 1; + E->mmte_var_04 = 1; + uint16 v2 = g_word_A28D68; + if ((samus_pose_x_dir & 0xF) == 8) + v2 = g_word_A28D6A; + E->mmte_var_E = v2; + } else { + uint16 v4 = E->mmte_var_00 - 1; + E->mmte_var_00 = v4; + if (!v4) { + uint16 v5 = addr_kMaridiaBeybladeTurtle_Ilist_8B80; + if ((E->mmte_var_E & 0x8000u) == 0) + v5 = addr_kMaridiaBeybladeTurtle_Ilist_8C72; + E->base.current_instruction = v5; + E->base.instruction_timer = 1; + E->mmte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func1); + } + } +} + +void MiniMaridiaBeybladeTurtle_Func4(uint16 k) { // 0xA291F8 + R18_ = 0; + Enemy_MiniMaridiaTurtle *E = Get_MiniMaridiaTurtle(k); + R20_ = E->mmte_var_E; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->mmte_var_E = -E->mmte_var_E; + } else { + R18_ = 0; + R20_ = E->mmte_var_04; + Enemy_MoveDown(k); + } +} + +void MiniMaridiaBeybladeTurtle_Func5(uint16 k) { // 0xA2921D + uint16 v1 = addr_kMaridiaBeybladeTurtle_Ilist_8B80; + Enemy_MiniMaridiaBeybladeTurtle *E = Get_MiniMaridiaBeybladeTurtle(k); + if ((E->mmbte_var_E & 0x8000u) == 0) + v1 = addr_kMaridiaBeybladeTurtle_Ilist_8C72; + E->base.current_instruction = v1; + E->base.instruction_timer = 1; + E->mmbte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func1); +} + +void MiniMaridiaBeybladeTurtle_Func6(uint16 k) { // 0xA29239 + if (CheckIfEnemyTouchesSamus(k)) { + uint16 v1 = addr_kMaridiaBeybladeTurtle_Ilist_8B80; + Enemy_MiniMaridiaBeybladeTurtle *E = Get_MiniMaridiaBeybladeTurtle(k); + if ((E->mmbte_var_E & 0x8000u) == 0) + v1 = addr_kMaridiaBeybladeTurtle_Ilist_8C72; + E->base.current_instruction = v1; + E->base.instruction_timer = 1; + E->mmbte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func1); + } else { + MiniMaridiaBeybladeTurtle_Func4(k); + } +} + +void MiniMaridiaBeybladeTurtle_Func7(void) { // 0xA2925E + Enemy_MiniMaridiaTurtle *E = Get_MiniMaridiaTurtle(cur_enemy_index); + Get_MiniMaridiaTurtle(E->mmte_var_B)->mmte_var_06 = E->base.y_height; + if (!CheckIfEnemyTouchesSamus(cur_enemy_index)) + Get_MiniMaridiaTurtle(cur_enemy_index)->mmte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func1); +} + +void MaridiaBeybladeTurtle_Touch(void) { // 0xA29281 + Enemy_MiniMaridiaTurtle *E = Get_MiniMaridiaTurtle(cur_enemy_index); + if ((E->base.properties & 0x8000u) == 0) { + Enemy_NormalTouchAI_A2(); + E->mmte_var_A = FUNC16(MaridiaBeybladeTurtle_Func11); + E->mmte_var_04 = 2; + } +} + +void MiniMaridiaBeybladeTurtle_Touch(void) { // 0xA2929F + int16 v2; + + Enemy_MiniMaridiaBeybladeTurtle *E = Get_MiniMaridiaBeybladeTurtle(cur_enemy_index); + if (E->mmbte_var_A != 0x925E) { + if ((E->mmbte_var_E & 0x8000u) != 0) { + E->base.current_instruction = addr_kMaridiaBeybladeTurtle_Ilist_8C72; + v2 = 1; + } else { + E->base.current_instruction = addr_kMaridiaBeybladeTurtle_Ilist_8B80; + v2 = -1; + } + E->mmbte_var_E = v2; + E->base.instruction_timer = 1; + uint16 v3; + if ((int16)(E->base.x_pos - samus_x_pos) >= 0) + v3 = E->base.x_width + samus_x_radius + samus_x_pos; + else + v3 = (__PAIR32__(samus_x_pos - samus_x_radius, samus_x_pos) + - __PAIR32__(E->base.x_width, samus_x_radius)) >> 16; + E->base.x_pos = v3; + E->mmbte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func1); + R18_ = 0; + R20_ = E->mmbte_var_E; + Enemy_MoveRight_IgnoreSlopes(cur_enemy_index); + MaridiaBeybladeTurtle_Func21(); + } +} + +void MaridiaBeybladeTurtle_Func21(void) { // 0xA292FF + uint16 mbte_var_B = Get_MaridiaBeybladeTurtle(cur_enemy_index)->mbte_var_B; + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(mbte_var_B); + if (E->mbte_var_F) + --E->mbte_var_F; +} + +void MiniMaridiaBeybladeTurtle_Shot(void) { // 0xA2930F + NormalEnemyShotAi(); + MaridiaBeybladeTurtle_Func21(); +} + +void MaridiaBeybladeTurtle_Func4(void) { // 0xA29315 + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(0); + R18_ = E->base.x_pos - E->base.x_width - 8; + R20_ = E->base.x_width + E->base.x_pos + 8; + R22_ = E->base.y_pos - E->base.y_height + 4; + R24_ = E->base.y_height + E->base.y_pos - 4; + if (sign16(samus_x_pos - samus_x_radius - 1 - R20_) + && !sign16(samus_x_radius + samus_x_pos - R18_) + && sign16(samus_y_pos - samus_y_radius + 1 - R24_) + && !sign16(samus_y_radius + samus_y_pos - R22_) + && !samus_invincibility_timer) { + NormalEnemyTouchAi(); + } +} + +uint16 MaridiaBeybladeTurtle_Instr_9381(uint16 k, uint16 j) { // 0xA29381 + R48 = 0; + if (CheckIfEnemyTouchesSamus(cur_enemy_index)) { + extra_samus_x_displacement += Get_MaridiaBeybladeTurtle(cur_enemy_index)->mbte_var_E; + R48 = 1; + } + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(cur_enemy_index); + R50 = E->base.y_pos; + E->base.y_pos = E->mbte_var_D; + R18_ = 0; + R20_ = E->mbte_var_E; + Enemy_MoveRight_IgnoreSlopes(cur_enemy_index); + if (Get_MaridiaBeybladeTurtle(E->mbte_var_B)->mbte_var_A == 0x8E0A) { + uint16 x_pos = Get_MaridiaBeybladeTurtle(E->mbte_var_B)->base.x_pos; + uint16 xd = x_pos - E->base.x_pos; + uint16 v7 = abs16(xd); + uint16 v8; + if (sign16(v7 - 24)) { + if (sign16(xd)) + v7 += 24; + v8 = g_word_A28E80[v7]; + } else { + v8 = 1; + } + R20_ = v8; + R18_ = 0; + uint16 v9 = cur_enemy_index; + Enemy_MoveDown(cur_enemy_index); + if (R48) + extra_samus_y_displacement += Get_MaridiaBeybladeTurtle(v9)->base.y_pos - R50; + } + return j; +} + +uint16 MaridiaBeybladeTurtle_Instr_9412(uint16 k, uint16 j) { // 0xA29412 + int16 v4; + + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(cur_enemy_index); + uint16 xd = E->mbte_var_C - E->base.x_pos; + if ((int16)(abs16(xd) - g_word_A28D50) >= 0) { + if (!sign16(xd)) + v4 = 1; + else + v4 = -1; + E->mbte_var_E = v4; + } + if ((Get_MaridiaBeybladeTurtle(cur_enemy_index)->mbte_var_E & 0x8000u) != 0) + return addr_kMaridiaBeybladeTurtle_Ilist_8B80; + return addr_kMaridiaBeybladeTurtle_Ilist_8C72; +} + +uint16 MaridiaBeybladeTurtle_Instr_9447(uint16 k, uint16 j) { // 0xA29447 + Get_MaridiaBeybladeTurtle(cur_enemy_index)->mbte_var_A = FUNC16(MaridiaBeybladeTurtle_Func5); + return j; +} + +uint16 MaridiaBeybladeTurtle_Instr_9451(uint16 k, uint16 j) { // 0xA29451 + Enemy_MaridiaTurtle *E = Get_MaridiaTurtle(cur_enemy_index); + E->mte_var_A = FUNC16(MaridiaBeybladeTurtle_Func7); + E->mte_var_E = -1; + E->mte_var_00 = 16; + return addr_kMaridiaBeybladeTurtle_Ilist_8C02; +} + +uint16 MaridiaBeybladeTurtle_Instr_946B(uint16 k, uint16 j) { // 0xA2946B + Enemy_MaridiaTurtle *E = Get_MaridiaTurtle(cur_enemy_index); + E->mte_var_A = FUNC16(MaridiaBeybladeTurtle_Func7); + E->mte_var_E = 1; + E->mte_var_00 = 16; + return addr_kMaridiaBeybladeTurtle_Ilist_8C02; +} + +uint16 MaridiaBeybladeTurtle_Instr_9485(uint16 k, uint16 j) { // 0xA29485 + if (CheckIfEnemyTouchesSamus(cur_enemy_index)) { + if ((Get_MaridiaBeybladeTurtle(cur_enemy_index)->mbte_var_E & 0x8000u) == 0) + return addr_kMaridiaBeybladeTurtle_Ilist_8D40; + else + return addr_kMaridiaBeybladeTurtle_Ilist_8C62; + } + return j; +} + +uint16 MaridiaBeybladeTurtle_Instr_94A1(uint16 k, uint16 j) { // 0xA294A1 + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(cur_enemy_index); + if (CheckIfEnemyTouchesSamus(cur_enemy_index)) + E->mbte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func7); + else + E->mbte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func1); + uint16 result = addr_kMaridiaBeybladeTurtle_Ilist_8B80; + if ((E->mbte_var_E & 0x8000u) == 0) + return addr_kMaridiaBeybladeTurtle_Ilist_8C72; + return result; +} + +uint16 MaridiaBeybladeTurtle_Instr_94C7(uint16 k, uint16 j) { // 0xA294C7 + Enemy_MaridiaBeybladeTurtle *E = Get_MaridiaBeybladeTurtle(cur_enemy_index); + E->mbte_var_A = FUNC16(MiniMaridiaBeybladeTurtle_Func6); + return j; +} + +uint16 MaridiaBeybladeTurtle_Instr_94D1(uint16 k, uint16 j) { // 0xA294D1 + QueueSfx2_Max6(0x3Au); + return j; +} + +void ThinHoppingBlobs_Init(void) { // 0xA29A3F + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A2; + E->thbs_var_A = 0; + sub_A29A6C(addr_kThinHoppingBlobs_Ilist_99AD); + E->thbs_var_00 = 0; + E->thbs_var_D = FUNC16(ThinHoppingBlobs_Func6); + E->thbs_var_C = E->thbs_parameter_1; + E->thbs_var_04 = 0; +} + +void sub_A29A6C(uint16 a) { // 0xA29A6C + EnemyData *v1 = gEnemyData(cur_enemy_index); + v1->current_instruction = a; + v1->instruction_timer = 1; + v1->timer = 0; +} + +void CallThinHoppingBlobs(uint32 ea) { + switch (ea) { + case fnThinHoppingBlobs_Func6: ThinHoppingBlobs_Func6(cur_enemy_index); return; + case fnThinHoppingBlobs_Func7: ThinHoppingBlobs_Func7(); return; + default: Unreachable(); + } +} + +void ThinHoppingBlobs_Main(void) { // 0xA29A7D + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + CallThinHoppingBlobs(E->thbs_var_D | 0xA20000); +} + +void ThinHoppingBlobs_Func1(uint16 k) { // 0xA29A84 + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(k); + if (sign16(E->thbs_var_00 - 3)) + TwinHoppingBlobs_Func2(); + ThinHoppingBlobs_Func3(); + ThinHoppingBlobs_Func5(); +} + +void TwinHoppingBlobs_Func2(void) { // 0xA29A9B + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + E->thbs_var_00 = IsSamusWithinEnemy_X(cur_enemy_index, E->thbs_parameter_2); +} + +void ThinHoppingBlobs_Func3(void) { // 0xA29AAA + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + E->thbs_var_02 = 1; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) + E->thbs_var_02 = 0; + if (E->thbs_var_04) + E->thbs_var_02 = E->thbs_var_05; + E->thbs_var_04 = 0; + ThinHoppingBlobs_Func4(); + uint16 thbs_var_00 = E->thbs_var_00; + if (sign16(thbs_var_00 - 3)) { + if (!thbs_var_00) + R28_ &= 1u; + thbs_var_00 = R28_; + if (!sign16(R28_ - 2)) + thbs_var_00 = 2; + } + uint16 v3 = 8 * thbs_var_00; + E->thbs_var_F = v3; + E->thbs_var_E = *(uint16 *)((char *)&g_word_A29A0D + v3); +} + +void ThinHoppingBlobs_Func4(void) { // 0xA29B06 + NextRandom(); + R28_ = (Get_ThinHoppingBlobs(cur_enemy_index)->base.frame_counter + random_number) & 7; +} + +void ThinHoppingBlobs_Func5(void) { // 0xA29B1A + int16 v2; + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + uint16 thbs_var_F = E->thbs_var_F; + R22_ = 0; + R24_ = 0; + do { + R22_ += *(uint16 *)((char *)&g_word_A29A09 + thbs_var_F); + R24_ += *(uint16 *)((char *)kCommonEnemySpeeds_Quadratic + + (uint16)(8 * (uint8)((uint16)(R22_ & 0xFF00) >> 8)) + + 1); + thbs_var_F = E->thbs_var_F; + LOBYTE(v2) = HIBYTE(*(uint16 *)((char *)&g_word_A29A07 + thbs_var_F)); + HIBYTE(v2) = *(uint16 *)((char *)&g_word_A29A07 + thbs_var_F); + } while (!sign16(v2 - R24_)); + E->thbs_var_B = R22_; + E->thbs_var_03 = 0; + uint16 v3 = R22_ >> 1; + E->thbs_var_07 = R22_ >> 1; + E->thbs_var_06 = E->thbs_var_07 + (v3 >> 1); +} + +void ThinHoppingBlobs_Func6(uint16 k) { // 0xA29B65 + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(k); + if ((--E->thbs_var_C & 0x8000u) != 0) { + E->thbs_var_D = FUNC16(ThinHoppingBlobs_Func7); + E->thbs_var_C = E->thbs_parameter_1; + E->thbs_var_01 = 1; + ThinHoppingBlobs_Func1(k); + } +} + +void CallThinHoppingBlobsVarE(uint32 ea) { + switch (ea) { + case fnThinHoppingBlobs_Func11: ThinHoppingBlobs_Func11(); return; + case fnThinHoppingBlobs_Func12: ThinHoppingBlobs_Func12(); return; + case fnThinHoppingBlobs_Func13: ThinHoppingBlobs_Func13(); return; + case fnThinHoppingBlobs_Func14: ThinHoppingBlobs_Func14(); return; + case fnThinHoppingBlobs_Func15: ThinHoppingBlobs_Func15(); return; + case fnThinHoppingBlobs_Func16: ThinHoppingBlobs_Func16(); return; + default: Unreachable(); + } +} + +void ThinHoppingBlobs_Func7(void) { // 0xA29B81 + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + CallThinHoppingBlobsVarE(E->thbs_var_E | 0xA20000); +} + +void ThinHoppingBlobs_Func8(void) { // 0xA29B88 + int16 thbs_var_B; + int16 v4; + char v5; // t0 + + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + thbs_var_B = E->thbs_var_B; + if (!sign16(thbs_var_B - 0x4000)) + thbs_var_B = 0x4000; + v4 = thbs_var_B & 0xFF00; + v5 = v4; + LOBYTE(v4) = HIBYTE(v4); + HIBYTE(v4) = v5; + uint16 v6 = 8 * v4; + if (E->thbs_var_03) + v6 -= 4; + int v7 = v6 >> 1; + R18_ = kCommonEnemySpeeds_Quadratic[v7 + 2]; + R20_ = kCommonEnemySpeeds_Quadratic[v7 + 3]; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + if (E->thbs_var_03) { + E->thbs_var_D = FUNC16(ThinHoppingBlobs_Func6); + } else { + E->thbs_var_04 = *(VoidP *)((char *)&R0_.addr + 1); + E->thbs_var_05 = E->thbs_var_02 ^ 1; + E->thbs_var_00 = 4; + E->thbs_var_E = FUNC16(ThinHoppingBlobs_Func15); + } + E->thbs_var_01 = 0; + } else { + uint16 thbs_var_F = E->thbs_var_F; + if (E->thbs_var_03) { + ThinHoppingBlobs_Func10(); + E->thbs_var_B += *(uint16 *)((char *)&g_word_A29A0B + thbs_var_F); + } else { + ThinHoppingBlobs_Func9(); + E->thbs_var_B -= *(uint16 *)((char *)&g_word_A29A0B + thbs_var_F); + } + if (sign16(E->thbs_var_B)) { + E->thbs_var_03 = 1; + E->thbs_var_B = 0; + } + R20_ = (uint8)((uint16)(*(uint16 *)((char *)&g_word_A29A09 + E->thbs_var_F) & 0xFF00) >> 8); + R18_ = 0; + if (E->thbs_var_02) + R20_ = -R20_; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->thbs_var_04 = 1; + E->thbs_var_05 = E->thbs_var_02 ^ 1; + E->thbs_var_01 = 0; + E->thbs_var_00 = 4; + E->thbs_var_E = FUNC16(ThinHoppingBlobs_Func15); + } + } +} + +void ThinHoppingBlobs_Func9(void) { // 0xA29C71 + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + uint16 v2; + if (E->thbs_var_02) { + uint16 thbs_var_B = E->thbs_var_B; + if ((int16)(thbs_var_B - E->thbs_var_06) >= 0) { + v2 = addr_kThinHoppingBlobs_Ilist_9A01; + } else if ((int16)(thbs_var_B - E->thbs_var_07) >= 0) { + v2 = addr_kThinHoppingBlobs_Ilist_99FB; + } else { + v2 = addr_kThinHoppingBlobs_Ilist_99F5; + } + } else { + uint16 v1 = E->thbs_var_B; + if ((int16)(v1 - E->thbs_var_06) >= 0) { + v2 = addr_kThinHoppingBlobs_Ilist_99E9; + } else if ((int16)(v1 - E->thbs_var_07) >= 0) { + v2 = addr_kThinHoppingBlobs_Ilist_99EF; + } else { + v2 = addr_kThinHoppingBlobs_Ilist_99F5; + } + } + sub_A29A6C(v2); +} + +void ThinHoppingBlobs_Func10(void) { // 0xA29CBE + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + uint16 v2; + if (E->thbs_var_02) { + uint16 thbs_var_B = E->thbs_var_B; + if ((int16)(thbs_var_B - E->thbs_var_07) < 0) { + v2 = addr_kThinHoppingBlobs_Ilist_99F5; + } else if ((int16)(thbs_var_B - E->thbs_var_06) < 0) { + v2 = addr_kThinHoppingBlobs_Ilist_99EF; + } else { + v2 = addr_kThinHoppingBlobs_Ilist_99E9; + } + } else { + uint16 v1 = E->thbs_var_B; + if ((int16)(v1 - E->thbs_var_07) < 0) { + v2 = addr_kThinHoppingBlobs_Ilist_99F5; + } else if ((int16)(v1 - E->thbs_var_06) < 0) { + v2 = addr_kThinHoppingBlobs_Ilist_99FB; + } else { + v2 = addr_kThinHoppingBlobs_Ilist_9A01; + } + } + sub_A29A6C(v2); +} + +void ThinHoppingBlobs_Func11(void) { // 0xA29D0B + + ThinHoppingBlobs_Func8(); + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + if (E->thbs_var_04 || !E->thbs_var_01) { + E->thbs_var_01 = 0; + sub_A29A6C(addr_kThinHoppingBlobs_Ilist_99D5); + } +} + +void ThinHoppingBlobs_Func12(void) { // 0xA29D2B + + ThinHoppingBlobs_Func8(); + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + if (E->thbs_var_04 || !E->thbs_var_01) { + E->thbs_var_01 = 0; + sub_A29A6C(addr_kThinHoppingBlobs_Ilist_99C1); + } +} + +void ThinHoppingBlobs_Func13(void) { // 0xA29D4B + + ThinHoppingBlobs_Func8(); + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + if (E->thbs_var_04 || !E->thbs_var_01) { + E->thbs_var_01 = 0; + sub_A29A6C(addr_kThinHoppingBlobs_Ilist_99AD); + } +} + +void ThinHoppingBlobs_Func14(void) { // 0xA29D6B + + ThinHoppingBlobs_Func8(); + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + if (!E->thbs_var_04) { + if (E->thbs_var_01) + return; + E->thbs_var_00 = 0; + E->thbs_var_D = FUNC16(ThinHoppingBlobs_Func6); + } + E->thbs_var_01 = 0; + sub_A29A6C(addr_kThinHoppingBlobs_Ilist_99D5); +} + +void ThinHoppingBlobs_Func15(void) { // 0xA29D98 + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + uint16 thbs_var_F = E->thbs_var_F; + R20_ = (uint8)((uint16)(*(uint16 *)((char *)&g_word_A29A0B + thbs_var_F) & 0xFF00) >> 8); + R18_ = *((uint8 *)&g_word_A29A0B + thbs_var_F) << 8; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + ThinHoppingBlobs_Func4(); + E->thbs_var_00 = (R28_ & 1) + 5; + E->thbs_var_D = FUNC16(ThinHoppingBlobs_Func6); + } +} + +void ThinHoppingBlobs_Func16(void) { // 0xA29DCD + + ThinHoppingBlobs_Func8(); + Enemy_ThinHoppingBlobs *E = Get_ThinHoppingBlobs(cur_enemy_index); + if (!E->thbs_var_01) { + E->thbs_var_01 = 0; + E->thbs_var_00 = 3; + E->thbs_var_D = FUNC16(ThinHoppingBlobs_Func6); + sub_A29A6C(addr_kThinHoppingBlobs_Ilist_99D5); + } +} + +uint16 SpikeShootingPlant_Instr_9F2A(uint16 k, uint16 j) { // 0xA29F2A + QueueSfx2_Max6(0x34u); + return j; +} + +void SpikeShootingPlant_Init(void) { // 0xA29F48 + Enemy_SpikeShootingPlant *E = Get_SpikeShootingPlant(cur_enemy_index); + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A2; + if (HIBYTE(E->sspt_parameter_1)) + SpikeShootingPlant_5(); + else + SpikeShootingPlant_7(); + uint16 sspt_parameter_1_low = LOBYTE(E->sspt_parameter_1); + E->sspt_var_E = sspt_parameter_1_low; + E->sspt_var_F = g_off_A29F42[sspt_parameter_1_low]; + int v2 = (uint16)(2 * LOBYTE(E->sspt_parameter_2)) >> 1; + E->sspt_var_01 = g_word_A29F36[v2] + E->base.x_pos; + E->sspt_var_00 = E->base.x_pos - g_word_A29F36[v2]; + int v3 = (uint16)(8 * HIBYTE(E->sspt_parameter_2)) >> 1; + E->sspt_var_B = kCommonEnemySpeeds_Linear[v3]; + E->sspt_var_A = kCommonEnemySpeeds_Linear[v3 + 1]; + E->sspt_var_D = kCommonEnemySpeeds_Linear[v3 + 2]; + E->sspt_var_C = kCommonEnemySpeeds_Linear[v3 + 3]; +} + +void SpikeShootingPlant_Main(void) { // 0xA29FB3 + Enemy_SpikeShootingPlant *E = Get_SpikeShootingPlant(cur_enemy_index); + CallEnemyPreInstr(E->sspt_var_F | 0xA20000); +} + +void SpikeShootingPlant_2(uint16 k) { // 0xA29FBA + Enemy_SpikeShootingPlant *E = Get_SpikeShootingPlant(cur_enemy_index); + uint16 x_subpos = E->base.x_subpos; + bool v2 = __CFADD__uint16(E->sspt_var_C, x_subpos); + uint16 v3 = E->sspt_var_C + x_subpos; + if (v2) + ++E->base.x_pos; + E->base.x_subpos = v3; + uint16 v4 = E->sspt_var_D + E->base.x_pos; + E->base.x_pos = v4; + if ((int16)(v4 - E->sspt_var_00) < 0) { + E->sspt_var_F = FUNC16(SpikeShootingPlant_3); + E->sspt_var_E = 1; + } + SpikeShootingPlant_4(); +} + +void SpikeShootingPlant_3(uint16 k) { // 0xA29FEC + Enemy_SpikeShootingPlant *E = Get_SpikeShootingPlant(cur_enemy_index); + uint16 x_subpos = E->base.x_subpos; + bool v2 = __CFADD__uint16(E->sspt_var_A, x_subpos); + uint16 v3 = E->sspt_var_A + x_subpos; + if (v2) + ++E->base.x_pos; + E->base.x_subpos = v3; + uint16 v4 = E->sspt_var_B + E->base.x_pos; + E->base.x_pos = v4; + if ((int16)(v4 - E->sspt_var_01) >= 0) { + E->sspt_var_F = FUNC16(SpikeShootingPlant_2); + E->sspt_var_E = 0; + } + SpikeShootingPlant_4(); +} + +void SpikeShootingPlant_4(void) { // 0xA2A01C + + NextRandom(); + Enemy_SpikeShootingPlant *E = Get_SpikeShootingPlant(cur_enemy_index); + if (sign16((uint8)(LOBYTE(E->base.frame_counter) + random_number) - 3)) { + E->sspt_var_F = FUNC16(nullsub_182); + if (HIBYTE(E->sspt_parameter_1)) + SpikeShootingPlant_6(); + else + SpikeShootingPlant_8(); + } +} + +void SpikeShootingPlant_5(void) { // 0xA2A049 + Enemy_SpikeShootingPlant *E = Get_SpikeShootingPlant(cur_enemy_index); + E->base.current_instruction = addr_kSpikeShootingPlant_Ilist_9E8A; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void SpikeShootingPlant_6(void) { // 0xA2A05C + Enemy_SpikeShootingPlant *E = Get_SpikeShootingPlant(cur_enemy_index); + E->base.current_instruction = addr_kSpikeShootingPlant_Ilist_9EB0; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void SpikeShootingPlant_7(void) { // 0xA2A06F + Enemy_SpikeShootingPlant *E = Get_SpikeShootingPlant(cur_enemy_index); + E->base.current_instruction = addr_kSpikeShootingPlant_Ilist_9EDA; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void SpikeShootingPlant_8(void) { // 0xA2A082 + Enemy_SpikeShootingPlant *E = Get_SpikeShootingPlant(cur_enemy_index); + E->base.current_instruction = addr_kSpikeShootingPlant_Ilist_9F00; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +uint16 SpikeShootingPlant_Instr_A095(uint16 k, uint16 j) { // 0xA2A095 + Enemy_SpikeShootingPlant *E = Get_SpikeShootingPlant(k); + E->sspt_var_F = FUNC16(SpikeShootingPlant_2); + if (E->sspt_var_E) + E->sspt_var_F = FUNC16(SpikeShootingPlant_3); + return j; +} + +uint16 SpikeShootingPlant_Instr_A0A7(uint16 k, uint16 j) { // 0xA2A0A7 + uint16 *v2 = (uint16 *)RomPtr_A2(j); + SpawnEnemyProjectileWithGfx(*v2, cur_enemy_index, addr_kEproj_SpikeShootingPlantSpikes); + return j + 2; +} + +static Func_V *const off_A2A3D3[7] = { // 0xA2A3F9 + MaridiaSpikeyShell_1, MaridiaSpikeyShell_2, + + MaridiaSpikeyShell_3, MaridiaSpikeyShell_4, + MaridiaSpikeyShell_5, MaridiaSpikeyShell_6, + MaridiaSpikeyShell_7, +}; + +void MaridiaSpikeyShell_Init(void) { + + Enemy_MaridiaSpikeyShell *E = Get_MaridiaSpikeyShell(cur_enemy_index); + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A2; + uint16 mssl_parameter_1_low = LOBYTE(E->mssl_parameter_1); + E->mssl_var_E = mssl_parameter_1_low; + off_A2A3D3[mssl_parameter_1_low & 1](); + int v3 = (uint16)(8 * LOBYTE(E->mssl_parameter_2)) >> 1; + E->mssl_var_B = kCommonEnemySpeeds_Linear[v3]; + E->mssl_var_A = kCommonEnemySpeeds_Linear[v3 + 1]; + E->mssl_var_D = kCommonEnemySpeeds_Linear[v3 + 2]; + E->mssl_var_C = kCommonEnemySpeeds_Linear[v3 + 3]; + int v4 = (uint16)(2 * HIBYTE(E->mssl_parameter_2)) >> 1; + E->mssl_var_02 = g_word_A2A3DD[v4] + E->base.x_pos; + E->mssl_var_01 = E->base.x_pos - g_word_A2A3DD[v4]; + E->mssl_var_00 = g_word_A2A3ED[(uint16)(2 * HIBYTE(E->mssl_parameter_1)) >> 1]; + E->mssl_var_F = 0; + if (E->mssl_var_E == 2) { + E->mssl_var_F = 16; + E->base.y_pos += 16; + } +} + +void MaridiaSpikeyShell_Main(void) { // 0xA2A47E + Enemy_MaridiaSpikeyShell *e = Get_MaridiaSpikeyShell(cur_enemy_index); + off_A2A3D3[(int16)e->mssl_var_E + 2](); +} + +void MaridiaSpikeyShell_1(void) { // 0xA2A48A + Enemy_MaridiaSpikeyShell *E = Get_MaridiaSpikeyShell(cur_enemy_index); + E->base.current_instruction = addr_kMaridiaSpikeyShell_Ilist_A3AB; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void MaridiaSpikeyShell_2(void) { // 0xA2A49D + Enemy_MaridiaSpikeyShell *E = Get_MaridiaSpikeyShell(cur_enemy_index); + E->base.current_instruction = addr_kMaridiaSpikeyShell_Ilist_A3BD; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void MaridiaSpikeyShell_3(void) { // 0xA2A4B0 + Enemy_MaridiaSpikeyShell *E = Get_MaridiaSpikeyShell(cur_enemy_index); + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->mssl_var_C, x_subpos); + uint16 v4 = E->mssl_var_C + x_subpos; + if (v3) + ++E->base.x_pos; + E->base.x_subpos = v4; + uint16 v5 = E->mssl_var_D + E->base.x_pos; + E->base.x_pos = v5; + if ((int16)(v5 - E->mssl_var_01) < 0) + --E->mssl_var_E; + MaridiaSpikeyShell_8(cur_enemy_index); +} + +void MaridiaSpikeyShell_4(void) { // 0xA2A4D9 + Enemy_MaridiaSpikeyShell *E = Get_MaridiaSpikeyShell(cur_enemy_index); + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->mssl_var_A, x_subpos); + uint16 v4 = E->mssl_var_A + x_subpos; + if (v3) + ++E->base.x_pos; + E->base.x_subpos = v4; + uint16 v5 = E->mssl_var_B + E->base.x_pos; + E->base.x_pos = v5; + if ((int16)(v5 - E->mssl_var_02) >= 0) + E->mssl_var_E = 0; + MaridiaSpikeyShell_8(cur_enemy_index); +} + +void MaridiaSpikeyShell_5(void) { // 0xA2A502 + Enemy_MaridiaSpikeyShell *E = Get_MaridiaSpikeyShell(cur_enemy_index); + uint16 v1 = E->mssl_var_00 - 1; + E->mssl_var_00 = v1; + if (!v1) + E->mssl_var_E = 4; +} + +void MaridiaSpikeyShell_6(void) { // 0xA2A517 + Enemy_MaridiaSpikeyShell *E = Get_MaridiaSpikeyShell(cur_enemy_index); + ++E->base.y_pos; + if (!sign16(++E->mssl_var_F - 16)) { + E->mssl_var_E = 2; + E->mssl_var_00 = g_word_A2A3ED[(uint16)(2 * HIBYTE(E->mssl_parameter_1)) >> 1]; + } +} + +void MaridiaSpikeyShell_7(void) { // 0xA2A53E + Enemy_MaridiaSpikeyShell *E = Get_MaridiaSpikeyShell(cur_enemy_index); + --E->base.y_pos; + if (E->mssl_var_F-- == 1) + E->mssl_var_E = HIBYTE(random_number) & 1; +} + +void MaridiaSpikeyShell_8(uint16 k) { // 0xA2A553 + NextRandom(); + Enemy_MaridiaSpikeyShell *E = Get_MaridiaSpikeyShell(k); + if (sign16((uint8)(LOBYTE(E->base.frame_counter) + random_number) - 6)) + E->mssl_var_E = 3; +} + +uint16 MaridiaSpikeyShell_Instr_A56D(uint16 k, uint16 j) { // 0xA2A56D + Get_MaridiaSpikeyShell(k)->mssl_var_E = 0; + return j; +} + +uint16 MaridiaSpikeyShell_Instr_A571(uint16 k, uint16 j) { // 0xA2A571 + Get_MaridiaSpikeyShell(k)->mssl_var_E = 1; + return j; +} + +void MaridiaSpikeyShell_Shot(void) { // 0xA2A579 + Enemy_MaridiaSpikeyShell *E = Get_MaridiaSpikeyShell(cur_enemy_index); + if (sign16(E->mssl_var_E - 1)) + Enemy_NormalShotAI_A2(); +} + +void GunshipTop_Init(void) { // 0xA2A644 + Enemy_GunshipTop *E = Get_GunshipTop(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl | kEnemyProps_Tangible; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kGunshipTop_Ilist_A616; + E->base.palette_index = 3584; + if (game_state != 40 || demo_set) { + if (loading_game_state == kLoadingGameState_22_EscapingCeres) { + E->base.y_pos = samus_y_pos - 17; + E->gtp_var_F = FUNC16(GunshipTop_3); + } else { + uint16 v3 = E->base.y_pos - 25; + E->base.y_pos = v3; + E->gtp_var_E = v3; + E->gtp_var_F = FUNC16(GunshipTop_8); + } + } else { + samus_y_pos = 1138; + uint16 v5 = E->base.y_pos - 25; + E->base.y_pos = v5; + E->gtp_var_E = v5; + E->gtp_var_F = FUNC16(GunshipTop_14); + Get_GunshipTop(0)->gtp_var_A = 144; + } + SpawnPalfxObject(addr_stru_8DE1C0); + Get_GunshipTop(cur_enemy_index)->gtp_var_D = 1; + Get_GunshipTop(0)->gtp_var_C = 0; +} + +void GunshipBottom_Init(void) { // 0xA2A6D2 + Enemy_GunshipBottom *E = Get_GunshipBottom(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl | kEnemyProps_Tangible; + E->base.instruction_timer = 1; + E->base.timer = 0; + if (E->gbm_parameter_2) + E->base.current_instruction = addr_kGunshipTop_Ilist_A60E; + else + E->base.current_instruction = addr_kGunshipTop_Ilist_A61C; + int v2 = cur_enemy_index >> 1; + E->base.vram_tiles_index = enemy_drawing_queue[v2 + 106]; + E->base.palette_index = 3584; + if (E->gbm_parameter_2) { + E->base.y_pos = enemy_drawing_queue[v2 + 61] - 1; + if (game_state == kPose_28_FaceL_Crouch && !demo_set) { + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kGunshipTop_Ilist_A5BE; + } + } else if (loading_game_state == kGameState_34_CeresGoesBoom) { + E->base.y_pos = samus_y_pos + 23; + } else { + E->base.y_pos += 15; + E->gbm_var_D = 71; + } + E->gbm_var_F = FUNC16(nullsub_187); +} + +void GunshipTop_Main(void) { // 0xA2A759 + Enemy_GunshipTop *E1 = Get_GunshipTop(cur_enemy_index + 64); + bool v2 = E1->gtp_var_D == 1; + bool v3 = (--E1->gtp_var_D & 0x8000u) != 0; + if (v2 || v3) { + QueueSfx2_Max6(0x4Du); + E1->gtp_var_D = 70; + } + Enemy_GunshipTop *E0 = Get_GunshipTop(cur_enemy_index); + if (!sign16(E0->gtp_var_F + 0x56BE) && sign16(E0->gtp_var_F + 0x53E5)) + GunshipTop_1(cur_enemy_index); + CallEnemyPreInstr(E0->gtp_var_F | 0xA20000); +} + +void GunshipTop_1(uint16 k) { // 0xA2A784 + Enemy_GunshipTop *E0 = Get_GunshipTop(k); + bool v3 = E0->gtp_var_D == 1; + bool v4 = (--E0->gtp_var_D & 0x8000u) != 0; + if (v3 || v4) { + uint16 v5 = 2 * E0->gtp_var_C; + E0->gtp_var_D = g_byte_A2A7CF[v5]; + uint16 v6 = g_byte_A2A7CF[v5 + 1]; + if ((v6 & 0x80) != 0) + v6 |= 0xFF00u; + R18_ = v6; + E0->base.y_pos += v6; + Enemy_GunshipTop *E1 = Get_GunshipTop(k + 64); + E1->base.y_pos += R18_; + Enemy_GunshipTop *E2 = Get_GunshipTop(k + 128); + E2->base.y_pos += R18_; + E0->gtp_var_C = ((uint8)E0->gtp_var_C + 1) & 3; + } +} + +void GunshipTop_2(uint16 k) { // 0xA2A7D8 + samus_y_pos -= 8; + Enemy_GunshipTop *E2 = Get_GunshipTop(k + 128); + E2->base.y_pos -= 8; + Enemy_GunshipTop *E1 = Get_GunshipTop(k + 64); + E1->base.y_pos -= 8; + Enemy_GunshipTop *E0 = Get_GunshipTop(k); + uint16 v4 = E0->base.y_pos - 8; + E0->base.y_pos = v4; + if (sign16(v4 - 128)) + E0->gtp_var_F = FUNC16(GunshipTop_3); +} + +void GunshipTop_3(uint16 k) { // 0xA2A80C + bool v2; // cf + uint16 y_subpos; + uint16 v6; + uint16 v7; + uint16 v9; + uint16 v11; + uint16 v12; + uint16 v13; + + Enemy_GunshipTop *GunshipTop = Get_GunshipTop(k); + if (sign16(GunshipTop->base.y_pos - 768)) { + v2 = __CFADD__uint16(samus_y_subpos, 0x8000); + samus_y_subpos += 0x8000; + samus_y_pos += v2 + 4; + Enemy_GunshipTop *v3 = Get_GunshipTop(k + 128); + y_subpos = v3->base.y_subpos; + v3->base.y_subpos = y_subpos + 0x8000; + v3->base.y_pos += __CFADD__uint16(y_subpos, 0x8000) + 4; + Enemy_GunshipTop *v5 = Get_GunshipTop(k + 64); + v6 = v5->base.y_subpos; + v5->base.y_subpos = v6 + 0x8000; + v5->base.y_pos += __CFADD__uint16(v6, 0x8000) + 4; + v7 = GunshipTop->base.y_subpos; + GunshipTop->base.y_subpos = v7 + 0x8000; + GunshipTop->base.y_pos += __CFADD__uint16(v7, 0x8000) + 4; + } else { + v2 = __CFADD__uint16(samus_y_subpos, 0x8000); + samus_y_subpos += 0x8000; + samus_y_pos += v2 + 2; + Enemy_GunshipTop *v8 = Get_GunshipTop(k + 128); + v9 = v8->base.y_subpos; + v8->base.y_subpos = v9 + 0x8000; + v8->base.y_pos += __CFADD__uint16(v9, 0x8000) + 2; + Enemy_GunshipTop *v10 = Get_GunshipTop(k + 64); + v11 = v10->base.y_subpos; + v10->base.y_subpos = v11 + 0x8000; + v10->base.y_pos += __CFADD__uint16(v11, 0x8000) + 2; + v12 = GunshipTop->base.y_subpos; + GunshipTop->base.y_subpos = v12 + 0x8000; + v13 = __CFADD__uint16(v12, 0x8000) + GunshipTop->base.y_pos + 2; + GunshipTop->base.y_pos = v13; + if (!sign16(v13 - 1119)) { + GunshipTop->base.y_pos = 1119; + v10->base.y_pos = 1159; + v8->base.y_pos = GunshipTop->base.y_pos - 1; + GunshipTop->gtp_var_F = FUNC16(GunshipTop_4); + GunshipTop->gtp_var_E = 0; + } + } +} + + +void GunshipTop_4(uint16 k) { // 0xA2A8D0 + int v2; + uint16 v5; + + Enemy_GunshipTop *GunshipTop = Get_GunshipTop(k); + v2 = (uint16)(2 * GunshipTop->gtp_var_E) >> 1; + samus_y_pos += g_word_A2A622[v2]; + Enemy_GunshipTop *v3 = Get_GunshipTop(k + 128); + v3->base.y_pos += g_word_A2A622[v2]; + Enemy_GunshipTop *v4 = Get_GunshipTop(k + 64); + v4->base.y_pos += g_word_A2A622[v2]; + GunshipTop->base.y_pos += g_word_A2A622[v2]; + v5 = GunshipTop->gtp_var_E + 1; + GunshipTop->gtp_var_E = v5; + if (!sign16(v5 - 17)) { + GunshipTop->gtp_var_F = FUNC16(GunshipTop_5); + GunshipTop->gtp_var_E = GunshipTop->base.y_pos; + GunshipTop->gtp_var_D = 1; + Enemy_GunshipTop *v6 = Get_GunshipTop(0); + v6->gtp_var_C = 0; + samus_x_pos = GunshipTop->base.x_pos + 1; + samus_prev_x_pos = samus_x_pos; + Enemy_GunshipTop *v7 = Get_GunshipTop(k + 128); + v7->base.instruction_timer = 1; + v7->base.current_instruction = addr_kGunshipTop_Ilist_A5BE; + v6->gtp_var_A = 144; + QueueSfx3_Max6(0x14u); + } +} + +void GunshipTop_5(uint16 k) { // 0xA2A942 + Enemy_GunshipTop *E = Get_GunshipTop(0); + bool v2 = E->gtp_var_A == 1; + bool v3 = (--E->gtp_var_A & 0x8000u) != 0; + if (v2 || v3) + Get_GunshipTop(k)->gtp_var_F = FUNC16(GunshipTop_6); +} + +void GunshipTop_6(uint16 k) { // 0xA2A950 + Enemy_GunshipTop *E = Get_GunshipTop(k); + R18_ = E->gtp_var_E - 30; + if (sign16(--samus_y_pos - R18_)) { + E->gtp_var_F = FUNC16(GunshipTop_7); + Enemy_GunshipTop *E2 = Get_GunshipTop(k + 128); + E2->base.instruction_timer = 1; + E2->base.current_instruction = addr_kGunshipTop_Ilist_A5EE; + Get_GunshipTop(0)->gtp_var_A = 144; + QueueSfx3_Max6(0x15u); + } +} + +void GunshipTop_7(uint16 k) { // 0xA2A987 + Enemy_GunshipTop *E = Get_GunshipTop(0); + bool v2 = E->gtp_var_A == 1; + bool v3 = (--E->gtp_var_A & 0x8000u) != 0; + if (v2 || v3) { + Get_GunshipTop(k)->gtp_var_F = FUNC16(GunshipTop_8); + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func11); + frame_handler_beta = FUNC16(Samus_FrameHandlerBeta_Func17); + loading_game_state = kLoadingGameState_5_Main; + *(uint16 *)used_save_stations_and_elevators |= 1u; + load_station_index = 0; + SaveToSram(selected_save_slot); + } +} + +void GunshipTop_8(uint16 k) { // 0xA2A9BD + if (game_state == 8 && frame_handler_alfa == (uint16)FUNC16(Samus_FrameHandlerAlfa_Func11)) { + Enemy_GunshipTop *E = Get_GunshipTop(k); + if ((int16)(E->base.x_pos - 8 - samus_x_pos) < 0 + && (int16)(E->base.x_pos + 8 - samus_x_pos) >= 0 + && (int16)(E->base.y_pos - 64 - samus_y_pos) < 0 + && (int16)(E->base.y_pos - samus_y_pos) >= 0 + && !samus_movement_type + && (joypad1_newkeys & kButton_Down) != 0) { + E->gtp_var_F = FUNC16(GunshipTop_9); + if (samus_x_pos != 1152) { + samus_x_pos = E->base.x_pos; + samus_prev_x_pos = samus_x_pos; + } + MakeSamusFaceForward(); + CallSomeSamusCode(0x1Au); + elevator_status = 0; + uint16 v3 = E->base.y_pos - 1; + Enemy_GunshipTop *E2 = Get_GunshipTop(k + 128); + E2->base.y_pos = v3; + E2->base.instruction_timer = 1; + E2->base.current_instruction = addr_kGunshipTop_Ilist_A5BE; + Get_GunshipTop(0)->gtp_var_A = 144; + QueueSfx3_Max6(0x14u); + } + } +} + +void GunshipTop_9(uint16 k) { // 0xA2AA4F + Enemy_GunshipTop *E = Get_GunshipTop(0); + bool v2 = E->gtp_var_A == 1; + bool v3 = (--E->gtp_var_A & 0x8000u) != 0; + if (v2 || v3) + Get_GunshipTop(k)->gtp_var_F = FUNC16(GunshipTop_10); +} + +void GunshipTop_10(uint16 k) { // 0xA2AA5D + Enemy_GunshipTop *E = Get_GunshipTop(k); + R18_ = E->gtp_var_E + 18; + samus_y_pos += 2; + if (!sign16(samus_y_pos - R18_)) { + E->gtp_var_F = FUNC16(GunshipTop_11); + Enemy_GunshipTop *E2 = Get_GunshipTop(k + 128); + E2->base.instruction_timer = 1; + E2->base.current_instruction = addr_kGunshipTop_Ilist_A5EE; + Get_GunshipTop(0)->gtp_var_A = 144; + QueueSfx3_Max6(0x15u); + } +} + +void GunshipTop_11(uint16 k) { // 0xA2AA94 + Enemy_GunshipTop *E = Get_GunshipTop(0); + bool v2 = E->gtp_var_A == 1; + bool v3 = (--E->gtp_var_A & 0x8000u) != 0; + if (v2 || v3) + Get_GunshipTop(k)->gtp_var_F = FUNC16(GunshipTop_12); +} + +void GunshipTop_12(uint16 k) { // 0xA2AAA2 + if (CheckEventHappened(0xEu)) { + Get_GunshipTop(k)->gtp_var_F = FUNC16(GunshipTop_17); + Enemy_GunshipTop *E = Get_GunshipTop(k + 64); + E->gtp_var_F = 0; + E->gtp_var_E = 0; + substate = 0; + suit_pickup_light_beam_pos = 0; + *(uint16 *)&suit_pickup_color_math_R = 0; + *(uint16 *)&suit_pickup_color_math_B = 0; + CallSomeSamusCode(0xAu); + } else { + Samus_RestoreHealth(2u); + Samus_RestoreMissiles(2u); + Samus_RestoreSuperMissiles(2u); + Samus_RestorePowerBombs(2u); + if ((int16)(samus_reserve_health - samus_max_reserve_health) >= 0 + && (int16)(samus_health - samus_max_health) >= 0 + && (int16)(samus_missiles - samus_max_missiles) >= 0 + && (int16)(samus_super_missiles - samus_max_super_missiles) >= 0 + && (int16)(samus_power_bombs - samus_max_power_bombs) >= 0) { + Get_GunshipTop(k)->gtp_var_F = FUNC16(GunshipTop_13); + } + } +} + +void GunshipTop_13(uint16 k) { // 0xA2AB1F + // Returns rv >= 0 once it's done + int rv = DisplayMessageBox_Poll(0x1c); + if (rv < 0) + return; + + if (rv != 2) { + *(uint16 *)used_save_stations_and_elevators |= 1u; + load_station_index = 0; + SaveToSram(selected_save_slot); + } + Get_GunshipTop(k)->gtp_var_F = FUNC16(GunshipTop_14); + Enemy_GunshipTop *E = Get_GunshipTop(k + 128); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kGunshipTop_Ilist_A5BE; + Get_GunshipTop(0)->gtp_var_A = 144; + QueueSfx3_Max6(0x14u); +} + +void GunshipTop_14(uint16 k) { // 0xA2AB60 + Enemy_GunshipTop *E = Get_GunshipTop(0); + bool v2 = E->gtp_var_A == 1; + bool v3 = (--E->gtp_var_A & 0x8000u) != 0; + if (v2 || v3) + Get_GunshipTop(k)->gtp_var_F = FUNC16(GunshipTop_15); +} + +void GunshipTop_15(uint16 k) { // 0xA2AB6E + Enemy_GunshipTop *E = Get_GunshipTop(k); + R18_ = E->gtp_var_E - 30; + samus_y_pos -= 2; + if (sign16(samus_y_pos - R18_)) { + E->gtp_var_F = FUNC16(GunshipTop_16); + Enemy_GunshipTop *E2 = Get_GunshipTop(k + 128); + E2->base.instruction_timer = 1; + E2->base.current_instruction = addr_kGunshipTop_Ilist_A5EE; + Get_GunshipTop(0)->gtp_var_A = 144; + QueueSfx3_Max6(0x15u); + } +} + +void GunshipTop_16(uint16 k) { // 0xA2ABA5 + Enemy_GunshipTop *E = Get_GunshipTop(0); + bool v2 = E->gtp_var_A == 1; + bool v3 = (--E->gtp_var_A & 0x8000u) != 0; + if (v2 || v3) { + Get_GunshipTop(k)->gtp_var_F = FUNC16(GunshipTop_8); + if (sign16(game_state - kGameState_40_TransitionToDemo)) { + frame_handler_alfa = FUNC16(Samus_FrameHandlerAlfa_Func11); + frame_handler_beta = FUNC16(Samus_FrameHandlerBeta_Func17); + } + } +} + +void GunshipTop_17(uint16 k) { // 0xA2ABC7 + uint16 v1 = substate; + uint16 v2 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 1024; + v2 += 2; + int v3 = v1 >> 1; + gVramWriteEntry(v2)->size = g_word_A2AC07[v3]; + v2 += 2; + LOBYTE(gVramWriteEntry(v2++)->size) = -108; + gVramWriteEntry(v2)->size = g_word_A2AC11[v3]; + vram_write_queue_tail = v2 + 2; + substate += 2; + if (!sign16(substate - 10)) { + Get_GunshipTop(k)->gtp_var_F = FUNC16(GunshipTop_18); + substate = 0; + } +} + +void GunshipTop_18(uint16 k) { // 0xA2AC1B + int16 v5; + + Enemy_GunshipTop *E1 = Get_GunshipTop(k + 64); + uint16 gtp_var_E = E1->gtp_var_E; + if (sign16(gtp_var_E - 64)) { + uint16 v3; + if ((gtp_var_E & 1) != 0) + v3 = samus_y_pos + 1; + else + v3 = samus_y_pos - 1; + samus_y_pos = v3; + samus_prev_y_pos = v3; + } else { + uint16 v4; + if ((gtp_var_E & 1) != 0) + v4 = samus_y_pos + 2; + else + v4 = samus_y_pos - 2; + samus_y_pos = v4; + samus_prev_y_pos = v4; + } + v5 = samus_y_pos - 17; + Enemy_GunshipTop *E0 = Get_GunshipTop(k); + E0->base.y_pos = samus_y_pos - 17; + Get_GunshipTop(k + 128)->base.y_pos = v5 - 1; + E1->base.y_pos = samus_y_pos + 23; + uint16 v7 = E1->gtp_var_E + 1; + E1->gtp_var_E = v7; + if (sign16(v7 - 128)) { + if (v7 == 64) { + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A379, 0); + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A379, 2u); + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A379, 4u); + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A379, 6u); + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A379, 8u); + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A379, 0xAu); + } + } else { + E0->gtp_var_F = FUNC16(GunshipTop_19); + Get_GunshipTop(0)->gtp_var_A = 0; + } +} + +void GunshipTop_19(uint16 k) { // 0xA2ACD7 + int16 v1; + + samus_y_pos -= 2; + v1 = samus_y_pos - 17; + Enemy_GunshipTop *E0 = Get_GunshipTop(k); + E0->base.y_pos = samus_y_pos - 17; + Get_GunshipTop(k + 128)->base.y_pos = v1 - 1; + Enemy_GunshipTop *E1 = Get_GunshipTop(k + 64); + E1->base.y_pos = samus_y_pos + 23; + if (sign16(E0->base.y_pos - 896)) { + E0->gtp_var_F = FUNC16(GunshipTop_20); + E1->gtp_var_F = 512; + } +} + +void GunshipTop_20(uint16 k) { // 0xA2AD0E + GunshipTop_21(k); + Enemy_GunshipTop *E = Get_GunshipTop(k); + if (sign16(E->base.y_pos - 256)) { + E->gtp_var_F = FUNC16(GunshipTop_21); + game_state = 38; + screen_fade_delay = 0; + screen_fade_counter = 0; + } +} + +void GunshipTop_21(uint16 k) { // 0xA2AD2D + int16 v4; + unsigned int v6; // kr00_4 + + Enemy_GunshipTop *E = Get_GunshipTop(k + 64); + uint16 v3 = E->gtp_var_F + 64; + E->gtp_var_F = v3; + if (!sign16((v3 & 0xFF00) - 2560)) + E->gtp_var_F = 2304; + LOBYTE(v4) = HIBYTE(E->gtp_var_F); + HIBYTE(v4) = E->gtp_var_F; + R20_ = v4 & 0xFF00; + R18_ = (uint8)v4; + v6 = __PAIR32__(samus_y_pos, samus_y_subpos) - __PAIR32__((uint8)v4, v4 & 0xFF00); + uint16 v5 = (__PAIR32__(samus_y_pos, samus_y_subpos) - __PAIR32__((uint8)v4, v4 & 0xFF00)) >> 16; + samus_y_subpos = v6; + samus_y_pos = v5; + v5 -= 17; + Get_GunshipTop(k)->base.y_pos = v5; + Get_GunshipTop(k + 128)->base.y_pos = v5 - 1; + E->base.y_pos = samus_y_pos + 23; +} + +void Flies_Init(void) { // 0xA2B06B + Enemy_Flies *E = Get_Flies(cur_enemy_index); + E->flies_var_E = 0; + E->flies_var_F = FUNC16(Flies_4); + E->base.current_instruction = addr_kFlies_Ilist_B013; + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A2; + E->base.instruction_timer = 1; + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A2; +} + +bool CarryAdd16(uint16 *rv, uint16 v) { + int i = *rv + v; + *rv = i; + return (i >> 16); +} + +void Flies_1(uint16 k) { // 0xA2B090 + Enemy_Flies *E = Get_Flies(k); + int v2 = E->flies_var_E >> 1; + bool carry = CarryAdd16(&E->base.x_subpos, LOBYTE(kSinCosTable8bit_Sext[v2 + 64]) << 8); + E->base.x_pos += (int8)HIBYTE(kSinCosTable8bit_Sext[v2 + 64]) + carry; + carry = CarryAdd16(&E->base.y_subpos, LOBYTE(kSinCosTable8bit_Sext[v2]) << 8); + E->base.y_pos += (int8)HIBYTE(kSinCosTable8bit_Sext[v2]) + carry; +} + +uint16 Flies_2(uint16 k) { // 0xA2B0DC + Enemy_Flies *E = Get_Flies(k); + bool carry = CarryAdd16(&E->base.x_subpos, LOBYTE(E->flies_var_B) << 8); + E->base.x_pos += (int8)HIBYTE(E->flies_var_B) + carry; + carry = CarryAdd16(&E->base.y_subpos, LOBYTE(E->flies_var_C) << 8); + uint16 result = E->base.y_pos + (int8)HIBYTE(E->flies_var_C) + carry; + E->base.y_pos = result; + return result; +} + +void Flies_Main(void) { // 0xA2B11F + NextRandom(); + Enemy_Flies *E = Get_Flies(cur_enemy_index); + CallEnemyPreInstr(E->flies_var_F | 0xA20000); +} + +void Flies_3(uint16 k) { // 0xA2B129 + int v1 = (uint16)(2 * CalculateAngleOfSamusFromEnemy(k)) >> 1; + Enemy_Flies *E = Get_Flies(k); + E->flies_var_B = 2 * kSinCosTable8bit_Sext[v1 + 64]; + E->flies_var_C = 4 * kSinCosTable8bit_Sext[v1]; + E->flies_var_D = samus_y_pos; + E->flies_var_F = FUNC16(Flies_6); +} + +void Flies_4(uint16 k) { // 0xA2B14E + Enemy_Flies *E = Get_Flies(k); + uint16 flies_var_A = E->flies_var_A; + if (flies_var_A) { + E->flies_var_A = flies_var_A - 1; + } else if (!(CompareDistToSamus_X(k, 0x70u) & 1)) { + Flies_3(k); + return; + } + Flies_1(k); + bool v3 = ((E->flies_var_E + 32) & 0x1FF) == 0; + E->flies_var_E = (E->flies_var_E + 32) & 0x1FF; + if (v3) + E->flies_var_F = FUNC16(Flies_5); +} + +void Flies_5(uint16 k) { // 0xA2B17C + Enemy_Flies *E = Get_Flies(k); + uint16 flies_var_A = E->flies_var_A; + if (flies_var_A) { + E->flies_var_A = flies_var_A - 1; + } else if (!(CompareDistToSamus_X(k, 0x70u) & 1)) { + Flies_3(k); + return; + } + Flies_1(k); + bool v3 = ((E->flies_var_E - 32) & 0x1FF) == 0; + E->flies_var_E = (E->flies_var_E - 32) & 0x1FF; + if (v3) + E->flies_var_F = FUNC16(Flies_4); +} + +void Flies_6(uint16 k) { // 0xA2B1AA + uint16 v1 = Flies_2(k); + Enemy_Flies *E = Get_Flies(k); + ++E->flies_var_A; + if ((E->flies_var_C & 0x8000u) == 0) { + if (v1 < E->flies_var_D) + return; + goto LABEL_5; + } + if (v1 < E->flies_var_D) { +LABEL_5: + E->flies_var_C = -E->flies_var_C; + E->flies_var_F = FUNC16(Flies_7); + } +} + +void Flies_7(uint16 k) { // 0xA2B1D2 + Flies_2(k); + Enemy_Flies *E = Get_Flies(k); + if ((--E->flies_var_A & 0x8000u) != 0) { + E->flies_var_A = 24; + E->flies_var_F = FUNC16(Flies_4); + } +} + +void NorfairErraticFireball_Init(void) { // 0xA2B3E0 + Enemy_NorfairErraticFireball *E = Get_NorfairErraticFireball(cur_enemy_index); + R18_ = E->nefl_parameter_1; + R20_ = LOBYTE(E->nefl_parameter_2); + ConvertAngleToXy(); + E->nefl_var_C = R22_; + E->nefl_var_D = R24_; + E->nefl_var_E = R26_; + E->nefl_var_F = R28_; + E->base.current_instruction = addr_kNorfairErraticFireball_Ilist_B2DC; +} + +void NorfairErraticFireball_Main(void) { // 0xA2B40F + Enemy_NorfairErraticFireball *E = Get_NorfairErraticFireball(cur_enemy_index); + R18_ = E->nefl_parameter_1; + R20_ = LOBYTE(E->nefl_parameter_2); + ConvertAngleToXy(); + E->nefl_var_C = R22_; + E->nefl_var_D = R24_; + E->nefl_var_E = R26_; + E->nefl_var_F = R28_; + if (((E->nefl_parameter_1 + 64) & 0x80) == 0) { + E->nefl_var_C = ~E->nefl_var_C; + E->nefl_var_D = -E->nefl_var_D; + } + R20_ = E->nefl_var_C; + R18_ = E->nefl_var_D; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->nefl_parameter_1 ^= 0x40u; + } else { + if (((E->nefl_parameter_1 + 128) & 0x80) == 0) { + E->nefl_var_E = ~E->nefl_var_E; + E->nefl_var_F = -E->nefl_var_F; + } + R20_ = E->nefl_var_E; + R18_ = E->nefl_var_F; + if (Enemy_MoveDown(cur_enemy_index) & 1) + E->nefl_parameter_1 ^= 0xC0u; + } +} + +void LavaquakeRocks_Init(void) { // 0xA2B570 + Enemy_LavaquakeRocks *E = Get_LavaquakeRocks(cur_enemy_index); + E->base.current_instruction = addr_kNorfairErraticFireball_Ilist_B51A; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->lrs_var_A = FUNC16(LavaquakeRocks_1); + random_number = 17; +} + +void CallLavaQuakeRocksFunc(uint32 ea) { + switch (ea) { + case fnLavaquakeRocks_1: LavaquakeRocks_1(); return; + case fnLavaquakeRocks_2: LavaquakeRocks_2(); return; + case fnLavaquakeRocks_3: LavaquakeRocks_3(); return; + default: Unreachable(); + } +} + +void LavaquakeRocks_Main(void) { // 0xA2B58F + Enemy_LavaquakeRocks *E = Get_LavaquakeRocks(cur_enemy_index); + CallLavaQuakeRocksFunc(E->lrs_var_A | 0xA20000); +} + +void LavaquakeRocks_1(void) { // 0xA2B596 + if (IsSamusWithinEnemy_X(cur_enemy_index, 0x40u)) { + if (IsSamusWithinEnemy_Y(cur_enemy_index, 0x40u)) + Get_LavaquakeRocks(cur_enemy_index)->lrs_var_A = FUNC16(LavaquakeRocks_2); + } +} + +void LavaquakeRocks_2(void) { // 0xA2B5B2 + enemy_projectile_unk1995 = g_word_A2B550[(uint8)(NextRandom() & 0x1E) >> 1]; + int v1 = (uint8)(NextRandom() & 0x1E) >> 1; + SpawnEnemyProjectileWithGfx(g_word_A2B530[v1], cur_enemy_index, addr_stru_86BD5A); + Enemy_LavaquakeRocks *E = Get_LavaquakeRocks(cur_enemy_index); + E->lrs_var_A = FUNC16(LavaquakeRocks_3); + E->lrs_var_B = g_word_A2B520[(uint16)(NextRandom() & 0xE) >> 1]; +} + +void LavaquakeRocks_3(void) { // 0xA2B5EA + Enemy_LavaquakeRocks *E = Get_LavaquakeRocks(cur_enemy_index); + if ((--E->lrs_var_B & 0x8000u) != 0) + E->lrs_var_A = FUNC16(LavaquakeRocks_1); +} + +void Rinka_Init(void) { // 0xA2B602 + Enemy_Rinka *E = Get_Rinka(cur_enemy_index); + if (E->rinka_parameter_1) { + Rinka_1(cur_enemy_index); + E->base.properties = E->base.properties & ~(kEnemyProps_RespawnIfKilled | kEnemyProps_DisableSamusColl | kEnemyProps_ProcessedOffscreen | kEnemyProps_Tangible) | 0x2C00; + } else { + E->base.properties = E->base.properties & ~(kEnemyProps_RespawnIfKilled | kEnemyProps_DisableSamusColl | kEnemyProps_ProcessedOffscreen | kEnemyProps_Tangible) | 0x6400; + } + E->base.palette_index = 1024; + Rinka_Init3(cur_enemy_index); +} + +void Rinka_Init2(uint16 k) { // 0xA2B63E + EnemySpawnData *v2; + + Enemy_Rinka *E = Get_Rinka(k); + if (E->rinka_parameter_1) + Rinka_1(k); + v2 = gEnemySpawnData(k); + E->base.x_pos = v2->x_pos; + E->base.y_pos = v2->y_pos; + Rinka_Init3(k); +} + +void Rinka_Init3(uint16 k) { // 0xA2B654 + Enemy_Rinka *E = Get_Rinka(k); + E->rinka_var_A = FUNC16(Rinka_5); + E->rinka_var_F = 26; + E->rinka_var_B = 0; + E->rinka_var_C = 0; + if (E->rinka_parameter_1) { + if (Get_Rinka(0)->rinka_var_1D) { + E->base.properties |= kEnemyProps_Deleted; + } else { + E->base.current_instruction = addr_kRinka_Ilist_BA0C; + E->base.instruction_timer = 1; + E->base.timer = 0; + } + } else { + E->base.current_instruction = addr_kRinka_Ilist_B9E0; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void Rinka_1(uint16 k) { // 0xA2B69B + EnemySpawnData *v1; + uint16 v2; + EnemySpawnData *v6; + EnemySpawnData *v13; + + v1 = gEnemySpawnData(k); + R18_ = v1->x_pos; + R20_ = v1->y_pos; + if (Rinka_10() || (v2 = Rinka_2(k), gRam8000_Default(v2)[31].var_3F & 1)) { + uint16 v3 = 0; + do { + int v4 = v3 >> 1; + R18_ = g_word_A2B75B[v4]; + R20_ = g_word_A2B75B[v4 + 1]; + if (!(Rinka_10() & 1) && !(gRam8000_Default(g_word_A2B75B[v4 + 2])[31].var_3F & 1)) { + uint16 v5 = R18_; + v6 = gEnemySpawnData(k); + v6->x_pos = R18_; + Enemy_Rinka *E = Get_Rinka(k); + E->base.x_pos = v5; + uint16 v8 = R20_; + v6->y_pos = R20_; + E->base.y_pos = v8; + uint16 v9 = g_word_A2B75B[(v3 >> 1) + 2]; + gRam8000_Default(v9)[31].var_3F = -1; + Get_Rinka(k)->rinka_var_D = v9; + return; + } + v3 += 6; + } while ((int16)(v3 - 66) < 0); + uint16 v10 = 0; + while (gRam8000_Default(g_word_A2B75B[(v10 >> 1) + 2])[31].var_3F & 1) { + v10 += 6; + if ((int16)(v10 - 66) >= 0) + return; + } + int v11 = v10 >> 1; + uint16 v12 = g_word_A2B75B[v11]; + v13 = gEnemySpawnData(k); + v13->x_pos = v12; + Enemy_Rinka *E = Get_Rinka(k); + E->base.x_pos = v12; + uint16 v15 = g_word_A2B75B[v11 + 1]; + v13->y_pos = v15; + E->base.y_pos = v15; + uint16 v16 = g_word_A2B75B[v11 + 2]; + E->rinka_var_D = v16; + gRam8000_Default(v16)[31].var_3F = -1; + } else { + Get_Rinka(k)->rinka_var_D = v2; + gRam8000_Default(v2)[31].var_3F = -1; + } +} + +uint16 Rinka_2(uint16 k) { // 0xA2B79D + EnemySpawnData *v3; + + uint16 v1 = 0; + while (1) { + int v2 = v1 >> 1; + v3 = gEnemySpawnData(k); + if (g_word_A2B75B[v2] == v3->x_pos && g_word_A2B75B[v2 + 1] == v3->y_pos) + break; + v1 += 6; + if (!sign16(v1 - 66)) { + v1 = 0; + return g_word_A2B75B[(v1 >> 1) + 2]; + } + } + return g_word_A2B75B[(v1 >> 1) + 2]; +} + +void CallRinkaFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnRinka_3: Rinka_3(k); return; + case fnRinka_4: Rinka_4(k); return; + case fnRinka_5: Rinka_5(k); return; + case fnRinka_B85B: Rinka_B85B(k); return; + default: Unreachable(); + } +} + +void Rinka_Main(void) { // 0xA2B7C4 + uint16 v2; + + Enemy_Rinka *E = Get_Rinka(cur_enemy_index); + if (E->rinka_parameter_1 && Get_Rinka(0)->rinka_var_1D) { + Rinka_6(cur_enemy_index); + Rinka_8(cur_enemy_index); + printf("A unknown\n"); v2 = 0; + RinkasDeathAnimation(v2); + } else { + CallRinkaFunc(E->rinka_var_A | 0xA20000, cur_enemy_index); + } +} + +void Rinka_3(uint16 k) { // 0xA2B7DF + Enemy_Rinka *E = Get_Rinka(k); + if ((--E->rinka_var_F & 0x8000u) != 0) { + E->rinka_var_A = FUNC16(Rinka_B85B); + uint16 v3; + if (E->rinka_parameter_1) + v3 = E->base.properties & ~kEnemyProps_Tangible; + else + v3 = E->base.properties & 0xF3FF | 0x800; + E->base.properties = v3; + R18_ = samus_x_pos - E->base.x_pos; + R20_ = samus_y_pos - E->base.y_pos; + R18_ = (uint8)-(int8)(CalculateAngleFromXY() + 0x80); + uint16 v4 = Math_MultBySin(0x120u); + Get_Rinka(cur_enemy_index)->rinka_var_B = v4; + uint16 v5 = Math_MultByCos(0x120u); + Get_Rinka(cur_enemy_index)->rinka_var_C = v5; + } +} + +void Rinka_4(uint16 k) { // 0xA2B844 + Enemy_Rinka *E = Get_Rinka(k); + if ((--E->rinka_var_F & 0x8000u) != 0) { + E->base.health = 10; + Rinka_Init2(k); + } +} + +void Rinka_5(uint16 k) { // 0xA2B852 + if (Rinka_9(k) & 1) + Rinka_B865(k); +} + +void Rinka_B85B(uint16 k) { // 0xA2B85B + MoveEnemyWithVelocity(); + if (Rinka_9(k) & 1) + Rinka_B865(k); +} + +void Rinka_B865(uint16 k) { // 0xA2B865 + if (Get_Rinka(k)->rinka_parameter_1 && (Rinka_8(k), Get_Rinka(0)->rinka_var_1D)) { + Rinka_6(k); + DeleteEnemyAndConnectedEnemies(); + } else { + Rinka_6(k); + Rinka_Init2(k); + } +} + +void Rinka_6(uint16 k) { // 0xA2B880 + int16 v3; + + Enemy_Rinka *E = Get_Rinka(k); + if (E->rinka_parameter_1 && (E->base.properties & kEnemyProps_Invisible) == 0) { + Enemy_Rinka *E0 = Get_Rinka(0); + v3 = E0->rinka_var_1E - 1; + if (v3 < 0) + v3 = 0; + E0->rinka_var_1E = v3; + } +} + +void Rinka_7(uint16 k) { // 0xA2B89C + Enemy_Rinka *E = Get_Rinka(k); + if ((enemy_damage_routine_exec_count & 3) == E->rinka_parameter_1) + E->base.properties &= ~kEnemyProps_Tangible; + else + E->base.properties |= kEnemyProps_Tangible; +} + +void Rinka_8(uint16 k) { // 0xA2B8BB + Enemy_Rinka *E = Get_Rinka(k); + if (E->rinka_parameter_1) { + uint16 rinka_var_D = E->rinka_var_D; + if (rinka_var_D) { + gRam8000_Default(rinka_var_D)[31].var_3F = 0; + Get_Rinka(k)->rinka_var_D = 0; + } + } +} + +uint8 Rinka_9(uint16 k) { // 0xA2B8D3 + int16 y_pos; + int16 v3; + int16 x_pos; + int16 v5; + + Enemy_Rinka *E = Get_Rinka(k); + y_pos = E->base.y_pos; + uint8 result = 1; + if (y_pos >= 0) { + v3 = y_pos + 16 - layer1_y_pos; + if (v3 >= 0) { + if (sign16(v3 - 256)) { + x_pos = E->base.x_pos; + if (x_pos >= 0) { + v5 = x_pos + 16 - layer1_x_pos; + if (v5 >= 0) { + if (sign16(v5 - 288)) + return 0; + } + } + } + } + } + return result; +} + +uint8 Rinka_10(void) { // 0xA2B8FF + return (R20_ & 0x8000u) != 0 + || (int16)(R20_ - layer1_y_pos) < 0 + || !sign16(R20_ - layer1_y_pos - 224) + || (R18_ & 0x8000u) != 0 + || (int16)(R18_ - layer1_x_pos) < 0 + || !sign16(R18_ - layer1_x_pos - 256); +} + +void Rinka_Frozen(uint16 k) { // 0xA2B929 + if (Rinka_9(k) & 1) + Get_Rinka(k)->base.frozen_timer = 0; + NormalEnemyFrozenAI(); + if (Get_Rinka(0)->rinka_var_1D) { + Rinka_6(k); + Rinka_8(k); + printf("A undefined!\n"); + uint16 v1 = 0; + RinkasDeathAnimation(v1); + } +} + +void Rinka_Touch(void) { // 0xA2B947 + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); + Rinka_B960(cur_enemy_index); +} + +void Rinka_Shot(void) { // 0xA2B94D + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + Rinka_B960(cur_enemy_index); +} + +void Rinka_Powerbomb(uint16 k) { // 0xA2B953 + if ((Get_Rinka(k)->base.properties & kEnemyProps_Invisible) == 0) { + NormalEnemyPowerBombAiSkipDeathAnim_CurEnemy(); + Rinka_B960(k); + } +} + +void Rinka_B960(uint16 k) { // 0xA2B960 + Enemy_Rinka *E = Get_Rinka(k); + if (!E->base.health) { + Rinka_6(k); + Rinka_8(k); + if (E->rinka_parameter_1) { + E->base.properties |= kEnemyProps_Tangible | kEnemyProps_Invisible; + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + SpawnEnemyProjectileWithRoomGfx(0xE509u, 3u); + E->rinka_var_A = FUNC16(Rinka_4); + E->rinka_var_F = 1; + } else { + RinkasDeathAnimation(0); + } + } +} + +uint16 Rinka_Instr_B9A2(uint16 k, uint16 j) { // 0xA2B9A2 + Enemy_Rinka *E = Get_Rinka(0); + if (sign16(E->rinka_var_1E - 3)) + return j + 2; + else + return *(uint16 *)RomPtr_A2(j); +} + +uint16 Rinka_Instr_B9B3(uint16 k, uint16 j) { // 0xA2B9B3 + Enemy_Rinka *E = Get_Rinka(k); + E->base.properties |= kEnemyProps_Tangible | kEnemyProps_Invisible; + return j; +} + +uint16 Rinka_Instr_B9BD(uint16 k, uint16 j) { // 0xA2B9BD + Enemy_Rinka *E = Get_Rinka(k); + E->base.properties |= kEnemyProps_ProcessedOffscreen | kEnemyProps_Tangible | kEnemyProps_Invisible; + return j; +} + +uint16 Rinka_Instr_B9C7(uint16 k, uint16 j) { // 0xA2B9C7 + Enemy_Rinka *E = Get_Rinka(k); + E->base.properties &= ~(kEnemyProps_Tangible | kEnemyProps_Invisible); + E->rinka_var_A = FUNC16(Rinka_3); + Enemy_Rinka *E0 = Get_Rinka(0); + ++E0->rinka_var_1E; + return j; +} + +uint16 EnemyInstr_Rio_Instr_1(uint16 k, uint16 j) { // 0xA2BBC3 + Get_Rio(cur_enemy_index)->rio_var_E = 1; + return j; +} + +void Rio_Init(void) { // 0xA2BBCD + Enemy_Rio *E = Get_Rio(cur_enemy_index); + E->rio_var_E = 0; + E->rio_var_F = 0; + E->base.current_instruction = addr_kRio_Ilist_BB4B; + E->rio_var_B = FUNC16(Rio_1); +} + +void CallRioFunc(uint32 ea) { + uint16 k = cur_enemy_index; + switch (ea) { + case fnRio_1: Rio_1(k); return; // 0x7c30a + case fnRio_2: Rio_2(k); return; // 0x7c396 + case fnRio_3: Rio_3(k); return; // 0x7c3d4 + case fnRio_4: Rio_4(k); return; // 0x7c4dc + case fnRio_5: Rio_5(k); return; // 0x7c599 + default: Unreachable(); + } +} + +void Rio_Main(void) { // 0xA2BBE3 + NextRandom(); + Enemy_Rio *E = Get_Rio(cur_enemy_index); + CallRioFunc(E->rio_var_B | 0xA20000); +} + +void Rio_1(uint16 k) { // 0xA2BBED + if (!(CompareDistToSamus_X(k, 0xA0u) & 1)) { + Enemy_Rio *E = Get_Rio(k); + E->rio_var_C = g_word_A2BBBB; + E->rio_var_D = g_word_A2BBBF; + if ((int16)(samus_x_pos - E->base.x_pos) < 0) + E->rio_var_D = -E->rio_var_D; + Rio_6(addr_kRio_Ilist_BB7F); + E->rio_var_B = FUNC16(Rio_3); + if (!CheckIfEnemyIsOnScreen()) + QueueSfx2_Max6(0x65u); + } +} + +void Rio_2(uint16 k) { // 0xA2BC32 + Enemy_Rio *E = Get_Rio(k); + if (E->rio_var_E) { + E->rio_var_E = 0; + Rio_6(addr_stru_A2BB53); + E->rio_var_B = FUNC16(Rio_1); + } +} + +void Rio_3(uint16 k) { // 0xA2BC48 + int16 rio_var_D; + int16 rio_var_C; + int16 v4; + + R18_ = 0; + R20_ = 0; + Enemy_Rio *E = Get_Rio(k); + rio_var_D = E->rio_var_D; + if (rio_var_D < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = rio_var_D; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->rio_var_D = -E->rio_var_D; +LABEL_13: + E->rio_var_C = -E->rio_var_C; + E->rio_var_B = FUNC16(Rio_4); + return; + } + R18_ = 0; + R20_ = 0; + rio_var_C = E->rio_var_C; + if (rio_var_C < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = rio_var_C; + if (Enemy_MoveDown(k) & 1) + goto LABEL_13; + v4 = E->rio_var_C - 24; + E->rio_var_C = v4; + if (v4 < 0) { + E->rio_var_A = E->rio_var_D; + E->rio_var_D = 0; + E->rio_var_C = 0; + E->rio_var_B = FUNC16(Rio_5); + } else if (E->rio_var_E) { + E->rio_var_E = 0; + Rio_6(addr_kRio_Ilist_BB97); + } +} + +void Rio_4(uint16 k) { // 0xA2BCB7 + int16 rio_var_D; + int16 rio_var_C; + + R18_ = 0; + R20_ = 0; + Enemy_Rio *E = Get_Rio(k); + rio_var_D = E->rio_var_D; + if (rio_var_D < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = rio_var_D; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) + E->rio_var_D = -E->rio_var_D; + R18_ = 0; + R20_ = 0; + rio_var_C = E->rio_var_C; + if (rio_var_C < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = rio_var_C; + if (Enemy_MoveDown(k) & 1) { + Rio_6(addr_kRio_Ilist_BBA3); + E->rio_var_B = FUNC16(Rio_2); + } else { + E->rio_var_C -= 24; + } +} + +void Rio_5(uint16 k) { // 0xA2BCFF + int16 rio_var_D; + int16 rio_var_C; + Enemy_Rio *E = Get_Rio(k); + if ((int16)(Get_Rio(k)->base.y_pos - samus_y_pos) >= 0) { + E->rio_var_D = E->rio_var_A; + E->rio_var_C = -1; + E->rio_var_B = FUNC16(Rio_4); + } else { + int v1 = (uint16)(2 * CalculateAngleOfSamusFromEnemy(k)) >> 1; + E->rio_var_D = kSinCosTable8bit_Sext[v1 + 64]; + E->rio_var_C = kSinCosTable8bit_Sext[v1]; + R18_ = 0; + R20_ = 0; + rio_var_D = E->rio_var_D; + if (rio_var_D < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = rio_var_D; + Enemy_MoveRight_IgnoreSlopes(k); + R18_ = 0; + R20_ = 0; + rio_var_C = E->rio_var_C; + if (rio_var_C < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = rio_var_C; + Enemy_MoveDown(k); + } +} + +void Rio_6(uint16 a) { // 0xA2BD54 + Enemy_Rio *E = Get_Rio(cur_enemy_index); + if (a != E->rio_var_F) { + E->rio_var_F = a; + E->base.current_instruction = a; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +uint16 NorfairLavajumpingEnemy_Instr_BE8E(uint16 k, uint16 j) { // 0xA2BE8E + Get_NorfairLavajumpingEnemy(cur_enemy_index)->nley_var_00 = 1; + return j; +} + +void NorfairLavajumpingEnemy_Init(void) { // 0xA2BE99 + Enemy_NorfairLavajumpingEnemy *E = Get_NorfairLavajumpingEnemy(cur_enemy_index); + E->nley_var_00 = 0; + E->nley_var_01 = 0; + if ((E->nley_parameter_1 & 0x8000u) != 0) { + E->base.current_instruction = addr_kNorfairLavajumpingEnemy_Ilist_BE62; + E->nley_var_F = FUNC16(NorfairLavajumpingEnemy_Func_1); + } else { + E->nley_var_D = E->base.x_pos; + E->nley_var_E = E->base.y_pos; + E->base.current_instruction = addr_kNorfairLavajumpingEnemy_Ilist_BE3C; + E->nley_var_F = FUNC16(NorfairLavajumpingEnemy_Func_2); + } +} + +void NorfairLavajumpingEnemy_Main(void) { // 0xA2BED2 + NextRandom(); + Enemy_NorfairLavajumpingEnemy *E = Get_NorfairLavajumpingEnemy(cur_enemy_index); + CallEnemyPreInstr(E->nley_var_F | 0xA20000); +} + +void NorfairLavajumpingEnemy_Func_1(uint16 k) { // 0xA2BEDC + Enemy_NorfairLavajumpingEnemy *E = Get_NorfairLavajumpingEnemy(k); + int v1 = k >> 1; + if (enemy_drawing_queue[v1 + 100]) { + uint16 v3 = enemy_drawing_queue[v1 + 109]; + E->base.frozen_timer = v3; + if (v3 || (enemy_drawing_queue_sizes[v1 + 2] & 0x8000u) == 0) { + E->base.properties |= kEnemyProps_Invisible; + } else { + E->base.properties &= ~kEnemyProps_Invisible; + E->base.y_pos = enemy_drawing_queue[v1 + 93]; + } + } else { + E->base.properties |= kEnemyProps_Deleted; + } +} + +void NorfairLavajumpingEnemy_Func_2(uint16 k) { // 0xA2BF1A + Enemy_NorfairLavajumpingEnemy *E = Get_NorfairLavajumpingEnemy(k); + E->nley_var_C = g_word_A2BE86[(uint16)(HIBYTE(random_number) & 6) >> 1]; + E->nley_var_F = FUNC16(NorfairLavajumpingEnemy_Func_3); + E->base.properties |= kEnemyProps_ProcessedOffscreen; + QueueSfx2_Max6(0xDu); +} + +void NorfairLavajumpingEnemy_Func_3(uint16 k) { // 0xA2BF3E + Enemy_NorfairLavajumpingEnemy *E = Get_NorfairLavajumpingEnemy(k); + int t = E->base.y_subpos + (LOBYTE(E->nley_var_C) << 8); + E->base.y_subpos = t; + E->base.y_pos += (int8)HIBYTE(E->nley_var_C) + (t >> 16); + uint16 v3 = E->nley_var_C + 56; + E->nley_var_C = v3; + if (v3 >= 0xFC00u) { + NorfairLavajumpingEnemy_Func_6(addr_kNorfairLavajumpingEnemy_Ilist_BE42); + E->nley_var_F = FUNC16(NorfairLavajumpingEnemy_Func_4); + } +} + +void NorfairLavajumpingEnemy_Func_4(uint16 k) { // 0xA2BF7C + Enemy_NorfairLavajumpingEnemy *E = Get_NorfairLavajumpingEnemy(k); + int t = E->base.y_subpos + (LOBYTE(E->nley_var_C) << 8); + E->base.y_subpos = t; + E->base.y_pos += (int8)HIBYTE(E->nley_var_C) + (t >> 16); + E->nley_var_C += 56; + if (E->nley_var_00) { + E->nley_var_00 = 0; + E->nley_var_F = FUNC16(NorfairLavajumpingEnemy_Func_5); + } +} + +void NorfairLavajumpingEnemy_Func_5(uint16 k) { // 0xA2BFBC + Enemy_NorfairLavajumpingEnemy *E = Get_NorfairLavajumpingEnemy(k); + int t = E->base.y_subpos + (LOBYTE(E->nley_var_C) << 8); + E->base.y_subpos = t; + E->base.y_pos = E->base.y_pos + (int8)HIBYTE(E->nley_var_C) + (t >> 16); + if ((E->base.y_pos & 0xF0) == 240) { + E->base.x_pos = E->nley_var_D; + E->base.y_pos = E->nley_var_E; + NorfairLavajumpingEnemy_Func_6(addr_kNorfairLavajumpingEnemy_Ilist_BE3C); + E->nley_var_F = FUNC16(NorfairLavajumpingEnemy_Func_2); + E->base.properties &= ~kEnemyProps_ProcessedOffscreen; + } else { + E->nley_var_C += 56; + } +} + +void NorfairLavajumpingEnemy_Func_6(uint16 a) { // 0xA2C012 + Enemy_NorfairLavajumpingEnemy *E = Get_NorfairLavajumpingEnemy(cur_enemy_index); + if (a != E->nley_var_01) { + E->nley_var_01 = a; + E->base.current_instruction = a; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +uint16 NorfairRio_Instr_C1C9(uint16 k, uint16 j) { // 0xA2C1C9 + Get_NorfairRio(cur_enemy_index)->nro_var_01 = 1; + return j; +} + +uint16 NorfairRio_Instr_C1D4(uint16 k, uint16 j) { // 0xA2C1D4 + Get_NorfairRio(cur_enemy_index)->nro_var_02 = 8; + return j; +} + +uint16 NorfairRio_Instr_C1DF(uint16 k, uint16 j) { // 0xA2C1DF + Get_NorfairRio(cur_enemy_index)->nro_var_02 = 8; + return j; +} + +uint16 NorfairRio_Instr_C1EA(uint16 k, uint16 j) { // 0xA2C1EA + Get_NorfairRio(cur_enemy_index)->nro_var_02 = 12; + return j; +} + +uint16 NorfairRio_Instr_C1F5(uint16 k, uint16 j) { // 0xA2C1F5 + Get_NorfairRio(cur_enemy_index)->nro_var_02 = -12; + return j; +} + +uint16 NorfairRio_Instr_C200(uint16 k, uint16 j) { // 0xA2C200 + Get_NorfairRio(cur_enemy_index)->nro_var_02 = 4; + return j; +} + +uint16 NorfairRio_Instr_C20B(uint16 k, uint16 j) { // 0xA2C20B + Get_NorfairRio(cur_enemy_index)->nro_var_02 = 0; + return j; +} + +uint16 NorfairRio_Instr_C216(uint16 k, uint16 j) { // 0xA2C216 + Get_NorfairRio(cur_enemy_index)->nro_var_02 = -4; + return j; +} + +uint16 NorfairRio_Instr_C221(uint16 k, uint16 j) { // 0xA2C221 + Get_NorfairRio(cur_enemy_index)->nro_var_02 = -12; + return j; +} + +uint16 NorfairRio_Instr_C22C(uint16 k, uint16 j) { // 0xA2C22C + Get_NorfairRio(cur_enemy_index)->nro_var_02 = -16; + return j; +} + +uint16 NorfairRio_Instr_C237(uint16 k, uint16 j) { // 0xA2C237 + Get_NorfairRio(cur_enemy_index)->nro_var_02 = 12; + return j; +} + +void NorfairRio_Init(void) { // 0xA2C242 + Enemy_NorfairRio *E = Get_NorfairRio(cur_enemy_index); + E->nro_var_01 = 0; + E->nro_var_02 = 0; + if ((E->nro_parameter_1 & 0x8000u) != 0) { + E->nro_var_00 = addr_kNorfairRio_Ilist_C18F; + E->base.current_instruction = addr_kNorfairRio_Ilist_C18F; + E->nro_var_F = FUNC16(NorfairRio_Func_1); + } else { + E->nro_var_00 = addr_kNorfairRio_Ilist_C0F1; + E->base.current_instruction = addr_kNorfairRio_Ilist_C0F1; + E->nro_var_F = FUNC16(NorfairRio_Func_2); + } +} + +void NorfairRio_Main(void) { // 0xA2C277 + NextRandom(); + Enemy_NorfairRio *E = Get_NorfairRio(cur_enemy_index); + CallEnemyPreInstr(E->nro_var_F | 0xA20000); +} + +void NorfairRio_Func_1(uint16 k) { // 0xA2C281 + Enemy_NorfairRio *E = Get_NorfairRio(k); + EnemySpawnData *v6; + + int v1 = k >> 1; + if (enemy_drawing_queue[v1 + 100]) { + uint16 v3 = enemy_drawing_queue[v1 + 109]; + E->base.frozen_timer = v3; + if (v3 + || (E->base.properties &= ~kEnemyProps_Invisible, + gEnemySpawnData(k)[31].some_flag == (uint16)addr_kNorfairRio_Ilist_C0F1)) { + E->base.properties |= kEnemyProps_Invisible; + } else { + R18_ = addr_kNorfairRio_Ilist_C18F; + v6 = gEnemySpawnData(k); + if ((v6[31].field_4 & 0x8000u) != 0) + R18_ = addr_kNorfairRio_Ilist_C1A3; + NorfairRio_Func_7(R18_); + E->base.properties &= ~kEnemyProps_Invisible; + E->base.x_pos = enemy_drawing_queue[v1 + 91]; + E->base.y_pos = v6[31].field_4 + enemy_drawing_queue[v1 + 93]; + } + } else { + E->base.properties |= kEnemyProps_Deleted; + } +} + +void NorfairRio_Func_2(uint16 k) { // 0xA2C2E7 + Enemy_NorfairRio *E = Get_NorfairRio(k); + if ((random_number & 0x101) != 0 && !(CompareDistToSamus_X(k, 0xC0u) & 1)) { + E->nro_var_A = g_word_A2C1C1[(uint16)((random_number >> 1) & 2) >> 1]; + E->nro_var_B = g_word_A2C1C5; + if ((int16)(samus_x_pos - E->base.x_pos) < 0) + E->nro_var_B = -E->nro_var_B; + NorfairRio_Func_7(addr_kNorfairRio_Ilist_C107); + E->nro_var_F = FUNC16(NorfairRio_Func_3); + } else { + if (E->nro_var_01) { + E->nro_var_01 = 0; + NorfairRio_Func_7(addr_kNorfairRio_Ilist_C0F1); + } + } +} + +void NorfairRio_Func_3(uint16 k) { // 0xA2C33F + Enemy_NorfairRio *E = Get_NorfairRio(k); + if (E->nro_var_01) { + E->nro_var_01 = 0; + NorfairRio_Func_7(addr_kNorfairRio_Ilist_C12F); + E->nro_var_F = FUNC16(NorfairRio_Func_4); + QueueSfx2_Max6(0x65u); + } +} + +void NorfairRio_Func_4(uint16 k) { // 0xA2C361 + int16 nro_var_B; + int16 nro_var_A; + int16 v4; + + R18_ = 0; + R20_ = 0; + Enemy_NorfairRio *E = Get_NorfairRio(k); + nro_var_B = E->nro_var_B; + if (nro_var_B < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = nro_var_B; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) + E->nro_var_B = -E->nro_var_B; + R18_ = 0; + R20_ = 0; + nro_var_A = E->nro_var_A; + if (nro_var_A < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = nro_var_A; + if (Enemy_MoveDown(k) & 1 || (v4 = E->nro_var_A - 32, E->nro_var_A = v4, v4 < 0)) { + E->nro_var_A = -1; + NorfairRio_Func_7(addr_kNorfairRio_Ilist_C145); + E->nro_var_F = FUNC16(NorfairRio_Func_5); + } +} + +void NorfairRio_Func_5(uint16 k) { // 0xA2C3B1 + int16 nro_var_B; + int16 nro_var_A; + + R18_ = 0; + R20_ = 0; + Enemy_NorfairRio *E = Get_NorfairRio(k); + nro_var_B = E->nro_var_B; + if (nro_var_B < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = nro_var_B; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) + E->nro_var_B = -E->nro_var_B; + R18_ = 0; + R20_ = 0; + nro_var_A = E->nro_var_A; + if (nro_var_A < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = nro_var_A; + if (Enemy_MoveDown(k) & 1) { + E->nro_var_F = FUNC16(NorfairRio_Func_6); + } else { + E->nro_var_A -= 32; + if (E->nro_var_01) { + E->nro_var_01 = 0; + NorfairRio_Func_7(addr_kNorfairRio_Ilist_C179); + } + } +} + +void NorfairRio_Func_6(uint16 k) { // 0xA2C406 + Get_NorfairRio(k)->nro_var_F = FUNC16(NorfairRio_Func_2); +} + +void NorfairRio_Func_7(uint16 a) { // 0xA2C40D + Enemy_NorfairRio *E = Get_NorfairRio(cur_enemy_index); + if (a != E->nro_var_00) { + E->nro_var_00 = a; + E->base.current_instruction = a; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +uint16 LowerNorfairRio_Instr_C6D2(uint16 k, uint16 j) { // 0xA2C6D2 + Get_NorfairRio(cur_enemy_index)->nro_var_01 = 1; + return j; +} + +uint16 LowerNorfairRio_Instr_C6DD(uint16 k, uint16 j) { // 0xA2C6DD + Get_NorfairRio(cur_enemy_index)->nro_var_02 = 0; + return j; +} + +uint16 LowerNorfairRio_Instr_C6E8(uint16 k, uint16 j) { // 0xA2C6E8 + Get_NorfairRio(cur_enemy_index)->nro_var_02 = 1; + return j; +} + +void LowerNorfairRio_Init(void) { // 0xA2C6F3 + Enemy_NorfairRio *E = Get_NorfairRio(cur_enemy_index); + E->nro_var_01 = 0; + if ((E->nro_parameter_1 & 0x8000u) == 0) { + E->nro_var_F = FUNC16(LowerNorfairRio_Func_2); + E->nro_var_00 = addr_kLowerNorfairRio_Ilist_C61A; + E->base.current_instruction = addr_kLowerNorfairRio_Ilist_C61A; + } else { + E->nro_var_F = FUNC16(LowerNorfairRio_Func_1); + E->nro_var_00 = addr_kLowerNorfairRio_Ilist_C6B0; + E->base.current_instruction = addr_kLowerNorfairRio_Ilist_C6B0; + } +} + +void LowerNorfairRio_Main(void) { // 0xA2C724 + NextRandom(); + Enemy_LowerNorfairRio *E = Get_LowerNorfairRio(cur_enemy_index); + CallEnemyPreInstr(E->lnro_var_F | 0xA20000); +} + +void LowerNorfairRio_Func_1(uint16 k) { // 0xA2C72E + Enemy_LowerNorfairRio *E = Get_LowerNorfairRio(k); + + int v1 = k >> 1; + if (enemy_drawing_queue[v1 + 100]) { + uint16 v3 = enemy_drawing_queue[v1 + 109]; + E->base.frozen_timer = v3; + if (!v3 && gEnemySpawnData(k)[31].field_4) { + E->base.properties &= ~kEnemyProps_Invisible; + E->base.x_pos = enemy_drawing_queue[v1 + 91]; + E->base.y_pos = enemy_drawing_queue[v1 + 93] + 12; + } else { + E->base.properties |= kEnemyProps_Invisible; + } + } else { + E->base.properties |= kEnemyProps_Deleted; + } +} + +void LowerNorfairRio_Func_2(uint16 k) { // 0xA2C771 + Enemy_NorfairRio *E = Get_NorfairRio(k); + if ((random_number & 0x101) != 0 && !(CompareDistToSamus_X(k, 0x70u) & 1)) { + E->nro_var_C = g_word_A2C6CA; + E->nro_var_D = g_word_A2C6CE; + if ((int16)(samus_x_pos - E->base.x_pos) < 0) + E->nro_var_D = -E->nro_var_D; + LowerNorfairRio_Func_7(addr_kLowerNorfairRio_Ilist_C630); + E->nro_var_F = FUNC16(LowerNorfairRio_Func_3); + } else { + E->nro_var_01 = 0; + LowerNorfairRio_Func_7(addr_kLowerNorfairRio_Ilist_C61A); + } +} + +void LowerNorfairRio_Func_3(uint16 k) { // 0xA2C7BB + Enemy_NorfairRio *E = Get_NorfairRio(k); + if (E->nro_var_01) { + E->nro_var_01 = 0; + LowerNorfairRio_Func_7(addr_kLowerNorfairRio_Ilist_C65A); + E->nro_var_F = FUNC16(LowerNorfairRio_Func_4); + } +} + +void LowerNorfairRio_Func_4(uint16 k) { // 0xA2C7D6 + int16 lnro_var_D; + int16 lnro_var_C; + int16 v4; + + R18_ = 0; + R20_ = 0; + Enemy_LowerNorfairRio *E = Get_LowerNorfairRio(k); + lnro_var_D = E->lnro_var_D; + if (lnro_var_D < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = lnro_var_D; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) + E->lnro_var_D = -E->lnro_var_D; + R18_ = 0; + R20_ = 0; + lnro_var_C = E->lnro_var_C; + if (lnro_var_C < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = lnro_var_C; + if (Enemy_MoveDown(k) & 1 || (v4 = E->lnro_var_C - 32, E->lnro_var_C = v4, v4 < 0)) { + E->lnro_var_C = -1; + LowerNorfairRio_Func_7(addr_kLowerNorfairRio_Ilist_C662); + E->lnro_var_F = FUNC16(LowerNorfairRio_Func_5); + QueueSfx2_Max6(0x64u); + } +} + +void LowerNorfairRio_Func_5(uint16 k) { // 0xA2C82D + int16 nro_var_D; + int16 nro_var_C; + + R18_ = 0; + R20_ = 0; + Enemy_NorfairRio *E = Get_NorfairRio(k); + nro_var_D = E->nro_var_D; + if (nro_var_D < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = nro_var_D; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) + E->nro_var_D = -E->nro_var_D; + R18_ = 0; + R20_ = 0; + nro_var_C = E->nro_var_C; + if (nro_var_C < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = nro_var_C; + if (Enemy_MoveDown(k) & 1) { + LowerNorfairRio_Func_7(addr_kLowerNorfairRio_Ilist_C686); + E->nro_var_F = FUNC16(LowerNorfairRio_Func_6); + } else { + E->nro_var_C -= 32; + if (E->nro_var_01) { + E->nro_var_01 = 0; + LowerNorfairRio_Func_7(addr_kLowerNorfairRio_Ilist_C674); + } + } +} + +void LowerNorfairRio_Func_6(uint16 k) { // 0xA2C888 + Enemy_NorfairRio *E = Get_NorfairRio(k); + if (E->nro_var_01) { + E->nro_var_01 = 0; + LowerNorfairRio_Func_7(addr_kLowerNorfairRio_Ilist_C686); + E->nro_var_F = FUNC16(LowerNorfairRio_Func_2); + } +} + +void LowerNorfairRio_Func_7(uint16 a) { // 0xA2C8A3 + Enemy_NorfairRio *E = Get_NorfairRio(cur_enemy_index); + if (a != E->nro_var_00) { + E->nro_var_00 = a; + E->base.current_instruction = a; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +uint16 MaridiaLargeSnail_Instr_CB6B(uint16 k, uint16 j) { // 0xA2CB6B + QueueSfx2_Max6(0xEu); + return j; +} + +uint16 MaridiaLargeSnail_Instr_CCB3(uint16 k, uint16 j) { // 0xA2CCB3 + Get_MaridiaLargeSnail(cur_enemy_index)->mlsl_var_02 = 1; + return j; +} + +uint16 MaridiaLargeSnail_Instr_CCBE(uint16 k, uint16 j) { // 0xA2CCBE + Get_MaridiaLargeSnail(cur_enemy_index)->mlsl_var_03 = 1; + return j; +} + +uint16 MaridiaLargeSnail_Instr_CCC9(uint16 k, uint16 j) { // 0xA2CCC9 + Get_MaridiaLargeSnail(cur_enemy_index)->mlsl_var_03 = 0; + return j; +} + +void MaridiaLargeSnail_Init(void) { // 0xA2CCD4 + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(cur_enemy_index); + E->mlsl_var_B = 0; + E->mlsl_var_D = 0; + E->mlsl_var_00 = 0; + E->mlsl_var_01 = 0; + E->mlsl_var_02 = 0; + E->mlsl_var_03 = 0; + E->mlsl_var_0A = 0; + E->mlsl_var_E = 3; + E->mlsl_var_C = 128; + E->base.current_instruction = addr_kMaridiaLargeSnail_Ilist_CA4B; + E->mlsl_var_A = FUNC16(MaridiaLargeSnail_Func_4); + E->mlsl_var_F = FUNC16(MaridiaLargeSnail_Func_7); +} + + +void CallMaridiaLargeSnailFunc(uint32 ea) { + switch (ea) { + case fnMaridiaLargeSnail_Func_4: MaridiaLargeSnail_Func_4(); return; + case fnMaridiaLargeSnail_Func_5: MaridiaLargeSnail_Func_5(); return; + case fnMaridiaLargeSnail_Func_6: MaridiaLargeSnail_Func_6(); return; + default: Unreachable(); + } +} +void MaridiaLargeSnail_Main(void) { // 0xA2CD13 + MaridiaLargeSnail_Func_1(cur_enemy_index); + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(cur_enemy_index); + CallMaridiaLargeSnailFunc(E->mlsl_var_A | 0xA20000); + MaridiaLargeSnail_Func_2(cur_enemy_index); + MaridiaLargeSnail_Func_3(cur_enemy_index); +} + +void MaridiaLargeSnail_Func_1(uint16 k) { // 0xA2CD23 + MaridiaLargeSnail_Func_11(); + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(k); + E->mlsl_var_06 = E->base.x_pos; + E->mlsl_var_08 = E->base.y_pos; +} + +void MaridiaLargeSnail_Func_2(uint16 k) { // 0xA2CD35 + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(k); + E->mlsl_var_0B = 0; + if (CheckIfEnemyTouchesSamus(k)) + extra_samus_y_displacement = E->base.y_pos - E->mlsl_var_08; + if (E->mlsl_var_04) { + R18_ = E->base.x_pos - E->mlsl_var_06; + if ((R18_ & 0x8000u) != 0) { + if (!E->mlsl_var_05) + return; + } else if (E->mlsl_var_05) { + return; + } + extra_samus_x_displacement += R18_; + } +} + +void MaridiaLargeSnail_Func_3(uint16 k) { // 0xA2CD77 + int16 v2; + + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(k); + if (E->mlsl_var_04) { + v2 = E->base.x_pos - E->mlsl_var_06; + if (!v2) { + if (E->mlsl_var_05) { + if (!E->mlsl_var_D || (joypad1_lastkeys & 0x100) == 0) + return; + } else if (E->mlsl_var_D || (joypad1_lastkeys & 0x200) == 0) { + return; + } + E->mlsl_var_0B = 1; + E->base.x_pos = E->mlsl_var_06; + return; + } + if (v2 < 0) { + if ((joypad1_lastkeys & 0x100) != 0) { + E->mlsl_var_0B = 1; + E->base.x_pos = E->mlsl_var_06; + } + } else if ((joypad1_lastkeys & 0x200) != 0) { + E->mlsl_var_0B = 1; + E->base.x_pos = E->mlsl_var_06; + } + } +} + +void MaridiaLargeSnail_Func_4(void) { // 0xA2CDE6 + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(cur_enemy_index); + if (E->mlsl_var_E) { + CallEnemyPreInstr(E->mlsl_var_F | 0xA20000); + } else { + E->mlsl_var_00 = 0; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) != 0) { + E->mlsl_var_D = 1; + E->mlsl_var_00 = 1; + } + MaridiaLargeSnail_Func_10(cur_enemy_index); + if (IsSamusWithinEnemy_X(cur_enemy_index, 0x18u)) { + E->mlsl_var_00 |= 2u; + MaridiaLargeSnail_Func_10(cur_enemy_index); + E->mlsl_var_A = FUNC16(MaridiaLargeSnail_Func_5); + } + } +} + +void MaridiaLargeSnail_Func_5(void) { // 0xA2CE2B + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(cur_enemy_index); + if (E->mlsl_var_E) { + CallEnemyPreInstr(E->mlsl_var_F | 0xA20000); + } else { + R18_ = 0; + R20_ = 1; + if (!(Enemy_MoveDown(cur_enemy_index) & 1)) { + E->mlsl_var_B = 0; + E->mlsl_var_F = FUNC16(MaridiaLargeSnail_Func_7); + E->mlsl_var_E = 3; + } + } + if (!E->mlsl_var_0B) { + R36 = 0; + bool v4 = (--E->mlsl_var_C & 0x8000u) != 0; + if (v4 && (E->mlsl_var_C = 0, IsSamusWithinEnemy_X(cur_enemy_index, 0x20u)) && E->mlsl_var_03 && !E->mlsl_var_E) { + E->mlsl_var_00 = 0; + E->mlsl_var_D = 0; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) != 0) { + E->mlsl_var_00 = 1; + E->mlsl_var_D = 1; + } + E->mlsl_var_C = 128; + E->mlsl_var_00 = E->mlsl_var_00 & 1 | 4; + MaridiaLargeSnail_Func_10(cur_enemy_index); + E->mlsl_var_A = FUNC16(MaridiaLargeSnail_Func_6); + } else { + uint16 v5 = 128; + if (E->mlsl_var_D) + v5 = 132; + int v6 = v5 >> 1; + R18_ = kCommonEnemySpeeds_Linear[v6 + 1]; + R20_ = kCommonEnemySpeeds_Linear[v6]; + if (E->mlsl_var_04 && E->mlsl_var_D == E->mlsl_var_05) { + if (E->mlsl_var_D) + R20_ -= 16; + else + R20_ += 16; + } + if (Enemy_MoveRight_SlopesAsWalls(cur_enemy_index) & 1) + ++R36; + if (E->mlsl_var_04 && E->mlsl_var_D == E->mlsl_var_05) { + uint16 v7; + if (E->mlsl_var_D) + v7 = E->base.x_pos + 16; + else + v7 = E->base.x_pos - 16; + E->base.x_pos = v7; + } + if (R36) { + E->mlsl_var_D ^= 1u; + E->mlsl_var_00 ^= 4u; + MaridiaLargeSnail_Func_10(cur_enemy_index); + } + } + } +} + +void MaridiaLargeSnail_Func_6(void) { // 0xA2CF40 + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(cur_enemy_index); + if (E->mlsl_var_02) { + E->mlsl_var_02 = 0; + E->mlsl_var_00 -= 2; + MaridiaLargeSnail_Func_10(cur_enemy_index); + E->mlsl_var_A = FUNC16(MaridiaLargeSnail_Func_5); + } +} + +void MaridiaLargeSnail_Func_7(uint16 k) { // 0xA2CF66 + int16 v2; + int16 v3; + char v4; // t0 + int16 v6; + + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(k); + v2 = E->mlsl_var_B + 384; + if (!sign16(E->mlsl_var_B - 16000)) + v2 = 0x4000; + E->mlsl_var_B = v2; + v3 = v2 & 0xFF00; + v4 = v3; + LOBYTE(v3) = HIBYTE(v3); + HIBYTE(v3) = v4; + int v5 = (uint16)(8 * v3) >> 1; + R18_ = kCommonEnemySpeeds_Quadratic[v5]; + R20_ = kCommonEnemySpeeds_Quadratic[v5 + 1]; + if (Enemy_MoveDown(k) & 1) { + --E->mlsl_var_E; + v6 = E->mlsl_var_B - 4096; + if (v6 < 0) + E->mlsl_var_E = 0; + E->mlsl_var_B = v6; + E->mlsl_var_F = FUNC16(MaridiaLargeSnail_Func_8); + } +} + +void MaridiaLargeSnail_Func_8(uint16 k) { // 0xA2CFA9 + int16 v2; + int16 v3; + char v4; // t0 + + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(k); + v2 = E->mlsl_var_B - 384; + E->mlsl_var_B = v2; + if (v2 >= 0) { + v3 = v2 & 0x7F00; + v4 = v3; + LOBYTE(v3) = HIBYTE(v3); + HIBYTE(v3) = v4; + int v5 = (uint16)(8 * v3) >> 1; + R18_ = kCommonEnemySpeeds_Quadratic[v5 + 2]; + R20_ = kCommonEnemySpeeds_Quadratic[v5 + 3]; + Enemy_MoveDown(k); + } else { + E->mlsl_var_B = 0; + E->mlsl_var_F = FUNC16(MaridiaLargeSnail_Func_7); + } +} +// 7DD25: mask 0xFF00 is shortened because ax.2 <= 0x7FFF + +void MaridiaLargeSnail_Func_9(void) { // 0xA2CFD7 + QueueSfx2_Max6(0x63u); +} + +void MaridiaLargeSnail_Func_10(uint16 k) { // 0xA2CFDF + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(k); + uint16 mlsl_var_00 = E->mlsl_var_00; + if (mlsl_var_00 != E->mlsl_var_01) { + E->mlsl_var_01 = mlsl_var_00; + E->base.current_instruction = g_off_A2CB77[mlsl_var_00]; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void MaridiaLargeSnail_Func_11(void) { // 0xA2CFFF + Enemy_MaridiaLargeSnail *E = Get_MaridiaLargeSnail(cur_enemy_index); + E->mlsl_var_04 = 0; + E->mlsl_var_05 = 0; + if (IsSamusWithinEnemy_Y(cur_enemy_index, 0x20u) && IsSamusWithinEnemy_X(cur_enemy_index, 0x18u)) { + E->mlsl_var_04 = 1; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) != 0) + E->mlsl_var_05 = 1; + } +} + +void MaridiaLargeSnail_Func_12(void) { // 0xA2D388 + Enemy_NormalTouchAI_A2(); + MaridiaLargeSnail_Touch(cur_enemy_index); +} + +void MaridiaLargeSnail_Touch(uint16 k) { // 0xA2D38C + if (!CheckIfEnemyTouchesSamus(k)) { + if ((int16)(samus_x_pos - Get_MaridiaLargeSnail(cur_enemy_index)->base.x_pos) < 0) + extra_samus_x_displacement -= 4; + else + extra_samus_x_displacement += 4; + } +} + +void MaridiaLargeSnail_Shot(void) { // 0xA2D3B4 + NormalEnemyShotAi(); + QueueSfx2_Max6(0x57u); +} + +void HirisingSlowfalling_Init(void) { // 0xA2DF76 + HirisingSlowfalling_Func_3(addr_kHirisingSlowfalling_Ilist_D82C); + Enemy_HirisingSlowfalling *E = Get_HirisingSlowfalling(cur_enemy_index); + E->hsg_var_A = FUNC16(HirisingSlowfalling_Func_4); + E->hsg_var_00 = E->base.x_pos; + E->hsg_var_01 = E->base.y_pos; + int v2 = (uint16)(2 * HIBYTE(E->hsg_parameter_1)) >> 1; + E->hsg_var_E = g_off_A2DF5E[v2]; + E->hsg_var_F = *(uint16 *)RomPtr_A2(g_off_A2DF6A[v2]); + HirisingSlowfalling_Func_1(cur_enemy_index); + HirisingSlowfalling_Func_2(cur_enemy_index); + E->hsg_var_03 = E->hsg_var_01 - R18_; + E->hsg_var_02 = E->hsg_var_00; + E->hsg_var_B = E->hsg_var_06; +} + +void HirisingSlowfalling_Func_1(uint16 k) { // 0xA2DFCE + Enemy_HirisingSlowfalling *E = Get_HirisingSlowfalling(k); + R18_ = Mult8x8(E->hsg_parameter_1, E->hsg_var_F); +} + +void HirisingSlowfalling_Func_2(uint16 k) { // 0xA2DFE9 + R20_ = 0; + R22_ = 0; + R24_ = 0; + do { + R24_ += 512; + int v1 = (uint16)(8 * (uint8)((uint16)(R24_ & 0xFF00) >> 8)) >> 1; + uint16 v2 = kCommonEnemySpeeds_Quadratic[v1] + R20_; + if (__CFADD__uint16(kCommonEnemySpeeds_Quadratic[v1], R20_)) + ++R22_; + R20_ = v2; + R22_ += kCommonEnemySpeeds_Quadratic[v1 + 1]; + } while (sign16(R22_ - R18_)); + Get_HirisingSlowfalling(k)->hsg_var_06 = R24_; +} + +void HirisingSlowfalling_Func_3(uint16 a) { // 0xA2E01E + Enemy_HirisingSlowfalling *E = Get_HirisingSlowfalling(cur_enemy_index); + E->base.current_instruction = a; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void CallHirisingSlowfalling(uint32 ea) { + switch (ea) { + case fnHirisingSlowfalling_Func_4: HirisingSlowfalling_Func_4(); return; + case fnHirisingSlowfalling_Func_5: HirisingSlowfalling_Func_5(); return; + case fnHirisingSlowfalling_Func_6: HirisingSlowfalling_Func_6(); return; + case fnHirisingSlowfalling_Func_7: HirisingSlowfalling_Func_7(); return; + default: Unreachable(); + } +} + +void HirisingSlowfalling_Main(void) { // 0xA2E02E + Enemy_HirisingSlowfalling *E = Get_HirisingSlowfalling(cur_enemy_index); + CallHirisingSlowfalling(E->hsg_var_A | 0xA20000); +} + +void HirisingSlowfalling_Func_4(void) { // 0xA2E035 + if (IsSamusWithinEnemy_X(cur_enemy_index, 0x50u)) { + Enemy_HirisingSlowfalling *E = Get_HirisingSlowfalling(cur_enemy_index); + E->hsg_var_07 = E->hsg_parameter_2; + E->hsg_var_A = FUNC16(HirisingSlowfalling_Func_5); + } +} + +void HirisingSlowfalling_Func_5(void) { // 0xA2E04F + int16 v1; + + Enemy_HirisingSlowfalling *E = Get_HirisingSlowfalling(cur_enemy_index); + v1 = E->hsg_var_07 - 1; + E->hsg_var_07 = v1; + if (v1 < 0) { + HirisingSlowfalling_Func_3(addr_kHirisingSlowfalling_Ilist_D834); + E->hsg_var_A = FUNC16(HirisingSlowfalling_Func_6); + } +} + +void HirisingSlowfalling_Func_6(void) { // 0xA2E06A + int16 v5; + + Enemy_HirisingSlowfalling *E = Get_HirisingSlowfalling(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + int v2 = (uint16)(8 * HIBYTE(E->hsg_var_B)) >> 1; + bool v3 = __CFADD__uint16(kCommonEnemySpeeds_Quadratic[v2 + 2], y_subpos); + uint16 v4 = kCommonEnemySpeeds_Quadratic[v2 + 2] + y_subpos; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v4; + E->base.y_pos += kCommonEnemySpeeds_Quadratic[v2 + 3]; + v5 = E->hsg_var_B - 512; + E->hsg_var_B = v5; + if (v5 < 0) { + uint16 hsg_var_02 = E->hsg_var_02; + E->base.x_pos = hsg_var_02; + E->hsg_var_04 = hsg_var_02; + uint16 hsg_var_03 = E->hsg_var_03; + E->base.y_pos = hsg_var_03; + E->hsg_var_05 = hsg_var_03; + E->hsg_var_C = 0; + E->hsg_var_D = LOBYTE(E->hsg_parameter_1) - 1; + HirisingSlowfalling_Func_3(addr_kHirisingSlowfalling_Ilist_D840); + E->hsg_var_A = FUNC16(HirisingSlowfalling_Func_7); + } +} + +void HirisingSlowfalling_Func_7(void) { // 0xA2E0CD + Enemy_HirisingSlowfalling *E = Get_HirisingSlowfalling(cur_enemy_index); + uint8 *v1 = RomPtr_A2(E->hsg_var_E + 4 * HIBYTE(E->hsg_var_C)); + if (*(uint16 *)v1 == 0x8000) { + E->hsg_var_05 += E->hsg_var_F; + E->hsg_var_C = 0; + if ((--E->hsg_var_D & 0x8000u) != 0) { + E->hsg_var_B = E->hsg_var_06; + E->base.x_pos = E->hsg_var_00; + E->base.x_subpos = 0; + E->base.y_pos = E->hsg_var_01; + E->base.y_subpos = 0; + HirisingSlowfalling_Func_3(addr_kHirisingSlowfalling_Ilist_D82C); + E->hsg_var_A = FUNC16(HirisingSlowfalling_Func_4); + } + } else { + E->base.x_pos = *(uint16 *)v1 + E->hsg_var_04; + E->base.y_pos = *((uint16 *)v1 + 1) + E->hsg_var_05; + E->hsg_var_C += 256; + } +} + +void Gripper_Init(void) { // 0xA2E1D3 + Enemy_Gripper *E = Get_Gripper(cur_enemy_index); + uint16 v1 = 8 * LOBYTE(E->base.current_instruction); + E->gripper_var_E = v1; + int v2 = v1 >> 1; + uint16 v3; + if ((E->base.current_instruction & 0xFEFF) != 0) { + E->gripper_var_D = kCommonEnemySpeeds_Linear[v2]; + v3 = kCommonEnemySpeeds_Linear[v2 + 1]; + } else { + E->gripper_var_D = kCommonEnemySpeeds_Linear[v2 + 2]; + v3 = kCommonEnemySpeeds_Linear[v2 + 3]; + } + E->gripper_var_C = v3; + uint16 v4 = addr_kGripper_Ilist_E19B; + if ((E->gripper_var_D & 0x8000u) == 0) + v4 = addr_kGripper_Ilist_E1AF; + E->base.current_instruction = v4; + E->gripper_var_A = E->gripper_parameter_1; + E->gripper_var_B = E->gripper_parameter_2; +} + +void Gripper_Main(void) { // 0xA2E221 + Enemy_Gripper *E = Get_Gripper(cur_enemy_index); + R18_ = E->gripper_var_C; + R20_ = E->gripper_var_D; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1 || Gripper_Func_1(cur_enemy_index) & 1 || Gripper_Func_2(cur_enemy_index) & 1) { + int v3 = E->gripper_var_E >> 1; + uint16 v4; + if ((E->gripper_var_D & 0x8000u) == 0) { + E->gripper_var_D = kCommonEnemySpeeds_Linear[v3 + 2]; + E->gripper_var_C = kCommonEnemySpeeds_Linear[v3 + 3]; + v4 = addr_kGripper_Ilist_E19B; + } else { + E->gripper_var_D = kCommonEnemySpeeds_Linear[v3]; + E->gripper_var_C = kCommonEnemySpeeds_Linear[v3 + 1]; + v4 = addr_kGripper_Ilist_E1AF; + } + E->base.current_instruction = v4; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +uint8 Gripper_Func_1(uint16 k) { // 0xA2E279 + Enemy_Gripper *E = Get_Gripper(k); + return (E->gripper_var_D & 0x8000u) != 0 && (int16)(E->base.x_pos - E->gripper_var_A) < 0; +} + +uint8 Gripper_Func_2(uint16 k) { // 0xA2E28A + Enemy_Gripper *E = Get_Gripper(k); + return (E->gripper_var_D & 0x8000u) == 0 && (int16)(E->base.x_pos - E->gripper_var_B) >= 0; +} + +void Gripper_Func_3(void) { // 0xA2E29B + Enemy_NormalFrozenAI_A2(); +} + +void Gripper_Func_4(void) { // 0xA2E2A4 + NormalEnemyShotAi(); + Enemy_Gripper *E = Get_Gripper(cur_enemy_index); + if (E->base.frozen_timer) { + uint16 v1 = addr_kGripper_Sprmap_E43F; + if ((E->gripper_var_D & 0x8000u) == 0) + v1 = addr_kGripper_Sprmap_E44B; + E->base.spritemap_pointer = v1; + } +} + +void JetPowerRipper_Init(void) { // 0xA2E318 + uint16 v0 = addr_kRipper_Ilist_E2E0; + Enemy_JetPowerRipper *E = Get_JetPowerRipper(cur_enemy_index); + if (E->jprr_parameter_2) + v0 = addr_kRipper_Ilist_E2F4; + E->base.current_instruction = v0; + uint16 v2 = 8 * E->jprr_parameter_1; + E->jprr_var_E = v2; + int v3 = v2 >> 1; + uint16 v4; + if (E->jprr_parameter_2) { + E->jprr_var_D = kCommonEnemySpeeds_Linear[v3]; + v4 = kCommonEnemySpeeds_Linear[v3 + 1]; + } else { + E->jprr_var_D = kCommonEnemySpeeds_Linear[v3 + 2]; + v4 = kCommonEnemySpeeds_Linear[v3 + 3]; + } + E->jprr_var_C = v4; +} + +void JetPowerRipper_Main(void) { // 0xA2E353 + int16 v3; + + Enemy_JetPowerRipper *E = Get_JetPowerRipper(cur_enemy_index); + R18_ = E->jprr_var_C; + R20_ = E->jprr_var_D; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + int v2 = E->jprr_var_E >> 1; + if ((E->jprr_var_D & 0x8000u) == 0) { + E->jprr_var_D = kCommonEnemySpeeds_Linear[v2 + 2]; + E->jprr_var_C = kCommonEnemySpeeds_Linear[v2 + 3]; + v3 = -7456; + } else { + E->jprr_var_D = kCommonEnemySpeeds_Linear[v2]; + E->jprr_var_C = kCommonEnemySpeeds_Linear[v2 + 1]; + v3 = -7436; + } + E->base.current_instruction = v3; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void Ripper_Func_1(void) { // 0xA2E3A0 + Enemy_NormalFrozenAI_A2(); +} + +void JetPowerRipper_Shot(void) { // 0xA2E3A9 + int16 v1; + + NormalEnemyShotAi(); + Enemy_JetPowerRipper *E = Get_JetPowerRipper(cur_enemy_index); + if (E->base.frozen_timer) { + v1 = -7105; + if ((E->jprr_var_D & 0x8000u) == 0) + v1 = -7093; + E->base.spritemap_pointer = v1; + } +} + +void Ripper_Init(void) { // 0xA2E49F + uint16 v0 = addr_kRipper_Ilist_E477; + Enemy_Ripper *E = Get_Ripper(cur_enemy_index); + if (!E->ripper_parameter_2) + v0 = addr_kRipper_Ilist_E48B; + E->base.current_instruction = v0; + uint16 v2 = 8 * E->ripper_parameter_1; + E->ripper_var_E = v2; + int v3 = v2 >> 1; + uint16 v4; + if (E->ripper_parameter_2) { + E->ripper_var_D = kCommonEnemySpeeds_Linear[v3]; + v4 = kCommonEnemySpeeds_Linear[v3 + 1]; + } else { + E->ripper_var_D = kCommonEnemySpeeds_Linear[v3 + 2]; + v4 = kCommonEnemySpeeds_Linear[v3 + 3]; + } + E->ripper_var_C = v4; +} + +void Ripper_Main(void) { // 0xA2E4DA + int16 v3; + + Enemy_Ripper *E = Get_Ripper(cur_enemy_index); + R18_ = E->ripper_var_C; + R20_ = E->ripper_var_D; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + int v2 = E->ripper_var_E >> 1; + if ((E->ripper_var_D & 0x8000u) == 0) { + E->ripper_var_D = kCommonEnemySpeeds_Linear[v2 + 2]; + E->ripper_var_C = kCommonEnemySpeeds_Linear[v2 + 3]; + v3 = -7029; + } else { + E->ripper_var_D = kCommonEnemySpeeds_Linear[v2]; + E->ripper_var_C = kCommonEnemySpeeds_Linear[v2 + 1]; + v3 = -7049; + } + E->base.current_instruction = v3; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +uint16 LavaSeahorse_Instr_E5FB(uint16 k, uint16 j) { // 0xA2E5FB + Get_LavaSeahorse(cur_enemy_index)->lse_var_02 = 1; + return j; +} + +void LavaSeahorse_Init(void) { // 0xA2E606 + Enemy_LavaSeahorse *E = Get_LavaSeahorse(cur_enemy_index); + E->lse_var_02 = 0; + if (E->lse_parameter_1) { + E->lse_var_00 = 2; + E->lse_var_01 = 2; + E->base.current_instruction = addr_kLavaSeahorse_Ilist_E5A1; + E->base.properties |= kEnemyProps_Tangible; + E->lse_var_F = FUNC16(nullsub_196); + } else { + E->lse_var_00 = 0; + E->lse_var_01 = 0; + E->base.current_instruction = addr_kLavaSeahorse_Ilist_E59B; + E->lse_var_F = FUNC16(LavaSeahorse_Func_1); + } +} + +void LavaSeahorse_Main(void) { // 0xA2E64E + Enemy_LavaSeahorse *E = Get_LavaSeahorse(cur_enemy_index); + CallEnemyPreInstr(E->lse_var_F | 0xA20000); +} + +void LavaSeahorse_Func_1(uint16 k) { // 0xA2E654 + Enemy_LavaSeahorse *E = Get_LavaSeahorse(k); + if ((--E->lse_var_D & 0x8000u) != 0) { + E->lse_var_D = 48; + E->lse_var_F = FUNC16(LavaSeahorse_Func_2); + uint16 t = GetSamusEnemyDelta_X(k); + E->lse_var_A = (E->lse_var_A & 0x7fff) | (t & 0x8000); + if ((E->lse_var_A & 0x8000u) != 0) { + LOBYTE(E->lse_var_00) &= ~1u; + Enemy_LavaSeahorse *E1 = Get_LavaSeahorse(k + 64); + LOBYTE(E1->lse_var_00) &= ~1u; + } else { + LOBYTE(E->lse_var_00) |= 1u; + Enemy_LavaSeahorse *E1 = Get_LavaSeahorse(k + 64); + LOBYTE(E1->lse_var_00) |= 1u; + } + LavaSeahorse_Func_6(); + LavaSeahorse_Func_7(); + } +} + +void LavaSeahorse_Func_2(uint16 k) { // 0xA2E6AD + Enemy_LavaSeahorse *E = Get_LavaSeahorse(k); + if ((--E->lse_var_D & 0x8000u) != 0) { + E->lse_var_00 += 4; + E->lse_var_D = 3; + E->lse_var_F = FUNC16(LavaSeahorse_Func_3); + } + --E->base.y_pos; + Enemy_LavaSeahorse *E1 = Get_LavaSeahorse(k + 64); + --E1->base.y_pos; +} + +void LavaSeahorse_Func_3(uint16 k) { // 0xA2E6F1 + LavaSeahorse_Func_6(); + Enemy_LavaSeahorse *E = Get_LavaSeahorse(k); + if (E->lse_var_02) { + E->lse_var_02 = 0; + E->lse_var_01 = -1; + SpawnEnemyProjectileWithGfx(0xFFFFu, k, addr_kEproj_LavaSeahorseFireball); + QueueSfx2_Max6(0x61u); + if (E->lse_var_D-- == 1) { + E->lse_var_00 -= 4; + E->lse_var_D = 96; + E->lse_var_F = FUNC16(LavaSeahorse_Func_4); + } + } +} + +void LavaSeahorse_Func_4(uint16 k) { // 0xA2E734 + Enemy_LavaSeahorse *E = Get_LavaSeahorse(k); + if (E->lse_var_D-- == 1) { + E->lse_var_D = 48; + E->lse_var_F = FUNC16(LavaSeahorse_Func_5); + LavaSeahorse_Func_6(); + } +} + +void LavaSeahorse_Func_5(uint16 k) { // 0xA2E749 + Enemy_LavaSeahorse *E = Get_LavaSeahorse(k); + if ((--E->lse_var_D & 0x8000u) != 0) { + E->lse_var_D = 128; + E->lse_var_F = FUNC16(LavaSeahorse_Func_1); + } + ++E->base.y_pos; + Enemy_LavaSeahorse *E1 = Get_LavaSeahorse(k + 64); + ++E1->base.y_pos; +} + +void LavaSeahorse_Func_6(void) { // 0xA2E782 + Enemy_LavaSeahorse *E = Get_LavaSeahorse(cur_enemy_index); + uint16 lse_var_00 = E->lse_var_00; + if (lse_var_00 != E->lse_var_01) { + E->lse_var_01 = lse_var_00; + E->base.current_instruction = g_off_A2E5EF[lse_var_00]; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void LavaSeahorse_Func_7(void) { // 0xA2E7A5 + Enemy_LavaSeahorse *E = Get_LavaSeahorse(cur_enemy_index + 64); + uint16 lse_var_00 = E->lse_var_00; + if (lse_var_00 != E->lse_var_01) { + E->lse_var_01 = lse_var_00; + E->base.current_instruction = g_off_A2E5EF[lse_var_00]; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void LavaSeahorse_Touch(void) { // 0xA2E7C8 + Enemy_NormalTouchAI_A2(); + LavaSeahorse_E7DA(); +} + +void LavaSeahorse_Shot(void) { // 0xA2E7CE + Enemy_NormalShotAI_A2(); + LavaSeahorse_E7DA(); +} + +void LavaSeahorse_Powerbomb(void) { // 0xA2E7D4 + Enemy_NormalPowerBombAI_A2(); + LavaSeahorse_E7DA(); +} + +void LavaSeahorse_E7DA(void) { // 0xA2E7DA + Enemy_LavaSeahorse *E = Get_LavaSeahorse(cur_enemy_index); + if (E->base.health) { + uint16 shake_timer = E->base.shake_timer; + Enemy_LavaSeahorse *E1 = Get_LavaSeahorse(cur_enemy_index + 64); + E1->base.shake_timer = shake_timer; + E1->base.invincibility_timer = E->base.invincibility_timer; + E1->base.flash_timer = E->base.flash_timer; + E1->base.frozen_timer = E->base.frozen_timer; + E1->base.ai_handler_bits = E->base.ai_handler_bits; + } else { + Enemy_LavaSeahorse *E1 = Get_LavaSeahorse(cur_enemy_index + 64); + E1->base.properties |= 0x200u; + } +} + +void TimedShutter_Init(void) { // 0xA2E9DA + Enemy_TimedShutter *E = Get_TimedShutter(cur_enemy_index); + E->tsr_var_A = g_off_A2EA4E[(uint16)(2 * (E->base.current_instruction + + 2 * E->base.extra_properties)) >> 1]; + uint16 y_pos = E->base.y_pos; + uint16 v3; + if (E->base.extra_properties) { + E->tsr_var_B = y_pos; + uint16 v2 = y_pos - 8; + E->tsr_var_C = v2; + v2 -= 8; + E->tsr_var_D = v2; + v3 = v2 - 8; + } else { + E->tsr_var_B = y_pos; + uint16 v4 = y_pos + 8; + E->tsr_var_C = v4; + v4 += 8; + E->tsr_var_D = v4; + v3 = v4 + 8; + } + E->tsr_var_E = v3; + E->base.extra_properties = 0; + E->tsr_var_F = 0; + E->base.current_instruction = addr_kTimedShutter_Ilist_E998; + int v5 = (uint16)(4 * LOBYTE(E->tsr_parameter_2)) >> 1; + E->tsr_var_00 = g_word_A2EA56[v5]; + E->tsr_var_01 = g_word_A2EA56[v5 + 1]; +} + +void CallTimedShutterFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnTimedShutter_Func_1: TimedShutter_Func_1(k); return; + case fnTimedShutter_Func_2: TimedShutter_Func_2(k); return; + case fnTimedShutter_Func_3: TimedShutter_Func_3(k); return; + case fnTimedShutter_Func_4: TimedShutter_Func_4(k); return; + case fnTimedShutter_Func_5: TimedShutter_Func_5(k); return; + case fnTimedShutter_Func_10: TimedShutter_Func_10(k); return; + default: Unreachable(); + } +} + +void TimedShutter_Main(void) { // 0xA2EAB6 + Enemy_TimedShutter *E = Get_TimedShutter(cur_enemy_index); + CallTimedShutterFunc(E->tsr_var_A | 0xA20000, cur_enemy_index); +} + +void TimedShutter_Func_1(uint16 k) { // 0xA2EABD + Enemy_TimedShutter *E = Get_TimedShutter(k); + uint16 tsr_parameter_1 = E->tsr_parameter_1; + if (tsr_parameter_1) { + E->tsr_parameter_1 = tsr_parameter_1 - 1; + } else { + RisingFallingPlatform_Func_8(); + E->tsr_var_A = FUNC16(TimedShutter_Func_10); + } +} + +void TimedShutter_Func_2(uint16 k) { // 0xA2EAD1 + Enemy_TimedShutter *E = Get_TimedShutter(k); + if (IsSamusWithinEnemy_X(k, E->tsr_parameter_1)) { + RisingFallingPlatform_Func_8(); + E->tsr_var_A = FUNC16(TimedShutter_Func_10); + } +} + +void TimedShutter_Func_3(uint16 k) { // 0xA2EAE7 + Enemy_TimedShutter *E = Get_TimedShutter(k); + if (IsSamusWithinEnemy_X(k, E->tsr_parameter_1)) { + RisingFallingPlatform_Func_8(); + E->tsr_var_A = FUNC16(TimedShutter_Func_5); + } +} + +void TimedShutter_Func_4(uint16 k) { // 0xA2EAFD + Enemy_TimedShutter *E = Get_TimedShutter(k); + uint16 tsr_parameter_1 = E->tsr_parameter_1; + if (tsr_parameter_1) { + E->tsr_parameter_1 = tsr_parameter_1 - 1; + } else { + RisingFallingPlatform_Func_8(); + E->tsr_var_A = FUNC16(TimedShutter_Func_5); + } +} + +void TimedShutter_Func_Null(void) { + ; +} + + +static Func_V *const off_A2EB1A[5] = { TimedShutter_Func_6, TimedShutter_Func_7, TimedShutter_Func_8, TimedShutter_Func_9, TimedShutter_Func_Null }; + +void TimedShutter_Func_5(uint16 k) { // 0xA2EB11 + int v1 = (uint16)(2 * Get_TimedShutter(k)->tsr_var_F) >> 1; + off_A2EB1A[v1](); +} + +void TimedShutter_Func_6(void) { // 0xA2EB25 + Enemy_TimedShutter *E = Get_TimedShutter(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + bool v2 = __CFADD__uint16(E->tsr_var_01, y_subpos); + E->base.y_subpos = E->tsr_var_01 + y_subpos; + E->base.y_pos += E->tsr_var_00 + v2; + if ((int16)(E->tsr_var_B + 16 - E->base.y_pos) < 0) { + E->base.y_pos = E->tsr_var_B + 9; + ++E->tsr_var_F; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kTimedShutter_Ilist_E99E; + E->base.y_height = 16; + } +} + +void TimedShutter_Func_7(void) { // 0xA2EB66 + Enemy_TimedShutter *E = Get_TimedShutter(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + bool v2 = __CFADD__uint16(E->tsr_var_01, y_subpos); + E->base.y_subpos = E->tsr_var_01 + y_subpos; + E->base.y_pos += E->tsr_var_00 + v2; + if ((int16)(E->tsr_var_C + 16 - E->base.y_pos) < 0) { + E->base.y_pos = E->tsr_var_C + 9; + ++E->tsr_var_F; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kTimedShutter_Ilist_E9A4; + E->base.y_height = 24; + } +} + +void TimedShutter_Func_8(void) { // 0xA2EBA7 + Enemy_TimedShutter *E = Get_TimedShutter(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + bool v2 = __CFADD__uint16(E->tsr_var_01, y_subpos); + E->base.y_subpos = E->tsr_var_01 + y_subpos; + E->base.y_pos += E->tsr_var_00 + v2; + if ((int16)(E->tsr_var_D + 16 - E->base.y_pos) < 0) { + E->base.y_pos = E->tsr_var_D + 9; + ++E->tsr_var_F; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kTimedShutter_Ilist_E9AA; + E->base.y_height = 32; + } +} + +void TimedShutter_Func_9(void) { // 0xA2EBE8 + Enemy_TimedShutter *E = Get_TimedShutter(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + bool v2 = __CFADD__uint16(E->tsr_var_01, y_subpos); + E->base.y_subpos = E->tsr_var_01 + y_subpos; + E->base.y_pos += E->tsr_var_00 + v2; + uint16 v3 = E->tsr_var_E + 16; + if ((int16)(v3 - E->base.y_pos) < 0) { + E->base.y_pos = v3; + ++E->tsr_var_F; + } +} + +void TimedShutter_Func_Null2(void) { + +} + +static Func_V *const off_A2EC3A[5] = { // 0xA2EC13 + TimedShutter_Func_11, + TimedShutter_Func_12, + TimedShutter_Func_13, + TimedShutter_Func_14, + TimedShutter_Func_Null2, +}; + +void TimedShutter_Func_10(uint16 k) { + int16 v4; + + Enemy_TimedShutter *E = Get_TimedShutter(k); + E->tsr_var_40 = E->base.y_pos; + uint16 v2 = 2 * E->tsr_var_F; + off_A2EC3A[v2 >> 1](); + if (CheckIfEnemyTouchesSamus(k)) { + v4 = E->base.y_pos - E->tsr_var_40; + if (v4 < 0) + extra_samus_y_displacement += v4; + } +} + +void TimedShutter_Func_11(void) { // 0xA2EC45 + int16 v3; + + Enemy_TimedShutter *E = Get_TimedShutter(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + bool v2 = y_subpos < E->tsr_var_01; + E->base.y_subpos = y_subpos - E->tsr_var_01; + E->base.y_pos -= v2 + E->tsr_var_00; + v3 = E->tsr_var_B - 16; + if ((int16)(v3 - E->base.y_pos) >= 0) { + E->base.y_pos = v3 + 7; + ++E->tsr_var_F; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kTimedShutter_Ilist_E99E; + E->base.y_height = 16; + } +} + +void TimedShutter_Func_12(void) { // 0xA2EC86 + int16 v3; + + Enemy_TimedShutter *E = Get_TimedShutter(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + bool v2 = y_subpos < E->tsr_var_01; + E->base.y_subpos = y_subpos - E->tsr_var_01; + E->base.y_pos -= v2 + E->tsr_var_00; + v3 = E->tsr_var_C - 16; + if ((int16)(v3 - E->base.y_pos) >= 0) { + E->base.y_pos = v3 + 7; + ++E->tsr_var_F; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kTimedShutter_Ilist_E9A4; + E->base.y_height = 24; + } +} + +void TimedShutter_Func_13(void) { // 0xA2ECC7 + int16 v3; + + Enemy_TimedShutter *E = Get_TimedShutter(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + bool v2 = y_subpos < E->tsr_var_01; + E->base.y_subpos = y_subpos - E->tsr_var_01; + E->base.y_pos -= v2 + E->tsr_var_00; + v3 = E->tsr_var_D - 16; + if ((int16)(v3 - E->base.y_pos) >= 0) { + E->base.y_pos = v3 + 7; + ++E->tsr_var_F; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kTimedShutter_Ilist_E9AA; + E->base.y_height = 32; + } +} + +void TimedShutter_Func_14(void) { // 0xA2ED08 + Enemy_TimedShutter *E = Get_TimedShutter(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + bool v2 = y_subpos < E->tsr_var_01; + E->base.y_subpos = y_subpos - E->tsr_var_01; + E->base.y_pos -= v2 + E->tsr_var_00; + uint16 v3 = E->tsr_var_E - 16; + if ((int16)(v3 - E->base.y_pos) >= 0) { + E->base.y_pos = v3; + ++E->tsr_var_F; + } +} + +void TimedShutter_Func_15(void) { // 0xA2ED33 + ; +} + +void RisingFallingPlatform_Init(void) { // 0xA2EE05 + RisingFallingPlatform_Func_1(cur_enemy_index); + Get_RisingFallingPlatform(cur_enemy_index)->base.current_instruction = addr_kRisingFallingPlatform_Ilist_EDE7; +} + +void ShootableShutter_Init(void) { // 0xA2EE12 + RisingFallingPlatform_Func_1(cur_enemy_index); + gEnemyData(cur_enemy_index)->current_instruction = addr_kTimedShutter_Ilist_E9AA; +} + +void RisingFallingPlatform_Func_1(uint16 k) { // 0xA2EE1F + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(k); + uint16 current_instruction_low = LOBYTE(E->base.current_instruction); + E->rfpm_var_00 = current_instruction_low; + int v3 = (uint16)(8 * current_instruction_low) >> 1; + E->rfpm_var_D = kCommonEnemySpeeds_Linear[v3]; + E->rfpm_var_C = kCommonEnemySpeeds_Linear[v3 + 1]; + E->rfpm_var_F = kCommonEnemySpeeds_Linear[v3 + 2]; + E->rfpm_var_E = kCommonEnemySpeeds_Linear[v3 + 3]; + uint16 current_instruction_high = HIBYTE(E->base.current_instruction); + E->rfpm_var_01 = current_instruction_high; + E->rfpm_var_20 = current_instruction_high; + uint16 extra_properties_low = LOBYTE(E->base.extra_properties); + E->rfpm_var_02 = extra_properties_low; + E->rfpm_var_08 = 16 * extra_properties_low; + uint16 extra_properties_high = HIBYTE(E->base.extra_properties); + E->rfpm_var_03 = extra_properties_high; + E->rfpm_var_09 = 16 * extra_properties_high; + uint16 rfpm_parameter_1_low = LOBYTE(E->rfpm_parameter_1); + E->rfpm_var_04 = rfpm_parameter_1_low; + E->rfpm_var_07 = 2 * rfpm_parameter_1_low; + E->rfpm_var_05 = HIBYTE(E->rfpm_parameter_1); + uint16 rfpm_parameter_2 = E->rfpm_parameter_2; + E->rfpm_var_06 = rfpm_parameter_2; + E->rfpm_var_B = rfpm_parameter_2; + uint16 y_pos = E->base.y_pos; + E->rfpm_var_0F = y_pos; + E->rfpm_var_10 = E->rfpm_var_05 + y_pos; + if (!E->rfpm_var_01) { + uint16 v10 = E->base.y_pos; + E->rfpm_var_10 = v10; + E->rfpm_var_0F = v10 - E->rfpm_var_05; + } + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_2); + E->base.extra_properties = 0; + E->rfpm_var_0A = 0; +} + +void CallRisingFallingPlatformFunc(uint32 ea) { + switch (ea) { + case fnRisingFallingPlatform_Func_2: RisingFallingPlatform_Func_2(); return; + case fnRisingFallingPlatform_Func_4: RisingFallingPlatform_Func_4(); return; + case fnRisingFallingPlatform_Func_9: RisingFallingPlatform_Func_9(); return; + case fnRisingFallingPlatform_Func_10: RisingFallingPlatform_Func_10(); return; + case fnRisingFallingPlatform_Func_11: RisingFallingPlatform_Func_11(); return; + case fnRisingFallingPlatform_Func_12: RisingFallingPlatform_Func_12(); return; + case fnRisingFallingPlatform_Func_13: RisingFallingPlatform_Func_13(); return; + case fnHorizontalShootableShutter_Func_2: HorizontalShootableShutter_Func_2(); return; + case fnHorizontalShootableShutter_Func_4: HorizontalShootableShutter_Func_4(); return; + case fnHorizontalShootableShutter_Func_8: HorizontalShootableShutter_Func_8(); return; + case fnHorizontalShootableShutter_Func_9: HorizontalShootableShutter_Func_9(); return; + case fnHorizontalShootableShutter_Func_12: HorizontalShootableShutter_Func_12(); return; + case fnHorizontalShootableShutter_Func_13: HorizontalShootableShutter_Func_13(); return; + case fnHorizontalShootableShutter_Func_14: HorizontalShootableShutter_Func_14(); return; + default: Unreachable(); + } +} + +void RisingFallingPlatform_Main(void) { // 0xA2EED1 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + CallRisingFallingPlatformFunc(E->rfpm_var_A | 0xA20000); + if (E->rfpm_var_A != (uint16)FUNC16(RisingFallingPlatform_Func_9) + && E->rfpm_var_A != (uint16)FUNC16(RisingFallingPlatform_Func_10) + && (enemy_index_colliding_dirs[3] & (uint16)(enemy_index_colliding_dirs[2] & enemy_index_colliding_dirs[1] & enemy_index_colliding_dirs[0])) != 0xFFFF + && (enemy_index_colliding_dirs[3] & (uint16)(enemy_index_colliding_dirs[2] & enemy_index_colliding_dirs[1] & enemy_index_colliding_dirs[0])) == cur_enemy_index) { + if (samus_contact_damage_index) + RisingFallingPlatform_Powerbomb(); + } +} + +static Func_V *const off_A2EDFB[5] = { // 0xA2EF09 + RisingFallingPlatform_Func_3, + RisingFallingPlatform_Func_4, + RisingFallingPlatform_Func_5, + RisingFallingPlatform_Func_6, + RisingFallingPlatform_Func_6, +}; + +void RisingFallingPlatform_Func_2(void) { + + int v0 = Get_RisingFallingPlatform(cur_enemy_index)->rfpm_var_07 >> 1; + off_A2EDFB[v0](); +} + +void RisingFallingPlatform_Func_3(void) { // 0xA2EF15 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + if (E->rfpm_var_B-- == 1) { + E->rfpm_var_B = E->rfpm_var_06; + RisingFallingPlatform_Func_7(cur_enemy_index); + } +} + +void RisingFallingPlatform_Func_4(void) { // 0xA2EF28 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + if (IsSamusWithinEnemy_X(cur_enemy_index, E->rfpm_var_06)) + RisingFallingPlatform_Func_7(cur_enemy_index); +} + +void RisingFallingPlatform_Func_5(void) { // 0xA2EF39 + RisingFallingPlatform_Func_7(cur_enemy_index); +} + +void RisingFallingPlatform_Func_6(void) { // 0xA2EF40 + ; +} + +void RisingFallingPlatform_Func_7(uint16 k) { // 0xA2EF44 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(k); + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_9); + if (E->rfpm_var_01) + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_10); + RisingFallingPlatform_Func_8(); +} + +void RisingFallingPlatform_Func_8(void) { // 0xA2EF5A + if (!CheckIfEnemyIsOnScreen()) + QueueSfx3_Max6(0xEu); +} + +void RisingFallingPlatform_Func_9(void) { // 0xA2EF68 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + E->rfpm_var_0E = E->base.y_pos; + E->rfpm_var_0A = 0; + if (CheckIfEnemyTouchesSamus(cur_enemy_index)) + E->rfpm_var_0A = 1; + uint16 y_subpos = E->base.y_subpos; + bool v3 = __CFADD__uint16(E->rfpm_var_E, y_subpos); + uint16 v4 = E->rfpm_var_E + y_subpos; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v4; + E->base.y_pos += E->rfpm_var_F; + if (E->rfpm_var_0A) + extra_samus_y_displacement = E->base.y_pos - E->rfpm_var_0E; + if ((int16)(E->rfpm_var_0F - E->base.y_pos) >= 0) { + if (E->rfpm_var_08 == 4080) { + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_13); + } else { + E->rfpm_var_B = E->rfpm_var_08; + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_11); + } + } +} + +void RisingFallingPlatform_Func_10(void) { // 0xA2EFD4 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + E->rfpm_var_0E = E->base.y_pos; + E->rfpm_var_0A = 0; + if (CheckIfEnemyTouchesSamus(cur_enemy_index)) + E->rfpm_var_0A = 1; + uint16 y_subpos = E->base.y_subpos; + bool v3 = __CFADD__uint16(E->rfpm_var_C, y_subpos); + uint16 v4 = E->rfpm_var_C + y_subpos; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v4; + E->base.y_pos += E->rfpm_var_D; + if (E->rfpm_var_0A) + extra_samus_y_displacement = E->base.y_pos - E->rfpm_var_0E; + if ((int16)(E->base.y_pos - E->rfpm_var_10) >= 0) { + if (E->rfpm_var_09 == 4080) { + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_13); + } else { + E->rfpm_var_B = E->rfpm_var_09; + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_12); + } + } +} + +void RisingFallingPlatform_Func_11(void) { // 0xA2F040 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + if ((--E->rfpm_var_B & 0x8000u) != 0) { + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_10); + if (E->rfpm_var_04 == 1 && E->rfpm_var_01) + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_4); + if (Get_RisingFallingPlatform(cur_enemy_index)->base.enemy_ptr != 0xD83F) + RisingFallingPlatform_Func_8(); + } +} + +void RisingFallingPlatform_Func_12(void) { // 0xA2F072 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + if ((--E->rfpm_var_B & 0x8000u) != 0) { + RisingFallingPlatform_Func_8(); + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_9); + if (E->rfpm_var_04 == 1 && !E->rfpm_var_01) + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_4); + } +} + +void RisingFallingPlatform_Func_13(void) { // 0xA2F099 + ; +} + +void RisingFallingPlatform_Touch(void) { // 0xA2F09D + RisingFallingPlatform_Powerbomb(); +} + +void RisingFallingPlatform_Shot(void) { // 0xA2F0A2 + RisingFallingPlatform_Powerbomb(); +} + +void ShootableShutter_Shot(void) { // 0xA2F0AA + NormalEnemyShotAi(); + RisingFallingPlatform_Powerbomb(); +} + +void RisingFallingPlatform_Powerbomb(void) { // 0xA2F0B6 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + if (sign16(E->rfpm_var_07 - 6)) { +LABEL_10: + RisingFallingPlatform_Func_8(); + return; + } + if (E->rfpm_var_07 != 8) { + if (E->rfpm_var_0C) + return; + E->rfpm_var_0C = 1; + } + if (E->rfpm_var_A != (uint16)FUNC16(RisingFallingPlatform_Func_9) + && E->rfpm_var_A != (uint16)FUNC16(RisingFallingPlatform_Func_10)) { + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_9); + if (E->rfpm_var_20) + E->rfpm_var_A = FUNC16(RisingFallingPlatform_Func_10); + E->rfpm_var_20 ^= 1u; + goto LABEL_10; + } +} + +void HorizontalShootableShutter_Init(void) { // 0xA2F111 + HorizontalShootableShutter_Func_1(cur_enemy_index); + Get_HorizontalShootableShutter(cur_enemy_index)->base.current_instruction = addr_kTimedShutter_Ilist_E9D4; +} + +void HorizontalShootableShutter_Func_1(uint16 k) { // 0xA2F11E + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(k); + uint16 current_instruction_low = LOBYTE(E->base.current_instruction); + E->rfpm_var_00 = current_instruction_low; + int v3 = (uint16)(8 * current_instruction_low) >> 1; + E->rfpm_var_D = kCommonEnemySpeeds_Linear[v3]; + E->rfpm_var_C = kCommonEnemySpeeds_Linear[v3 + 1]; + E->rfpm_var_F = kCommonEnemySpeeds_Linear[v3 + 2]; + E->rfpm_var_E = kCommonEnemySpeeds_Linear[v3 + 3]; + uint16 current_instruction_high = HIBYTE(E->base.current_instruction); + E->rfpm_var_01 = current_instruction_high; + E->rfpm_var_20 = current_instruction_high ^ 1; + uint16 extra_properties_low = LOBYTE(E->base.extra_properties); + E->rfpm_var_02 = extra_properties_low; + E->rfpm_var_08 = 16 * extra_properties_low; + uint16 extra_properties_high = HIBYTE(E->base.extra_properties); + E->rfpm_var_03 = extra_properties_high; + E->rfpm_var_09 = 16 * extra_properties_high; + uint16 rfpm_parameter_1_low = LOBYTE(E->rfpm_parameter_1); + E->rfpm_var_04 = rfpm_parameter_1_low; + E->rfpm_var_07 = 2 * rfpm_parameter_1_low; + E->rfpm_var_05 = HIBYTE(E->rfpm_parameter_1); + uint16 rfpm_parameter_2 = E->rfpm_parameter_2; + E->rfpm_var_06 = rfpm_parameter_2; + E->rfpm_var_B = rfpm_parameter_2; + uint16 x_pos = E->base.x_pos; + E->rfpm_var_11 = x_pos; + E->rfpm_var_12 = E->rfpm_var_05 + x_pos; + if (!E->rfpm_var_01) { + uint16 v10 = E->base.x_pos; + E->rfpm_var_12 = v10; + E->rfpm_var_11 = v10 - E->rfpm_var_05; + } + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_2); + E->rfpm_var_15 = samus_x_pos; + E->base.extra_properties = 0; + E->rfpm_var_0A = 0; + E->rfpm_var_0B = 0; +} + +void HorizontalShootableShutter_Main(void) { // 0xA2F1DE + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + CallRisingFallingPlatformFunc(E->rfpm_var_A | 0xA20000); + if (E->rfpm_var_A != (uint16)FUNC16(HorizontalShootableShutter_Func_8) + && E->rfpm_var_A != (uint16)FUNC16(HorizontalShootableShutter_Func_9) + && (enemy_index_colliding_dirs[3] & (uint16)(enemy_index_colliding_dirs[2] & enemy_index_colliding_dirs[1] & enemy_index_colliding_dirs[0])) != 0xFFFF + && (enemy_index_colliding_dirs[3] & (uint16)(enemy_index_colliding_dirs[2] & enemy_index_colliding_dirs[1] & enemy_index_colliding_dirs[0])) == cur_enemy_index + && samus_contact_damage_index) { + HorizontalShootableShutter_Powerbomb(); + } + E->rfpm_var_15 = samus_x_pos; + E->rfpm_var_16 = samus_x_subpos; +} + +static Func_V *const off_A2F107[5] = { // 0xA2F224 + HorizontalShootableShutter_Func_3, + HorizontalShootableShutter_Func_4, + HorizontalShootableShutter_Func_5, + HorizontalShootableShutter_Func_6, + HorizontalShootableShutter_Func_6, +}; +void HorizontalShootableShutter_Func_2(void) { + + int v0 = Get_RisingFallingPlatform(cur_enemy_index)->rfpm_var_07 >> 1; + off_A2F107[v0](); +} + +void HorizontalShootableShutter_Func_3(void) { // 0xA2F230 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + if (E->rfpm_var_B-- == 1) { + E->rfpm_var_B = E->rfpm_var_06; + HorizontalShootableShutter_Func_7(cur_enemy_index); + } +} + +void HorizontalShootableShutter_Func_4(void) { // 0xA2F243 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + if (IsSamusWithinEnemy_X(cur_enemy_index, E->rfpm_var_06)) + HorizontalShootableShutter_Func_7(cur_enemy_index); +} + +void HorizontalShootableShutter_Func_5(void) { // 0xA2F254 + HorizontalShootableShutter_Func_7(cur_enemy_index); +} + +void HorizontalShootableShutter_Func_6(void) { // 0xA2F25B + ; +} + +void HorizontalShootableShutter_Func_7(uint16 k) { // 0xA2F25F + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(k); + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_8); + if (E->rfpm_var_01) + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_9); +} + +void HorizontalShootableShutter_Func_8(void) { // 0xA2F272 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + E->rfpm_var_0D = E->base.x_pos; + E->rfpm_var_13 = 0; + if (EnemyFunc_AC67(cur_enemy_index) && (int16)(samus_x_pos - E->base.x_pos) < 0) + E->rfpm_var_13 = 1; + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->rfpm_var_E, x_subpos); + E->base.x_subpos = E->rfpm_var_E + x_subpos; + E->base.x_pos += E->rfpm_var_F + v3; + if (E->rfpm_var_13) { + extra_samus_x_subdisplacement = E->rfpm_var_E; + extra_samus_x_displacement = E->rfpm_var_F; + HorizontalShootableShutter_Func_10(cur_enemy_index); + } + if ((int16)(E->rfpm_var_11 - E->base.x_pos) >= 0) { + if (E->rfpm_var_08 == 4080) { + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_14); + } else { + E->rfpm_var_B = E->rfpm_var_08; + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_12); + } + } +} + +void HorizontalShootableShutter_Func_9(void) { // 0xA2F2E4 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + E->rfpm_var_0D = E->base.x_pos; + E->rfpm_var_13 = 0; + if (EnemyFunc_AC67(cur_enemy_index) && (int16)(samus_x_pos - E->base.x_pos) >= 0) + E->rfpm_var_13 = 1; + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->rfpm_var_C, x_subpos); + E->base.x_subpos = E->rfpm_var_C + x_subpos; + E->base.x_pos += E->rfpm_var_D + v3; + if (E->rfpm_var_13) { + extra_samus_x_subdisplacement = E->rfpm_var_C; + extra_samus_x_displacement = E->rfpm_var_D; + HorizontalShootableShutter_Func_11(cur_enemy_index); + } + if ((int16)(E->base.x_pos - E->rfpm_var_12) >= 0) { + if (E->rfpm_var_09 == 4080) { + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_14); + } else { + E->rfpm_var_B = E->rfpm_var_09; + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_13); + } + } +} + +void HorizontalShootableShutter_Func_10(uint16 k) { // 0xA2F356 + if (Get_RisingFallingPlatform(k)->rfpm_var_13) { + if ((joypad1_lastkeys & 0x100) != 0) { + extra_samus_x_displacement -= 4; + extra_samus_y_subdisplacement = 0; + } + } +} + +void HorizontalShootableShutter_Func_11(uint16 k) { // 0xA2F371 + if (Get_RisingFallingPlatform(k)->rfpm_var_13) { + if ((joypad1_lastkeys & 0x200) != 0) { + extra_samus_x_displacement += 4; + extra_samus_y_subdisplacement = 0; + } + } +} + +void HorizontalShootableShutter_Func_12(void) { // 0xA2F38C + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + if ((--E->rfpm_var_B & 0x8000u) != 0) { + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_9); + if (E->rfpm_var_04 == 1) { + if (E->rfpm_var_01) + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_4); + } + } +} + +void HorizontalShootableShutter_Func_13(void) { // 0xA2F3B0 + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + if ((--E->rfpm_var_B & 0x8000u) != 0) { + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_8); + if (E->rfpm_var_04 == 1 && !E->rfpm_var_01) + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_4); + } +} + +void HorizontalShootableShutter_Func_14(void) { // 0xA2F3D4 + ; +} + +void HorizontalShootableShutter_Touch(void) { // 0xA2F3D8 + Enemy_HorizontalShootableShutter *E = Get_HorizontalShootableShutter(cur_enemy_index); + if (E->hssr_var_A == (uint16)FUNC16(HorizontalShootableShutter_Func_14)) { + if ((int16)(samus_x_pos - E->base.x_pos) >= 0) { + if ((joypad1_lastkeys & 0x200) != 0) { + extra_samus_x_displacement = 4; + extra_samus_y_subdisplacement = 0; + } + } else if ((joypad1_lastkeys & 0x100) != 0) { + extra_samus_x_displacement = -4; + extra_samus_y_subdisplacement = 0; + } + } +} + +void HorizontalShootableShutter_Shot(void) { // 0xA2F40E + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + HorizontalShootableShutter_Powerbomb(); +} + +void HorizontalShootableShutter_Powerbomb(void) { // 0xA2F41A + Enemy_RisingFallingPlatform *E = Get_RisingFallingPlatform(cur_enemy_index); + if (!sign16(E->rfpm_var_07 - 6)) { + if (E->rfpm_var_07 != 8) { + if (E->rfpm_var_0C) + return; + E->rfpm_var_0C = 1; + } + if (E->rfpm_var_A != (uint16)FUNC16(HorizontalShootableShutter_Func_8) + && E->rfpm_var_A != (uint16)FUNC16(HorizontalShootableShutter_Func_9)) { + E->rfpm_var_20 ^= 1u; + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_8); + if (E->rfpm_var_20) + E->rfpm_var_A = FUNC16(HorizontalShootableShutter_Func_9); + } + } +} diff --git a/src/sm_a3.c b/src/sm_a3.c new file mode 100644 index 0000000..c6673f9 --- /dev/null +++ b/src/sm_a3.c @@ -0,0 +1,3720 @@ +// Enemy AI - inc. elevator & metroid +#include "ida_types.h" +#include "variables.h" +#include "sm_rtl.h" +#include "funcs.h" +#include "enemy_types.h" + +#define g_off_A386DB ((uint16*)RomPtr(0xa386db)) +#define g_off_A3894E ((uint16*)RomPtr(0xa3894e)) +#define g_word_A38D1D ((uint16*)RomPtr(0xa38d1d)) +#define g_word_A394E2 ((uint16*)RomPtr(0xa394e2)) +#define g_off_A396DB ((uint16*)RomPtr(0xa396db)) +#define g_off_A3992B ((uint16*)RomPtr(0xa3992b)) +#define g_off_A3A111 ((uint16*)RomPtr(0xa3a111)) +#define g_off_A3A121 ((uint16*)RomPtr(0xa3a121)) +static const int16 g_word_A3A76D[4] = { 2, 0, -2, 0 }; +static const int16 g_word_A3A775[4] = { 0, -2, 0, 2 }; + +#define g_off_A3AAC2 ((uint16*)RomPtr(0xa3aac2)) +#define g_off_A3AACA ((uint16*)RomPtr(0xa3aaca)) +#define g_off_A3AAD2 ((uint16*)RomPtr(0xa3aad2)) +#define g_off_A3AADA ((uint16*)RomPtr(0xa3aada)) +#define g_off_A3AAE2 ((uint16*)RomPtr(0xa3aae2)) +#define g_word_A3AAE6 ((uint16*)RomPtr(0xa3aae6)) +#define g_word_A3AAEA ((uint16*)RomPtr(0xa3aaea)) +#define g_word_A3AAEE ((uint16*)RomPtr(0xa3aaee)) +#define g_word_A3AAF2 ((uint16*)RomPtr(0xa3aaf2)) +#define g_word_A3AAF6 ((uint16*)RomPtr(0xa3aaf6)) +#define g_word_A3AAFA ((uint16*)RomPtr(0xa3aafa)) +#define g_word_A3B415 ((uint16*)RomPtr(0xa3b415)) +#define g_off_A3B40D ((uint16*)RomPtr(0xa3b40d)) +#define g_off_A3B667 ((uint16*)RomPtr(0xa3b667)) +#define g_word_A3BA84 ((uint16*)RomPtr(0xa3ba84)) +#define g_word_A3BA94 ((uint16*)RomPtr(0xa3ba94)) +#define g_word_A3BC4A ((uint16*)RomPtr(0xa3bc4a)) +#define g_word_A3BC6A ((uint16*)RomPtr(0xa3bc6a)) +#define g_off_A3B722 ((uint16*)RomPtr(0xa3b722)) +#define g_off_A3C69C ((uint16*)RomPtr(0xa3c69c)) +#define g_stru_A3CD42 ((MaridiaSnailData2*)RomPtr(0xa3cd42)) +#define g_word_A3CD82 ((uint16*)RomPtr(0xa3cd82)) +#define g_word_A3CDC2 ((uint16*)RomPtr(0xa3cdc2)) +#define g_word_A3CCA2 ((uint16*)RomPtr(0xa3cca2)) +#define g_off_A3CDD2 ((uint16*)RomPtr(0xa3cdd2)) +#define g_off_A3D1AB ((uint16*)RomPtr(0xa3d1ab)) +#define g_off_A3D30D ((uint16*)RomPtr(0xa3d30d)) +#define g_off_A3D50F ((uint16*)RomPtr(0xa3d50f)) +#define g_word_A3D517 ((uint16*)RomPtr(0xa3d517)) +#define g_off_A3D5A4 ((uint16*)RomPtr(0xa3d5a4)) +#define g_word_A3DABC ((uint16*)RomPtr(0xa3dabc)) +#define g_off_A3DC0B ((uint16*)RomPtr(0xa3dc0b)) +#define g_word_A3DCAE ((uint16*)RomPtr(0xa3dcae)) +#define g_off_A3DCA6 ((uint16*)RomPtr(0xa3dca6)) +#define g_off_A3E03B ((uint16*)RomPtr(0xa3e03b)) +#define g_word_A3E5F0 ((uint16*)RomPtr(0xa3e5f0)) +#define g_off_A3E2CC ((uint16*)RomPtr(0xa3e2cc)) +#define g_off_A3E630 ((uint16*)RomPtr(0xa3e630)) +#define g_off_A3E63C ((uint16*)RomPtr(0xa3e63c)) +#define g_off_A3E648 ((uint16*)RomPtr(0xa3e648)) +#define g_off_A3E654 ((uint16*)RomPtr(0xa3e654)) +#define g_word_A3E931 ((uint16*)RomPtr(0xa3e931)) +#define g_word_A3EAD6 ((uint16*)RomPtr(0xa3ead6)) +#define g_word_A3EA3F ((uint16*)RomPtr(0xa3ea3f)) + +uint16 EnemyInstr_EnableOffScreenProcessing_A3(uint16 k, uint16 j) { // 0xA38173 + EnemyData *v2 = gEnemyData(k); + v2->properties |= kEnemyProps_ProcessedOffscreen; + return j; +} + +uint16 EnemyInstr_DisableOffScreenProcessing_A3(uint16 k, uint16 j) { // 0xA3817D + EnemyData *v2 = gEnemyData(k); + v2->properties &= ~kEnemyProps_ProcessedOffscreen; + return j; +} + +uint16 EnemyInstr_Goto_A3(uint16 k, uint16 j) { // 0xA380ED + return *(uint16 *)RomPtr_A3(j); +} + + +uint16 EnemyInstr_Sleep_A3(uint16 k, uint16 j) { // 0xA3812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + +void Enemy_GrappleReact_NoInteract_A3(void) { // 0xA38000 + SwitchEnemyAiToMainAi(); +} + +void Enemy_GrappleReact_KillEnemy_A3(void) { // 0xA3800A + EnemyGrappleDeath(); +} + +void Enemy_GrappleReact_CancelBeam_A3(void) { // 0xA3800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_NormalTouchAI_A3(void) { // 0xA38023 + NormalEnemyTouchAi(); +} + +void Enemy_NormalShotAI_A3(void) { // 0xA3802D + NormalEnemyShotAi(); +} + +void Enemy_NormalShotAI_SkipSomeParts_A3(void) { // 0xA38032 + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); +} + +void Enemy_NormalPowerBombAI_A3(void) { // 0xA38037 + NormalEnemyPowerBombAi(); +} + +void Enemy_NormalFrozenAI_A3(void) { // 0xA38041 + NormalEnemyFrozenAI(); +} + +uint16 Waver_Instr_1(uint16 k, uint16 j) { // 0xA386E3 + Get_Waver(cur_enemy_index)->waver_var_E = 1; + return j; +} + +void Waver_Init(void) { // 0xA386ED + Enemy_Waver *E = Get_Waver(cur_enemy_index); + E->waver_var_B = 1; + E->waver_var_A = 0x8000; + if ((E->waver_parameter_1 & 1) == 0) { + E->waver_var_B = SignExtend8(0xFEu); + E->waver_var_A = SignExtend8(0x8000u); + } + E->waver_var_F = 0; + E->waver_var_C = 0; + E->waver_var_E = 0; + E->base.current_instruction = addr_kWaver_Ilist_86A7; + E->waver_var_F = E->waver_parameter_1 & 1; + Waver_Func_1(); +} + +void Waver_Main(void) { // 0xA3874C + uint16 v2; + + Enemy_Waver *E = Get_Waver(cur_enemy_index); + R18_ = E->waver_var_A; + R20_ = E->waver_var_B; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + R18_ = *(uint16 *)((char *)&E->waver_var_A + 1); + E->waver_var_B = SignExtend8((uint8)((uint16)(-R18_ & 0xFF00) >> 8)); + LOBYTE(v2) = 0; + HIBYTE(v2) = -(int8)R18_; + E->waver_var_A = SignExtend8(v2); + E->waver_var_F = ((uint8)E->waver_var_F ^ 1) & 1; + Waver_Func_1(); + } else { + draw_enemy_layer = 4; + R20_ = SineMult8bitNegative(LOBYTE(E->waver_var_D)); + R18_ = 0; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->waver_var_D = (uint8)(E->waver_var_D + 0x80); + } else { + E->waver_var_D += 2; + } + } + if ((E->waver_var_D & 0x7F) == 56) { + E->waver_var_F |= 2u; + Waver_Func_1(); + } + if (E->waver_var_E) { + E->waver_var_E = 0; + E->waver_var_F = E->waver_var_F & 1; + Waver_Func_1(); + } +} + +void Waver_Func_1(void) { // 0xA387FE + Enemy_Waver *E = Get_Waver(cur_enemy_index); + uint16 waver_var_F = E->waver_var_F; + if (waver_var_F != E->waver_var_C) { + E->waver_var_C = waver_var_F; + E->base.current_instruction = g_off_A386DB[waver_var_F]; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +uint16 Metalee_Instr_1(uint16 k, uint16 j) { // 0xA38956 + Get_Metalee(cur_enemy_index)->metalee_var_E = 1; + return j; +} + +void Metalee_Init(void) { // 0xA38960 + Enemy_Metalee *E = Get_Metalee(cur_enemy_index); + E->metalee_var_C = 0; + E->metalee_var_D = 0; + E->metalee_var_E = 0; + E->base.current_instruction = addr_kMetalee_Ilist_8910; + E->metalee_var_B = FUNC16(Metalee_Func_1); +} + +void CallMetaleeFunc(uint32 ea) { + switch (ea) { + case fnMetalee_Func_1: Metalee_Func_1(); return; + case fnMetalee_Func_3: Metalee_Func_3(cur_enemy_index); return; + case fnMetalee_Func_4: Metalee_Func_4(); return; + case fnMetalee_Func_5: Metalee_Func_5(); return; + default: Unreachable(); + } +} + +void Metalee_Main(void) { // 0xA38979 + Enemy_Metalee *E = Get_Metalee(cur_enemy_index); + CallMetaleeFunc(E->metalee_var_B | 0xA30000); +} + +void Metalee_Func_1(void) { // 0xA38987 + Enemy_Metalee *E = Get_Metalee(cur_enemy_index); + if (abs16(E->base.x_pos - samus_x_pos) < 0x48u) { + Metalee_Func_2(cur_enemy_index); + ++E->metalee_var_C; + Metalee_Func_6(); + E->metalee_var_B = FUNC16(Metalee_Func_3); + } +} + +void Metalee_Func_2(uint16 k) { // 0xA389AC + Enemy_Metalee *E = Get_Metalee(k); + uint16 div = SnesDivide(samus_y_pos - E->base.y_pos, 24); + E->metalee_var_F = div + 4; +} + +void Metalee_Func_3(uint16 k) { // 0xA389D4 + Enemy_Metalee *E = Get_Metalee(k); + if (E->metalee_var_E) { + E->metalee_var_E = 0; + ++E->metalee_var_C; + Metalee_Func_6(); + E->metalee_var_B = FUNC16(Metalee_Func_4); + QueueSfx2_Max6(0x5Bu); + } +} + +void Metalee_Func_4(void) { // 0xA389F3 + Enemy_Metalee *E = Get_Metalee(cur_enemy_index); + E->metalee_var_A = 21; + R20_ = E->metalee_var_F; + R18_ = 0; + uint16 v1 = E->base.properties | 3; + E->base.properties = v1; + if (EnemyFunc_BF8A(cur_enemy_index, v1) & 1) { + E->base.instruction_timer = 1; + E->base.timer = 0; + E->metalee_var_B = FUNC16(Metalee_Func_5); + QueueSfx2_Max6(0x5Cu); + } else { + E->base.y_pos += E->metalee_var_F; + varE24 = 2; + if ((int16)(E->base.x_pos - samus_x_pos) >= 0) + varE24 = -2; + E->base.x_pos += varE24; + } +} + +void Metalee_Func_5(void) { // 0xA38A5C + Enemy_Metalee *E = Get_Metalee(cur_enemy_index); + if (E->metalee_var_A-- == 1) { + gEnemySpawnData(cur_enemy_index)->vram_tiles_index = E->base.vram_tiles_index | E->base.palette_index; + E->base.palette_index = 2560; + E->base.vram_tiles_index = 0; + E->base.properties |= kEnemyProps_Deleted; + } else { + if (E->metalee_var_A == 8) { + uint16 v2 = cur_enemy_index; + SpawnEnemyProjectileWithGfx(0, v2, addr_stru_868BFA); + SpawnEnemyProjectileWithGfx(0, v2, addr_stru_868C08); + SpawnEnemyProjectileWithGfx(0, v2, addr_stru_868C16); + SpawnEnemyProjectileWithGfx(0, v2, addr_stru_868C24); + } + ++E->base.y_pos; + } +} + +void Metalee_Func_6(void) { // 0xA38AB2 + Enemy_Metalee *E = Get_Metalee(cur_enemy_index); + uint16 metalee_var_C = E->metalee_var_C; + if (metalee_var_C != E->metalee_var_D) { + E->metalee_var_D = metalee_var_C; + E->base.current_instruction = g_off_A3894E[metalee_var_C]; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void Metalee_Shot(void) { // 0xA38B0F + Enemy_Metalee *E = Get_Metalee(cur_enemy_index); + varE2A = E->base.vram_tiles_index; + varE2C = E->base.palette_index; + Enemy_NormalShotAI_A3(); + if (!Get_Metalee(cur_enemy_index)->base.health) { + E->base.vram_tiles_index = varE2A; + E->base.palette_index = varE2C; + uint16 v2 = cur_enemy_index; + SpawnEnemyProjectileWithGfx(E->metalee_var_A, cur_enemy_index, addr_stru_868BFA); + SpawnEnemyProjectileWithGfx(0, v2, addr_stru_868C08); + SpawnEnemyProjectileWithGfx(0, v2, addr_stru_868C16); + SpawnEnemyProjectileWithGfx(0, v2, addr_stru_868C24); + E->base.vram_tiles_index = 0; + E->base.palette_index = 0; + } +} + +void Fireflea_Init(void) { // 0xA38D2D + Enemy_Fireflea *E = Get_Fireflea(cur_enemy_index); + E->base.current_instruction = addr_kFireflea_Ilist_8C2F; + R18_ = LOBYTE(E->firefl_parameter_1); + if ((R18_ & 2) != 0) { + Fireflea_Func_1(cur_enemy_index); + Fireflea_Func_2(cur_enemy_index); + Fireflea_Func_3(cur_enemy_index); + Fireflea_Func_4(cur_enemy_index); + Fireflea_Func_5(cur_enemy_index); + } else { + Fireflea_Func_3(cur_enemy_index); + Fireflea_Func_4(cur_enemy_index); + Fireflea_Func_6(cur_enemy_index); + } +} + +void Fireflea_Func_1(uint16 k) { // 0xA38D5D + Enemy_Fireflea *E = Get_Fireflea(k); + E->firefl_var_E = E->base.x_pos; + E->firefl_var_F = E->base.y_pos; +} + +void Fireflea_Func_2(uint16 k) { // 0xA38D6A + Enemy_Fireflea *E = Get_Fireflea(k); + E->firefl_var_D = HIBYTE(E->firefl_parameter_1) << 8; +} + +void Fireflea_Func_3(uint16 k) { // 0xA38D75 + Enemy_FireFlea *E = Get_FireFlea(k); + uint16 v2 = 8 * LOBYTE(E->ffa_parameter_2); + if ((R18_ & 1) == 0) + v2 += 4; + E->ffa_var_02 = v2; + int v3 = v2 >> 1; + E->ffa_var_B = kCommonEnemySpeeds_Linear[v3]; + E->ffa_var_A = kCommonEnemySpeeds_Linear[v3 + 1]; +} + +void Fireflea_Func_4(uint16 k) { // 0xA38D9C + Enemy_Fireflea *E = Get_Fireflea(k); + E->firefl_var_C = LOBYTE(g_word_A38D1D[(uint16)(2 * HIBYTE(E->firefl_parameter_2)) >> 1]); +} + +void Fireflea_Func_5(uint16 k) { // 0xA38DAE + Enemy_Fireflea *E = Get_Fireflea(k); + draw_enemy_layer = E->firefl_var_C; + E->base.x_pos = E->firefl_var_E + CosineMult8bit(E->firefl_var_D); + draw_enemy_layer = E->firefl_var_C; + E->base.y_pos = E->firefl_var_F + SineMult8bitNegative(E->firefl_var_D); +} + +void Fireflea_Func_6(uint16 k) { // 0xA38DD7 + Enemy_FireFlea *E = Get_FireFlea(k); + E->ffa_var_00 = E->base.y_pos - E->ffa_var_C; + E->ffa_var_01 = E->ffa_var_C + E->base.y_pos; +} + +void Fireflea_Main(void) { // 0xA38DEE + Enemy_FireFlea *E = Get_FireFlea(cur_enemy_index); + if ((E->ffa_parameter_1 & 2) != 0) { + draw_enemy_layer = E->ffa_var_C; + E->base.x_pos = E->ffa_var_E + CosineMult8bit(HIBYTE(E->ffa_var_D)); + draw_enemy_layer = E->ffa_var_C; + E->base.y_pos = E->ffa_var_F + SineMult8bitNegative(HIBYTE(E->ffa_var_D)); + E->ffa_var_D += *(uint16 *)((char *)&E->ffa_var_A + 1); + } else { + uint16 y_subpos = E->base.y_subpos; + int v2 = E->ffa_var_02 >> 1; + bool v3 = __CFADD__uint16(kCommonEnemySpeeds_Linear[v2 + 1], y_subpos); + E->base.y_subpos = kCommonEnemySpeeds_Linear[v2 + 1] + y_subpos; + E->base.y_pos += kCommonEnemySpeeds_Linear[v2] + v3; + if ((int16)(E->base.y_pos - E->ffa_var_00) < 0 + || (int16)(E->base.y_pos - E->ffa_var_01) >= 0) { + E->ffa_var_02 ^= 4u; + } + } +} + +void Fireflea_Touch(uint16 k) { // 0xA38E6B + uint16 v1 = 0; + + Enemy_NormalTouchAI_A3(); + EnemyDeathAnimation(k, v1); + if (sign16(fireflea_darkness_level - 12)) + fireflea_darkness_level += 2; +} + +void Fireflea_Powerbomb(void) { // 0xA38E83 + Enemy_NormalPowerBombAI_A3(); + Fireflea_Common(); +} + +void Fireflea_Shot(void) { // 0xA38E89 + Enemy_NormalShotAI_A3(); + Fireflea_Common(); +} + +void Fireflea_Common(void) { // 0xA38E8D + if (!Get_Fireflea(cur_enemy_index)->base.health) { + if (sign16(fireflea_darkness_level - 12)) + fireflea_darkness_level += 2; + } +} + +uint16 MaridiaFish_Instr_3(uint16 k, uint16 j) { // 0xA39096 + Get_MaridiaFish(cur_enemy_index)->base.layer = 6; + return j; +} + +uint16 MaridiaFish_Instr_1(uint16 k, uint16 j) { // 0xA390A0 + Get_MaridiaFish(cur_enemy_index)->base.layer = 2; + return j; +} + +uint16 MaridiaFish_Instr_2(uint16 k, uint16 j) { // 0xA390AA + Get_MaridiaFish(cur_enemy_index)->mfh_var_01 = 1; + return j; +} + +void MaridiaFish_Init(void) { // 0xA390B5 + Enemy_MaridiaFish *E = Get_MaridiaFish(cur_enemy_index); + E->base.current_instruction = addr_kMaridiaFish_Ilist_902A; + E->mfh_var_A = FUNC16(MaridiaFish_Func_1); + if (!HIBYTE(E->mfh_parameter_1)) { + E->base.current_instruction = addr_kMaridiaFish_Ilist_9060; + E->mfh_var_A = FUNC16(MaridiaFish_Func_2); + } + int v1 = (uint16)(8 * LOBYTE(E->mfh_parameter_1)) >> 1; + E->mfh_var_C = kCommonEnemySpeeds_Linear[v1]; + E->mfh_var_B = kCommonEnemySpeeds_Linear[v1 + 1]; + E->mfh_var_E = kCommonEnemySpeeds_Linear[v1 + 2]; + E->mfh_var_D = kCommonEnemySpeeds_Linear[v1 + 3]; + E->mfh_var_00 = LOBYTE(E->mfh_parameter_2); + E->mfh_var_02 = HIBYTE(E->mfh_parameter_2); + E->mfh_var_F = 0; + E->mfh_var_01 = 0; + draw_enemy_layer = E->mfh_var_00; + E->mfh_var_03 = SineMult8bitNegative(E->mfh_var_F); +} + +void CallMaridiaFishFunc(uint32 ea) { + switch (ea) { + case fnMaridiaFish_Func_1: MaridiaFish_Func_1(); return; + case fnMaridiaFish_Func_2: MaridiaFish_Func_2(); return; + case fnMaridiaFish_Func_3: MaridiaFish_Func_3(); return; + case fnMaridiaFish_Func_4: MaridiaFish_Func_4(); return; + default: Unreachable(); + } +} + +void MaridiaFish_Main(void) { // 0xA3912B + Enemy_MaridiaFish *E = Get_MaridiaFish(cur_enemy_index); + CallMaridiaFishFunc(E->mfh_var_A | 0xA30000); +} + +void MaridiaFish_Func_1(void) { // 0xA39132 + Enemy_MaridiaFish *E = Get_MaridiaFish(cur_enemy_index); + R18_ = E->mfh_var_D; + R20_ = E->mfh_var_E; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->mfh_var_A = FUNC16(MaridiaFish_Func_3); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMaridiaFish_Ilist_903C; + } else { + draw_enemy_layer = E->mfh_var_00; + uint16 v2 = SineMult8bitNegative(E->mfh_var_F); + E->mfh_var_04 = v2; + R20_ = v2 - E->mfh_var_03; + R18_ = 0; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->mfh_var_A = FUNC16(MaridiaFish_Func_3); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMaridiaFish_Ilist_903C; + } else { + E->mfh_var_F = (uint8)(LOBYTE(E->mfh_var_02) + E->mfh_var_F); + } + } + E->mfh_var_03 = E->mfh_var_04; +} + +void MaridiaFish_Func_2(void) { // 0xA391AB + Enemy_MaridiaFish *E = Get_MaridiaFish(cur_enemy_index); + R18_ = E->mfh_var_B; + R20_ = E->mfh_var_C; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->mfh_var_A = FUNC16(MaridiaFish_Func_4); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMaridiaFish_Ilist_9072; + } else { + draw_enemy_layer = E->mfh_var_00; + uint16 v2 = SineMult8bitNegative(E->mfh_var_F); + E->mfh_var_04 = v2; + R20_ = v2 - E->mfh_var_03; + R18_ = 0; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->mfh_var_A = FUNC16(MaridiaFish_Func_4); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMaridiaFish_Ilist_9072; + } else { + E->mfh_var_F = (uint8)(LOBYTE(E->mfh_var_02) + E->mfh_var_F); + } + } + E->mfh_var_03 = E->mfh_var_04; +} + +void MaridiaFish_Func_3(void) { // 0xA39224 + Enemy_MaridiaFish *E = Get_MaridiaFish(cur_enemy_index); + if (E->mfh_var_01) { + E->mfh_var_01 = 0; + E->mfh_var_A = FUNC16(MaridiaFish_Func_2); + E->mfh_var_02 = -E->mfh_var_02; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMaridiaFish_Ilist_9060; + } +} + +void MaridiaFish_Func_4(void) { // 0xA39256 + Enemy_MaridiaFish *E = Get_MaridiaFish(cur_enemy_index); + if (E->mfh_var_01) { + E->mfh_var_01 = 0; + E->mfh_var_A = FUNC16(MaridiaFish_Func_1); + E->mfh_var_02 = -E->mfh_var_02; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMaridiaFish_Ilist_902A; + } +} + +void Elevator_Init(void) { // 0xA394E6 + Enemy_Elevator *E = Get_Elevator(cur_enemy_index); + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A3; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kElevator_Ilist_94D6; + E->elevat_parameter_1 *= 2; + E->elevat_var_A = E->base.y_pos; + if (elevator_status != 2) { + elevator_flags = 0; + elevator_status = 0; + } + if (__PAIR32__(elevator_status, elevator_flags)) { + E->base.y_pos = E->elevat_parameter_2; + Elevator_Func_4(); + } +} +static Func_V *const off_A39540[4] = { Elevator_Func_1, Elevator_Func_2, Elevator_Func_3, Elevator_Func3b }; +void Elevator_Frozen(void) { // 0xA3952A + if (!door_transition_flag_elevator_zebetites) { + if (__PAIR32__(elevator_status, elevator_flags)) + off_A39540[elevator_status](); + } +} + +void Elevator_Func_1(void) { // 0xA39548 + if ((g_word_A394E2[Get_Elevator(cur_enemy_index)->elevat_parameter_1 >> 1] & joypad1_newkeys) != 0) { + QueueSfx3_Max6(0xBu); + QueueSfx1_Max6(0x32u); + CallSomeSamusCode(7u); + ResetProjectileData(); + Elevator_Func_4(); + ++elevator_status; + } else { + elevator_flags = 0; + } +} + +void Elevator_Func_2(void) { // 0xA39579 + Enemy_Elevator *E = Get_Elevator(cur_enemy_index); + uint16 v2; + if (E->elevat_parameter_1) { + elevator_direction = FUNC16(Enemy_GrappleReact_NoInteract_A3); + uint16 y_subpos = E->base.y_subpos; + E->base.y_subpos = y_subpos + 0x8000; + v2 = (__PAIR32__(E->base.y_pos, y_subpos) - 98304) >> 16; + } else { + elevator_direction = 0; + uint16 v1 = E->base.y_subpos; + E->base.y_subpos = v1 + 0x8000; + v2 = __CFADD__uint16(v1, 0x8000) + E->base.y_pos + 1; + } + E->base.y_pos = v2; + Elevator_Func_4(); +} + +void Elevator_Func_3(void) { // 0xA395B9 + ++elevator_status; + Elevator_Func3b(); +} + +void Elevator_Func3b(void) { // 0xA395BC + Enemy_Elevator *E = Get_Elevator(cur_enemy_index); + if (E->elevat_parameter_1) { + uint16 y_subpos; + y_subpos = E->base.y_subpos; + E->base.y_subpos = y_subpos + 0x8000; + uint16 v2; + v2 = __CFADD__uint16(y_subpos, 0x8000) + E->base.y_pos + 1; + E->base.y_pos = v2; + if (v2 < E->elevat_var_A) { +LABEL_3: + Elevator_Func_4(); + return; + } + } else { + uint16 v3 = E->base.y_subpos; + E->base.y_subpos = v3 + 0x8000; + uint16 v4 = (__PAIR32__(E->base.y_pos, v3) - 98304) >> 16; + E->base.y_pos = v4; + if (v4 >= E->elevat_var_A) + goto LABEL_3; + } + elevator_status = 0; + elevator_flags = 0; + QueueSfx3_Max6(0x25u); + E->base.y_pos = E->elevat_var_A; + CallSomeSamusCode(0xBu); + Elevator_Func_4(); +} + +void Elevator_Func_4(void) { // 0xA39612 + Enemy_Elevator *E = Get_Elevator(cur_enemy_index); + samus_y_pos = E->base.y_pos - 26; + samus_y_subpos = 0; + samus_x_pos = E->base.x_pos; + samus_y_speed = 0; + samus_y_subspeed = 0; +} + +void Crab_Init(void) { // 0xA396E3 + EnemyData *v1 = gEnemyData(cur_enemy_index); + v1->parameter_2 = 8; + v1->current_instruction = g_off_A396DB[v1->current_instruction & 3]; + StoneZoomer_E67A(cur_enemy_index); +} + +void Crab_Func_1(void) { // 0xA396FD + ; +} + +void Slug_Init(void) { // 0xA3993B + EnemyData *v1 = gEnemyData(cur_enemy_index); + v1->parameter_2 = 10; + v1->current_instruction = g_off_A3992B[v1->current_instruction & 3]; + StoneZoomer_E67A(cur_enemy_index); +} + +void Slug_Func_1(void) { // 0xA39955 + ; +} + +uint16 PlatformThatFallsWithSamus_Instr_3(uint16 k, uint16 j) { // 0xA39C6B + Get_PlatformThatFallsWithSamus(cur_enemy_index)->ptfwss_var_02 = 0; + return j; +} + +uint16 PlatformThatFallsWithSamus_Instr_4(uint16 k, uint16 j) { // 0xA39C76 + Get_PlatformThatFallsWithSamus(cur_enemy_index)->ptfwss_var_02 = 1; + return j; +} + +uint16 PlatformThatFallsWithSamus_Instr_1(uint16 k, uint16 j) { // 0xA39C81 + Get_PlatformThatFallsWithSamus(cur_enemy_index)->ptfwss_var_02 = 0; + return j; +} + +uint16 PlatformThatFallsWithSamus_Instr_2(uint16 k, uint16 j) { // 0xA39C8C + Get_PlatformThatFallsWithSamus(cur_enemy_index)->ptfwss_var_02 = 1; + return j; +} + +void PlatformThatFallsWithSamus_Init(void) { // 0xA39C9F + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + E->ptfwss_var_1F = -1; + uint16 ptfwss_parameter_1 = E->ptfwss_parameter_1; + E->ptfwss_var_02 = ptfwss_parameter_1; + if (ptfwss_parameter_1) + PlatformThatFalls_Init(cur_enemy_index, addr_kPlatformThatFallsWithSamus_Ilist_9BFD); + else + PlatformThatFalls_Init(cur_enemy_index, addr_kPlatformThatFallsWithSamus_Ilist_9BE7); +} + +void FastMovingSlowSinkingPlatform_Init(void) { // 0xA39CBA + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + uint16 ptfwss_parameter_1 = E->ptfwss_parameter_1; + E->ptfwss_var_02 = ptfwss_parameter_1; + if (ptfwss_parameter_1) + PlatformThatFalls_Init(cur_enemy_index, addr_kPlatformThatFallsWithSamus_Ilist_9C55); + else + PlatformThatFalls_Init(cur_enemy_index, addr_kPlatformThatFallsWithSamus_Ilist_9C3F); +} + +void PlatformThatFalls_Init(uint16 k, uint16 j) { // 0xA39CCC + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(k); + E->base.current_instruction = j; + int v3 = (uint16)(8 * LOBYTE(E->ptfwss_parameter_2)) >> 1; + E->ptfwss_var_C = kCommonEnemySpeeds_Linear[v3]; + E->ptfwss_var_B = kCommonEnemySpeeds_Linear[v3 + 1]; + E->ptfwss_var_E = kCommonEnemySpeeds_Linear[v3 + 2]; + E->ptfwss_var_D = kCommonEnemySpeeds_Linear[v3 + 3]; + E->ptfwss_var_00 = 0; + E->ptfwss_var_03 = 0; + E->ptfwss_var_04 = 0; + E->ptfwss_var_A = E->base.y_pos + 1; + E->ptfwss_var_F = 0; + E->ptfwss_var_05 = HIBYTE(E->ptfwss_parameter_2); +} +static Func_V *const off_A39C97[2] = { PlatformThatFallsWithSamus_Func_1, PlatformThatFallsWithSamus_Func_2 }; +static Func_V *const off_A39C9B[2] = { PlatformThatFallsWithSamus_Func_3, PlatformThatFallsWithSamus_Func_4 }; +void PlatformThatFallsWithSamus_Main(void) { // 0xA39D16 + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + E->ptfwss_var_00 = 0; + if (CheckIfEnemyTouchesSamus(cur_enemy_index)) + E->ptfwss_var_00 = 1; + off_A39C97[E->ptfwss_var_02](); + int v3 = (uint16)(2 * Get_PlatformThatFallsWithSamus(cur_enemy_index)->ptfwss_var_00) >> 1; + off_A39C9B[v3](); + if (E->ptfwss_var_00 != E->ptfwss_var_06) + E->ptfwss_var_F = 0; + E->ptfwss_var_06 = E->ptfwss_var_00; +} + +void PlatformThatFallsWithSamus_Func_1(void) { // 0xA39D5E + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + E->ptfwss_var_01 = E->base.x_pos; + R18_ = E->ptfwss_var_D; + R20_ = E->ptfwss_var_E; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->ptfwss_var_02 = 1; + PlatformThatFallsWithSamus_Func_8(); + } +} + +void PlatformThatFallsWithSamus_Func_2(void) { // 0xA39D83 + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + E->ptfwss_var_01 = E->base.x_pos; + R18_ = E->ptfwss_var_B; + R20_ = E->ptfwss_var_C; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->ptfwss_var_02 = 0; + PlatformThatFallsWithSamus_Func_7(); + } +} + +void PlatformThatFallsWithSamus_Func_3(void) { // 0xA39DA8 + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + if ((int16)(E->base.y_pos - E->ptfwss_var_A) < 0) + goto LABEL_5; + PlatformThatFallsWithSamus_Func_9(); + uint16 ptfwss_var_05; + ptfwss_var_05 = ++E->ptfwss_var_F; + if ((int16)(ptfwss_var_05 - E->ptfwss_var_05) >= 0) { + ptfwss_var_05 = E->ptfwss_var_05; + E->ptfwss_var_F = ptfwss_var_05; + } + int v3; + v3 = (uint16)(8 * ptfwss_var_05) >> 1; + R18_ = kCommonEnemySpeeds_Quadratic[v3 + 2]; + R20_ = kCommonEnemySpeeds_Quadratic[v3 + 3]; + if (Enemy_MoveDown(cur_enemy_index) & 1) { +LABEL_5: + E->ptfwss_var_F = 0; + PlatformThatFallsWithSamus_Func_10(); + } +} + +void PlatformThatFallsWithSamus_Func_4(void) { // 0xA39DE4 + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + if ((int16)(++E->ptfwss_var_F - E->ptfwss_var_05) >= 0) + E->ptfwss_var_F = E->ptfwss_var_05; + extra_samus_x_displacement += E->base.x_pos - E->ptfwss_var_01; + E->ptfwss_var_01 = E->base.y_pos; + int v2 = (uint16)(8 * E->ptfwss_var_F) >> 1; + R18_ = kCommonEnemySpeeds_Quadratic[v2]; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 1]; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->ptfwss_var_F = 0; + PlatformThatFallsWithSamus_Func_10(); + } + extra_samus_y_displacement += E->base.y_pos - E->ptfwss_var_01; +} + +void PlatformThatFallsWithSamus_Func_5(void) { // 0xA39E47 + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + uint16 v0 = addr_kPlatformThatFallsWithSamus_Ilist_9C13; + if ((E->ptfwss_var_1F & 0x8000u) != 0) + v0 = addr_kPlatformThatFallsWithSamus_Ilist_9BBB; + E->base.current_instruction = v0; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void PlatformThatFallsWithSamus_Func_6(void) { // 0xA39E64 + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + uint16 v0 = addr_kPlatformThatFallsWithSamus_Ilist_9C29; + if ((E->ptfwss_var_1F & 0x8000u) != 0) + v0 = addr_kPlatformThatFallsWithSamus_Ilist_9BD1; + E->base.current_instruction = v0; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void PlatformThatFallsWithSamus_Func_7(void) { // 0xA39E81 + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + uint16 v0 = addr_kPlatformThatFallsWithSamus_Ilist_9C3F; + if ((E->ptfwss_var_1F & 0x8000u) != 0) + v0 = addr_kPlatformThatFallsWithSamus_Ilist_9BE7; + E->base.current_instruction = v0; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void PlatformThatFallsWithSamus_Func_8(void) { // 0xA39E9E + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + uint16 v0 = addr_kPlatformThatFallsWithSamus_Ilist_9C55; + if ((E->ptfwss_var_1F & 0x8000u) != 0) + v0 = addr_kPlatformThatFallsWithSamus_Ilist_9BFD; + E->base.current_instruction = v0; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void PlatformThatFallsWithSamus_Func_9(void) { // 0xA39EBB + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + if (!E->ptfwss_var_03) { + E->ptfwss_var_03 = 1; + if (E->ptfwss_var_02) + PlatformThatFallsWithSamus_Func_6(); + else + PlatformThatFallsWithSamus_Func_5(); + } + E->ptfwss_var_04 = 0; +} + +void PlatformThatFallsWithSamus_Func_10(void) { // 0xA39EE1 + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + if (!E->ptfwss_var_04) { + E->ptfwss_var_04 = 1; + if (E->ptfwss_var_02) + PlatformThatFallsWithSamus_Func_8(); + else + PlatformThatFallsWithSamus_Func_7(); + } + E->ptfwss_var_03 = 0; +} + +void FastMovingSlowSinkingPlatform_Shot(void) { // 0xA39F08 + Enemy_NormalShotAI_A3(); + Enemy_PlatformThatFallsWithSamus *E = Get_PlatformThatFallsWithSamus(cur_enemy_index); + if (E->base.frozen_timer) { + if (E->ptfwss_var_02) + E->base.spritemap_pointer = addr_kPlatformThatFallsWithSamus_Sprmap_A015; + else + E->base.spritemap_pointer = addr_kPlatformThatFallsWithSamus_Sprmap_A009; + } +} + +void Roach_Func_1(void) { // 0xA3A12F + Enemy_Roach *E = Get_Roach(cur_enemy_index); + uint16 roach_var_24 = E->roach_var_24; + if (roach_var_24 != E->roach_var_25) { + E->roach_var_25 = roach_var_24; + E->base.current_instruction = roach_var_24; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void Roach_Init(void) { // 0xA3A14D + Enemy_Roach *E = Get_Roach(cur_enemy_index); + E->roach_var_25 = 0; + E->roach_var_24 = 0; + Roach_Func_2(cur_enemy_index); + Roach_Func_4(cur_enemy_index); + Roach_Func_5(cur_enemy_index); + Roach_Func_6(cur_enemy_index); + Roach_Func_7(cur_enemy_index); + Roach_Func_8(cur_enemy_index); + E->roach_var_24 = g_off_A3A111[E->roach_var_20 >> 1]; + Roach_Func_1(); + E->roach_var_B = FUNC16(Roach_Func_9); +} + +void Roach_Func_2(uint16 k) { // 0xA3A183 + Enemy_Roach *E = Get_Roach(k); + R20_ = LOBYTE(E->roach_parameter_1); + R18_ = HIBYTE(E->roach_parameter_1); + ConvertAngleToXy(); + E->roach_var_01 = R22_; + E->roach_var_00 = R24_; + E->roach_var_03 = R26_; + E->roach_var_02 = R28_; +} + +void Roach_Func_3(uint16 k) { // 0xA3A1B0 + Enemy_Roach *E = Get_Roach(k); + draw_enemy_layer = LOBYTE(E->roach_parameter_1); + CosineMult8bit(HIBYTE(E->roach_parameter_1)); + E->roach_var_01 = loop_index_end; + E->roach_var_00 = loop_index; + draw_enemy_layer = LOBYTE(E->roach_parameter_1); + SineMult8bitNegative(HIBYTE(E->roach_parameter_1)); + E->roach_var_03 = loop_index_end; + E->roach_var_02 = loop_index; +} + +void Roach_Func_4(uint16 k) { // 0xA3A1F3 + Enemy_Roach *E = Get_Roach(k); + draw_enemy_layer = LOBYTE(E->roach_parameter_1); + CosineMult8bit((uint8)(*(uint16 *)((char *)&E->roach_parameter_1 + 1) - 32)); + E->roach_var_05 = loop_index_end; + E->roach_var_04 = loop_index; + draw_enemy_layer = LOBYTE(E->roach_parameter_1); + SineMult8bitNegative((uint8)(*(uint16 *)((char *)&E->roach_parameter_1 + 1) - 32)); + E->roach_var_07 = loop_index_end; + E->roach_var_06 = loop_index; +} + +void Roach_Func_5(uint16 k) { // 0xA3A23E + Enemy_Roach *E = Get_Roach(k); + draw_enemy_layer = LOBYTE(E->roach_parameter_1); + CosineMult8bit((uint8)(*(uint16 *)((char *)&E->roach_parameter_1 + 1) + 32)); + E->roach_var_09 = loop_index_end; + E->roach_var_08 = loop_index; + draw_enemy_layer = LOBYTE(E->roach_parameter_1); + SineMult8bitNegative((uint8)(*(uint16 *)((char *)&E->roach_parameter_1 + 1) + 32)); + E->roach_var_0B = loop_index_end; + E->roach_var_0A = loop_index; +} + +void Roach_Func_6(uint16 k) { // 0xA3A289 + Enemy_Roach *E = Get_Roach(k); + E->roach_var_20 = 2 * ((uint8)(*(uint16 *)((char *)&E->roach_parameter_1 + 1) - 48) >> 5); +} + +void Roach_Func_7(uint16 k) { // 0xA3A29E + Enemy_Roach *E = Get_Roach(k); + E->roach_var_21 = 2 * ((uint8)(*(uint16 *)((char *)&E->roach_parameter_1 + 1) - 80) >> 5); +} + +void Roach_Func_8(uint16 k) { // 0xA3A2B7 + Enemy_Roach *E = Get_Roach(k); + E->roach_var_22 = 2 * ((uint8)(*(uint16 *)((char *)&E->roach_parameter_1 + 1) - 48 + 32) >> 5); +} +void CallRoachFunc(uint32 ea) { + switch (ea) { + case fnRoach_Func_9: Roach_Func_9(); return; // 0xa3a2d7 + case fnRoach_Func_10: Roach_Func_10(); return; // 0xa3a301 + case fnRoach_Func_11: Roach_Func_11(); return; // 0xa3a30b + case fnRoach_Func_12: Roach_Func_12(); return; // 0xa3a315 + case fnRoach_Func_13: Roach_Func_13(); return; // 0xa3a325 + case fnRoach_Func_14: Roach_Func_14(); return; // 0xa3a33b + case fnRoach_Func_15: Roach_Func_15(); return; // 0xa3a34b + case fnRoach_Func_16: Roach_Func_16(); return; // 0xa3a380 + case fnRoach_Func_19: Roach_Func_19(); return; // 0xa3a407 + case fnRoach_Func_20: Roach_Func_20(); return; // 0xa3a40e + case fnRoach_Func_21: Roach_Func_21(); return; // 0xa3a440 + case fnRoach_Func_22: Roach_Func_22(); return; // 0xa3a447 + case fnRoach_Func_23: Roach_Func_23(); return; // 0xa3a44e + case fnRoach_Func_24: Roach_Func_24(); return; // 0xa3a462 + case fnRoach_Func_25: Roach_Func_25(); return; // 0xa3a476 + case fnRoach_Func_26: Roach_Func_26(); return; // 0xa3a4b6 + case fnRoach_Func_27: Roach_Func_27(); return; // 0xa3a4f0 + default: Unreachable(); + } +} + + +void Roach_Main(void) { // 0xA3A2D0 + Enemy_Roach *E = Get_Roach(cur_enemy_index); + CallRoachFunc(E->roach_var_B | 0xA30000); +} + +void Roach_Func_9(void) { // 0xA3A2D7 + Enemy_Roach *E = Get_Roach(cur_enemy_index); + if (IsSamusWithinEnemy_X(cur_enemy_index, LOBYTE(E->roach_parameter_2))) { + if (IsSamusWithinEnemy_Y(cur_enemy_index, LOBYTE(E->roach_parameter_2))) + E->roach_var_B = g_off_A3A121[(uint16)(2 * HIBYTE(E->roach_parameter_2)) >> 1]; + } +} + +void Roach_Func_10(void) { // 0xA3A301 + Get_Roach(cur_enemy_index)->roach_var_B = FUNC16(Roach_Func_19); +} + +void Roach_Func_11(void) { // 0xA3A30B + Get_Roach(cur_enemy_index)->roach_var_B = FUNC16(Roach_Func_20); +} + +void Roach_Func_12(void) { // 0xA3A315 + random_number = 11; + Get_Roach(cur_enemy_index)->roach_var_B = FUNC16(Roach_Func_27); +} + +void Roach_Func_13(void) { // 0xA3A325 + Enemy_Roach *E = Get_Roach(cur_enemy_index); + E->roach_var_A = 512; + random_number = 11; + E->roach_var_B = FUNC16(Roach_Func_26); +} + +void Roach_Func_14(void) { // 0xA3A33B + Enemy_Roach *E = Get_Roach(cur_enemy_index); + E->roach_var_F = 32; + E->roach_var_B = FUNC16(Roach_Func_23); +} + +void Roach_Func_15(void) { // 0xA3A34B + uint8 v1 = 64 - CalculateAngleOfSamusFromEnemy(cur_enemy_index); + Enemy_Roach *E = Get_Roach(cur_enemy_index); + E->roach_var_C = v1; + Roach_Func_18(cur_enemy_index); + Roach_Func_17(cur_enemy_index); + E->roach_var_24 = g_off_A3A111[E->roach_var_23 >> 1]; + Roach_Func_1(); + E->roach_var_B = FUNC16(Roach_Func_21); +} + +void Roach_Func_16(void) { // 0xA3A380 + uint16 v1 = (uint8)(64 - CalculateAngleOfSamusFromEnemy(cur_enemy_index) + 0x80); + Enemy_Roach *E = Get_Roach(cur_enemy_index); + E->roach_var_C = v1; + Roach_Func_18(cur_enemy_index); + Roach_Func_17(cur_enemy_index); + E->roach_var_24 = g_off_A3A111[E->roach_var_23 >> 1]; + Roach_Func_1(); + E->roach_var_B = FUNC16(Roach_Func_22); +} + +void Roach_Func_17(uint16 k) { // 0xA3A3B5 + Enemy_Roach *E = Get_Roach(k); + E->roach_var_23 = 2 * ((uint8)(E->roach_var_C - 48) >> 5); +} + +void Roach_Func_18(uint16 k) { // 0xA3A3CA + Enemy_Roach *E = Get_Roach(k); + draw_enemy_layer = LOBYTE(E->roach_parameter_1); + CosineMult8bit(E->roach_var_C); + E->roach_var_0D = loop_index_end; + E->roach_var_0C = loop_index; + draw_enemy_layer = LOBYTE(E->roach_parameter_1); + SineMult8bitNegative(E->roach_var_C); + E->roach_var_0F = loop_index_end; + E->roach_var_0E = loop_index; +} + +void Roach_Func_19(void) { // 0xA3A407 + Roach_Func_29(cur_enemy_index); +} + +void Roach_Func_20(void) { // 0xA3A40E + Enemy_Roach *E = Get_Roach(cur_enemy_index); + if ((E->base.frame_counter & 0x10) != 0) { + E->roach_var_24 = g_off_A3A111[E->roach_var_22 >> 1]; + Roach_Func_1(); + Roach_Func_31(cur_enemy_index); + } else { + E->roach_var_24 = g_off_A3A111[E->roach_var_21 >> 1]; + Roach_Func_1(); + Roach_Func_30(cur_enemy_index); + } +} + +void Roach_Func_21(void) { // 0xA3A440 + Roach_Func_32(cur_enemy_index); +} + +void Roach_Func_22(void) { // 0xA3A447 + Roach_Func_32(cur_enemy_index); +} + +void Roach_Func_23(void) { // 0xA3A44E + Enemy_Roach *E = Get_Roach(cur_enemy_index); + if ((--E->roach_var_F & 0x8000u) != 0) + E->roach_var_B = FUNC16(Roach_Func_9); + else + Roach_Func_29(cur_enemy_index); +} + +void Roach_Func_24(void) { // 0xA3A462 + Enemy_Roach *E = Get_Roach(cur_enemy_index); + if ((--E->roach_var_F & 0x8000u) != 0) + E->roach_var_B = FUNC16(Roach_Func_27); + else + Roach_Func_33(cur_enemy_index); +} + +void Roach_Func_25(void) { // 0xA3A476 + Enemy_Roach *E = Get_Roach(cur_enemy_index); + bool v2 = (--E->roach_var_A & 0x8000u) != 0; + if (v2) { +LABEL_6: + Roach_Func_32(cur_enemy_index); + return; + } + v2 = (--E->roach_var_F & 0x8000u) != 0; + if (!v2) { + uint16 v3 = Abs16(E->base.x_pos - samus_x_pos); + if (!sign16(v3 - 96)) { + uint16 v4 = Abs16(E->base.y_pos - samus_y_pos); + if (!sign16(v4 - 96)) + Roach_Func_28(); + } + goto LABEL_6; + } + E->roach_var_B = FUNC16(Roach_Func_26); +} + +void Roach_Func_26(void) { // 0xA3A4B6 + uint8 v1 = NextRandom() - 64; + Enemy_Roach *E = Get_Roach(cur_enemy_index); + E->roach_var_C += v1; + Roach_Func_18(cur_enemy_index); + Roach_Func_17(cur_enemy_index); + E->roach_var_24 = g_off_A3A111[E->roach_var_23 >> 1]; + Roach_Func_1(); + E->roach_var_F = 32; + E->roach_var_B = FUNC16(Roach_Func_25); +} + +void Roach_Func_27(void) { // 0xA3A4F0 + uint8 v1 = NextRandom() - 64; + Enemy_Roach *E = Get_Roach(cur_enemy_index); + E->roach_var_C += v1; + Roach_Func_18(cur_enemy_index); + Roach_Func_17(cur_enemy_index); + E->roach_var_24 = g_off_A3A111[E->roach_var_23 >> 1]; + Roach_Func_1(); + E->roach_var_F = 32; + E->roach_var_B = FUNC16(Roach_Func_24); +} + +void Roach_Func_28(void) { // 0xA3A52A + Enemy_Roach *E = Get_Roach(cur_enemy_index); + E->roach_var_0D = -E->roach_var_0D; + E->roach_var_0C = -E->roach_var_0C; + E->roach_var_0F = -E->roach_var_0F; + E->roach_var_0E = -E->roach_var_0E; + uint16 v1 = ((uint8)E->roach_var_23 + 4) & 7; + E->roach_var_23 = v1; + E->roach_var_24 = g_off_A3A111[v1 >> 1]; + Roach_Func_1(); +} + +void Roach_Func_29(uint16 k) { // 0xA3A578 + Enemy_Roach *E = Get_Roach(k); + varE24 = E->roach_var_01; + varE26 = E->roach_var_00; + varE28 = E->roach_var_03; + varE2A = E->roach_var_02; + enemy_population_ptr = HIBYTE(E->roach_parameter_1); + EnemyFunc_B691(); +} + +void Roach_Func_30(uint16 k) { // 0xA3A5A3 + Enemy_Roach *E = Get_Roach(k); + E->base.x_pos += E->roach_var_05; + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->roach_var_04, x_subpos); + uint16 v4 = E->roach_var_04 + x_subpos; + if (v3) + ++E->base.x_pos; + E->base.x_subpos = v4; + E->base.y_pos += E->roach_var_07; + uint16 y_subpos = E->base.y_subpos; + v3 = __CFADD__uint16(E->roach_var_06, y_subpos); + uint16 v6 = E->roach_var_06 + y_subpos; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v6; +} + +void Roach_Func_31(uint16 k) { // 0xA3A5DA + Enemy_Roach *E = Get_Roach(k); + E->base.x_pos += E->roach_var_09; + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->roach_var_08, x_subpos); + uint16 v4 = E->roach_var_08 + x_subpos; + if (v3) + ++E->base.x_pos; + E->base.x_subpos = v4; + E->base.y_pos += E->roach_var_0B; + uint16 y_subpos = E->base.y_subpos; + v3 = __CFADD__uint16(E->roach_var_0A, y_subpos); + uint16 v6 = E->roach_var_0A + y_subpos; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v6; +} + +void Roach_Func_32(uint16 k) { // 0xA3A611 + Enemy_Roach *E = Get_Roach(k); + E->base.x_pos += E->roach_var_0D; + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->roach_var_0C, x_subpos); + uint16 v4 = E->roach_var_0C + x_subpos; + if (v3) + ++E->base.x_pos; + E->base.x_subpos = v4; + E->base.y_pos += E->roach_var_0F; + uint16 y_subpos = E->base.y_subpos; + v3 = __CFADD__uint16(E->roach_var_0E, y_subpos); + uint16 v6 = E->roach_var_0E + y_subpos; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v6; +} + +void Roach_Func_33(uint16 k) { // 0xA3A648 + Enemy_Roach *E = Get_Roach(k); + R18_ = E->roach_var_0C; + R20_ = E->roach_var_0D; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->roach_var_B = FUNC16(Roach_Func_9); + } else { + R18_ = E->roach_var_0E; + R20_ = E->roach_var_0F; + if (Enemy_MoveDown(k) & 1) + E->roach_var_B = FUNC16(Roach_Func_9); + } +} + +void Mochtroid_Init(void) { // 0xA3A77D + Enemy_Mochtroid *E = Get_Mochtroid(cur_enemy_index); + E->base.layer = 2; + Mochtroid_Func_4(cur_enemy_index, addr_kMochtroid_Ilist_A745); + E->mochtr_var_F = 0; +} +static Func_V *const off_A3A7A4[3] = { Mochtroid_Func_1, Mochtroid_Func_3, Mochtroid_Func_2 }; +void Mochtroid_Main(void) { // 0xA3A790 + uint16 v0 = 2 * Get_Mochtroid(cur_enemy_index)->mochtr_var_F; + Get_Mochtroid(cur_enemy_index)->mochtr_var_F = 0; + off_A3A7A4[v0 >> 1](); +} + +void Mochtroid_Func_1(void) { // 0xA3A7AA + int16 v4; + int16 v5; + int16 v9; + int16 v10; + + R18_ = 0; + R20_ = 0; + Enemy_Mochtroid *E = Get_Mochtroid(cur_enemy_index); + *(uint16 *)((char *)&R18_ + 1) = (uint16)(E->base.y_pos - samus_y_pos) >> 2; + if ((*(uint16 *)((char *)&R18_ + 1) & 0x2000) != 0) + R20_ = (uint8)R20_ | 0xFFC0; + uint16 mochtr_var_C = E->mochtr_var_C; + bool v3 = mochtr_var_C < R18_; + E->mochtr_var_C = mochtr_var_C - R18_; + v4 = E->mochtr_var_D - (v3 + R20_); + E->mochtr_var_D = v4; + if (v4 < 0) { + if ((uint16)v4 < 0xFFFDu) { + v5 = -3; + goto LABEL_8; + } + } else if ((uint16)v4 >= 3u) { + v5 = 3; +LABEL_8: + E->mochtr_var_D = v5; + E->mochtr_var_C = 0; + } + if (!E->mochtr_var_C && !E->mochtr_var_D) { + E->mochtr_var_C = 0; + E->mochtr_var_D = 0; + } + R18_ = E->mochtr_var_C; + R20_ = E->mochtr_var_D; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->mochtr_var_C = 0; + E->mochtr_var_D = 0; + } + R18_ = 0; + R20_ = 0; + *(uint16 *)((char *)&R18_ + 1) = (uint16)(E->base.x_pos - samus_x_pos) >> 2; + if ((*(uint16 *)((char *)&R18_ + 1) & 0x2000) != 0) + R20_ = (uint8)R20_ | 0xFFC0; + uint16 mochtr_var_A = E->mochtr_var_A; + v3 = mochtr_var_A < R18_; + E->mochtr_var_A = mochtr_var_A - R18_; + v9 = E->mochtr_var_B - (v3 + R20_); + E->mochtr_var_B = v9; + if (v9 < 0) { + if ((uint16)v9 < 0xFFFDu) { + v10 = -3; + goto LABEL_21; + } + } else if ((uint16)v9 >= 3u) { + v10 = 3; +LABEL_21: + E->mochtr_var_B = v10; + E->mochtr_var_A = 0; + } + if (!E->mochtr_var_A && !E->mochtr_var_B) { + E->mochtr_var_A = 0; + E->mochtr_var_B = 0; + } + R18_ = E->mochtr_var_A; + R20_ = E->mochtr_var_B; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->mochtr_var_A = 0; + E->mochtr_var_B = 0; + } + Mochtroid_Func_4(cur_enemy_index, addr_kMochtroid_Ilist_A745); +} + +void Mochtroid_Func_2(void) { // 0xA3A88F + Enemy_Mochtroid *E = Get_Mochtroid(cur_enemy_index); + int v2 = (uint8)(E->mochtr_var_E & 6) >> 1; + E->base.x_pos += g_word_A3A76D[v2]; + E->base.y_pos += g_word_A3A775[v2]; + E->mochtr_var_A = 0; + E->mochtr_var_B = 0; + E->mochtr_var_C = 0; + E->mochtr_var_D = 0; + if (E->mochtr_var_E-- == 1) + E->mochtr_var_F = 0; + Mochtroid_Func_4(cur_enemy_index, addr_kMochtroid_Ilist_A745); +} + +void Mochtroid_Func_3(void) { // 0xA3A8C8 + Enemy_Mochtroid *E = Get_Mochtroid(cur_enemy_index); + uint16 x_pos = E->base.x_pos; + if (x_pos == samus_x_pos) { + E->mochtr_var_A = 0; + E->mochtr_var_B = 0; + } else if ((int16)(x_pos - samus_x_pos) >= 0) { + E->mochtr_var_A = 0; + E->mochtr_var_B = -1; + } else { + E->mochtr_var_A = 0; + E->mochtr_var_B = 1; + } + R18_ = E->mochtr_var_A; + R20_ = E->mochtr_var_B; + Enemy_MoveRight_IgnoreSlopes(cur_enemy_index); + uint16 y_pos = E->base.y_pos; + if (y_pos == samus_y_pos) { + E->mochtr_var_C = 0; + E->mochtr_var_D = 0; + } else if ((int16)(y_pos - samus_y_pos) >= 0) { + E->mochtr_var_C = 0; + E->mochtr_var_D = -1; + } else { + E->mochtr_var_C = 0; + E->mochtr_var_D = 1; + } + R18_ = E->mochtr_var_C; + R20_ = E->mochtr_var_D; + Enemy_MoveDown(cur_enemy_index); +} + +void Mochtroid_Func_4(uint16 k, uint16 a) { // 0xA3A93C + Enemy_Mochtroid *E = Get_Mochtroid(k); + if (a != E->mochtr_var_01) { + E->mochtr_var_01 = a; + E->base.current_instruction = a; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void Mochtroid_Touch(void) { // 0xA3A953 + Enemy_Mochtroid *E = Get_Mochtroid(cur_enemy_index); + E->mochtr_var_F = 1; + Mochtroid_Func_4(cur_enemy_index, addr_kMochtroid_Ilist_A759); + ++E->mochtr_var_20; + if (samus_contact_damage_index) + goto LABEL_7; + if ((enemy_damage_routine_exec_count & 7) == 7 && !sign16(samus_health - 30)) + QueueSfx3_Max6(0x2Du); + if (!sign16(E->mochtr_var_20 - 80)) { + E->mochtr_var_20 = 0; +LABEL_7: + Enemy_NormalTouchAI_A3(); + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + } +} + +void Mochtroid_Shot(void) { // 0xA3A9A8 + Enemy_NormalShotAI_A3(); +} + +uint16 Sidehopper_Func_1(uint16 k, uint16 j) { // 0xA3AA68 + uint16 *v2 = (uint16 *)RomPtr_A3(j); + QueueSfx2_Max3(*v2); + return j + 2; +} + +uint16 Sidehopper_Instr_1(uint16 k, uint16 j) { // 0xA3AAFE + Get_Sidehopper(cur_enemy_index)->sideh_var_04 = 1; + return j; +} + +void Sidehopper_Init(void) { // 0xA3AB09 + random_number = 37; + NextRandom(); + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + E->sideh_var_03 = 0; + E->sideh_var_04 = 0; + E->sideh_var_05 = 0; + uint16 v2 = 2 * get_EnemyDef_A2(E->base.enemy_ptr)->field_2A; + E->sideh_var_06 = v2; + uint16 v4; + if (E->sideh_parameter_1) + v4 = g_off_A3AACA[E->sideh_var_06 >> 1]; + else + v4 = g_off_A3AAC2[E->sideh_var_06 >> 1]; + E->sideh_var_00 = v4; + Sidehopper_Func_3(); + if (get_EnemyDef_A2(E->base.enemy_ptr)->field_2A) + Get_Sidehopper(cur_enemy_index)->sideh_var_05 = 2; + int v6 = E->sideh_var_05 >> 1; + R22_ = g_word_A3AAEE[v6]; + R24_ = g_word_A3AAE6[v6]; + E->sideh_var_01 = Sidehopper_Func_2(); + int v8 = E->sideh_var_05 >> 1; + R22_ = g_word_A3AAFA[v8]; + R24_ = g_word_A3AAF2[v8]; + E->sideh_var_02 = Sidehopper_Func_2(); + E->sideh_var_B = FUNC16(Sidehopper_Func_4); +} + +uint16 Sidehopper_Func_2(void) { // 0xA3AB9D + R18_ = 0; + R20_ = 0; + do { + R18_ += R24_; + R20_ += *(uint16 *)((char *)kCommonEnemySpeeds_Quadratic + (uint16)(8 * R18_) + 1); + } while (sign16(R20_ - R22_)); + return R18_; +} + +void Sidehopper_Func_3(void) { // 0xA3ABBB + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + E->base.current_instruction = E->sideh_var_00; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void CallSidehopperFunc(uint32 ea) { + switch (ea) { + case fnSidehopper_Func_4: Sidehopper_Func_4(cur_enemy_index); return; // 0xa3abd6 + case fnSidehopper_Func_5: Sidehopper_Func_5(); return; // 0xa3abe6 + case fnSidehopper_Func_6: Sidehopper_Func_6(); return; // 0xa3ac13 + case fnSidehopper_Func_7: Sidehopper_Func_7(); return; // 0xa3ac40 + case fnSidehopper_Func_8: Sidehopper_Func_8(); return; // 0xa3ac56 + case fnSidehopper_Func_9: Sidehopper_Func_9(); return; // 0xa3ac6c + case fnSidehopper_Func_10: Sidehopper_Func_10(); return; // 0xa3ac8f + case fnSidehopper_Func_11: Sidehopper_Func_11(); return; // 0xa3aca8 + case fnSidehopper_Func_12: Sidehopper_Func_12(); return; // 0xa3accb + case fnSidehopper_Func_13: Sidehopper_Func_13(); return; // 0xa3ace4 + case fnSidehopper_Func_14: Sidehopper_Func_14(); return; // 0xa3ad0e + case fnSidehopper_Func_15: Sidehopper_Func_15(); return; // 0xa3ad20 + case fnSidehopper_Func_16: Sidehopper_Func_16(); return; // 0xa3ad32 + case fnSidehopper_Func_17: Sidehopper_Func_17(); return; // 0xa3ad44 + case fnSidehopper_Func_18: Sidehopper_Func_18(); return; // 0xa3ad56 + default: Unreachable(); + } +} + +void Sidehopper_Main(void) { // 0xA3ABCF + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + CallSidehopperFunc(E->sideh_var_B | 0xA30000); +} + +void Sidehopper_Func_4(uint16 k) { // 0xA3ABD6 + uint16 v1 = g_off_A3AAE2[NextRandom() & 1]; + Get_Sidehopper(k)->sideh_var_B = v1; +} + +void Sidehopper_Func_5(void) { // 0xA3ABE6 + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + int v1 = E->sideh_var_05 >> 1; + E->sideh_var_E = g_word_A3AAE6[v1]; + E->sideh_var_D = g_word_A3AAEA[v1]; + E->sideh_var_C = E->sideh_var_01; + E->sideh_var_B = FUNC16(Sidehopper_Func_7); + if (E->sideh_parameter_1) + E->sideh_var_B = FUNC16(Sidehopper_Func_8); +} + +void Sidehopper_Func_6(void) { // 0xA3AC13 + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + int v1 = E->sideh_var_05 >> 1; + E->sideh_var_E = g_word_A3AAF2[v1]; + E->sideh_var_D = g_word_A3AAF6[v1]; + E->sideh_var_C = E->sideh_var_02; + E->sideh_var_B = FUNC16(Sidehopper_Func_7); + if (E->sideh_parameter_1) + E->sideh_var_B = FUNC16(Sidehopper_Func_8); +} + +void Sidehopper_Func_7(void) { // 0xA3AC40 + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + E->sideh_var_B = FUNC16(Sidehopper_Func_9); + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) + E->sideh_var_B = FUNC16(Sidehopper_Func_10); +} + +void Sidehopper_Func_8(void) { // 0xA3AC56 + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + E->sideh_var_B = FUNC16(Sidehopper_Func_11); + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) + E->sideh_var_B = FUNC16(Sidehopper_Func_12); +} + +void Sidehopper_Func_9(void) { // 0xA3AC6C + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + E->sideh_var_D = -E->sideh_var_D; + E->sideh_var_00 = g_off_A3AAD2[E->sideh_var_06 >> 1]; + Sidehopper_Func_3(); + E->sideh_var_B = FUNC16(Sidehopper_Func_14); +} + +void Sidehopper_Func_10(void) { // 0xA3AC8F + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + E->sideh_var_00 = g_off_A3AAD2[E->sideh_var_06 >> 1]; + Sidehopper_Func_3(); + E->sideh_var_B = FUNC16(Sidehopper_Func_15); +} + +void Sidehopper_Func_11(void) { // 0xA3ACA8 + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + E->sideh_var_D = -E->sideh_var_D; + E->sideh_var_00 = g_off_A3AADA[E->sideh_var_06 >> 1]; + Sidehopper_Func_3(); + E->sideh_var_B = FUNC16(Sidehopper_Func_16); +} + +void Sidehopper_Func_12(void) { // 0xA3ACCB + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + E->sideh_var_00 = g_off_A3AADA[E->sideh_var_06 >> 1]; + Sidehopper_Func_3(); + E->sideh_var_B = FUNC16(Sidehopper_Func_17); +} + +void Sidehopper_Func_13(void) { // 0xA3ACE4 + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + E->sideh_var_00 = g_off_A3AAC2[E->sideh_var_06 >> 1]; + if (E->sideh_parameter_1) + E->sideh_var_00 = g_off_A3AACA[E->sideh_var_06 >> 1]; + Sidehopper_Func_3(); + E->sideh_var_B = FUNC16(Sidehopper_Func_18); +} + +void Sidehopper_Func_14(void) { // 0xA3AD0E + if (Get_Sidehopper(cur_enemy_index)->sideh_var_03) + Sidehopper_Func_20(); + else + Sidehopper_Func_19(); +} + +void Sidehopper_Func_15(void) { // 0xA3AD20 + if (Get_Sidehopper(cur_enemy_index)->sideh_var_03) + Sidehopper_Func_20(); + else + Sidehopper_Func_19(); +} + +void Sidehopper_Func_16(void) { // 0xA3AD32 + if (Get_Sidehopper(cur_enemy_index)->sideh_var_03) + Sidehopper_Func_22(); + else + Sidehopper_Func_21(); +} + +void Sidehopper_Func_17(void) { // 0xA3AD44 + if (Get_Sidehopper(cur_enemy_index)->sideh_var_03) + Sidehopper_Func_22(); + else + Sidehopper_Func_21(); +} + +void Sidehopper_Func_18(void) { // 0xA3AD56 + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + if (E->sideh_var_04) { + E->sideh_var_04 = 0; + E->sideh_var_B = FUNC16(Sidehopper_Func_4); + } +} + +void Sidehopper_Func_19(void) { // 0xA3AD6D + int16 v3; + + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + int v2 = (uint16)(8 * E->sideh_var_C) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 3]; + R18_ = kCommonEnemySpeeds_Quadratic[v2 + 2]; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->sideh_var_D = -E->sideh_var_D; + E->sideh_var_03 = 1; + } else { + R20_ = E->sideh_var_D; + R18_ = 0; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->sideh_var_D = -E->sideh_var_D; + E->sideh_var_03 = 1; + } else { + v3 = E->sideh_var_C - E->sideh_var_E; + E->sideh_var_C = v3; + if (v3 < 0) { + E->sideh_var_03 = 1; + E->sideh_var_C = 0; + } + } + } +} + +void Sidehopper_Func_20(void) { // 0xA3ADD4 + int16 v3; + + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + int v2 = (uint16)(8 * E->sideh_var_C) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 1]; + R18_ = kCommonEnemySpeeds_Quadratic[v2]; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->sideh_var_03 = 0; + E->sideh_var_B = FUNC16(Sidehopper_Func_13); + } else { + R20_ = E->sideh_var_D; + R18_ = 0; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) + E->sideh_var_D = -E->sideh_var_D; + v3 = E->sideh_var_E + E->sideh_var_C; + if (!sign16(v3 - 64)) + v3 = 64; + E->sideh_var_C = v3; + } +} + +void Sidehopper_Func_21(void) { // 0xA3AE27 + int16 v3; + + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + int v2 = (uint16)(8 * E->sideh_var_C) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 1]; + R18_ = kCommonEnemySpeeds_Quadratic[v2]; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->sideh_var_D = -E->sideh_var_D; + E->sideh_var_03 = 1; + } else { + R20_ = E->sideh_var_D; + R18_ = 0; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->sideh_var_D = -E->sideh_var_D; + E->sideh_var_03 = 1; + } else { + v3 = E->sideh_var_C - E->sideh_var_E; + E->sideh_var_C = v3; + if (v3 < 0) { + E->sideh_var_03 = 1; + E->sideh_var_C = 0; + } + } + } +} + +void Sidehopper_Func_22(void) { // 0xA3AE8E + int16 v3; + + Enemy_Sidehopper *E = Get_Sidehopper(cur_enemy_index); + int v2 = (uint16)(8 * E->sideh_var_C) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 3]; + R18_ = kCommonEnemySpeeds_Quadratic[v2 + 2]; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->sideh_var_03 = 0; + E->sideh_var_B = FUNC16(Sidehopper_Func_13); + } else { + R20_ = E->sideh_var_D; + R18_ = 0; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) + E->sideh_var_D = -E->sideh_var_D; + v3 = E->sideh_var_E + E->sideh_var_C; + if (!sign16(v3 - 64)) + v3 = 64; + E->sideh_var_C = v3; + } +} + +uint16 MaridiaRefillCandy_Instr_1(uint16 k, uint16 j) { // 0xA3B429 + Get_MaridiaRefillCandy(cur_enemy_index)->mrcy_var_00 = 4; + return j; +} + +uint16 MaridiaRefillCandy_Instr_2(uint16 k, uint16 j) { // 0xA3B434 + Get_MaridiaRefillCandy(cur_enemy_index)->mrcy_var_00 = 8; + return j; +} + +uint16 MaridiaRefillCandy_Instr_3(uint16 k, uint16 j) { // 0xA3B43F + Get_MaridiaRefillCandy(cur_enemy_index)->mrcy_var_00 = 12; + return j; +} + +void MaridiaRefillCandy_Init(void) { // 0xA3B44A + Enemy_MaridiaRefillCandy *E = Get_MaridiaRefillCandy(cur_enemy_index); + E->mrcy_parameter_1 = FUNC16(MaridiaRefillCandy_Func_1); + E->mrcy_var_D = 0; + E->mrcy_var_E = 0; + E->mrcy_var_00 = 0; + E->base.current_instruction = addr_kMaridiaRefillCandy_Ilist_B3C1; + E->base.properties |= kEnemyProps_Invisible; + E->mrcy_var_B = E->base.x_pos; + E->mrcy_var_C = E->base.y_pos; +} + +void CallMaridiaRefillCandyFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnMaridiaRefillCandy_Func_1: MaridiaRefillCandy_Func_1(); return; + case fnMaridiaRefillCandy_Func_2: MaridiaRefillCandy_Func_2(k); return; + case fnMaridiaRefillCandy_Func_3: MaridiaRefillCandy_Func_3(k); return; + default: Unreachable(); + } +} + +void MaridiaRefillCandy_Main(void) { // 0xA3B47C + Enemy_MaridiaRefillCandy *E = Get_MaridiaRefillCandy(cur_enemy_index); + CallMaridiaRefillCandyFunc(E->mrcy_parameter_1 | 0xA30000, cur_enemy_index); +} + +void MaridiaRefillCandy_Func_1(void) { // 0xA3B482 + int16 v1; + + if (IsSamusWithinEnemy_X(cur_enemy_index, 0x80)) { + v1 = 1; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) + v1 = 3; + Enemy_MaridiaRefillCandy *E = Get_MaridiaRefillCandy(cur_enemy_index); + E->mrcy_var_D = v1; + MaridiaRefillCandy_Func_4(); + E->mrcy_parameter_1 = FUNC16(MaridiaRefillCandy_Func_2); + } +} + +void MaridiaRefillCandy_Func_2(uint16 k) { // 0xA3B4A8 + Enemy_MaridiaRefillCandy *E = Get_MaridiaRefillCandy(k); + E->base.properties &= ~kEnemyProps_Invisible; + if ((GetSamusEnemyDelta_Y(k) & 0x8000u) != 0) { + R20_ = 0; + R18_ = FUNC16(Enemy_GrappleReact_NoInteract_A3); + Enemy_SubPos_Y(k); + } else { + --E->mrcy_var_D; + MaridiaRefillCandy_Func_4(); + E->mrcy_var_F = 0; + E->mrcy_parameter_1 = FUNC16(MaridiaRefillCandy_Func_3); + } +} + +void MaridiaRefillCandy_Func_3(uint16 k) { // 0xA3B4D6 + Enemy_MaridiaRefillCandy *E = Get_MaridiaRefillCandy(k); + if (E->mrcy_var_D) { + int v2; + v2 = E->mrcy_var_00 >> 1; + R20_ = g_word_A3B415[v2]; + R18_ = g_word_A3B415[v2 + 1]; + Enemy_AddPos_X(k); + if (!CheckIfEnemyIsOnScreen()) { +LABEL_3: + MaridiaRefillCandy_Func_4(); + return; + } + } else { + int v3 = E->mrcy_var_00 >> 1; + R20_ = g_word_A3B415[v3]; + R18_ = g_word_A3B415[v3 + 1]; + Enemy_SubPos_X(k); + if (!CheckIfEnemyIsOnScreen()) + goto LABEL_3; + } + E->base.properties |= kEnemyProps_Invisible; + E->base.x_pos = E->mrcy_var_B; + E->base.y_pos = E->mrcy_var_C; + E->mrcy_var_D = 0; + MaridiaRefillCandy_Func_4(); + E->mrcy_parameter_1 = FUNC16(MaridiaRefillCandy_Func_1); +} + +void MaridiaRefillCandy_Func_4(void) { // 0xA3B537 + Enemy_MaridiaRefillCandy *E = Get_MaridiaRefillCandy(cur_enemy_index); + uint16 mrcy_var_D = E->mrcy_var_D; + if (mrcy_var_D != E->mrcy_var_E) { + E->mrcy_var_E = mrcy_var_D; + E->base.current_instruction = g_off_A3B40D[mrcy_var_D]; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void MaridiaRefillCandy_Func_5(void) { // 0xA3B557 + ; +} + +void MaridiaRefillCandy_Func_6(void) { // 0xA3B55B + ; +} + +void NorfairSlowFireball_Init(void) { // 0xA3B66F + EnemyData *v1 = gEnemyData(cur_enemy_index); + v1->parameter_2 = 6; + v1->current_instruction = g_off_A3B667[v1->properties & 3]; + StoneZoomer_E67A(cur_enemy_index); +} + +void NorfairSlowFireball_Func_1(void) { // 0xA3B6F9 + uint16 current_instruction = gEnemyData(cur_enemy_index)->current_instruction; + while (current_instruction) + ; +} + +uint16 Bang_Instr_1(uint16 k, uint16 j) { // 0xA3BA78 + QueueSfx2_Max6(0x56u); + return j; +} + +uint16 Bang_Instr_2(uint16 k, uint16 j) { // 0xA3BAA8 + Get_Bang(cur_enemy_index)->bang_var_22 = 1; + return j; +} + +void Bang_Init(void) { // 0xA3BAB3 + Enemy_Bang *E = Get_Bang(cur_enemy_index); + E->bang_var_B = E->base.palette_index; + E->base.properties |= kEnemyProps_BlockPlasmaBeam; + E->bang_var_F = FUNC16(Bang_Func_6); + E->bang_var_00 = 16; + E->bang_var_01 = 0; + E->bang_var_02 = 0; + E->bang_var_20 = 0; + E->bang_var_21 = 0; + E->bang_var_22 = 0; + E->bang_var_0B = g_word_A3BA84[(uint16)(2 * LOBYTE(E->bang_parameter_2)) >> 1]; + int v1 = (uint16)(4 * HIBYTE(E->bang_parameter_2)) >> 1; + uint16 v2 = g_word_A3BC6A[v1]; + E->bang_var_0C = v2; + E->bang_var_0D = v2; + E->bang_var_0E = g_word_A3BC6A[v1 + 1]; + if (!E->base.current_instruction) + E->bang_var_F = FUNC16(Bang_Func_7); + E->base.current_instruction = addr_kBang_Ilist_B75E; +} + +void Bang_Main(void) { // 0xA3BB25 + Enemy_Bang *E = Get_Bang(cur_enemy_index); + Call(E->bang_parameter_1 | 0xA30000); +} + +void Bang_Func_1(void) { // 0xA3BB2B + uint16 v0 = Get_Bang(cur_enemy_index + 64)->bang_var_20 + 10; + Get_Bang(cur_enemy_index)->bang_var_20 = v0; + Bang_Func_18(); + Enemy_Bang *E = Get_Bang(cur_enemy_index); + E->base.properties |= kEnemyProps_Tangible; +} + +void Bang_Func_2(void) { // 0xA3BB4A + uint16 v0 = Get_Bang(cur_enemy_index + 1984)->bang_var_00 + 20; + Enemy_Bang *E = Get_Bang(cur_enemy_index); + E->bang_var_20 = v0; + Bang_Func_18(); + E->base.properties |= kEnemyProps_Tangible; +} + +void Bang_Func_3(void) { // 0xA3BB66 + int16 bang_var_B; + + Bang_Func_5(); + Enemy_Bang *E0 = Get_Bang(cur_enemy_index); + uint16 x_pos = E0->base.x_pos; + int v3 = cur_enemy_index >> 1; + enemy_drawing_queue[v3 + 91] = x_pos; + Enemy_Bang *E1 = Get_Bang(cur_enemy_index + 64); + E1->base.x_pos = x_pos; + uint16 y_pos = E0->base.y_pos; + enemy_drawing_queue[v3 + 93] = y_pos; + E1->base.y_pos = y_pos; + bang_var_B = E0->bang_var_B; + if ((E0->bang_var_20 & 1) != 0) + bang_var_B = 3072; + E0->base.palette_index = bang_var_B; + Bang_Func_18(); + if (E0->bang_var_22) { + E0->bang_var_22 = 0; + if (E0->bang_var_20 == 9) { + E0->base.invincibility_timer = 16; + E0->base.properties |= kEnemyProps_Tangible; + uint16 v7 = DetermineDirectionOfSamusFromEnemy(); + uint16 v8 = Bang_Func_4(v7); + EnemyDeathAnimation(cur_enemy_index, v8); + uint16 v9 = cur_enemy_index; + Enemy_Bang *E = Get_Bang(cur_enemy_index + 64); + E->base.properties |= 0x200u; + enemy_drawing_queue[(v9 >> 1) + 97] |= 0x200u; + } else { + ++E0->bang_var_20; + Bang_Func_18(); + } + } +} + +uint16 Bang_Func_4(uint16 a) { // 0xA3BBEB + int i; + + enemy_bottom_border_collision = a; + if (!sign16(projectile_counter - 5)) + return 1; + for (i = 0; projectile_damage[i >> 1]; i += 2) + ; + Enemy_Bang *E = Get_Bang(cur_enemy_index); + int v3 = i >> 1; + projectile_x_pos[v3] = E->base.x_pos; + projectile_y_pos[v3] = E->base.y_pos; + projectile_dir[v3] = enemy_bottom_border_collision; + projectile_type[v3] = equipped_beams & 0xF | 0x10; + ++projectile_counter; + R20_ = i; + ProjectileReflection(); + projectile_damage[v3] = E->bang_var_E; + QueueSfx1_Max6(g_word_A3BC4A[projectile_type[v3] & 0xF]); + return 0; +} + +void Bang_Func_5(void) { // 0xA3BC9E + Enemy_Bang *E = Get_Bang(cur_enemy_index); + CallEnemyPreInstr(E->bang_var_F | 0xA30000); +} + +void Bang_Func_6(uint16 k) { // 0xA3BCA5 + Enemy_Bang *E = Get_Bang(cur_enemy_index); + uint16 v1 = E->bang_var_00 - 1; + E->bang_var_00 = v1; + if (!v1) { + E->bang_var_00 = 16; + E->bang_var_F = FUNC16(Bang_Func_8); + } +} + +void Bang_Func_7(uint16 k) { // 0xA3BCC1 + ; +} + +void Bang_Func_8(uint16 k) { // 0xA3BCC5 + uint8 v1 = CalculateAngleOfSamusFromEnemy(cur_enemy_index) - 64; + Enemy_Bang *E = Get_Bang(cur_enemy_index); + E->bang_var_01 = v1; + E->bang_var_F = FUNC16(Bang_Func_10); + E->bang_var_07 = 0; + E->bang_var_08 = 0; + E->bang_var_09 = 0; + E->bang_var_0A = 0; +} + +void Bang_Func_9(void) { // 0xA3BCF1 + uint8 v1 = CalculateAngleOfSamusFromEnemy(cur_enemy_index) - 64; + Enemy_Bang *E = Get_Bang(cur_enemy_index); + E->bang_var_02 = v1; + uint16 v3 = SignExtend8(v1 - E->bang_var_01); + uint16 v4 = Abs16(v3); + if (!sign16(v4 - 48)) + E->bang_var_F = FUNC16(Bang_Func_11); +} + +void Bang_Func_10(uint16 k) { // 0xA3BD1C + Bang_Func_14(); + Bang_Func_15(); + Bang_Func_12(); + Bang_Func_9(); +} + +void Bang_Func_11(uint16 k) { // 0xA3BD2C + Bang_Func_14(); + Bang_Func_15(); + Bang_Func_13(); + Enemy_Bang *E = Get_Bang(cur_enemy_index); + if (E->bang_var_0A || (int16)E->bang_var_09 <= 0) + E->bang_var_F = FUNC16(Bang_Func_6); +} + +void Bang_Func_12(void) { // 0xA3BD4F + int16 v1; + + Enemy_Bang *E = Get_Bang(cur_enemy_index); + v1 = E->bang_var_0C - 1; + E->bang_var_0C = v1; + if (v1 < 0) { + E->bang_var_0C = E->bang_var_0D; + if ((int16)(E->bang_var_0A - E->bang_var_0B) < 0) { + E->bang_var_09 += 22; + E->bang_var_0A += E->bang_var_09; + } + } +} + +void Bang_Func_13(void) { // 0xA3BD89 + int16 v1; + + Enemy_Bang *E = Get_Bang(cur_enemy_index); + v1 = E->bang_var_0C - 1; + E->bang_var_0C = v1; + if (v1 < 0) { + E->bang_var_0C = E->bang_var_0E; + E->bang_var_09 -= 22; + E->bang_var_0A -= E->bang_var_09; + } +} + +void Bang_Func_14(void) { // 0xA3BDB9 + char v2; // t0 + + R18_ = kSine16bit[(uint8)(Get_Bang(cur_enemy_index)->bang_var_01 + 64)]; + if ((R18_ & 0x8000u) != 0) + Get_Bang(cur_enemy_index)->bang_var_07 = 1; + uint16 v1 = Abs16(R18_) & 0xFF00; + v2 = v1; + LOBYTE(v1) = HIBYTE(v1); + HIBYTE(v1) = v2; + R22_ = v1; + Enemy_Bang *E = Get_Bang(cur_enemy_index); + R24_ = E->bang_var_0A; + Bang_Func_16(); + R22_ = R28_; + R24_ = g_word_7E001E; + if (E->bang_var_07) { + Bang_Func_17(); + R22_ = R28_; + R24_ = g_word_7E001E; + } + uint16 x_subpos = E->base.x_subpos; + bool v5 = __CFADD__uint16(R22_, x_subpos); + E->base.x_subpos = R22_ + x_subpos; + E->base.x_pos += R24_ + v5; +} + +void Bang_Func_15(void) { // 0xA3BE1C + char v2; // t0 + + R18_ = kSine16bit[(uint16)(2 * (uint8)Get_Bang(cur_enemy_index)->bang_var_01) >> 1]; + if ((R18_ & 0x8000u) != 0) + Get_Bang(cur_enemy_index)->bang_var_08 = 1; + uint16 v1 = Abs16(R18_) & 0xFF00; + v2 = v1; + LOBYTE(v1) = HIBYTE(v1); + HIBYTE(v1) = v2; + R22_ = v1; + Enemy_Bang *E = Get_Bang(cur_enemy_index); + R24_ = E->bang_var_0A; + Bang_Func_16(); + R22_ = R28_; + R24_ = g_word_7E001E; + if (E->bang_var_08) { + Bang_Func_17(); + R22_ = R28_; + R24_ = g_word_7E001E; + } + uint16 y_subpos = E->base.y_subpos; + bool v5 = __CFADD__uint16(R22_, y_subpos); + E->base.y_subpos = R22_ + y_subpos; + E->base.y_pos += R24_ + v5; +} + +void Bang_Func_16(void) { // 0xA3BE7B + int16 v1; + + R28_ = Mult8x8(R22_, R24_); + uint16 prod = Mult8x8(R22_, HIBYTE(R24_)); + g_word_7E001E = (uint8)((uint16)(prod & 0xFF00) >> 8); + uint16 RegWord = (uint8)prod; + LOBYTE(v1) = HIBYTE(RegWord); + HIBYTE(v1) = RegWord; + bool v2 = __CFADD__uint16(R28_, v1); + R28_ += v1; + if (v2) + ++g_word_7E001E; +} + +void Bang_Func_17(void) { // 0xA3BEBE + if (R22_ || R24_) { + R28_ = -R22_; + g_word_7E001E = ~R24_; + } +} + +void Bang_Func_18(void) { // 0xA3BEDA + Enemy_Bang *E = Get_Bang(cur_enemy_index); + uint16 bang_var_20 = E->bang_var_20; + if (bang_var_20 != E->bang_var_21) { + E->bang_var_21 = bang_var_20; + E->base.current_instruction = g_off_A3B722[bang_var_20]; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void Bang_Shot(void) { // 0xA3BEFD + Enemy_Bang *E = Get_Bang(cur_enemy_index); + if (E->bang_var_F != 0xBCC1) { + E->bang_var_01 = g_word_A3BA94[(uint16)(2 + * (projectile_dir[collision_detection_index] & 0xF)) >> 1]; + E->bang_var_F = FUNC16(Bang_Func_11); + E->bang_var_07 = 0; + E->bang_var_08 = 0; + E->bang_var_09 = 256; + E->bang_var_0A = 1536; + } + if (E->bang_var_20 != 9) { + ++E->bang_var_20; + Bang_Func_18(); + int v1 = collision_detection_index; + E->bang_var_E += projectile_damage[v1]; + projectile_dir[v1] |= 0x10u; + if (E->bang_var_20 == 9) + E->bang_var_D = 1; + } +} + +uint16 Skree_Instr_1(uint16 k, uint16 j) { // 0xA3C6A4 + Get_Skree(cur_enemy_index)->skree_var_E = 1; + return j; +} + +void Skree_Init(void) { // 0xA3C6AE + Enemy_Skree *E = Get_Skree(cur_enemy_index); + E->skree_var_C = 0; + E->skree_var_D = 0; + E->skree_var_E = 0; + E->base.current_instruction = addr_kSkree_Ilist_C65E; + E->skree_var_B = FUNC16(Skree_Func_1); +} + +void CallSkreeFunc(uint32 ea) { + switch (ea) { + case fnSkree_Func_1: Skree_Func_1(); return; + case fnSkree_Func_2: Skree_Func_2(cur_enemy_index); return; + case fnSkree_Func_3: Skree_Func_3(); return; + case fnSkree_Func_4: Skree_Func_4(); return; + default: Unreachable(); + } +} +void Skree_Main(void) { // 0xA3C6C7 + Enemy_Skree *E = Get_Skree(cur_enemy_index); + CallSkreeFunc(E->skree_var_B | 0xA30000); +} + +void Skree_Func_1(void) { // 0xA3C6D5 + Enemy_Skree *E = Get_Skree(cur_enemy_index); + if (abs16(E->base.x_pos - samus_x_pos) < 0x30u) { + ++E->skree_var_C; + Skree_Func_5(); + E->skree_var_B = FUNC16(Skree_Func_2); + } +} + +void Skree_Func_2(uint16 k) { // 0xA3C6F7 + Enemy_Skree *E = Get_Skree(k); + if (E->skree_var_E) { + E->skree_var_E = 0; + ++E->skree_var_C; + Skree_Func_5(); + E->skree_var_B = FUNC16(Skree_Func_3); + QueueSfx2_Max6(0x5Bu); + } +} + +void Skree_Func_3(void) { // 0xA3C716 + Enemy_Skree *E = Get_Skree(cur_enemy_index); + E->skree_var_A = 21; + R20_ = 6; + R18_ = 0; + uint16 v1 = E->base.properties | 3; + E->base.properties = v1; + if (EnemyFunc_BF8A(cur_enemy_index, v1) & 1) { + E->base.instruction_timer = 1; + E->base.timer = 0; + E->skree_var_B = FUNC16(Skree_Func_4); + QueueSfx2_Max6(0x5Cu); + } else { + E->base.y_pos += 6; + varE24 = 1; + if ((int16)(E->base.x_pos - samus_x_pos) >= 0) + varE24 = -1; + E->base.x_pos += varE24; + } +} + +void Skree_Func_4(void) { // 0xA3C77F + Enemy_Skree *E = Get_Skree(cur_enemy_index); + if (E->skree_var_A-- == 1) { + gEnemySpawnData(cur_enemy_index)->vram_tiles_index = E->base.vram_tiles_index | E->base.palette_index; + E->base.palette_index = 2560; + E->base.vram_tiles_index = 0; + E->base.properties |= kEnemyProps_Deleted; + } else { + if (E->skree_var_A == 8) { + uint16 v2 = cur_enemy_index; + SpawnEnemyProjectileWithGfx(8u, cur_enemy_index, addr_stru_868BC2); + SpawnEnemyProjectileWithGfx(0, v2, addr_stru_868BD0); + SpawnEnemyProjectileWithGfx(0, v2, addr_stru_868BDE); + SpawnEnemyProjectileWithGfx(0, v2, addr_stru_868BEC); + } + ++E->base.y_pos; + } +} + +void Skree_Func_5(void) { // 0xA3C7D5 + Enemy_Skree *E = Get_Skree(cur_enemy_index); + uint16 skree_var_C = E->skree_var_C; + if (skree_var_C != E->skree_var_D) { + E->skree_var_D = skree_var_C; + E->base.current_instruction = g_off_A3C69C[skree_var_C]; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void Skree_Shot(void) { // 0xA3C7F5 + Enemy_NormalShotAI_SkipSomeParts_A3(); + Enemy_Skree *E = Get_Skree(cur_enemy_index); + if (!E->base.health) { + uint16 v1 = cur_enemy_index; + SpawnEnemyProjectileWithGfx(E->skree_var_A, cur_enemy_index, addr_stru_868BC2); + SpawnEnemyProjectileWithGfx(0, v1, addr_stru_868BD0); + SpawnEnemyProjectileWithGfx(0, v1, addr_stru_868BDE); + SpawnEnemyProjectileWithGfx(0, v1, addr_stru_868BEC); + uint16 v5 = 2; + if ((projectile_type[collision_detection_index] & 0xF00) != 512) + v5 = 0; + EnemyDeathAnimation(2 * collision_detection_index, v5); + } +} + +uint16 MaridiaSnail_Instr_1(uint16 k, uint16 j) { // 0xA3CC36 + uint16 v2 = *(uint16 *)RomPtr_A3(j); + Get_MaridiaSnail(k)->msl_var_F = v2; + return j + 2; +} + +uint16 MaridiaSnail_Instr_2(uint16 k, uint16 j) { // 0xA3CC3F + uint16 v2 = *(uint16 *)RomPtr_A3(j); + Get_MaridiaSnail(k)->msl_var_D = v2; + return j + 2; +} + +uint16 MaridiaSnail_Instr_4(uint16 k, uint16 j) { // 0xA3CC48 + uint16 v2 = *(uint16 *)RomPtr_A3(j); + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + E->msl_var_07 = v2; + E->msl_var_C = *(uint16 *)((char *)&g_stru_A3CD42[0].field_6 + (uint16)(8 * v2)); + return j + 2; +} + +uint16 MaridiaSnail_Instr_3(uint16 k, uint16 j) { // 0xA3CC5F + uint8 *v2 = RomPtr_A3(j); + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + E->base.x_pos += *(uint16 *)v2; + E->base.y_pos += *((uint16 *)v2 + 1); + return j + 4; +} + +uint16 MaridiaSnail_Instr_5(uint16 k, uint16 j) { // 0xA3CC78 + if (Get_MaridiaSnail(k)->msl_var_08 == 2 || (NextRandom() & 1) != 0) + j -= 6; + return j; +} + +void MaridiaSnail_Func_1(uint16 k) { // 0xA3CC92 + MaridiaSnail_Func_17(k); +} + +void MaridiaSnail_Init(void) { // 0xA3CDE2 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(cur_enemy_index); + E->msl_var_F = FUNC16(nullsub_215); + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A3; + E->base.instruction_timer = 1; + uint16 current_instruction = E->base.current_instruction; + E->base.current_instruction = g_stru_A3CD42[current_instruction].field_0; + E->base.properties |= g_stru_A3CD42[current_instruction].field_2; + E->msl_var_D = g_stru_A3CD42[current_instruction].field_4; + E->msl_var_C = g_stru_A3CD42[current_instruction].field_6; + E->msl_var_08 = 0; + E->msl_var_06 = E->msl_parameter_1; + MaridiaSnail_Func_2(cur_enemy_index, current_instruction * 8); +} + +void MaridiaSnail_Func_2(uint16 k, uint16 j) { // 0xA3CE27 + int v2 = j >> 1; + R18_ = g_word_A3CD82[v2]; + R20_ = g_word_A3CD82[v2 + 1]; + R22_ = g_word_A3CD82[v2 + 2]; + R24_ = g_word_A3CD82[v2 + 3]; + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + int v4 = (uint16)(2 * E->msl_parameter_1) >> 1; + E->msl_var_A = R20_ + (R18_ ^ g_word_A3CCA2[v4]); + E->msl_var_B = R24_ + (R22_ ^ g_word_A3CCA2[v4]); +} + +void MaridiaSnail_Func_3(uint16 k) { // 0xA3CE57 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + E->msl_var_F = g_off_A3CDD2[E->msl_var_07]; +} + +void MaridiaSnail_Main(void) { // 0xA3CE64 + MaridiaSnail_Func_4(cur_enemy_index); + MaridiaSnail_Func_5(cur_enemy_index); + MaridiaSnail_Func_6(cur_enemy_index); + Enemy_MaridiaSnail *E = Get_MaridiaSnail(cur_enemy_index); + CallEnemyPreInstr(E->msl_var_F | 0xA30000); +} + +void MaridiaSnail_Func_4(uint16 k) { // 0xA3CE73 + uint16 msl_var_08 = Get_MaridiaSnail(k)->msl_var_08; + if (msl_var_08 != 3 && msl_var_08 != 4 && msl_var_08 != 5 && earthquake_timer == 30 && earthquake_type == 20) + MaridiaSnail_Func_14(k); +} + +void MaridiaSnail_Func_5(uint16 k) { // 0xA3CE9A + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + uint16 msl_var_08 = E->msl_var_08; + if (msl_var_08 != 1 && msl_var_08 != 3 && msl_var_08 != 4 && msl_var_08 != 5) { + if (!sign16(E->base.y_pos - samus_y_pos + 96)) { + if ((int16)(E->base.x_pos - samus_x_pos) < 0) { + if (samus_pose_x_dir != 4) + goto LABEL_14; + } else if (samus_pose_x_dir != 8) { + goto LABEL_14; + } + if (E->msl_var_08 == 2) + return; + if (E->msl_var_D != FUNC16(nullsub_215)) { + E->base.current_instruction = E->msl_var_D; + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A3; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->msl_var_08 = 2; + return; + } + } +LABEL_14: + E->msl_var_08 = 0; + } +} + +void MaridiaSnail_Func_6(uint16 k) { // 0xA3CF11 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + if (E->msl_var_F == FUNC16(MaridiaSnail_Func_15)) + goto LABEL_11; + if (E->msl_var_08 == 1) { + if (samus_has_momentum_flag || E->msl_var_F != FUNC16(nullsub_215)) + goto LABEL_11; +LABEL_10: + E->base.properties |= 0x8000u; + return; + } + if (!samus_has_momentum_flag) { + uint16 msl_var_08 = E->msl_var_08; + if (msl_var_08 == 2 || msl_var_08 != 3 && msl_var_08 != 5) + goto LABEL_10; + } +LABEL_11: + E->base.properties &= 0x7FFFu; +} + +void MaridiaSnail_Func_7(uint16 k) { // 0xA3CF60 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + if (E->msl_var_07 >= 4u) { + R18_ = 0; + R20_ = 0; + MaridiaSnail_Func_8(E->msl_var_B); + if (EnemyFunc_BC76(k) & 1) + return; + goto LABEL_5; + } + R18_ = 0; + R20_ = 0; + MaridiaSnail_Func_8(E->msl_var_A); + if (!(EnemyFunc_BBBF(k) & 1)) + LABEL_5: + MaridiaSnail_Func_14(k); +} + +void MaridiaSnail_Func_8(uint16 a) { // 0xA3CF8F + if ((a & 0x8000u) != 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = a; + uint16 v1; + if ((R20_ & 0x8000u) == 0) + v1 = R20_ + 7; + else + v1 = R20_ - 7; + R20_ = v1; +} + +void MaridiaSnail_Func_9(uint16 k) { // 0xA3CFA6 + uint16 v1; + if (Get_MaridiaSnail(k)->msl_var_05) + v1 = addr_stru_A3CD22; + else + v1 = addr_stru_A3CCE2; + MaridiaSnail_D07E(k, v1); +} + +void MaridiaSnail_CFB7(uint16 k) { // 0xA3CFB7 + MaridiaSnail_D002(k, addr_stru_A3CCEA); +} + +void MaridiaSnail_CFBD(uint16 k) { // 0xA3CFBD + uint16 v1; + if (Get_MaridiaSnail(k)->msl_var_05) + v1 = addr_stru_A3CD2A; + else + v1 = addr_stru_A3CCF2; + MaridiaSnail_D07E(k, v1); +} + +void MaridiaSnail_CFCE(uint16 k) { // 0xA3CFCE + MaridiaSnail_D002(k, addr_stru_A3CCFA); +} + +void MaridiaSnail_CFD4(uint16 k) { // 0xA3CFD4 + uint16 v1; + if (Get_MaridiaSnail(k)->msl_var_05) + v1 = addr_stru_A3CD32; + else + v1 = addr_stru_A3CD02; + MaridiaSnail_D07E(k, v1); +} + +void MaridiaSnail_CFE5(uint16 k) { // 0xA3CFE5 + MaridiaSnail_D002(k, addr_stru_A3CD0A); +} + +void MaridiaSnail_CFEB(uint16 k) { // 0xA3CFEB + uint16 v1; + if (Get_MaridiaSnail(k)->msl_var_05) + v1 = addr_stru_A3CD3A; + else + v1 = addr_stru_A3CD12; + MaridiaSnail_D07E(k, v1); +} + +void MaridiaSnail_CFFC(uint16 k) { // 0xA3CFFC + MaridiaSnail_D002(k, addr_stru_A3CD1A); +} + +void MaridiaSnail_D002(uint16 k, uint16 j) { // 0xA3D002 + int16 msl_var_A; + int16 msl_var_B; + + MaridiaSnail_Func_10(k, j); + R18_ = 0; + R20_ = 0; + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + msl_var_A = E->msl_var_A; + if (msl_var_A < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = msl_var_A; + uint16 v4; + if ((R20_ & 0x8000u) == 0) + v4 = R20_ + 1; + else + v4 = R20_ - 1; + R20_ = v4; + uint8 rv = Enemy_MoveRight_ProcessSlopes(k); + MaridiaSnail_Func_11(k, j); + if (rv) { + E->msl_var_E = 0; + uint8 carry = EnemyFunc_C8AD(k); + MaridiaSnail_Func_12(k, carry); + R18_ = 0; + R20_ = 0; + msl_var_B = E->msl_var_B; + if (msl_var_B < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = msl_var_B; + if (Enemy_MoveDown(k) & 1) { + E->msl_var_A = -E->msl_var_A; + uint8 *v6 = RomPtr_A3(j); + MaridiaSnail_Func_13(k, *((uint16 *)v6 + 3)); + } + } else { + uint16 v7 = E->msl_var_E + 1; + E->msl_var_E = v7; + if (sign16(v7 - 4)) { + E->msl_var_B = -E->msl_var_B; + uint8 *v8 = RomPtr_A3(j); + MaridiaSnail_Func_13(k, *((uint16 *)v8 + 2)); + } else { + MaridiaSnail_Func_14(k); + } + } +} + +void MaridiaSnail_D07E(uint16 k, uint16 j) { // 0xA3D07E + int16 msl_var_B; + int16 msl_var_A; + + MaridiaSnail_Func_10(k, j); + R18_ = 0; + R20_ = 0; + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + msl_var_B = E->msl_var_B; + if (msl_var_B < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = msl_var_B; + uint16 v4; + if ((R20_ & 0x8000u) == 0) + v4 = R20_ + 1; + else + v4 = R20_ - 1; + R20_ = v4; + uint8 rv = Enemy_MoveDown(k); + MaridiaSnail_Func_11(k, j); + if (rv) { + E->msl_var_E = 0; + R18_ = 0; + R20_ = 0; + msl_var_A = E->msl_var_A; + if (msl_var_A < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = msl_var_A; + if (Enemy_MoveRight_ProcessSlopes(k) & 1) { + E->msl_var_B = -E->msl_var_B; + uint8 *v6 = RomPtr_A3(j); + MaridiaSnail_Func_13(k, *((uint16 *)v6 + 3)); + } else { + uint8 carry = EnemyFunc_C8AD(k); + MaridiaSnail_Func_12(k, carry); + } + } else { + uint16 v7 = E->msl_var_E + 1; + E->msl_var_E = v7; + if (sign16(v7 - 4)) { + E->msl_var_A = -E->msl_var_A; + uint8 *v8 = RomPtr_A3(j); + MaridiaSnail_Func_13(k, *((uint16 *)v8 + 2)); + } else { + MaridiaSnail_Func_14(k); + } + } +} + +void MaridiaSnail_Func_10(uint16 k, uint16 j) { // 0xA3D0F8 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + uint8 *v3 = RomPtr_A3(j); + E->base.x_pos += *(uint16 *)v3; + E->base.y_pos += *((uint16 *)v3 + 1); +} + +void MaridiaSnail_Func_11(uint16 k, uint16 j) { // 0xA3D10D + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + uint8 *v3 = RomPtr_A3(j); + E->base.x_pos -= *(uint16 *)v3; + E->base.y_pos = E->base.y_pos - *((uint16 *)v3 + 1); +} + +void MaridiaSnail_Func_12(uint16 k, uint16 carry) { // 0xA3D124 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + if (!carry) { + if ((uint16)(E->msl_var_04 + 1) >= 0x10u) + E->msl_var_05 = 0; + else + ++E->msl_var_04; + } else { + E->msl_var_05 = 1; + E->msl_var_04 = 0; + } +} + +void MaridiaSnail_Func_13(uint16 k, uint16 a) { // 0xA3D14C + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + E->base.current_instruction = a; + E->base.instruction_timer = 1; + E->msl_var_05 = 1; + E->msl_var_04 = 0; +} + +void MaridiaSnail_Func_14(uint16 k) { // 0xA3D164 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + if (E->msl_var_08 != 3) { + E->msl_var_08 = 3; + E->msl_var_F = FUNC16(MaridiaSnail_Func_15); + int v2 = (uint16)(4 * E->msl_var_C) >> 1; + E->base.current_instruction = g_off_A3D1AB[v2]; + E->msl_var_D = g_off_A3D1AB[v2 + 1]; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->msl_var_02 = 0; + E->msl_var_03 = 0; + E->msl_var_00 = 0; + E->msl_var_01 = 0; + } +} + +void MaridiaSnail_Func_15(uint16 k) { // 0xA3D1B3 + int16 msl_var_01; + + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + if (E->msl_var_08 != 3) { + R18_ = E->msl_var_02; + R20_ = E->msl_var_03; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->msl_var_02 = -E->msl_var_02; + E->msl_var_03 = -E->msl_var_03; + E->msl_var_20 = 1; + QueueSfx2_Max3(0x70u); + } else { + if ((E->msl_var_03 & 0x8000u) != 0) { + R22_ = 4096; + R24_ = 0; + } else { + R22_ = -4096; + R24_ = -1; + } + uint16 msl_var_02 = E->msl_var_02; + bool v3 = __CFADD__uint16(R22_, msl_var_02); + E->msl_var_02 = R22_ + msl_var_02; + uint16 v4 = R24_ + v3 + E->msl_var_03; + if (v4) + E->msl_var_03 = v4; + } + } + R18_ = E->msl_var_00; + R20_ = E->msl_var_01; + if (Enemy_MoveDown(k) & 1) { + msl_var_01 = E->msl_var_01; + if (msl_var_01 >= 0 && sign16(msl_var_01 - 3)) { + E->msl_var_03 = 0; + E->msl_var_02 = 0; + E->msl_var_01 = 0; + E->msl_var_00 = 0; + E->msl_var_E = 0; + E->msl_var_04 = 0; + E->msl_var_05 = 1; + if (E->msl_var_08 == 3) { + E->msl_var_08 = 0; + } else { + E->msl_var_08 = 1; + E->msl_parameter_1 = 8; + MaridiaSnail_Func_18(k); + MaridiaSnail_Func_16(k); + } + E->base.properties = E->msl_var_C | E->base.properties & ~3u; + StoneZoomer_E67A(k); + E->msl_var_F = FUNC16(nullsub_215); + E->base.current_instruction = E->msl_var_D; + E->base.instruction_timer = 1; + E->base.timer = 0; + } else { + E->msl_var_00 = -E->msl_var_00; + E->msl_var_01 = -E->msl_var_01; + E->msl_var_20 = 0; + } + } else { + uint16 msl_var_00 = E->msl_var_00; + E->msl_var_00 = msl_var_00 + 0x2000; + uint16 v6 = __CFADD__uint16(msl_var_00, 0x2000) + E->msl_var_01; + if (sign16(v6 - 4)) + E->msl_var_01 = v6; + } +} + +void MaridiaSnail_Func_16(uint16 k) { // 0xA3D2FA + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + int v2 = (uint16)(4 * E->msl_var_C) >> 1; + E->base.current_instruction = g_off_A3D30D[v2]; + E->msl_var_D = g_off_A3D30D[v2 + 1]; +} + +uint8 MaridiaSnail_Func_17(uint16 k) { // 0xA3D315 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + if (E->msl_var_05) + return 0; + uint16 msl_var_07 = E->msl_var_07; + if (msl_var_07 >= 4u) + return MaridiaSnail_Func_18(k) & 1; + if ((msl_var_07 & 1) != 0) { + uint16 y_pos = E->base.y_pos; + if (y_pos >= samus_y_pos) + return MaridiaSnail_Func_19(k) & 1; + return y_pos >= samus_y_pos; + } else { + if (E->base.y_pos < samus_y_pos) + return MaridiaSnail_Func_19(k) & 1; + return 0; + } +} + +uint8 MaridiaSnail_Func_18(uint16 k) { // 0xA3D33E + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + if (E->msl_var_C) { + uint16 x_pos = E->base.x_pos; + if (x_pos >= samus_x_pos) + return MaridiaSnail_Func_19(k) & 1; + return x_pos >= samus_x_pos; + } else { + if (E->base.x_pos < samus_x_pos) + return MaridiaSnail_Func_19(k) & 1; + return 0; + } +} + +uint8 MaridiaSnail_Func_19(uint16 k) { // 0xA3D356 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + if (E->msl_var_08 == 2 || E->msl_var_F == 0xCF5F) + return 0; + uint16 v2 = g_word_A3CDC2[E->msl_var_07]; + E->msl_var_07 = v2; + E->base.current_instruction = *(VoidP *)((char *)&g_stru_A3CD42[0].field_0 + (uint16)(8 * v2)); + E->base.properties = *(uint16 *)((char *)&g_stru_A3CD42[0].field_2 + (uint16)(8 * v2)) | E->base.properties & ~3u; + E->msl_var_D = *(VoidP *)((char *)&g_stru_A3CD42[0].field_4 + (uint16)(8 * v2)); + E->msl_var_C = *(uint16 *)((char *)&g_stru_A3CD42[0].field_6 + (uint16)(8 * v2)); + MaridiaSnail_Func_2(k, 8 * v2); + MaridiaSnail_Func_3(k); + E->msl_var_05 = 1; + E->msl_var_04 = 0; + return 1; +} + +void MaridiaSnail_Touch(void) { // 0xA3D3B0 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(cur_enemy_index); + if ((E->msl_var_08 != 1 + || E->msl_var_F == 0xCF5F + || !(MaridiaSnail_Func_20(cur_enemy_index) & 1)) + && (E->msl_var_F == 0xD1B3 || samus_has_momentum_flag)) { + MaridiaSnail_Func_22(cur_enemy_index); + if (E->msl_var_F == 0xD1B3) + QueueSfx2_Max3(0x70u); + } else if (E->msl_var_F != 0xCF5F && E->msl_var_08 != 4 && E->msl_var_08 != 3) { + Enemy_NormalTouchAI_A3(); + E->msl_parameter_1 = E->msl_var_06; + if (E->msl_var_08) + MaridiaSnail_Func_19(cur_enemy_index); + E->msl_var_08 = 0; + } +} + +uint8 MaridiaSnail_Func_20(uint16 k) { // 0xA3D421 + R18_ = ((uint16)(joypad1_lastkeys & 0x300) >> 8) - 1; + R20_ = Get_MaridiaSnail(k)->msl_var_C & 1; + if ((uint16)(joypad1_lastkeys & 0x300) >> 8 == 1) { + if (R20_) + return 0; + } else if (!R20_) { + return 0; + } + return 1; +} + +uint8 MaridiaSnail_Func_21(uint16 k) { // 0xA3D446 + if ((Get_MaridiaSnail(k)->msl_var_A & 0x8000u) != 0) + return samus_pose_x_dir == 8; + return samus_pose_x_dir == 4; +} + +void MaridiaSnail_Shot(void) { // 0xA3D469 + int16 v0; + + v0 = projectile_type[collision_detection_index] & 0xFF00; + if (v0 == 768 || v0 == 1280) { + Enemy_NormalShotAI_A3(); + } else { + uint16 msl_var_08 = Get_MaridiaSnail(cur_enemy_index)->msl_var_08; + if (msl_var_08 != 3 && msl_var_08 != 4) + MaridiaSnail_Func_23(cur_enemy_index); + QueueSfx2_Max3(0x70u); + } +} + +void MaridiaSnail_Func_22(uint16 k) { // 0xA3D49F + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + E->msl_var_08 = 4; + E->msl_var_F = FUNC16(MaridiaSnail_Func_15); + int v2 = (uint16)(4 * E->msl_var_C) >> 1; + E->base.current_instruction = g_off_A3D50F[v2]; + E->msl_var_D = g_off_A3D50F[v2 + 1]; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->msl_var_02 = absolute_moved_last_frame_x_fract; + uint16 v3 = absolute_moved_last_frame_x; + E->msl_var_03 = absolute_moved_last_frame_x; + if (v3 >= 0x10u) + v3 = 15; + int v4 = (uint16)(4 * v3) >> 1; + E->msl_var_00 = g_word_A3D517[v4]; + E->msl_var_01 = g_word_A3D517[v4 + 1]; + if ((samus_pose_x_dir & 4) != 0) { + E->msl_var_02 = -E->msl_var_02; + E->msl_var_03 = -E->msl_var_03; + } +} + +void MaridiaSnail_Func_23(uint16 k) { // 0xA3D557 + Enemy_MaridiaSnail *E = Get_MaridiaSnail(k); + E->msl_var_08 = 5; + E->msl_var_F = FUNC16(MaridiaSnail_Func_15); + int v2 = (uint16)(4 * E->msl_var_C) >> 1; + E->base.current_instruction = g_off_A3D5A4[v2]; + E->msl_var_D = g_off_A3D5A4[v2 + 1]; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->msl_var_01 = -1; + if (samus_pose_x_dir == 4) + E->msl_var_03 = -1; + else + E->msl_var_03 = 1; +} + +void Reflec_Func_1(void) { // 0xA3DB0C + if (!door_transition_flag_enemies && !--variables_for_enemy_graphics_drawn_hook[2]) { + variables_for_enemy_graphics_drawn_hook[2] = 16; + uint16 v0 = variables_for_enemy_graphics_drawn_hook[0]; + uint16 v1 = 8 * variables_for_enemy_graphics_drawn_hook[1]; + remaining_enemy_spritemap_entries = 4; + do { + palette_buffer[(v0 >> 1) + 137] = g_word_A3DABC[v1 >> 1]; + v1 += 2; + v0 += 2; + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); + variables_for_enemy_graphics_drawn_hook[1] = (LOBYTE(variables_for_enemy_graphics_drawn_hook[1]) + 1) & 7; + } +} + +uint16 Reflec_Instr_1(uint16 k, uint16 j) { // 0xA3DBC8 + uint16 v2 = *(uint16 *)RomPtr_A3(j); + Get_Reflec(k)->reflec_parameter_2 = v2; + return j + 2; +} + +void Reflec_Init(void) { // 0xA3DBD3 + Enemy_Reflec *E = Get_Reflec(cur_enemy_index); + E->base.properties |= kEnemyProps_BlockPlasmaBeam; + E->base.current_instruction = g_off_A3DC0B[E->reflec_parameter_1]; + enemy_gfx_drawn_hook.addr = FUNC16(Reflec_Func_1); + *(uint16 *)&enemy_gfx_drawn_hook.bank = 163; + variables_for_enemy_graphics_drawn_hook[0] = (uint8)((uint16)((16 * E->base.palette_index) & 0xFF00) >> 8); + variables_for_enemy_graphics_drawn_hook[2] = 16; +} + +static Func_V *const off_A3DD2E[64] = { // 0xA3DC1C + 0, Reflec_Func_2, 0, Reflec_Func_2, 0, 0, Reflec_Func_3, 0, Reflec_Func_3, 0, 0, 0, 0, 0, 0, 0, + Reflec_Func_4, 0, Reflec_Func_5, 0, Reflec_Func_6, Reflec_Func_6, 0, Reflec_Func_7, 0, Reflec_Func_4, 0, 0, 0, 0, 0, 0, + 0, Reflec_Func_8, 0, Reflec_Func_9, 0, 0, Reflec_Func_9, 0, Reflec_Func_8, 0, 0, 0, 0, 0, 0, 0, + Reflec_Func_10, 0, Reflec_Func_11, 0, Reflec_Func_12, Reflec_Func_12, 0, Reflec_Func_13, 0, Reflec_Func_10, 0, 0, 0, 0, 0, 0, +}; + +void Reflec_Shot(void) { + int16 v4; + + uint16 v0 = 2 * collision_detection_index; + Enemy_Reflec *EK = Get_Reflec(cur_enemy_index); + EK->base.invincibility_timer = 10; + draw_enemy_layer = 32 * EK->reflec_parameter_2; + uint16 v2 = draw_enemy_layer + 2 * (projectile_dir[v0 >> 1] & 0xF); + draw_enemy_layer = v2; + int v3 = v2 >> 1; + if (g_word_A3DCAE[v3] == 0x8000) { + projectile_dir[v0 >> 1] |= 0x10u; + printf("Possible bug. What is X?\n"); + Enemy_Reflec *ET = Get_Reflec(v2); + if (ET->base.health) { + Enemy_NormalShotAI_SkipSomeParts_A3(); + if (!ET->base.health) { + ET->base.current_instruction = g_off_A3DCA6[ET->reflec_parameter_2]; + ET->base.instruction_timer = 1; + ET->base.timer = 0; + } + } + } else { + v4 = g_word_A3DCAE[v3]; + if (v4 < 0) { + off_A3DD2E[v3](); + v4 = -g_word_A3DCAE[draw_enemy_layer >> 1]; + } + int v5 = v0 >> 1; + projectile_dir[v5] = v4; + projectile_type[v5] &= ~0x8000u; + R20_ = v0; + ProjectileReflection(); + QueueSfx2_Max6(0x57u); + } +} + +void Reflec_Func_2(void) { // 0xA3DDAE + loop_index_end = Get_Reflec(cur_enemy_index)->base.x_pos - 8; +} + +void Reflec_Func_3(void) { // 0xA3DDCF + loop_index_end = Get_Reflec(cur_enemy_index)->base.x_pos + 8; +} + +void Reflec_Func_4(void) { // 0xA3DDF0 + loop_index_end = Get_Reflec(cur_enemy_index)->base.x_pos; +} + +void Reflec_Func_5(void) { // 0xA3DE0D + loop_index_end = Get_Reflec(cur_enemy_index)->base.y_pos; +} + +void Reflec_Func_6(void) { // 0xA3DE2A + loop_index_end = Get_Reflec(cur_enemy_index)->base.x_pos; +} + +void Reflec_Func_7(void) { // 0xA3DE47 + loop_index_end = Get_Reflec(cur_enemy_index)->base.y_pos; +} + +void Reflec_Func_8(void) { // 0xA3DE64 + loop_index_end = Get_Reflec(cur_enemy_index)->base.y_pos + 8; +} + +void Reflec_Func_9(void) { // 0xA3DE85 + loop_index_end = Get_Reflec(cur_enemy_index)->base.y_pos - 8; +} + +void Reflec_Func_10(void) { // 0xA3DEA6 + loop_index_end = Get_Reflec(cur_enemy_index)->base.x_pos; +} + +void Reflec_Func_11(void) { // 0xA3DEC3 + loop_index_end = Get_Reflec(cur_enemy_index)->base.y_pos; +} + +void Reflec_Func_12(void) { // 0xA3DEE0 + loop_index_end = Get_Reflec(cur_enemy_index)->base.x_pos; +} + +void Reflec_Func_13(void) { // 0xA3DEFD + loop_index_end = Get_Reflec(cur_enemy_index)->base.y_pos; +} + +uint16 WreckedShipOrangeZoomer_Func_1(uint16 k, uint16 j) { // 0xA3DFC2 + uint16 v2 = *(uint16 *)RomPtr_A3(j); + Get_WreckedShipOrangeZoomer(k)->wsozr_var_F = v2; + return j + 2; +} + +void WreckedShipOrangeZoomer_Init(void) { // 0xA3E043 + Enemy_WreckedShipOrangeZoomer *E = Get_WreckedShipOrangeZoomer(cur_enemy_index); + E->base.current_instruction = g_off_A3E03B[(uint16)(2 + * (E->base.current_instruction & 3)) >> 1]; + E->wsozr_var_F = addr_locret_A3E08A; + uint16 v1 = g_word_A3E5F0[E->wsozr_parameter_1]; + E->wsozr_var_A = v1; + E->wsozr_var_B = v1; + if ((E->base.properties & 3) != 0) { + if ((E->base.properties & 3) == 2) + E->wsozr_var_B = -E->wsozr_var_B; + } else { + E->wsozr_var_A = -E->wsozr_var_A; + } +} + +void WreckedShipOrangeZoomer_Main(void) { // 0xA3E08B + Enemy_WreckedShipOrangeZoomer *E = Get_WreckedShipOrangeZoomer(cur_enemy_index); + CallEnemyPreInstr(E->wsozr_var_F | 0xA30000); +} + +void WreckedShipOrangeZoomer_Func_2(uint16 k) { // 0xA3E091 + int16 wsozr_var_A; + int16 wsozr_var_B; + int16 v7; + uint16 v9; + uint16 v12; + Enemy_WreckedShipOrangeZoomer *E = Get_WreckedShipOrangeZoomer(k); + + if (earthquake_timer == 30 && earthquake_type == 20) { + E->wsozr_var_03 = E->wsozr_var_F; + E->wsozr_var_F = FUNC16(FireZoomer_Func_2); + } + R18_ = 0; + R20_ = 0; + wsozr_var_A = E->wsozr_var_A; + if (wsozr_var_A < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = wsozr_var_A; + uint16 v4; + if ((R20_ & 0x8000u) == 0) + v4 = R20_ + 1; + else + v4 = R20_ - 1; + R20_ = v4; + if (Enemy_MoveRight_ProcessSlopes(k) & 1) { + E->wsozr_var_04 = 0; + EnemyFunc_C8AD(k); + R18_ = 0; + R20_ = 0; + wsozr_var_B = E->wsozr_var_B; + if (wsozr_var_B < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = wsozr_var_B; + if (!(Enemy_MoveDown(k) & 1)) { + if ((int16)(samus_y_pos - E->base.y_pos) >= 0) { + v7 = E->wsozr_var_B; + if (v7 < 0) + LABEL_17: + v7 = -v7; + } else { + v7 = E->wsozr_var_B; + if (v7 >= 0) + goto LABEL_17; + } + E->wsozr_var_B = v7; + return; + } + E->wsozr_var_A = -E->wsozr_var_A; + v9 = addr_kWreckedShipOrangeZoomer_Ilist_E01F; + if ((E->wsozr_var_B & 0x8000u) != 0) + v9 = addr_kWreckedShipOrangeZoomer_Ilist_E003; + E->base.current_instruction = v9; + E->base.instruction_timer = 1; + } else { + uint16 v11 = E->wsozr_var_04 + 1; + E->wsozr_var_04 = v11; + if (sign16(v11 - 4)) { + E->wsozr_var_B = -E->wsozr_var_B; + v12 = addr_kWreckedShipOrangeZoomer_Ilist_E01F; + if ((E->wsozr_var_B & 0x8000u) != 0) + v12 = addr_kWreckedShipOrangeZoomer_Ilist_E003; + E->base.current_instruction = v12; + E->base.instruction_timer = 1; + } else { + E->wsozr_var_03 = E->wsozr_var_F; + E->wsozr_var_F = FUNC16(FireZoomer_Func_2); + } + } +} + +void sub_A3E168(uint16 k) { // 0xA3E168 + int16 wsozr_var_B; + int16 wsozr_var_A; + int16 v7; + uint16 v9; + uint16 v12; + Enemy_WreckedShipOrangeZoomer *E = Get_WreckedShipOrangeZoomer(k); + + if (earthquake_timer == 30 && earthquake_type == 20) { + E->wsozr_var_03 = E->wsozr_var_F; + E->wsozr_var_F = FUNC16(FireZoomer_Func_2); + } + R18_ = 0; + R20_ = 0; + + wsozr_var_B = E->wsozr_var_B; + if (wsozr_var_B < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = wsozr_var_B; + uint16 v4; + if ((R20_ & 0x8000u) == 0) + v4 = R20_ + 1; + else + v4 = R20_ - 1; + R20_ = v4; + if (Enemy_MoveDown(k) & 1) { + E->wsozr_var_04 = 0; + R18_ = 0; + R20_ = 0; + wsozr_var_A = E->wsozr_var_A; + if (wsozr_var_A < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = wsozr_var_A; + if (!(Enemy_MoveRight_ProcessSlopes(k) & 1)) { + EnemyFunc_C8AD(k); + if ((int16)(samus_x_pos - E->base.x_pos) >= 0) { + v7 = E->wsozr_var_A; + if (v7 < 0) + LABEL_17: + v7 = -v7; + } else { + v7 = E->wsozr_var_A; + if (v7 >= 0) + goto LABEL_17; + } + E->wsozr_var_A = v7; + return; + } + E->wsozr_var_B = -E->wsozr_var_B; + v9 = addr_kWreckedShipOrangeZoomer_Ilist_DFE7; + if ((E->wsozr_var_A & 0x8000u) != 0) + v9 = addr_kWreckedShipOrangeZoomer_Ilist_DFCB; + E->base.current_instruction = v9; + E->base.instruction_timer = 1; + } else { + uint16 v11 = E->wsozr_var_04 + 1; + E->wsozr_var_04 = v11; + if (sign16(v11 - 4)) { + E->wsozr_var_A = -E->wsozr_var_A; + v12 = addr_kWreckedShipOrangeZoomer_Ilist_DFE7; + if ((E->wsozr_var_A & 0x8000u) != 0) + v12 = addr_kWreckedShipOrangeZoomer_Ilist_DFCB; + E->base.current_instruction = v12; + E->base.instruction_timer = 1; + } else { + E->wsozr_var_03 = E->wsozr_var_F; + E->wsozr_var_F = FUNC16(FireZoomer_Func_2); + } + } +} + +void BigEyeBugs_Init(void) { // 0xA3E2D4 + EnemyData *v1 = gEnemyData(cur_enemy_index); + v1->current_instruction = g_off_A3E2CC[v1->current_instruction & 3]; + StoneZoomer_E67A(cur_enemy_index); +} + +void FireZoomer_Init(void) { // 0xA3E59C + Enemy_FireZoomer *E = Get_FireZoomer(cur_enemy_index); + E->base.current_instruction = g_off_A3E2CC[(uint16)(2 * (E->base.current_instruction & 3)) >> 1]; + StoneZoomer_E67A(cur_enemy_index); +} + +uint16 Zoomer_Instr_SetPreinstr(uint16 k, uint16 j) { // 0xA3E660 + uint16 v2 = *(uint16 *)RomPtr_A3(j); + gEnemyData(k)->ai_preinstr = v2; + return j + 2; +} + +void StoneZoomer_Init(void) { // 0xA3E669 + Enemy_StoneZoomer *E = Get_StoneZoomer(cur_enemy_index); + E->base.current_instruction = g_off_A3E2CC[(uint16)(2 * (E->base.current_instruction & 3)) >> 1]; + StoneZoomer_E67A(cur_enemy_index); +} + +void StoneZoomer_E67A(uint16 k) { // 0xA3E67A + Enemy_StoneZoomer *E = Get_StoneZoomer(k); + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A3; + E->base.instruction_timer = 1; + E->szr_var_F = FUNC16(nullsub_304); + if (E->szr_parameter_1 != 255) { + uint16 v2 = g_word_A3E5F0[E->szr_parameter_1]; + E->szr_var_A = v2; + E->szr_var_B = v2; + } + if ((E->base.properties & 3) != 0) { + if ((E->base.properties & 3) == 2) + E->szr_var_B = -E->szr_var_B; + } else { + E->szr_var_A = -E->szr_var_A; + } +} + +void StoneZoomer_Main(void) { // 0xA3E6C2 + Enemy_StoneZoomer *E = Get_StoneZoomer(cur_enemy_index); + CallEnemyPreInstr(E->szr_var_F | 0xA30000); +} + +void FireZoomer_Func_1(uint16 k) { // 0xA3E6C8 + int16 fzr_var_A; + int16 fzr_var_B; + + Enemy_FireZoomer *E = Get_FireZoomer(k); + if (earthquake_timer == 30 && earthquake_type == 20) { + E->fzr_var_03 = E->fzr_var_F; + E->fzr_var_F = FUNC16(FireZoomer_Func_2); + } + R18_ = 0; + R20_ = 0; + + fzr_var_A = E->fzr_var_A; + if (fzr_var_A < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = fzr_var_A; + uint16 v4; + if ((R20_ & 0x8000u) == 0) + v4 = R20_ + 1; + else + v4 = R20_ - 1; + R20_ = v4; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->fzr_var_04 = 0; + EnemyFunc_C8AD(k); + R18_ = 0; + R20_ = 0; + fzr_var_B = E->fzr_var_B; + if (fzr_var_B < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = fzr_var_B; + if (Enemy_MoveDown(k) & 1) { + E->fzr_var_A = -E->fzr_var_A; + uint16 fzr_parameter_2 = E->fzr_parameter_2, v7; + if ((E->fzr_var_B & 0x8000u) == 0) + v7 = g_off_A3E63C[fzr_parameter_2 >> 1]; + else + v7 = g_off_A3E630[fzr_parameter_2 >> 1]; + E->base.current_instruction = v7; + E->base.instruction_timer = 1; + } + } else { + uint16 v8 = E->fzr_var_04 + 1; + E->fzr_var_04 = v8; + if (sign16(v8 - 4)) { + E->fzr_var_B = -E->fzr_var_B; + uint16 v9 = E->fzr_parameter_2, v10; + if ((E->fzr_var_B & 0x8000u) == 0) + v10 = g_off_A3E63C[v9 >> 1]; + else + v10 = g_off_A3E630[v9 >> 1]; + E->base.current_instruction = v10; + E->base.instruction_timer = 1; + } else { + E->fzr_var_03 = E->fzr_var_F; + E->fzr_var_F = FUNC16(FireZoomer_Func_2); + } + } +} + +void FireZoomer_Func_2(uint16 k) { // 0xA3E785 + Enemy_FireZoomer *E = Get_FireZoomer(k); + R18_ = E->fzr_var_01; + R20_ = E->fzr_var_02; + if (Enemy_MoveDown(k) & 1) { + if (E->fzr_parameter_1 == 255) { + E->fzr_var_A = 128; + E->fzr_var_B = 128; + } + E->fzr_var_01 = 0; + E->fzr_var_02 = 0; + E->fzr_var_04 = 0; + E->fzr_var_F = E->fzr_var_03; + } else { + if (sign16(E->fzr_var_02 - 4)) { + uint16 fzr_var_01 = E->fzr_var_01; + E->fzr_var_01 = fzr_var_01 + 0x8000; + E->fzr_var_02 += __CFADD__uint16(fzr_var_01, 0x8000); + } + if (!E->fzr_var_01 && !E->fzr_var_02) + E->fzr_var_F = FUNC16(FireZoomer_Func_1); + } +} + +void FireZoomer_Func_3(uint16 k) { // 0xA3E7F2 + int16 fzr_var_B; + Enemy_FireZoomer *E = Get_FireZoomer(k); + + if (earthquake_timer == 30 && earthquake_type == 20) { + E->fzr_var_03 = E->fzr_var_F; + E->fzr_var_F = FUNC16(FireZoomer_Func_2); + } + R18_ = 0; + R20_ = 0; + + fzr_var_B = E->fzr_var_B; + if (fzr_var_B < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = fzr_var_B; + uint16 v4; + if ((R20_ & 0x8000u) == 0) + v4 = R20_ + 1; + else + v4 = R20_ - 1; + R20_ = v4; + if (Enemy_MoveDown(k) & 1) { + E->fzr_var_04 = 0; + FireZoomer_E8A5(k); + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->fzr_var_B = -E->fzr_var_B; + uint16 fzr_parameter_2 = E->fzr_parameter_2, v6; + if ((E->fzr_var_A & 0x8000u) == 0) + v6 = g_off_A3E654[fzr_parameter_2 >> 1]; + else + v6 = g_off_A3E648[fzr_parameter_2 >> 1]; + E->base.current_instruction = v6; + E->base.instruction_timer = 1; + } else { + EnemyFunc_C8AD(k); + } + } else { + uint16 v7 = E->fzr_var_04 + 1; + E->fzr_var_04 = v7; + if (sign16(v7 - 4)) { + E->fzr_var_A = -E->fzr_var_A; + uint16 v8 = E->fzr_parameter_2, v9; + if ((E->fzr_var_A & 0x8000u) == 0) + v9 = g_off_A3E654[v8 >> 1]; + else + v9 = g_off_A3E648[v8 >> 1]; + E->base.current_instruction = v9; + E->base.instruction_timer = 1; + } else { + E->fzr_var_03 = E->fzr_var_F; + E->fzr_var_F = FUNC16(FireZoomer_Func_2); + } + } +} + +void FireZoomer_E8A5(uint16 k) { // 0xA3E8A5 + int16 fzr_var_A; + int16 v3; + Enemy_FireZoomer *E = Get_FireZoomer(cur_enemy_index); + + uint16 xpos = E->base.x_pos; + uint16 ypos = sign16(E->fzr_var_B) ? + E->base.y_pos - E->base.y_height : + E->base.y_pos + E->base.y_height - 1; + CalculateBlockContainingPixelPos(xpos, ypos); + + if ((level_data[cur_block_index] & 0xF000) == 4096 + && (BTS[cur_block_index] & 0x1Fu) >= 5) { + uint16 v1 = g_word_A3E931[(uint16)(4 * (BTS[cur_block_index] & 0x1F)) >> 1]; + fzr_var_A = E->fzr_var_A; + if (fzr_var_A >= 0) { + Multiply16x16(fzr_var_A, v1); + R18_ = mult_product_lo; + R20_ = mult_product_hi; + } else { + Multiply16x16(-fzr_var_A, v1); + Negate32(&mult_product_hi, &mult_product_lo, &R20_, &R18_); + } + } else { + R18_ = 0; + R20_ = 0; + v3 = E->fzr_var_A; + if (v3 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v3; + } +} + +void Metroid_Init(void) { // 0xA3EA4F + Enemy_Metroid *E = Get_Metroid(cur_enemy_index); + E->base.current_instruction = addr_kMetroid_Ilist_E9CF; + R24_ = E->base.vram_tiles_index | E->base.palette_index; + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + R22_ = 50; + CreateSpriteAtPos(); + E->metroid_var_00 = R18_; + R24_ = E->base.vram_tiles_index | E->base.palette_index; + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + R22_ = 52; + CreateSpriteAtPos(); + E->metroid_var_01 = R18_; + E->metroid_var_02 = 0; +} + +uint16 Metroid_Instr_2(uint16 k, uint16 j) { // 0xA3EAA5 + QueueSfx2_Max6(0x50u); + return j; +} + +uint16 Metroid_Instr_1(uint16 k, uint16 j) { // 0xA3EAB1 + int v2 = (uint16)(2 * (NextRandom() & 7)) >> 1; + QueueSfx2_Max6(g_word_A3EAD6[v2]); + return j; +} + +void Metroid_Frozen(void) { // 0xA3EAE6 + Enemy_NormalFrozenAI_A3(); + Enemy_Metroid *E = Get_Metroid(cur_enemy_index); + if (E->metroid_var_E) { + --E->metroid_var_E; + E->base.flash_timer = 2; + } + int v1 = E->metroid_var_00 >> 1; + sprite_palettes[v1] = 3072; + sprite_disable_flag[v1] = 1; + sprite_instr_list_ptrs[v1] = addr_kSpriteObject_Ilist_C3BA; + int v2 = E->metroid_var_01 >> 1; + sprite_palettes[v2] = 3072; + sprite_disable_flag[v2] = 1; + sprite_instr_list_ptrs[v2] = addr_kSpriteObject_Ilist_C4B6; +} + +void Metroid_Hurt(void) { // 0xA3EB33 + Enemy_Metroid *E = Get_Metroid(cur_enemy_index); + if ((E->base.flash_timer & 2) != 0) { + R18_ = E->base.palette_index; + int v1 = E->metroid_var_00 >> 1; + sprite_palettes[v1] = R18_ | sprite_palettes[v1] & 0xF1FF; + int v2 = E->metroid_var_01 >> 1; + sprite_palettes[v2] = R18_ | sprite_palettes[v2] & 0xF1FF; + } else { + int v3 = E->metroid_var_00 >> 1; + sprite_palettes[v3] &= 0xF1FFu; + uint16 metroid_var_01 = E->metroid_var_01; + sprite_palettes[metroid_var_01 >> 1] &= 0xF1FFu; + } +} + +static Func_V *const off_A3EC09[4] = { Metroid_Func_1, Metroid_Func_2, Metroid_Func_3, Metroid_Func_4 }; +void Metroid_Main(void) { // 0xA3EB98 + Enemy_Metroid *E = Get_Metroid(cur_enemy_index); + draw_enemy_layer = samus_y_pos - 8; + uint16 v0 = 2 * E->metroid_var_F; + off_A3EC09[v0 >> 1](); + R24_ = E->base.vram_tiles_index | E->base.palette_index; + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + int v2 = E->metroid_var_00 >> 1; + sprite_x_pos[v2] = R18_; + sprite_y_pos[v2] = R20_; + sprite_palettes[v2] = R24_; + sprite_disable_flag[v2] = 0; + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + int v4 = E->metroid_var_01 >> 1; + sprite_x_pos[v4] = R18_; + sprite_y_pos[v4] = R20_; + sprite_palettes[v4] = R24_; + sprite_disable_flag[v4] = 0; +} + +void Metroid_Func_1(void) { // 0xA3EC11 + int16 v3; + int16 v4; + int16 v8; + int16 v9; + + R18_ = 0; + R20_ = 0; + Enemy_Metroid *E = Get_Metroid(cur_enemy_index); + *(uint16 *)((char *)&R18_ + 1) = (uint16)(E->base.y_pos - draw_enemy_layer) >> 2; + if ((*(uint16 *)((char *)&R18_ + 1) & 0x2000) != 0) + R20_ = (uint8)R20_ | 0xFFC0; + uint16 metroid_var_C = E->metroid_var_C; + bool v2 = metroid_var_C < R18_; + E->metroid_var_C = metroid_var_C - R18_; + v3 = E->metroid_var_D - (v2 + R20_); + E->metroid_var_D = v3; + if (v3 < 0) { + if ((uint16)v3 >= 0xFFFDu) + goto LABEL_9; + v4 = -3; + } else { + if ((uint16)v3 < 3u) + goto LABEL_9; + v4 = 3; + } + E->metroid_var_D = v4; + E->metroid_var_C = 0; +LABEL_9: + R18_ = E->metroid_var_C; + R20_ = E->metroid_var_D; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->metroid_var_C = 0; + E->metroid_var_D = 0; + } + R18_ = 0; + R20_ = 0; + *(uint16 *)((char *)&R18_ + 1) = (uint16)(E->base.x_pos - samus_x_pos) >> 2; + if ((*(uint16 *)((char *)&R18_ + 1) & 0x2000) != 0) + R20_ = (uint8)R20_ | 0xFFC0; + uint16 metroid_var_A = E->metroid_var_A; + v2 = metroid_var_A < R18_; + E->metroid_var_A = metroid_var_A - R18_; + v8 = E->metroid_var_B - (v2 + R20_); + E->metroid_var_B = v8; + if (v8 < 0) { + if ((uint16)v8 >= 0xFFFDu) + goto LABEL_19; + v9 = -3; + } else { + if ((uint16)v8 < 3u) + goto LABEL_19; + v9 = 3; + } + E->metroid_var_B = v9; + E->metroid_var_A = 0; +LABEL_19: + R18_ = E->metroid_var_A; + R20_ = E->metroid_var_B; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->metroid_var_A = 0; + E->metroid_var_B = 0; + } +} + +void Metroid_Func_2(void) { // 0xA3ECDC + int16 v1; + int16 v5; + uint16 v2, v6; + R18_ = 0; + R20_ = 0; + Enemy_Metroid *E = Get_Metroid(cur_enemy_index); + LOBYTE(v1) = (uint16)(draw_enemy_layer - E->base.y_pos) >> 8; + HIBYTE(v1) = draw_enemy_layer - LOBYTE(E->base.y_pos); + R20_ = (uint16)(v1 & 0xFF00) >> 3; + if ((R20_ & 0x1000) != 0) + R20_ |= 0xE000u; + if ((R20_ & 0x8000u) != 0) { + if (R20_ >= 0xFFFDu) + goto LABEL_9; + v2 = -3; + } else { + if (R20_ < 3u) + goto LABEL_9; + v2 = 3; + } + R20_ = v2; + R18_ = 0; +LABEL_9: + E->metroid_var_C = R18_; + E->metroid_var_D = R20_; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->metroid_var_C = 0; + E->metroid_var_D = 0; + } + R18_ = 0; + R20_ = 0; + LOBYTE(v5) = (uint16)(samus_x_pos - E->base.x_pos) >> 8; + HIBYTE(v5) = samus_x_pos - LOBYTE(E->base.x_pos); + R20_ = (uint16)(v5 & 0xFF00) >> 3; + if ((R20_ & 0x1000) != 0) + R20_ |= 0xE000u; + if ((R20_ & 0x8000u) != 0) { + if (R20_ >= 0xFFFDu) + goto LABEL_19; + v6 = -3; + } else { + if (R20_ < 3u) + goto LABEL_19; + v6 = 3; + } + R20_ = v6; + R18_ = 0; +LABEL_19: + E->metroid_var_A = R18_; + E->metroid_var_B = R20_; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->metroid_var_A = 0; + E->metroid_var_B = 0; + } +} + +void Metroid_Func_3(void) { // 0xA3ED8F + Enemy_Metroid *E = Get_Metroid(cur_enemy_index); + E->base.x_pos = samus_x_pos; + E->base.y_pos = draw_enemy_layer; + E->metroid_var_A = 0; + E->metroid_var_B = 0; + E->metroid_var_C = 0; + E->metroid_var_D = 0; +} + +void Metroid_Func_4(void) { // 0xA3EDAB + Enemy_Metroid *E = Get_Metroid(cur_enemy_index); + int v1 = E->metroid_var_E & 3; + E->base.x_pos += g_word_A3EA3F[v1]; + E->base.y_pos += g_word_A3EA3F[v1 + 4]; + E->metroid_var_A = 0; + E->metroid_var_B = 0; + E->metroid_var_C = 0; + E->metroid_var_D = 0; + if (E->metroid_var_E-- == 1) { + E->metroid_var_F = 0; + E->base.current_instruction = addr_kMetroid_Ilist_E9CF; + E->base.instruction_timer = 1; + } +} + +void Metroid_Touch(void) { // 0xA3EDEB + int16 v1; + int16 v2; + int16 v3; + int16 v4; + int16 v7; + + Enemy_Metroid *E = Get_Metroid(cur_enemy_index); + draw_enemy_layer = samus_y_pos - 8; + if (samus_contact_damage_index) { + if (E->metroid_var_F != 2) { + E->metroid_var_A = 0; + E->metroid_var_C = 0; + v1 = 0; + v2 = E->base.x_pos - samus_x_pos; + if (v2 < 0) + v1 = -256; + E->metroid_var_B = v1; + *(uint16 *)((char *)&E->metroid_var_A + 1) = v2 << 6; + v3 = 0; + v4 = E->base.y_pos - draw_enemy_layer; + if (v4 < 0) + v3 = -256; + E->metroid_var_D = v3; + *(uint16 *)((char *)&E->metroid_var_C + 1) = v4 << 6; + E->metroid_var_F = 0; + E->base.current_instruction = addr_kMetroid_Ilist_E9CF; + E->base.instruction_timer = 1; + } + } else { + uint16 v5 = cur_enemy_index; + if (E->metroid_var_F != 3) { + if ((enemy_damage_routine_exec_count & 7) == 7 && !sign16(samus_health - 30)) + QueueSfx3_Max6(0x2Du); + Metroid_Func_5(v5); + } + if (E->metroid_var_F < 2u) { + v7 = 1; + if (abs16(E->base.x_pos - samus_x_pos) < 8u && abs16(E->base.y_pos - draw_enemy_layer) < 8u) { + v7 = 2; + CallSomeSamusCode(0x12u); + } + E->metroid_var_F = v7; + if (v7 == 2) { + E->base.current_instruction = addr_kMetroid_Ilist_EA25; + E->base.instruction_timer = 1; + } + } + } +} + +void Metroid_Func_5(uint16 k) { // 0xA3EECE + uint16 v1; + draw_enemy_layer = samus_y_pos - 8; + if ((equipped_items & 0x20) != 0) { + v1 = 12288; + } else if (equipped_items & 1) { + v1 = 24576; + } else { + v1 = -16384; + } + R18_ = v1; + Enemy_Metroid *E = Get_Metroid(k); + uint16 metroid_var_02 = E->metroid_var_02; + bool v4 = metroid_var_02 < R18_; + E->metroid_var_02 = metroid_var_02 - R18_; + if (v4) + Samus_DealDamage(1u); +} + +void Metroid_Shot(void) { // 0xA3EF07 + int16 v3; + int16 v6; + int16 v7; + int16 v8; + int16 v9; + + draw_enemy_layer = samus_y_pos - 8; + uint16 v0 = 2 * collision_detection_index; + Enemy_Metroid *E = Get_Metroid(cur_enemy_index); + if (E->base.frozen_timer) { + v3 = projectile_type[v0 >> 1] & 0xF00; + if (v3 == 256 || v3 == 512) { + special_death_item_drop_x_origin_pos = E->base.x_pos; + special_death_item_drop_y_origin_pos = E->base.y_pos; + Enemy_NormalShotAI_SkipSomeParts_A3(); + if (!E->base.health) { + E->metroid_var_B = 0; + EnemyDeathAnimation(cur_enemy_index, 4u); + CallSomeSamusCode(0x13u); + sprite_instr_list_ptrs[E->metroid_var_00 >> 1] = 0; + uint16 metroid_var_01 = E->metroid_var_01; + sprite_instr_list_ptrs[metroid_var_01 >> 1] = 0; + Enemy_ItemDrop_Metroid(metroid_var_01); + } + } + } else { + if (E->metroid_var_F == 2) { + if ((projectile_type[v0 >> 1] & 0xF00) == 1280) { + E->metroid_var_E = 4; + E->metroid_var_F = 3; + E->base.current_instruction = addr_kMetroid_Ilist_E9CF; + E->base.instruction_timer = 1; + CallSomeSamusCode(0x13u); + } + } else { + E->metroid_var_A = 0; + E->metroid_var_C = 0; + v6 = 0; + v7 = E->base.x_pos - projectile_x_pos[0]; + if (v7 < 0) + v6 = -256; + E->metroid_var_B = v6; + *(uint16 *)((char *)&E->metroid_var_A + 1) = 32 * v7; + v8 = 0; + v9 = E->base.y_pos - projectile_y_pos[0]; + if (v9 < 0) + v8 = -256; + E->metroid_var_D = v8; + *(uint16 *)((char *)&E->metroid_var_C + 1) = 32 * v9; + E->metroid_var_F = 0; + E->base.current_instruction = addr_kMetroid_Ilist_E9CF; + E->base.instruction_timer = 1; + int v10 = collision_detection_index; + if ((projectile_type[v10] & 2) != 0) { + QueueSfx3_Max6(0xAu); + R18_ = projectile_damage[v10]; + E->base.flash_timer = 4; + uint16 metroid_parameter_2 = E->metroid_parameter_2; + bool v13 = metroid_parameter_2 < R18_; + uint16 v12 = metroid_parameter_2 - R18_; + v13 = !v13; + if (!v12 || !v13) { + E->metroid_parameter_2 = 0; + E->base.frozen_timer = 400; + E->base.ai_handler_bits |= 4u; + return; + } + E->metroid_parameter_2 = v12; + } + QueueSfx2_Max6(0x5Au); + } + } +} + +void Metroid_Powerbomb(uint16 k) { // 0xA3F042 + NormalEnemyPowerBombAi(); + if (!Get_Metroid(k)->base.health) { + CallSomeSamusCode(0x13u); + sprite_instr_list_ptrs[Get_Metroid(cur_enemy_index)->metroid_var_00 >> 1] = 0; + sprite_instr_list_ptrs[Get_Metroid(cur_enemy_index)->metroid_var_01 >> 1] = 0; + } +} diff --git a/src/sm_a4.c b/src/sm_a4.c new file mode 100644 index 0000000..2e8ca5d --- /dev/null +++ b/src/sm_a4.c @@ -0,0 +1,1781 @@ +// Enemy AI - Crocomire +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" + +static const uint16 g_word_A48692 = 8; +static const uint16 g_word_A48694 = 8; +static const uint16 g_word_A48696 = 0; +static const uint16 g_word_A48698 = 2; +static const uint16 g_word_A4869A = 1; +static const uint16 g_word_A4869C = 3; +static const uint16 g_word_A4869E = 3; +static const uint16 g_word_A486A0 = 8; +static const uint16 g_word_A486A2 = 0x300; +static const uint16 g_word_A486A4 = 0x640; +#define g_word_A4B89D ((uint16*)RomPtr(0xa4b89d)) +#define g_word_A4B8BD ((uint16*)RomPtr(0xa4b8bd)) +#define g_word_A4B8DD ((uint16*)RomPtr(0xa4b8dd)) +#define g_word_A4B8FD ((uint16*)RomPtr(0xa4b8fd)) +#define g_word_A4B91D ((uint16*)RomPtr(0xa4b91d)) +#define g_off_A48B79 ((uint16*)RomPtr(0xa48b79)) +#define g_word_A49156 ((uint16*)RomPtr(0xa49156)) +#define g_word_A49C79 ((uint16*)RomPtr(0xa49c79)) +#define g_word_A49E7B ((uint16*)RomPtr(0xa49e7b)) +#define g_word_A49BC5 (*(uint16*)RomPtr(0xa49bc5)) +#define g_word_A49BC7 (*(uint16*)RomPtr(0xa49bc7)) +#define g_word_A49BC9 (*(uint16*)RomPtr(0xa49bc9)) +#define g_word_A49BCB (*(uint16*)RomPtr(0xa49bcb)) +#define g_byte_A49697 ((uint8*)RomPtr(0xa49697)) +#define g_word_A49BBD ((uint16*)RomPtr(0xa49bbd)) +#define g_word_A498CA ((uint16*)RomPtr(0xa498ca)) +#define g_word_A499CB ((uint16*)RomPtr(0xa499cb)) +#define g_word_A499D9 ((uint16*)RomPtr(0xa499d9)) + + +uint16 EnemyInstr_Goto_A4(uint16 k, uint16 j) { // 0xA480ED + return *(uint16 *)RomPtr_A4(j); +} + +uint16 EnemyInstr_Sleep_A4(uint16 k, uint16 j) { // 0xA4812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + +void Enemy_GrappleReact_SamusLatchesOn_A4(void) { // 0xA48005 + SamusLatchesOnWithGrapple(); +} + +void Enemy_NormalTouchAI_A4(void) { // 0xA48023 + NormalEnemyTouchAi(); +} + +void Enemy_NormalShotAI_A4(void) { // 0xA4802D + NormalEnemyShotAi(); +} + +void Enemy_NormalFrozenAI_A4(void) { // 0xA48041 + NormalEnemyFrozenAI(); +} + +void Crocomire_Hurt(void) { // 0xA48687 + Crocomire_Func_27(cur_enemy_index); + Crocomire_Func_31(); +} + +static Func_XY_Y *const off_A486B3[21] = { // 0xA486A6 + Crocomire_Func_2, Crocomire_Func_3, Crocomire_Func_4, Crocomire_Func_5, + Crocomire_Func_7, Crocomire_Func_8, Crocomire_Func_9, Crocomire_Func_10, + Crocomire_Func_11, Crocomire_Func_13, Crocomire_Func_14, Crocomire_Func_15, + Crocomire_Func_16, Crocomire_Func_17, Crocomire_Func_18, Crocomire_Func_21, + Crocomire_Func_22, Crocomire_Func_23, Crocomire_Func_24, Crocomire_Func_25, + Crocomire_Func_26, +}; + +uint16 Crocomire_Instr_1(uint16 k, uint16 j) { + + uint16 crocom_var_C = Get_Crocomire(cur_enemy_index)->crocom_var_C; + return off_A486B3[crocom_var_C >> 1](crocom_var_C, j); +} + +uint16 Crocomire_Func_2(uint16 k, uint16 j) { // 0xA486DE + uint16 result = addr_kCrocomire_Ilist_BADE; + Get_Crocomire(k)->base.instruction_timer = 1; + return result; +} + +uint16 Crocomire_Func_3(uint16 k, uint16 j) { // 0xA486E8 + Get_Crocomire(0)->crocom_var_C = 4; + return addr_kCrocomire_Ilist_BBCE; +} + +uint16 Crocomire_Func_4(uint16 k, uint16 j) { // 0xA486F2 + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 v1 = abs16(E->base.x_pos - samus_x_pos); + if (sign16(v1 - 224)) { + E->crocom_var_B |= 0x8000u; + j = addr_kCrocomire_Ilist_BC56; + E->crocom_var_C = 18; + } + return j; +} + +uint16 Crocomire_Func_5(uint16 k, uint16 j) { // 0xA48717 + Enemy_Crocomire *E = Get_Crocomire(0); + if ((E->crocom_var_B & 0x800) != 0 && (E->crocom_var_B &= ~0x800u, E->crocom_var_D)) { + j = addr_kCrocomire_Ilist_BC30; + E->crocom_var_C = 12; + } else if ((int16)(E->base.x_pos - g_word_A486A2) < 0) { + j = addr_kCrocomire_Ilist_BE7E; + E->crocom_var_C = 10; + } else if ((int16)(j + 0x43CC) >= 0) { + return addr_kCrocomire_Ilist_BBCE; + } + return j; +} + +uint16 Crocomire_Instr_14(uint16 k, uint16 j) { // 0xA48752 + if (sign16((random_number & 0xFFF) - 1024)) { + Enemy_Crocomire *E = Get_Crocomire(0); + E->crocom_var_C = 8; + E->crocom_var_F = 0; + return addr_kCrocomire_Ilist_BB36; + } + return j; +} + +uint16 Crocomire_Func_7(uint16 k, uint16 j) { // 0xA4876C + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 crocom_var_B = E->crocom_var_B; + if ((crocom_var_B & 0x800) != 0) { + E->crocom_var_B = crocom_var_B & 0xF7FF; + j = addr_kCrocomire_Ilist_BC30; + E->crocom_var_C = 12; + } else { + uint16 crocom_var_F = E->crocom_var_F; + if (sign16(crocom_var_F - 18)) { + ++E->crocom_var_F; + ++E->crocom_var_F; + SpawnEnemyProjectileWithGfx(crocom_var_F, cur_enemy_index, addr_stru_868F8F); + QueueSfx3_Max6(0x1Cu); + } else { + j = addr_kCrocomire_Ilist_BBCA; + E->crocom_var_C = 6; + } + } + return j; +} + +uint16 Crocomire_Func_8(uint16 k, uint16 j) { // 0xA487B2 + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 crocom_var_B = E->crocom_var_B; + if ((crocom_var_B & 0x800) != 0) { + E->crocom_var_B = crocom_var_B & 0xF7FF; + j = addr_kCrocomire_Ilist_BC30; + E->crocom_var_C = 12; + } + return j; +} + +uint16 Crocomire_Func_9(uint16 k, uint16 j) { // 0xA487CA + uint16 v2; + + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 crocom_var_D = E->crocom_var_D; + if (crocom_var_D && (v2 = crocom_var_D - 1, (E->crocom_var_D = v2) != 0)) { + E->crocom_var_C = 12; + return addr_kCrocomire_Ilist_BC34; + } else { + E->crocom_var_C = 6; + return addr_kCrocomire_Ilist_BBCE; + } +} + +uint16 Crocomire_Func_10(uint16 k, uint16 j) { // 0xA487E9 + Enemy_Crocomire *E = Get_Crocomire(0); + if ((int16)(E->base.x_pos - g_word_A486A2) >= 0) { + E->crocom_var_C = 6; + return addr_kCrocomire_Ilist_BBCE; + } + return j; +} + +uint16 Crocomire_Func_11(uint16 k, uint16 j) { // 0xA487FB + Get_Crocomire(0)->crocom_var_C = 6; + return addr_kCrocomire_Ilist_BD2A; +} + +uint16 Crocomire_Func_12(uint16 k, uint16 j) { // 0xA48805 + Enemy_Crocomire *E = Get_Crocomire(0); + E->crocom_var_B &= ~0x400u; + return addr_kCrocomire_Ilist_BCD8; +} + +uint16 Crocomire_Func_13(uint16 k, uint16 j) { // 0xA48812 + Enemy_Crocomire *E = Get_Crocomire(0); + if ((E->crocom_var_B & 0x800) != 0) { + E->crocom_var_B &= ~0x800u; + E->crocom_var_C = 20; + return addr_kCrocomire_Ilist_BC30; + } else if ((int16)(j + 0x425E) >= 0) { + return addr_kCrocomire_Ilist_BD2A; + } + return j; +} + +uint16 Crocomire_Func_14(uint16 k, uint16 j) { // 0xA48836 + Enemy_Crocomire *E = Get_Crocomire(0); + if ((E->crocom_var_B & 0x800) != 0) { + E->crocom_var_B &= ~0x800u; + E->crocom_var_C = 12; + return addr_kCrocomire_Ilist_BC30; + } else if ((int16)(j + 0x425E) >= 0) { + return addr_kCrocomire_Ilist_BD2A; + } + return j; +} + +uint16 Crocomire_Func_15(uint16 k, uint16 j) { // 0xA4885A + Enemy_Crocomire *E = Get_Crocomire(0); + if ((E->crocom_var_B & 0x800) != 0) { + E->crocom_var_B &= ~0x800u; + E->crocom_var_C = 12; + return addr_kCrocomire_Ilist_BC30; + } else if ((int16)(j + 0x425E) >= 0) { + return addr_kCrocomire_Ilist_BD2A; + } + return j; +} + +uint16 Crocomire_Func_16(uint16 k, uint16 j) { // 0xA4887E + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 v1 = E->crocom_var_D - 1; + E->crocom_var_D = v1; + if (sign16(v1 - 2)) { + E->crocom_var_D = 0; + E->crocom_var_C = 6; + return addr_kCrocomire_Ilist_BBCE; + } + return j; +} + +uint16 Crocomire_Func_17(uint16 k, uint16 j) { // 0xA4889A + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 crocom_var_B = E->crocom_var_B; + if ((crocom_var_B & 0x800) != 0) { + E->crocom_var_B = crocom_var_B & 0x1F00 | 0xA000; + E->crocom_var_D = 1; + E->crocom_var_E = 10; + E->crocom_var_C = 12; + QueueSfx2_Max6(0x54u); + } else { + Get_Crocomire(cur_enemy_index)->crocom_var_C = 10; + return addr_kCrocomire_Ilist_BD8E; + } + return j; +} + +uint16 Crocomire_Func_18(uint16 k, uint16 j) { // 0xA488D2 + uint16 result = Crocomire_Func_2(cur_enemy_index, j); + Enemy_Crocomire *E = Get_Crocomire(0); + E->crocom_var_B |= 0x200u; + E->crocom_var_D = 32; + E->crocom_var_C = 30; + return result; +} + +uint16 Crocomire_Func_19(uint16 k, uint16 j) { // 0xA488EE + bool v2; // zf + + j = Crocomire_Func_2(cur_enemy_index, j); + Enemy_Crocomire *E = Get_Crocomire(0); + if (!E->crocom_var_D || (v2 = E->crocom_var_D == 1, --E->crocom_var_D, v2)) { + j = Crocomire_Func_20(cur_enemy_index); + E->crocom_var_C = 32; + } + return j; +} + +uint16 Crocomire_Func_20(uint16 k) { // 0xA4890B + Get_Crocomire(k)->crocom_var_C = 20; + Enemy_Crocomire *E = Get_Crocomire(0); + E->crocom_var_B = E->crocom_var_B; + return addr_kCrocomire_Ilist_BAEA; +} + +uint16 Crocomire_Func_21(uint16 k, uint16 j) { // 0xA4891B + Enemy_Crocomire *E = Get_Crocomire(0); + if ((E->crocom_var_B & 0x100) != 0) { + j = Crocomire_Func_2(cur_enemy_index, j); + E->crocom_var_D = 16; + E->crocom_var_C = 34; + } else { + j = Crocomire_Func_20(cur_enemy_index); + E->crocom_var_C = 32; + } + return j; +} + +uint16 Crocomire_Func_22(uint16 k, uint16 j) { // 0xA48940 + k = cur_enemy_index; + j = Crocomire_Func_2(k, j); + Enemy_Crocomire *E = Get_Crocomire(0); + if (!E->crocom_var_D) { + E->crocom_var_B |= 0x2000u; + j = Crocomire_Func_3(k, j); + E->crocom_var_C = 36; + } + return j; +} + +uint16 Crocomire_Func_23(uint16 k, uint16 j) { // 0xA4895E + k = cur_enemy_index; + + Enemy_Crocomire *E = Get_Crocomire(0); + if (sign16(E->base.x_pos - 672)) { + j = Crocomire_Func_3(k, j); + E->crocom_var_C = 36; + E->crocom_var_D = 3; + } else { + if ((E->crocom_var_B & 0x4000) == 0) { + E->crocom_var_C = 38; + j = Crocomire_Func_12(k, j); + } + if ((E->crocom_var_B & 0x4000) != 0) { + E->crocom_var_D = 5; + j = addr_kCrocomire_Ilist_BCD8; + E->crocom_var_F = E->crocom_var_C; + E->crocom_var_C = 42; + } + } + return j; +} + +uint16 Crocomire_Func_24(uint16 k, uint16 j) { // 0xA489A8 + bool v2; // zf + + k = cur_enemy_index; + Enemy_Crocomire *E = Get_Crocomire(0); + if (!E->crocom_var_D || (v2 = E->crocom_var_D == 1, --E->crocom_var_D, v2)) { + j = Crocomire_Func_3(k, j); + E->crocom_var_C = 40; + E->crocom_var_B &= ~0x400u; + } else { + E->crocom_var_C = 36; + Get_Crocomire(0x40u)->crocom_var_D = 0; + E->crocom_var_B |= 0x400u; + return addr_kCrocomire_Ilist_BCD8; + } + return j; +} + +uint16 Crocomire_Func_25(uint16 k, uint16 j) { // 0xA489DE + k = cur_enemy_index; + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 crocom_var_B = E->crocom_var_B; + if ((crocom_var_B & 0x2000) == 0) + E->crocom_var_B = crocom_var_B & 0xFCFF; + j = Crocomire_Func_3(k, j); + E->crocom_var_C = 40; + return j; +} + +uint16 Crocomire_Func_26(uint16 k, uint16 j) { // 0xA489F9 + Enemy_Crocomire *E = Get_Crocomire(0); + if (E->crocom_var_D) { + uint16 crocom_var_B = E->crocom_var_B; + if ((crocom_var_B & 0x4000) != 0) { + --E->crocom_var_D; + QueueSfx2_Max6(0x3Bu); + return addr_kCrocomire_Ilist_BCD8; + } else { + E->crocom_var_B = crocom_var_B & 0xBFFF; + E->crocom_var_C = 12; + } + } else { + E->crocom_var_B &= ~0x4000u; + E->base.instruction_timer = 1; + E->crocom_var_C = E->crocom_var_F; + return addr_kCrocomire_Ilist_BCD8; + } + return j; +} + +void Crocomire_Init(void) { // 0xA48A5A + VramWriteEntry *v7; + + boss_id = 6; + uint16 v0 = 0; + do { + tilemap_stuff[v0 >> 1] = 824; + v0 += 2; + } while ((int16)(v0 - 4096) < 0); + if ((*(uint16 *)&boss_bits_for_area[area_index] & 2) != 0) { + *(uint16 *)scrolls = 257; + *(uint16 *)&scrolls[2] = 257; + *(uint16 *)&g_byte_7E0688 = 0; + Enemy_Crocomire *E = Get_Crocomire(0); + E->base.properties = E->base.properties & 0x7BFF | 0x400; + static const SpawnHardcodedPlmArgs unk_A48AFA = { 0x20, 0x03, 0xb753 }; + static const SpawnHardcodedPlmArgs unk_A48B02 = { 0x1e, 0x03, 0xb753 }; + static const SpawnHardcodedPlmArgs unk_A48B0A = { 0x61, 0x0b, 0xb747 }; + SpawnHardcodedPlm(&unk_A48AFA); + SpawnHardcodedPlm(&unk_A48B02); + SpawnHardcodedPlm(&unk_A48B0A); + E->crocom_var_A = 84; + E->base.current_instruction = addr_kCrocomire_Ilist_E1CC; + E->base.instruction_timer = 1; + E->base.x_pos = 576; + E->base.y_pos = 144; + E->base.y_height = 28; + E->base.x_width = 40; + uint16 v6 = vram_write_queue_tail; + v7 = gVramWriteEntry(vram_write_queue_tail); + v7->size = 2048; + v7->src.addr = 0x2000; + *(uint16 *)&v7->src.bank = 126; + v7->vram_dst = (reg_BG2SC & 0xFC) << 8; + vram_write_queue_tail = v6 + 7; + } else { + DisableMinimapAndMarkBossRoomAsExplored(); + g_word_7E069A = 0; + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + E->crocom_var_A = 0; + E->crocom_var_E = 0; + *(uint16 *)scrolls = 0; + for (int i = 32; i >= 0; i -= 2) { + int v3 = i >> 1; + target_palettes[v3 + 160] = g_word_A4B8BD[v3]; + target_palettes[v3 + 208] = g_word_A4B8DD[v3]; + } + E->crocom_var_C = 4; + UNUSED_word_7E179E = 16; + camera_distance_index = 2; + enemy_bg2_tilemap_size = 1024; + E->base.current_instruction = addr_kCrocomire_Ilist_BADE; + E->base.extra_properties |= 4u; + E->base.instruction_timer = 1; + } +} + +void Crocomire_Func_27(uint16 k) { // 0xA48B5B + reg_BG2VOFS = 67 - Get_Crocomire(k)->base.y_pos; + uint16 v1 = 32; + uint16 spritemap_pointer; + while (1) { + spritemap_pointer = Get_Crocomire(0)->base.spritemap_pointer; + if (spritemap_pointer == g_off_A48B79[v1 >> 1]) + break; + v1 -= 2; + if ((v1 & 0x8000u) != 0) { + Crocomire_8BA4(); + return; + } + } + reg_BG2VOFS += *((uint16 *)RomPtr_A4(spritemap_pointer) + 14); + Crocomire_8BA4(); +} + +void Crocomire_8BA4(void) { // 0xA48BA4 + Enemy_Crocomire *E0 = Get_Crocomire(cur_enemy_index); + Enemy_Crocomire *E1 = Get_Crocomire(cur_enemy_index + 64); + E1->base.x_pos = E1->crocom_var_A + E0->base.x_pos; + E1->base.y_pos = E0->base.y_pos; + uint16 x_pos = E0->base.x_pos; + if ((int16)(x_pos - layer1_x_pos) >= 0) { + R18_ = layer1_x_pos + 256; + if (sign16(E0->base.x_pos - 128 - (layer1_x_pos + 256))) + goto LABEL_3; +LABEL_6: + reg_BG2HOFS = 256; + return; + } + if ((int16)(x_pos + 128 - layer1_x_pos) < 0) + goto LABEL_6; +LABEL_3:; + uint16 v6 = layer1_x_pos - E0->base.x_pos + 51; + uint16 v4 = abs16(v6); + if (!sign16(v4 - 284)) + v6 = 256; + reg_BG2HOFS = v6; +} + +void nullsub_305(void) {} + +static Func_V *const off_A48C14[45] = { // 0xA48C04 + Crocomire_Func_28, Crocomire_Func_52, Crocomire_Func_36, Crocomire_92CE, Crocomire_Func_54, Crocomire_Func_36, Crocomire_92CE, Crocomire_Func_54, + Crocomire_Func_57, Crocomire_Func_60, Crocomire_Func_62, Crocomire_929E, Crocomire_Func_64, Crocomire_Func_65, Crocomire_Func_66, Crocomire_Func_51, + Crocomire_8D47, Crocomire_929E, Crocomire_Func_51, Crocomire_8D47, Crocomire_929E, Crocomire_Func_51, Crocomire_Func_59, Crocomire_Func_60, + Crocomire_Func_62, Crocomire_Func_63, Crocomire_Func_56, Crocomire_9506, Crocomire_Func_65, Crocomire_Func_66, Crocomire_Func_49, Crocomire_Func_68, + Crocomire_Func_70, Crocomire_Func_71, Crocomire_Func_72, Crocomire_Func_73, Crocomire_Func_88, Crocomire_9B65, Crocomire_Func_90, Crocomire_Func_89, + Crocomire_9B86, nullsub_305, Crocomire_Func_91, Crocomire_Func_29, Crocomire_Func_69, +}; + +void Crocomire_Main(void) { + + int v0 = Get_Crocomire(0)->crocom_var_A >> 1; + off_A48C14[v0](); + Crocomire_Func_30(); + Crocomire_Func_31(); +} + +void Crocomire_Func_28(void) { // 0xA48C6E + Crocomire_Func_37(); + *(uint16 *)&scrolls[4] = 257; + if (!sign16(samus_x_pos - 1312)) + *(uint16 *)&scrolls[4] = 256; + Crocomire_Func_27(cur_enemy_index); +} + +void Crocomire_Func_29(void) { // 0xA48C90 + reg_BG2HOFS = 0; + reg_BG2VOFS = 0; +} + +void Crocomire_Func_30(void) { // 0xA48C95 + Enemy_Crocomire *E = Get_Crocomire(0); + if (!E->crocom_var_A + && (((__PAIR32__(E->base.x_pos - E->base.x_width, E->base.x_pos) + - __PAIR32__(samus_x_radius, E->base.x_width) + - __PAIR32__(samus_x_pos, (E->base.x_pos < E->base.x_width) + samus_x_radius)) >> 16) & 0x8000u) != 0) { + NormalEnemyTouchAi(); + samus_x_pos = E->base.x_pos - E->base.x_width - samus_x_radius; + samus_prev_x_pos = samus_x_pos; + extra_samus_x_displacement = -4; + extra_samus_y_displacement = -1; + } +} + +void Crocomire_Func_31(void) { // 0xA48CCB + uint16 j; + + if (!door_transition_flag_enemies) { + if (Get_Crocomire(0)->base.flash_timer && (enemy_damage_routine_exec_count & 2) != 0) { + for (int i = 14; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 112] = 0x7FFF; + } else { + for (j = 14; (j & 0x8000u) == 0; j -= 2) + palette_buffer[(j >> 1) + 112] = g_word_A4B89D[j >> 1]; + } + } +} + +uint16 Crocomire_Instr_11(uint16 k, uint16 j) { // 0xA48CFB + QueueSfx2_Max6(0x74u); + return j; +} + +uint16 Crocomire_Instr_7(uint16 k, uint16 j) { // 0xA48D07 + QueueSfx2_Max6(0x25u); + return j; +} + +uint16 Crocomire_Instr_19(uint16 k, uint16 j) { // 0xA48D13 + QueueSfx2_Max6(0x75u); + return j; +} + +void Crocomire_Func_35(void) { // 0xA48D1F + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 crocom_var_20 = E->crocom_var_20; + if (crocom_var_20) { + uint16 v2 = crocom_var_20 - 1; + E->crocom_var_20 = v2; + if (!v2) { + E->crocom_var_20 = 32; + QueueSfx3_Max6(0x22u); + } + } +} + +void Crocomire_Func_36(void) { // 0xA48D3F + Crocomire_Func_35(); + Crocomire_8BA4(); + Crocomire_8D47(); +} + +void Crocomire_8D47(void) { // 0xA48D47 + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 crocom_var_D = E->crocom_var_D; + if (crocom_var_D) { + E->crocom_var_D = crocom_var_D - 1; + } else { + ++E->crocom_var_A; + ++E->crocom_var_A; + E->crocom_var_E = 768; + } +} + +void Crocomire_Func_37(void) { // 0xA48D5E + static const SpawnHardcodedPlmArgs unk_A48DC2 = { 0x61, 0x0b, 0xb74b }; + static const SpawnHardcodedPlmArgs unk_A48E0B = { 0x62, 0x0b, 0xb74b }; + static const SpawnHardcodedPlmArgs unk_A48E13 = { 0x63, 0x0b, 0xb74b }; + static const SpawnHardcodedPlmArgs unk_A48EA3 = { 0x4e, 0x03, 0xb757 }; + + Enemy_Crocomire *E0 = Get_Crocomire(0); + if (sign16(E0->base.x_pos - 1536)) { + kraid_unk9000 = 0; + g_word_7E9002 = 0; + g_word_7E9006 = 0; + g_word_7E900A = 0; + } else if (sign16(E0->base.x_pos - 1552)) { + if (!kraid_unk9000) { + kraid_unk9000 = 1; + R18_ = 1536; + R20_ = 176; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + } + } else if (sign16(E0->base.x_pos - 1552)) { + g_word_7E9002 = 0; + g_word_7E9006 = 0; + g_word_7E900A = 0; + } else if (sign16(E0->base.x_pos - 1568)) { + if (!g_word_7E9002) { + g_word_7E9002 = 1; + SpawnHardcodedPlm(&unk_A48DC2); + R18_ = 1568; + R20_ = 176; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + } + } else { + uint16 x_pos = E0->base.x_pos; + if (sign16(x_pos - 1568)) { + g_word_7E9006 = 0; + g_word_7E900A = 0; + } else if (sign16(x_pos - 1584)) { + if (!g_word_7E9006) { + g_word_7E9006 = 1; + SpawnHardcodedPlm(&unk_A48E0B); + SpawnHardcodedPlm(&unk_A48E13); + R18_ = 1584; + R20_ = 176; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + } + } else if ((int16)(x_pos - g_word_A486A4) >= 0) { + Crocomire_8EE5(); + E0->crocom_var_20 = 1; + g_word_7E9018 = 1; + uint16 v3 = cur_enemy_index; + Enemy_Crocomire *EK = Get_Crocomire(cur_enemy_index); + ++EK->crocom_var_A; + ++EK->crocom_var_A; + Get_Crocomire(0)->crocom_var_00 = 2; + Get_Crocomire(0x40u)->crocom_var_00 = 2; + Get_Crocomire(0x80)->crocom_var_00 = 2; + Get_Crocomire(0xC0u)->crocom_var_00 = 2; + Get_Crocomire(0x100u)->crocom_var_00 = 2; + Get_Crocomire(0x140u)->crocom_var_00 = 2; + Get_Crocomire(0)->crocom_var_01 = 0; + Get_Crocomire(0x40u)->crocom_var_01 = 0; + Get_Crocomire(0x80)->crocom_var_01 = 0; + Get_Crocomire(0xC0u)->crocom_var_01 = 0; + Get_Crocomire(0x100u)->crocom_var_01 = 0; + Get_Crocomire(0x140u)->crocom_var_01 = 0; + QueueSfx2_Max6(0x3Bu); + *(uint16 *)((char *)&g_word_7E9015 + 1) = 0; + SpawnHardcodedPlm(&unk_A48EA3); + EK->base.current_instruction = addr_kCrocomire_Ilist_BFB0; + EK->base.instruction_timer = 1; + EK->base.properties |= kEnemyProps_Tangible; + Enemy_Crocomire *E1 = Get_Crocomire(cur_enemy_index + 64); + E1->base.instruction_timer = 0x7FFF; + E1->base.current_instruction = addr_kCrocomire_Ilist_BF62; + Get_Crocomire(0x40u)->base.properties |= 0x100u; + EK->crocom_var_E = 0; + EK->crocom_var_F = 0; + EK->crocom_var_D = 2048; + Get_Crocomire(0)->base.y_height = 16; + } + } +} + +void Crocomire_8EE5(void) { // 0xA48EE5 + static const SpawnHardcodedPlmArgs unk_A48DC2 = { 0x61, 0x0b, 0xb74b }; + static const SpawnHardcodedPlmArgs unk_A48E0B = { 0x62, 0x0b, 0xb74b }; + static const SpawnHardcodedPlmArgs unk_A48E13 = { 0x63, 0x0b, 0xb74b }; + static const SpawnHardcodedPlmArgs unk_A48EA3 = { 0x4e, 0x03, 0xb757 }; + static const SpawnHardcodedPlmArgs unk_A48EE9 = { 0x61, 0x0b, 0xb74f }; + static const SpawnHardcodedPlmArgs unk_A48EF1 = { 0x62, 0x0b, 0xb74f }; + static const SpawnHardcodedPlmArgs unk_A48EF9 = { 0x63, 0x0b, 0xb74f }; + static const SpawnHardcodedPlmArgs unk_A48F01 = { 0x64, 0x0b, 0xb74f }; + static const SpawnHardcodedPlmArgs unk_A48F09 = { 0x65, 0x0b, 0xb74f }; + static const SpawnHardcodedPlmArgs unk_A48F11 = { 0x66, 0x0b, 0xb74f }; + static const SpawnHardcodedPlmArgs unk_A48F19 = { 0x67, 0x0b, 0xb74f }; + static const SpawnHardcodedPlmArgs unk_A48F21 = { 0x68, 0x0b, 0xb74f }; + static const SpawnHardcodedPlmArgs unk_A48F29 = { 0x69, 0x0b, 0xb74f }; + static const SpawnHardcodedPlmArgs unk_A48F31 = { 0x6a, 0x0b, 0xb74f }; + SpawnHardcodedPlm(&unk_A48EE9); + SpawnHardcodedPlm(&unk_A48EF1); + SpawnHardcodedPlm(&unk_A48EF9); + SpawnHardcodedPlm(&unk_A48F01); + SpawnHardcodedPlm(&unk_A48F09); + SpawnHardcodedPlm(&unk_A48F11); + SpawnHardcodedPlm(&unk_A48F19); + SpawnHardcodedPlm(&unk_A48F21); + SpawnHardcodedPlm(&unk_A48F29); + SpawnHardcodedPlm(&unk_A48F31); + R18_ = 1536; + R20_ = 176; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + R18_ = 1552; + R20_ = 192; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + R18_ = 1568; + R20_ = 176; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + R18_ = 1584; + R20_ = 192; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + R18_ = 1600; + R20_ = 192; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + R18_ = 1616; + R20_ = 192; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + R18_ = 1632; + R20_ = 192; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); +} + +void Crocomire_Func_38(uint16 k) { // 0xA48FC2 + Enemy_MoveDown(k); +} + +uint16 Crocomire_Instr_2(uint16 k, uint16 j) { // 0xA48FC7 + earthquake_type = 4; + earthquake_timer = 5; + QueueSfx2_Max6(0x76u); + return j; +} + +uint16 Crocomire_Instr_4(uint16 k, uint16 j) { // 0xA48FDF + if ((Get_Crocomire(0)->crocom_var_B & 0x800) == 0) { + R18_ = 0; + R20_ = -4; + Enemy_MoveRight_IgnoreSlopes(cur_enemy_index); + } + return j; +} + +uint16 Crocomire_Instr_3(uint16 k, uint16 j) { // 0xA48FFA + Crocomire_Func_43(); + return Crocomire_Instr_4(k, j); +} + +uint16 Crocomire_Instr_15(uint16 k, uint16 j) { // 0xA48FFF + Crocomire_Func_43(); + return Crocomire_Instr_4(k, j); +} + +void Crocomire_Func_43(void) { // 0xA49004 + uint16 v1 = random_number & 0x1F; + if ((int16)(random_number - 4096) >= 0) + v1 = -v1; + Crocomire_Func_87(0, v1); +} + +uint16 Crocomire_Instr_16(uint16 k, uint16 j) { // 0xA4901D + R18_ = 0; + R20_ = -4; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + Get_Crocomire(0)->crocom_var_C = 14; + return addr_kCrocomire_Ilist_BF3C; + } else { + uint16 v2 = 32; + if (!sign16(random_number - 2048)) + v2 = -32; + R18_ = v2; + return Crocomire_Func_87(j, v2 + (random_number & 0xF)); + } +} + +uint16 Crocomire_Instr_13(uint16 k, uint16 j) { // 0xA4905B + R18_ = 0; + R20_ = 4; + Enemy_Crocomire *E = Get_Crocomire(0); + if ((int16)(((__PAIR32__(E->base.x_pos - E->base.x_width, E->base.x_pos) + - (E->base.x_width | 0x1000000) + - ((uint16)((E->base.x_pos < E->base.x_width) + 256) | 0x40000)) >> 16) + - layer1_x_pos) < 0) + Enemy_MoveRight_IgnoreSlopes(cur_enemy_index); + return j; +} + +uint16 Crocomire_Instr_18(uint16 k, uint16 j) { // 0xA4907F + R18_ = 0; + R20_ = 4; + Enemy_MoveRight_IgnoreSlopes(k); + return j; +} + +uint16 Crocomire_Instr_12(uint16 k, uint16 j) { // 0xA4908F + Crocomire_Func_43(); + return Crocomire_Instr_13(k, j); +} + +uint16 Crocomire_Instr_17(uint16 k, uint16 j) { // 0xA49094 + Crocomire_Func_43(); + return Crocomire_Instr_18(k, j); +} + +void Crocomire_Func_49(void) { // 0xA49099 + static const SpawnHardcodedPlmArgs unk_A490D4 = { 0x4e, 0x03, 0xb753 }; + + Crocomire_Func_50(); + Crocomire_Func_53(); + Crocomire_Func_55(); + Enemy_Crocomire *E = Get_Crocomire(0); + if (E->crocom_var_A == 62) { + QueueMusic_Delayed8(6u); + E->crocom_var_A = 88; + E->base.current_instruction = addr_kCrocomire_Ilist_E1D2; + *(uint16 *)&scrolls[4] = 257; + debug_disable_minimap = 0; + Get_Crocomire(0x40u)->base.properties |= 0x200u; + SpawnHardcodedPlm(&unk_A490D4); + camera_distance_index = 0; + *(uint16 *)&g_byte_7E0688 = 0; + } +} + +void Crocomire_Func_50(void) { // 0xA490DF + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 y_pos = E->base.y_pos; + uint16 v2 = addr_kCrocomire_Ilist_BF7E; + if (sign16(y_pos - 280)) { + v2 = addr_kCrocomire_Ilist_BF86; + if (sign16(y_pos - 264)) { + v2 = addr_kCrocomire_Ilist_BF8C; + if (sign16(y_pos - 248)) + v2 = addr_kCrocomire_Ilist_BF92; + } + } + E->base.current_instruction = v2; + E->base.instruction_timer = 1; +} + +void Crocomire_Func_51(void) { // 0xA49108 + Crocomire_Func_53(); + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 y_pos = E->base.y_pos; + uint16 v2 = addr_kCrocomire_Ilist_BF64; + if (sign16(y_pos - 280)) { + v2 = addr_kCrocomire_Ilist_BF6C; + if (sign16(y_pos - 264)) { + v2 = addr_kCrocomire_Ilist_BF72; + if (sign16(y_pos - 248)) + v2 = addr_kCrocomire_Ilist_BF78; + } + } + E->base.current_instruction = v2; + E->base.instruction_timer = 1; + Crocomire_Func_55(); +} + +void Crocomire_Func_52(void) { // 0xA49136 + uint16 v0 = *(uint16 *)((char *)&g_word_7E9015 + 1); + if (sign16(*(uint16 *)((char *)&g_word_7E9015 + 1) - 22)) { + uint16 v1 = *(uint16 *)((char *)&g_word_7E9015 + 1); + *(uint16 *)((char *)&g_word_7E9015 + 1) += 2; + SpawnEnemyProjectileWithGfx(g_word_A49156[v0 >> 1], v1, addr_stru_868F9D); + } + Crocomire_Func_54(); +} + +void Crocomire_Func_53(void) { // 0xA4916C + int16 v0; + + if (!--g_word_7E9018) { + g_word_7E9018 = 6; + v0 = random_number & 0x3F; + if ((random_number & 2) == 0) + v0 = ~v0; + R18_ = Get_Crocomire(0)->base.x_pos + v0; + R20_ = (uint16)(random_number & 0x1F00) >> 8; + R20_ = lava_acid_y_pos + 16 - R20_; + R22_ = 21; + R24_ = 0; + CreateSpriteAtPos(); + } +} + +void Crocomire_Func_54(void) { // 0xA491BA + Crocomire_Func_35(); + Crocomire_Func_53(); + Crocomire_Func_55(); +} + +void Crocomire_Func_55(void) { // 0xA491C1 + char crocom_var_D; + char v7; + char v9; + char crocom_var_E; + char crocom_var_E_high; + char v12; + + Crocomire_Func_58(); + Enemy_Crocomire *E0 = Get_Crocomire(0); + E0->crocom_var_B &= ~0x800u; + Crocomire_Func_27(cur_enemy_index); + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + if (sign16(E->base.y_pos - 280)) { + uint16 v3 = 8 * ((reg_BG2VOFS + 288) & 0xFFF8); + R18_ = 32; + do { + tilemap_stuff[v3 >> 1] = 824; + v3 += 2; + --R18_; + } while (R18_); + nmi_flag_bg2_enemy_vram_transfer = 1; + E0->base.extra_properties &= ~0x8000u; + crocom_var_D = E->crocom_var_D; + LOBYTE(E->crocom_var_D) = crocom_var_D + 0x80; + v7 = __CFADD__uint8(crocom_var_D, 0x80) + HIBYTE(E->crocom_var_D) + 3; + if (!sign8(v7 - 48)) + v7 = 48; + HIBYTE(E->crocom_var_D) = v7; + bool v8 = __CFADD__uint8(LOBYTE(E->crocom_var_E), v7); + LOBYTE(E->crocom_var_E) += v7; + v9 = v8 + HIBYTE(E->crocom_var_E); + if (!sign8(v9 - 3)) + v9 = 3; + HIBYTE(E->crocom_var_E) = v9; + crocom_var_E = E->crocom_var_E; + v8 = __CFADD__uint8(HIBYTE(E->crocom_var_F), crocom_var_E); + HIBYTE(E->crocom_var_F) += crocom_var_E; + crocom_var_E_high = HIBYTE(E->crocom_var_E); + bool v13 = v8; + v8 = __CFADD__uint8(v8, crocom_var_E_high); + v12 = v13 + crocom_var_E_high; + v8 |= __CFADD__uint8(LOBYTE(E->base.y_pos), v12); + LOBYTE(E->base.y_pos) += v12; + HIBYTE(E->base.y_pos) += v8; + } else { + ++E->crocom_var_A; + ++E->crocom_var_A; + E0->crocom_var_D = 48; + } +} + +void Crocomire_Func_56(void) { // 0xA4926E + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + uint16 y_pos = E->base.y_pos; + uint16 v2 = addr_kCrocomire_Ilist_BF7E; + if (sign16(y_pos - 280)) { + v2 = addr_kCrocomire_Ilist_BF86; + if (sign16(y_pos - 264)) { + v2 = addr_kCrocomire_Ilist_BF8C; + if (sign16(y_pos - 248)) + v2 = addr_kCrocomire_Ilist_BF92; + } + } + E->base.current_instruction = v2; + E->base.instruction_timer = 1; + Crocomire_Func_53(); + Crocomire_92D8(); +} + +void Crocomire_929E(void) { // 0xA4929E + Crocomire_Func_53(); + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + uint16 y_pos = E->base.y_pos; + uint16 v2 = addr_kCrocomire_Ilist_BF64; + if (sign16(y_pos - 280)) { + v2 = addr_kCrocomire_Ilist_BF6C; + if (sign16(y_pos - 264)) { + v2 = addr_kCrocomire_Ilist_BF72; + if (sign16(y_pos - 248)) + v2 = addr_kCrocomire_Ilist_BF78; + } + } + E->base.current_instruction = v2; + E->base.instruction_timer = 1; + Crocomire_92D8(); +} + +void Crocomire_92CE(void) { // 0xA492CE + Crocomire_Func_35(); + Crocomire_Func_53(); + Crocomire_92D8(); +} + +void Crocomire_92D8(void) { // 0xA492D8 + int16 v3; + char v6; + + Crocomire_Func_58(); + Enemy_Crocomire *EK = Get_Crocomire(cur_enemy_index); + if (sign16(EK->base.y_pos - 218)) { + ++EK->crocom_var_A; + ++EK->crocom_var_A; + } else { + Crocomire_Func_27(cur_enemy_index); + Enemy_Crocomire *E0 = Get_Crocomire(0); + v3 = E0->crocom_var_D + 256; + if (!sign16(E0->crocom_var_D - 7680)) + v3 = 7936; + E0->crocom_var_D = v3; + uint8 crocom_var_E = E0->crocom_var_E; + bool v5 = crocom_var_E < HIBYTE(E0->crocom_var_D); + LOBYTE(E0->crocom_var_E) = crocom_var_E - HIBYTE(E0->crocom_var_D); + v6 = HIBYTE(E0->crocom_var_E) - v5; + if (v6 < 0) { + LOBYTE(E0->crocom_var_E) = -1; + v6 = 0; + } + HIBYTE(E0->crocom_var_E) = v6; + uint8 crocom_var_F_high = HIBYTE(E0->crocom_var_F); + v5 = crocom_var_F_high < LOBYTE(E0->crocom_var_E); + HIBYTE(E0->crocom_var_F) = crocom_var_F_high - LOBYTE(E0->crocom_var_E); + uint8 y_pos = E0->base.y_pos; + uint8 v9 = v5 + HIBYTE(E0->crocom_var_E); + LOBYTE(E0->base.y_pos) = y_pos - v9; + HIBYTE(E0->base.y_pos) -= y_pos < v9; + } +} + +void Crocomire_Func_57(void) { // 0xA49341 + int i; + + *(uint16 *)&g_byte_7E068C = 48; + *(uint16 *)&g_byte_7E0688 = 48; + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + ++E->crocom_var_A; + ++E->crocom_var_A; + E->base.current_instruction = addr_kCrocomire_Ilist_BF64; + E->base.instruction_timer = 1; + nmi_flag_bg2_enemy_vram_transfer = 1; + Enemy_Crocomire *E1 = Get_Crocomire(cur_enemy_index + 64); + E1->base.current_instruction = addr_kCrocomire_Ilist_BF98; + E1->base.instruction_timer = 1; + E1->base.properties = E1->base.properties & 0xD2FF | 0x2C00; + E1->base.x_pos = E->base.x_pos; + E1->base.y_pos = E->base.y_pos + 16; + uint16 v3 = 0; + do { + int v4 = v3 >> 1; + tilemap_stuff[v4] = 824; + tilemap_stuff[v4 + 1] = 824; + v3 += 4; + } while ((int16)(v3 - 1024) < 0); + for (i = 0; ; i += 2) { + int v6 = i >> 1; + if (g_word_A49C79[v6] == 0xFFFF) + break; + tilemap_stuff[v6 + 32] = g_word_A49C79[v6]; + } + Crocomire_93BE(i + 1024); +} + +void Crocomire_93BE(uint16 k) { // 0xA493BE + VramWriteEntry *v3; + + uint16 v2 = vram_write_queue_tail; + v3 = gVramWriteEntry(vram_write_queue_tail); + v3->size = k; + v3->src.addr = 0x2000; + *(uint16 *)&v3->src.bank = 126; + v3->vram_dst = (reg_BG2SC & 0xFC) << 8; + vram_write_queue_tail = v2 + 7; +} + +void Crocomire_Func_58(void) { // 0xA493DF + uint16 v0 = reg_BG2VOFS; + for (int i = 510; i >= 0; i -= 2) + crocomire_bg2_scroll_hdma_data[i >> 1] = v0; +} + +void Crocomire_Func_59(void) { // 0xA493ED + int i; + + Crocomire_Func_58(); + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + ++E->crocom_var_A; + ++E->crocom_var_A; + E->base.instruction_timer = 1; + *(uint16 *)&g_byte_7E068C = 48; + *(uint16 *)&g_byte_7E0688 = 48; + E->base.current_instruction = addr_kCrocomire_Ilist_BF7E; + uint16 v1 = 0; + do { + tilemap_stuff[v1 >> 1] = 824; + v1 += 2; + } while ((int16)(v1 - 2048) < 0); + for (i = 0; ; i += 2) { + int v3 = i >> 1; + if (g_word_A49E7B[v3] == 0xFFFF) + break; + tilemap_stuff[v3 + 32] = g_word_A49E7B[v3]; + } + Crocomire_93BE(i + 1024); +} + +void Crocomire_Func_60(void) { // 0xA4943D + int i; + int16 v4; + int16 j; + + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + ++E->crocom_var_A; + ++E->crocom_var_A; + g_word_7E0692 = 256; + g_word_7E0690 = 0; + g_word_7E0698 = *(uint16 *)((char *)&g_word_A49BC5 + g_word_7E069A); + g_word_7E0694 = g_word_7E0698; + g_word_7E0696 = *(uint16 *)((char *)&g_word_A49BC7 + g_word_7E069A); + g_word_7E068E = *(uint16 *)((char *)&g_word_A49BC9 + g_word_7E069A); + R0_.addr = 0; + *(uint16 *)&R0_.bank = *(uint16 *)((char *)&g_word_A49BCB + g_word_7E069A); + uint16 v6; + for (i = g_word_7E069A + 8; ; i = v6 + 4) { + uint16 v2 = *(uint16 *)((char *)&g_word_A49BC5 + i); + if (v2 == 0xFFFF) + break; + v6 = i; + uint16 v3 = *(uint16 *)((char *)&g_word_A49BC7 + i); + R18_ = g_word_7E068E; + do { + v4 = *(uint16 *)IndirPtr(&R0_, v2); + *(uint16 *)RomPtr_7E(v3) = v4; + v3 += 2; + v2 += 2; + --R18_; + } while ((R18_ & 0x8000u) == 0); + } + g_word_7E069A = i + 2; + g_word_7E068A = i + 2; + for (j = 128; j >= 0; j -= 2) + *(uint16 *)&g_byte_7E069C[(uint16)j] = 0; +} + +void Crocomire_Func_61(void) { // 0xA494B2 + Crocomire_Func_62(); +} + +void Crocomire_Func_62(void) { // 0xA494B6 + VramWriteEntry *v2; + + uint16 v0 = g_word_7E068A; + uint16 v1 = vram_write_queue_tail; + if (*(uint16 *)((char *)&g_word_A49BC5 + g_word_7E068A) == 0xFFFF) { + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + ++E->crocom_var_A; + ++E->crocom_var_A; + g_word_7E068A = 0; + } else { + v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = *(uint16 *)((char *)&g_word_A49BC5 + g_word_7E068A); + v2->src.addr = *(uint16 *)((char *)&g_word_A49BCB + v0); + *(uint16 *)&v2->src.bank = *(uint16 *)((char *)&g_word_A49BC9 + v0); + v2->vram_dst = *(uint16 *)((char *)&g_word_A49BC7 + v0); + g_word_7E068A = v0 + 8; + vram_write_queue_tail = v1 + 7; + } +} + +void Crocomire_Func_64(void) { // 0xA494FB + QueueSfx2_Max6(0x77u); + Crocomire_950F(); +} + +void Crocomire_9506(void) { // 0xA49506 + QueueSfx2_Max6(0x2Du); + Crocomire_950F(); +} + +void Crocomire_950F(void) { // 0xA4950F + static const SpawnHdmaObject_Args unk_A49559 = { 0x42, 0x10, 0x9563 }; + Enemy_Crocomire *v4; // r10 + + uint16 v1 = 2 * (Get_Crocomire(0x40u)->base.y_pos - 72); + uint16 v2 = reg_BG2VOFS; + do { + crocomire_bg2_scroll_hdma_data[v1 >> 1] = v2; + v1 -= 2; + } while ((v1 & 0x8000u) == 0); + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + ++E->crocom_var_A; + ++E->crocom_var_A; + v4 = Get_Crocomire(0); + Get_Crocomire(0x80)->crocom_var_D = v4->base.x_pos; + *(uint16 *)crocomire_bg2_scroll_hdma_indirect = 255; + *(uint16 *)&crocomire_bg2_scroll_hdma_indirect[1] = -13584; + *(uint16 *)&crocomire_bg2_scroll_hdma_indirect[3] = 225; + *(uint16 *)&crocomire_bg2_scroll_hdma_indirect[4] = -13330; + *(uint16 *)&crocomire_bg2_scroll_hdma_indirect[6] = 0; + v4->crocom_var_1F = SpawnHdmaObject(0xa4, &unk_A49559); +} + +void Crocomire_Func_63(void) { // 0xA49576 + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + ++E->crocom_var_A; + ++E->crocom_var_A; +} + +void Crocomire_Func_65(void) { // 0xA49580 + int i; + + Crocomire_Func_53(); + Enemy_Crocomire *E0 = Get_Crocomire(0); + Enemy_Crocomire *E1 = Get_Crocomire(0x40); + Enemy_Crocomire *E2 = Get_Crocomire(0x80); + uint16 crocom_var_D = E2->crocom_var_D; + --E1->crocom_var_D; + if ((E1->crocom_var_D & 2) != 0) + crocom_var_D += 4; + E0->base.x_pos = crocom_var_D; + if (!Crocomire_Func_67()) + goto LABEL_4; + Crocomire_Func_27(cur_enemy_index); + R18_ = (uint8)((uint16)(g_word_7E0692 & 0xFF00) >> 8); + uint16 v4; + v4 = g_word_7E0694 - 3; + if (sign16(g_word_7E0694 - 19)) { + if ((int16)(g_word_7E0692 - 20480) >= 0) { +LABEL_4:; + Enemy_Crocomire *EK = Get_Crocomire(cur_enemy_index); + ++EK->crocom_var_A; + ++EK->crocom_var_A; + for (i = g_word_7E069A; *(uint16 *)((char *)&g_word_A49BC5 + i) != 0xFFFF; i += 8) + ; + g_word_7E069A = i + 2; + hdma_object_channels_bitmask[E0->crocom_var_1F >> 1] = 0; + return; + } + v4 = 16; + } + g_word_7E0694 = v4; + uint16 v5 = g_word_7E0692 + 384; + if (!sign16(g_word_7E0692 - 20096)) + v5 = 20480; + g_word_7E0692 = v5; + R18_ = 0; + uint16 v6 = 2 * (E1->base.y_pos - 72); + uint16 v7 = g_word_7E0694; + message_box_animation_y1 = g_word_7E0694; + do { + crocomire_bg2_scroll_hdma_data[v6 >> 1] = reg_BG2VOFS + v7 - message_box_animation_y1; + bool v8 = __CFADD__uint16(g_word_7E0692, R18_); + R18_ += g_word_7E0692; + if (!v8) + ++v7; + ++message_box_animation_y1; + v6 += 2; + } while ((int16)(v7 - g_word_7E0698) < 0); + if ((int16)(v6 - 512) < 0) { + uint16 v9 = reg_BG2VOFS; + do { + crocomire_bg2_scroll_hdma_data[v6 >> 1] = v9; + v6 += 2; + } while ((int16)(v6 - 512) < 0); + } +} + +void Crocomire_Func_66(void) { // 0xA49653 + VramWriteEntry *v3; + + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + E->crocom_var_E = 0; + E->crocom_var_F = 0; + E->crocom_var_D = 2048; + for (int i = 4094; i >= 0; i -= 2) + tilemap_stuff[i >> 1] = 824; + uint16 v2 = vram_write_queue_tail; + v3 = gVramWriteEntry(vram_write_queue_tail); + v3->size = 2048; + v3->src.addr = 0x2000; + *(uint16 *)&v3->src.bank = 126; + v3->vram_dst = (reg_BG2SC & 0xFE) << 8; + vram_write_queue_tail = v2 + 7; + Crocomire_9BB3(); +} + + +static const uint8 g_byte_A49BBD[8] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe }; + +uint16 Crocomire_Func_67(void) { // 0xA496C8 + VramWriteEntry *v9; + + uint16 result = 0; + R18_ = g_byte_7E068C; + R20_ = 0; + R22_ = 0; + uint16 v2 = g_word_7E0690; + while (1) { + LOBYTE(result) = g_byte_A49697[v2]; + if ((int8)(g_byte_7E069C[result] - g_byte_7E0688) < 0) + break; + if ((int16)(++v2 - 128) >= 0) { + LOBYTE(g_word_7E0690) = 0; + return 0; + } + } + g_word_7E0690 = v2; + result = v2 & 7; + uint16 v3 = result; + do { + uint16 v4 = g_byte_A49697[g_word_7E0690]; + R20_ = 4 * (v4 & 0xFFF8); + R20_ += 2 * (g_byte_7E069C[v4] & 7); + uint16 v5 = R20_ + ((*(uint16 *)&g_byte_7E069C[v4] & 0xFFF8) << 6); + ram4000.backups.field_0[v5] &= g_byte_A49BBD[v3]; + ram4000.backups.field_0[v5 + 1] &= g_byte_A49BBD[v3]; + ram4000.backups.field_0[v5 + 16] &= g_byte_A49BBD[v3]; + ram4000.backups.field_0[v5 + 17] &= g_byte_A49BBD[v3]; + uint8 v6 = g_byte_A49697[g_word_7E0690]; + if (g_byte_7E069C[v6] == 48) + break; + ++ *(uint16 *)&g_byte_7E069C[v6]; + R22_ = g_byte_7E069C[v6]; + --R18_; + } while (R18_); + uint16 v7, v8; + while (1) { + v7 = g_word_7E068A + g_word_7E069A; + v8 = vram_write_queue_tail; + if (*(uint16 *)((char *)&g_word_A49BC5 + (uint16)(g_word_7E068A + g_word_7E069A)) != 0xFFFF) + break; + g_word_7E068A = 0; + } + v9 = gVramWriteEntry(vram_write_queue_tail); + v9->size = *(uint16 *)((char *)&g_word_A49BC5 + (uint16)(g_word_7E068A + g_word_7E069A)); + v9->src.addr = *(uint16 *)((char *)&g_word_A49BCB + v7); + *(uint16 *)&v9->src.bank = *(uint16 *)((char *)&g_word_A49BC9 + v7); + v9->vram_dst = *(uint16 *)((char *)&g_word_A49BC7 + v7); + vram_write_queue_tail = v8 + 7; + g_word_7E068A += 8; + uint16 v10 = g_word_7E0690; + if (!sign16(g_word_7E0690 - 128)) + g_word_7E0690 = 0; + g_word_7E0690 = v10; + return 1; +} + +void Crocomire_Func_68(void) { // 0xA497D3 + static const SpawnHardcodedPlmArgs unk_A497EF = { 0x30, 0x03, 0xb757 }; + + if (sign16(samus_x_pos - 640)) { + QueueMusic_Delayed8(5u); + *(uint16 *)&scrolls[3] = 256; + SpawnHardcodedPlm(&unk_A497EF); + camera_distance_index = 6; + Enemy_Crocomire *E0 = Get_Crocomire(0); + E0->base.properties = E0->base.properties & 0x7BFF | kEnemyProps_Tangible; + Enemy_Crocomire *E1 = Get_Crocomire(0x40u); + E1->base.properties |= 0x500u; + E0->crocom_var_D = 4; + E1->crocom_var_D = 0; + Get_Crocomire(0x80)->crocom_var_D = 10; + Get_Crocomire(0xC0u)->crocom_var_D = 1; + E0->crocom_var_B = 0; + E0->base.y_height = 56; + Crocomire_9BB3(); + } +} + +void Crocomire_Func_69(void) { // 0xA49830 + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 v1 = E->base.x_pos - 2; + E->base.x_pos = v1; + if (sign16(v1 - 480)) { + E->base.x_pos = 480; + E->base.y_pos = 54; + E->crocom_var_A = 62; + } else { + E->base.y_pos = 220; + } +} + +void Crocomire_Func_70(void) { // 0xA49859 + Enemy_Crocomire *E0 = Get_Crocomire(0); + Enemy_Crocomire *E1 = Get_Crocomire(0x40); + Enemy_Crocomire *E2 = Get_Crocomire(0x80); + Enemy_Crocomire *E3 = Get_Crocomire(0xc0); + if (g_word_A498CA[E0->crocom_var_D >> 1] == 0x8080) { + E1->crocom_var_D = -32640; + E0->crocom_var_D = 128; + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 176] = g_word_A4B91D[i >> 1]; + Crocomire_9BB3(); + } else { + uint16 crocom_var_D = E0->crocom_var_D; + uint16 v3 = E1->crocom_var_D; + int v4 = crocom_var_D >> 1; + if (v3 == g_word_A498CA[v4]) { + if ((g_word_A498CA[crocom_var_D >> 1] & 0x8000u) != 0) { + uint16 v7 = E2->crocom_var_D; + if (v7) { + E2->crocom_var_D = v7 - 1; + E0->crocom_var_D = crocom_var_D - 2; + QueueSfx2_Max6(0x2Bu); + return; + } + uint16 v8 = crocom_var_D + 2; + E2->crocom_var_D = g_word_A498CA[v8 >> 1]; + crocom_var_D = v8 + 2; + E3->crocom_var_D = g_word_A498CA[crocom_var_D >> 1]; + } + E0->crocom_var_D = crocom_var_D + 2; + } else { + uint16 v5; + if ((int16)(v3 - g_word_A498CA[v4]) >= 0) + v5 = v3 - E3->crocom_var_D; + else + v5 = E3->crocom_var_D + v3; + E1->crocom_var_D = v5; + } + } +} + +void Crocomire_Func_71(void) { // 0xA4990A + static const SpawnHardcodedPlmArgs unk_A4996E = { 0x20, 0x03, 0xb753 }; + static const SpawnHardcodedPlmArgs unk_A49976 = { 0x1e, 0x03, 0xb757 }; + static const SpawnHardcodedPlmArgs unk_A4997E = { 0x70, 0x0b, 0xb747 }; + int16 v3; + VramWriteEntry *v6; + + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 crocom_var_D = E->crocom_var_D; + if (crocom_var_D) { + E->crocom_var_D = crocom_var_D - 1; + v3 = *(uint16 *)&g_byte_7E0688; + int v4 = *(uint16 *)&g_byte_7E0688 >> 1; + if (g_word_A499CB[v4] != 0xFFFF) { + uint16 v5 = vram_write_queue_tail; + v6 = gVramWriteEntry(vram_write_queue_tail); + v6->size = 512; + v6->src.addr = g_word_A499D9[v4]; + *(uint16 *)&v6->src.bank = 173; + R18_ = (reg_OBSEL & 7) << 13; + v6->vram_dst = g_word_A499CB[v4] + R18_; + vram_write_queue_tail = v5 + 7; + *(uint16 *)&g_byte_7E0688 = v3 + 2; + } + } else { + E->base.x_pos = 480; + E->base.y_pos = 54; + Get_Crocomire(0x80)->crocom_var_D = 80; + E->crocom_var_E = 0; + E->crocom_var_F = 0; + SpawnHardcodedPlm(&unk_A4996E); + SpawnHardcodedPlm(&unk_A49976); + SpawnHardcodedPlm(&unk_A4997E); + QueueSfx2_Max6(0x29u); + E->base.current_instruction = addr_kCrocomire_Ilist_E158; + E->base.instruction_timer = 1; + E->base.palette_index = 0; + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 144] = g_word_A4B8FD[i >> 1]; + ClearEnemyProjectiles(); + uint16 v8 = 8; + R18_ = 8; + do { + SpawnEnemyProjectileWithGfx(v8, cur_enemy_index, addr_kEproj_CrocomireSpikeWallPieces); + --R18_; + } while (R18_); + QueueSfx2_Max6(0x30u); + Crocomire_9BB3(); + } +} + +void Crocomire_Func_72(void) { // 0xA499E5 + int16 v3; + + Enemy_Crocomire *E = Get_Crocomire(0); + if (sign16(E->base.x_pos - 224)) { + uint16 crocom_var_E = E->crocom_var_E; + E->crocom_var_E = crocom_var_E + 0x8000; + v3 = __CFADD__uint16(crocom_var_E, 0x8000) + E->crocom_var_F; + if (!sign16(v3 - 2)) + v3 = 2; + E->crocom_var_F = v3; + uint16 x_subpos = E->base.x_subpos; + bool v5 = __CFADD__uint16(E->crocom_var_E, x_subpos); + E->base.x_subpos = E->crocom_var_E + x_subpos; + E->base.x_pos += E->crocom_var_F + v5; + } + Enemy_Crocomire *E2 = Get_Crocomire(0x80); + if (E2->crocom_var_D) { + if (E2->crocom_var_D-- == 1) { + E->crocom_var_E = 0; + E->base.current_instruction = addr_kCrocomire_Ilist_E14A; + E->base.instruction_timer = 1; + Crocomire_9BB3(); + } + } +} + +void Crocomire_Func_73(void) { // 0xA49A38 + int16 v3; + + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 crocom_var_E = E->crocom_var_E; + E->crocom_var_E = crocom_var_E + 2048; + v3 = __CFADD__uint16(crocom_var_E, 2048) + E->crocom_var_F; + if (!sign16(v3 - 5)) + v3 = 5; + E->crocom_var_F = v3; + bool v4 = __CFADD__uint16(E->base.y_subpos, -8192); + E->base.y_subpos -= 0x2000; + E->base.y_pos += v4; + uint16 x_subpos = E->base.x_subpos; + v4 = __CFADD__uint16(E->crocom_var_E, x_subpos); + E->base.x_subpos = E->crocom_var_E + x_subpos; + uint16 v6 = E->crocom_var_F + v4 + E->base.x_pos; + E->base.x_pos = v6; + if (!sign16(v6 - 576)) { + QueueSfx2_Max6(0x25u); + Get_Crocomire(0x40u)->base.palette_index = E->base.palette_index; + E->base.current_instruction = addr_kCrocomire_Ilist_E158; + E->base.instruction_timer = 1; + Crocomire_9BB3(); + } +} + +uint16 Crocomire_Instr_8(uint16 k, uint16 j) { // 0xA49A9B + return Crocomire_Func_87(j, 0xFFE0u); +} + +uint16 Crocomire_Instr_6(uint16 k, uint16 j) { // 0xA49AA0 + return Crocomire_Func_87(j, 0); +} + +uint16 Crocomire_Instr_9(uint16 k, uint16 j) { // 0xA49AA5 + return Crocomire_Func_87(j, 0xFFF0u); +} + +uint16 Crocomire_Instr_5(uint16 k, uint16 j) { // 0xA49AAA + return Crocomire_Func_87(j, 0x10u); +} + +uint16 Crocomire_Instr_20(uint16 k, uint16 j) { // 0xA49AAF + return Crocomire_Func_87(j, 0); +} + +uint16 Crocomire_Instr_21(uint16 k, uint16 j) { // 0xA49AB4 + return Crocomire_Func_87(j, 8u); +} + +uint16 Crocomire_Instr_22(uint16 k, uint16 j) { // 0xA49AB9 + return Crocomire_Func_87(j, 0x10u); +} + +uint16 Crocomire_Instr_23(uint16 k, uint16 j) { // 0xA49ABE + return Crocomire_Func_87(j, 0x18u); +} + +uint16 Crocomire_Instr_24(uint16 k, uint16 j) { // 0xA49AC3 + return Crocomire_Func_87(j, 0x20u); +} + +uint16 Crocomire_Instr_10(uint16 k, uint16 j) { // 0xA49AC8 + return Crocomire_Func_87(j, 0x28u); +} + +uint16 Crocomire_Instr_25(uint16 k, uint16 j) { // 0xA49ACD + return Crocomire_Func_87(j, 0x30u); +} + +uint16 Crocomire_Instr_26(uint16 k, uint16 j) { // 0xA49AD2 + return Crocomire_Func_87(j, 0x38u); +} + +uint16 Crocomire_Instr_27(uint16 k, uint16 j) { // 0xA49AD7 + return Crocomire_Func_87(j, 0x40u); +} + +uint16 Crocomire_Func_87(uint16 j, uint16 a) { // 0xA49ADA + R18_ = a; + Enemy_Crocomire *E = Get_Crocomire(0); + R18_ = a + E->base.x_pos + (random_number & 7); + R20_ = E->base.y_height + E->base.y_pos - 16; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x15u); + return j; +} + +static const SpawnHardcodedPlmArgs unk_A49B3E = { 0x30, 0x03, 0xb753 }; +static const SpawnHardcodedPlmArgs unk_A49B74 = { 0x1e, 0x03, 0xb753 }; + +void Crocomire_Func_88(void) { // 0xA49B06 + int16 v3; + + Enemy_Crocomire *E = Get_Crocomire(0); + if (sign16(E->base.current_instruction + 0x1E3A)) { + uint16 crocom_var_E = E->crocom_var_E; + E->crocom_var_E = crocom_var_E + 4096; + v3 = __CFADD__uint16(crocom_var_E, 4096) + E->crocom_var_F; + if (!sign16(v3 - 6)) + v3 = 6; + E->crocom_var_F = v3; + } else { + E->base.current_instruction = addr_kCrocomire_Ilist_E1CC; + E->base.instruction_timer = 1; + E->base.x_pos += 64; + E->base.y_pos += 21; + E->base.y_height = 28; + E->base.x_width = 40; + SpawnHardcodedPlm(&unk_A49B3E); + printf("X unknown!\n"); + Enemy_ItemDrop_Crocomire(0); + Crocomire_9BB3(); + } +} + +void Crocomire_9B65(void) { // 0xA49B65 + static const SpawnHardcodedPlmArgs unk_A49B74 = { 0x1e, 0x03, 0xb753 }; + *(uint16 *)scrolls = 257; + *(uint16 *)&scrolls[2] = 257; + SpawnHardcodedPlm(&unk_A49B74); + Crocomire_9BB3(); +} + +void Crocomire_Func_89(void) { // 0xA49B7B + Crocomire_9BB3(); +} + +void Crocomire_Func_90(void) { // 0xA49B7D + Enemy_Crocomire *E = Get_Crocomire(0); + if (!sign16(E->base.current_instruction + 0x1E3A)) + Crocomire_9BB3(); +} + +void Crocomire_9B86(void) { // 0xA49B86 + QueueMusic_Delayed8(6u); + camera_distance_index = 0; + *(uint16 *)&boss_bits_for_area[area_index] |= 2u; + QueueMusic_Delayed8(6u); + Crocomire_Func_87(0, 0xFFF0u); + Crocomire_Func_87(0, 0x10u); + Crocomire_9BB3(); +} + +void Crocomire_9BB3(void) { // 0xA49BB3 + Enemy_Crocomire *E = Get_Crocomire(0); + ++E->crocom_var_A; + ++E->crocom_var_A; +} + +void Crocomire_Func_91(void) { // 0xA49BBA + Crocomire_9BB3(); +} + +void Crocomire_Func_92(void) { // 0xA4B93D + NormalEnemyTouchAi(); + Enemy_Crocomire *E = Get_Crocomire(0); + E->crocom_var_B |= 0x4000u; + extra_samus_x_displacement = -4; +} + +void Crocomire_Func_93(void) { // 0xA4B951 + Enemy_Crocomire *E = Get_Crocomire(0); + uint16 v1 = E->crocom_var_B & 0xF; + if (sign16(v1 - 15)) + ++v1; + R18_ = v1; + E->crocom_var_B |= v1; +} + +void Crocomire_Func_94(void) { // 0xA4B968 + int v0 = collision_detection_index; + R18_ = projectile_x_pos[v0]; + R20_ = projectile_y_pos[v0]; + uint16 v1 = 29; + if ((projectile_type[v0] & 0x200) == 0) + v1 = 6; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, v1); +} + +void Crocomire_Powerbomb(void) { // 0xA4B992 + uint16 v2; + + Enemy_Crocomire *E = Get_Crocomire(0); + if (!E->crocom_var_A) { + if (g_word_A4869E) { + E->crocom_var_D = g_word_A4869E; + if (E->crocom_var_C != 24) { + E->crocom_var_B = E->crocom_var_B & 0x3FF0 | 0x8000; + E->crocom_var_E = 10; + E->base.flash_timer += 4; + E->base.ai_handler_bits |= 2u; + E->crocom_var_C = 24; + uint16 spritemap_pointer = E->base.spritemap_pointer; + uint16 v3; + R18_ = *(uint16 *)RomPtr_A4(spritemap_pointer); + while (1) { + v2 = *((uint16 *)RomPtr_A4(spritemap_pointer) + 3); + v3 = addr_kCrocomire_Ilist_BDAE; + if (v2 == addr_kCrocomire_BigSprmap_D600) + break; + v3 = addr_kCrocomire_Ilist_BDB2; + if (v2 == addr_kCrocomire_BigSprmap_D51C) + break; + spritemap_pointer += 8; + if (!--R18_) { + v3 = addr_kCrocomire_Ilist_BDB6; + break; + } + } + Enemy_Crocomire *E0 = Get_Crocomire(0); + E0->base.current_instruction = v3; + E0->base.instruction_timer = 1; + } + } + } +} + +void Crocomire_Func_95(void) { // 0xA4BA05 + int16 v3; + + Enemy_Crocomire *E = Get_Crocomire(0); + E->base.invincibility_timer = 0; + if ((int16)(E->base.x_pos - E->base.x_width - 256 - layer1_x_pos) >= 0) + goto LABEL_10; + uint16 v1, v2; + v1 = projectile_type[collision_detection_index]; + if ((v1 & 0xF00) != 0) { + v3 = v1 & 0xF00; + v2 = g_word_A4869A; + if (v3 != 256) { + v2 = g_word_A4869C; + if (v3 != 512) + v2 = 0; + } + } else { + v2 = g_word_A48698; + if ((v1 & 0x10) == 0) { + E->base.instruction_timer = g_word_A486A0; + Crocomire_Func_1(); + return; + } + } + if (v2) { + E->crocom_var_D += v2; +LABEL_10:; + uint16 v4 = E->crocom_var_B & 0xF; + if (sign16(v4 - 15)) + ++v4; + R18_ = v4; + if ((E->crocom_var_B & 0x800) == 0) { + uint16 v5 = g_word_A48692; + if (E->crocom_var_C == 8) + v5 = g_word_A48694; + E->base.instruction_timer += v5; + } + E->crocom_var_B = R18_ | E->crocom_var_B & 0xB7F0 | 0x800; + E->crocom_var_E = 10; + } + E->base.flash_timer += 14; + E->base.ai_handler_bits |= 2u; +} + +void Crocomire_Func_1(void) { // 0xA4BAB4 + int v0 = collision_detection_index; + R18_ = projectile_x_pos[v0]; + R20_ = projectile_y_pos[v0]; + uint16 v1 = 29; + if ((projectile_type[v0] & 0x200) == 0) + v1 = 6; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, v1); +} + +void GetCurEnemyIndex(void) { // 0xA4CB01 + ; +} + +void CrocomireTongue_Init(void) { // 0xA4F67A + Enemy_Crocomire *E = Get_Crocomire(cur_enemy_index); + if ((*(uint16 *)&boss_bits_for_area[area_index] & 2) != 0) { + E->base.properties = E->base.properties & 0xDCFF | 0x300; + } else { + E->base.current_instruction = addr_kCrocomire_Ilist_BE56; + E->base.extra_properties |= 0x404u; + E->base.instruction_timer = 1; + E->crocom_var_A = 23; + E->base.palette_index = 3584; + } +} + +void CrocomireTongue_Main(void) { // 0xA4F6BB + ; +} diff --git a/src/sm_a5.c b/src/sm_a5.c new file mode 100644 index 0000000..433ed46 --- /dev/null +++ b/src/sm_a5.c @@ -0,0 +1,1933 @@ +// Enemy AI - Draygon & Spore Spawn + +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" +#define kDraygon_MorePalettes ((uint16*)RomPtr(0xa5a217)) +#define kDraygon_MorePalettes2 ((uint16*)RomPtr(0xa5a277)) +#define g_word_A5A297 ((uint16*)RomPtr(0xa5a297)) +#define g_word_A587DC ((uint16*)RomPtr(0xa587dc)) +#define g_word_A596AF ((uint16*)RomPtr(0xa596af)) +#define g_word_A596EF ((uint16*)RomPtr(0xa596ef)) +#define g_word_A5A19F ((uint16*)RomPtr(0xa5a19f)) +#define g_word_A5A1AF ((uint16*)RomPtr(0xa5a1af)) +#define g_word_A5A1C7 ((uint16*)RomPtr(0xa5a1c7)) +#define g_word_A5A1DF ((uint16*)RomPtr(0xa5a1df)) +#define g_byte_A5CE07 ((uint8*)RomPtr(0xa5ce07)) +#define g_word_A5E379 ((uint16*)RomPtr(0xa5e379)) +#define g_word_A5E3F9 ((uint16*)RomPtr(0xa5e3f9)) +#define g_word_A5E4F9 ((uint16*)RomPtr(0xa5e4f9)) +#define g_word_A5E5D9 ((uint16*)RomPtr(0xa5e5d9)) + +#define kSporeSpawn_Palette ((uint16*)RomPtr(0xa5e359)) + +uint16 EnemyInstr_Goto_A5(uint16 k, uint16 j) { // 0xA580ED + return *(uint16 *)RomPtr_A5(j); +} + +uint16 EnemyInstr_DecTimerAndGoto2_A5(uint16 k, uint16 j) { // 0xA58110 + EnemyData *v2 = gEnemyData(k); + if (v2->timer-- == 1) + return j + 2; + else + return EnemyInstr_Goto_A5(k, j); +} + +uint16 EnemyInstr_SetTimer_A5(uint16 k, uint16 j) { // 0xA58123 + uint16 v2 = *(uint16 *)RomPtr_A5(j); + gEnemyData(k)->timer = v2; + return j + 2; +} +uint16 EnemyInstr_Sleep_A5(uint16 k, uint16 j) { // 0xA5812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} +uint16 EnemyInstr_StopScript_A5(uint16 k, uint16 j) { // 0xA5807C + EnemyData *v2 = gEnemyData(k); + v2->properties |= kEnemyProps_Deleted; + return 0; +} + +uint16 EnemyInstr_WaitNframes_A5(uint16 k, uint16 j) { // 0xA5813A + uint16 v2 = *(uint16 *)RomPtr_A5(j); + EnemyData *v3 = gEnemyData(k); + v3->instruction_timer = v2; + v3->current_instruction = j + 2; + return 0; +} + +void Enemy_GrappleReact_NoInteract_A5(void) { // 0xA58000 + SwitchEnemyAiToMainAi(); +} + +void Enemy_GrappleReact_CancelBeam_A5(void) { // 0xA5800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_NormalTouchAI_A5(void) { // 0xA58023 + NormalEnemyTouchAi(); +} + +void Enemy_NormalShotAI_A5(void) { // 0xA5802D + NormalEnemyShotAi(); +} + +void Enemy_NormalFrozenAI_A5(void) { // 0xA58041 + NormalEnemyFrozenAI(); +} + +void Draygon_Init(void) { // 0xA58687 + uint16 j; + + for (int i = 48; i >= 0; i -= 2) + target_palettes[(i >> 1) + 144] = kDraygon_MorePalettes[i >> 1]; + for (j = 4094; (j & 0x8000u) == 0; j -= 2) + tilemap_stuff[j >> 1] = 824; + Get_Draygon(cur_enemy_index)->base.palette_index = 3584; + *(uint16 *)&enemy_gfx_drawn_hook.bank = 165; + enemy_gfx_drawn_hook.addr = FUNC16(Draygon_Func_36); + flag_process_all_enemies = -1; + Get_Draygon(0)->base.current_instruction = addr_kDraygon_Ilist_9889; + Get_Draygon(0x40u)->base.current_instruction = addr_kDraygon_Ilist_9944; + Get_Draygon(0x80)->base.current_instruction = addr_kDraygon_Ilist_99FC; + Get_Draygon(0xC0u)->base.current_instruction = addr_kDraygon_Ilist_9813; + enemy_bg2_tilemap_size = 1024; + Get_Draygon(cur_enemy_index)->draygon_var_A = FUNC16(Draygon_Func_1); + sub_88DF34(); + room_loading_irq_handler = 12; + SpawnBG3ScrollHdmaObject(); + Get_Draygon(0)->draygon_var_45 = 1; + DisableMinimapAndMarkBossRoomAsExplored(); +} + +void CallDraygonFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnnullsub_169_A5: return; + case fnDraygon_Func_1: Draygon_Func_1(); return; + case fnDraygon_Func_2: Draygon_Func_2(); return; + case fnDraygon_Func_4: Draygon_Func_4(); return; + case fnDraygon_Func_6: Draygon_Func_6(); return; + case fnDraygon_Func_8: Draygon_Func_8(); return; + case fnDraygon_Func_9: Draygon_Func_9(); return; + case fnDraygon_Func_10: Draygon_Func_10(); return; + case fnDraygon_Func_11: Draygon_Func_11(); return; + case fnDraygon_Func_12: Draygon_Func_12(); return; + case fnDraygon_Func_13: Draygon_Func_13(); return; + case fnDraygon_Func_14: Draygon_Func_14(); return; + case fnDraygon_Func_15: Draygon_Func_15(); return; + case fnDraygon_Func_16: Draygon_Func_16(); return; + case fnDraygon_Func_17: Draygon_Func_17(k); return; + case fnDraygon_Func_18: Draygon_Func_18(); return; + case fnDraygon_Func_19: Draygon_Func_19(); return; + case fnDraygon_Func_20: Draygon_Func_20(); return; + case fnDraygon_Func_21: Draygon_Func_21(k); return; + case fnDraygon_Func_22: Draygon_Func_22(); return; + case fnDraygon_Func_23: Draygon_Func_23(); return; + case fnDraygon_Func_24: Draygon_Func_24(k); return; + case fnDraygon_Func_25: Draygon_Func_25(k); return; + case fnDraygon_Func_26: Draygon_Func_26(k); return; + case fnDraygon_Func_27: Draygon_Func_27(k); return; + case fnDraygon_Func_28: Draygon_Func_28(k); return; + case fnDraygon_Func_29: Draygon_Func_29(); return; + case fnDraygon_Func_30: Draygon_Func_30(); return; + case fnDraygon_Func_31: Draygon_Func_31(); return; + case fnDraygon_Func_32: Draygon_Func_32(); return; + case fnDraygon_Func_33: Draygon_Func_33(); return; + case fnDraygon_Func_48: Draygon_Func_48(k); return; + case fnDraygon_Func_49: Draygon_Func_49(k); return; + case fnnullsub_223: return; + case fnSporeSpawn_Func_1: SporeSpawn_Func_1(); return; + case fnSporeSpawn_Func_2: SporeSpawn_Func_2(k); return; + case fnSporeSpawn_Func_3: SporeSpawn_Func_3(); return; + case fnSporeSpawn_Func_4: SporeSpawn_Func_4(); return; + default: Unreachable(); + } +} + +void Draygon_Main(void) { // 0xA586FC + Enemy_Draygon *EK = Get_Draygon(cur_enemy_index); + CallDraygonFunc(EK->draygon_var_A | 0xA50000, cur_enemy_index); + + Enemy_Draygon *E0 = Get_Draygon(0); + uint16 x_pos = E0->base.x_pos; + Enemy_Draygon *E1 = Get_Draygon(0x40u); + E1->base.x_pos = x_pos; + Enemy_Draygon *E2 = Get_Draygon(0x80); + E2->base.x_pos = x_pos; + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.x_pos = x_pos; + uint16 y_pos = E0->base.y_pos; + E1->base.y_pos = y_pos; + E2->base.y_pos = y_pos; + E3->base.y_pos = y_pos; +} + +void Draygon_Func_1(void) { // 0xA5871B + VramWriteEntry *v2; + + Draygon_Func_3(); + Enemy_Draygon *E = Get_Draygon(0); + if (sign16(E->draygon_var_B - 256)) { + if (!E->draygon_var_B) { + v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 1536; + v2->src.addr = -27648; + *(uint16 *)&v2->src.bank = 177; + v2->vram_dst = 27904; + vram_write_queue_tail += 7; + Draygon_Func_45(); + } + ++E->draygon_var_B; + } else { + E->draygon_var_A = FUNC16(Draygon_Func_2); + E->draygon_var_B = 0; + uint16 x_pos = E->base.x_pos; + E->draygon_var_00 = x_pos; + E->draygon_var_02 = x_pos + 672; + E->draygon_var_01 = E->base.y_pos; + E->base.x_pos = E->draygon_var_00; + E->base.y_pos = E->draygon_var_01; + E->draygon_var_0F = 24; + } +} + +void Draygon_Func_2(void) { // 0xA5878B + Draygon_Func_3(); + Enemy_Draygon *E = Get_Draygon(0); + if (sign16(E->draygon_var_B - 1232)) { + Draygon_Func_46(); + ++E->draygon_var_B; + } else { + E->draygon_var_A = FUNC16(Draygon_Func_4); + E->draygon_var_B = 0; + } +} + +void Draygon_Func_3(void) { // 0xA587AA + char Random; + + if ((nmi_frame_counter_word & 0x3F) == 0) { + Random = NextRandom(); + uint16 result = 2 * ((Random & 3) + 2); + if (!Get_Draygon(result)->draygon_var_40) { + int v2 = (uint16)(4 * ((Random & 3) + 2)) >> 1; + R18_ = g_word_A587DC[v2]; + R20_ = g_word_A587DC[v2 + 1]; + SpawnEnemyProjectileWithGfx(3u, result, addr_stru_868E5E); + } + } +} + +void Draygon_Func_4(void) { // 0xA587F4 + Draygon_Func_3(); + Draygon_Func_5(); + Enemy_Draygon *E = Get_Draygon(0); + E->draygon_var_A = FUNC16(Draygon_Func_6); + E->base.current_instruction = addr_kDraygon_Ilist_97D1; + E->base.instruction_timer = 1; + E->draygon_var_20 = 1; +} + +void Draygon_Func_5(void) { // 0xA58817 + Enemy_Draygon *E = Get_Draygon(0); + int16 draygon_var_00; + + varE28 = 384; + varE24 = 384; + draw_oam_x_offset = 0; + varE26 = 0; + while (1) { + + draw_oam_x_offset += E->draygon_var_0F; + uint16 v1 = varE24 - HIBYTE(draw_oam_x_offset); + if ((int16)(v1 - E->draygon_var_01) < 0) + break; + varE24 -= HIBYTE(draw_oam_x_offset); + *(uint16 *)((char *)&g_word_7E9002 + varE26++) = v1; + ++varE26; + ++varE26; + if (!sign16(++varE26 - 2048)) { + while (1) + ; + } + } + draygon_var_00 = E->draygon_var_00; + uint16 v4; + if (draygon_var_00 < 0) { + uint16 v5 = Abs16(draygon_var_00); + v4 = Abs16(samus_x_pos + v5); + } else { + v4 = Abs16(draygon_var_00 - samus_x_pos); + } + R44 = v4; + R42 = 0; + R46 = varE26 >> 2; + R48 = 0; + EnemyFunc_B761(); + E->draygon_var_D = R44; + E->draygon_var_E = R42; + uint16 v6 = varE26; + *(uint16 *)((char *)&g_word_7E9002 + varE26) = E->base.y_pos; + E->draygon_var_B = v6; + E->draygon_var_C = v6; +} + +void Draygon_Func_6(void) { // 0xA588B1 + Draygon_Func_3(); + Draygon_Func_35(); + Enemy_Draygon *E = Get_Draygon(0); + uint16 draygon_var_B = E->draygon_var_B; + if (draygon_var_B == 104) { + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.current_instruction = addr_kDraygon_Ilist_9C06; + E3->base.instruction_timer = 1; + } + Get_Draygon(cur_enemy_index)->base.y_pos = *(uint16 *)((char *)&g_word_7E9002 + draygon_var_B); + E->draygon_var_B -= 4; + if (E->draygon_var_B) { + uint16 x_subpos = E->base.x_subpos; + bool v6 = __CFADD__uint16(E->draygon_var_E, x_subpos); + E->base.x_subpos = E->draygon_var_E + x_subpos; + E->base.x_pos += E->draygon_var_D + v6; + } else { + E->draygon_var_A = FUNC16(Draygon_Func_8); + } +} + +void Draygon_Func_7(void) { // 0xA58901 + Enemy_Draygon *E = Get_Draygon(0); + if ((nmi_frame_counter_word & 0xF) == 0) { + E->base.current_instruction = addr_kDraygon_Ilist_98FE; + if (E->draygon_var_20) + E->base.current_instruction = addr_kDraygon_Ilist_9C90; + E->base.instruction_timer = 1; + } +} + +void Draygon_Func_8(void) { // 0xA58922 + Draygon_Func_3(); + Enemy_Draygon *E = Get_Draygon(0); + R44 = 672 - E->base.x_pos; + R42 = 0; + R46 = E->draygon_var_C >> 2; + R48 = 0; + EnemyFunc_B761(); + E->draygon_var_D = R44; + E->draygon_var_E = R42; + E->draygon_var_A = FUNC16(Draygon_Func_9); +} + +void Draygon_Func_9(void) { // 0xA58951 + Draygon_Func_3(); + Enemy_Draygon *E = Get_Draygon(0); + uint16 draygon_var_B = E->draygon_var_B; + if (draygon_var_B == 104) { + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.current_instruction = addr_kDraygon_Ilist_9BDA; + E3->base.instruction_timer = 1; + } + Get_Draygon(cur_enemy_index)->base.y_pos = *(uint16 *)((char *)&g_word_7E9002 + draygon_var_B); + E->draygon_var_B += 4; + if (E->draygon_var_B == E->draygon_var_C) { + E->draygon_var_B = 0; + if ((random_number & 1) != 0) + E->draygon_var_A = FUNC16(Draygon_Func_10); + else + E->draygon_var_A = FUNC16(Draygon_Func_18); + } else { + uint16 x_subpos = E->base.x_subpos; + bool v5 = __CFADD__uint16(E->draygon_var_E, x_subpos); + E->base.x_subpos = E->draygon_var_E + x_subpos; + E->base.x_pos += E->draygon_var_D + v5; + } +} + +void Draygon_Func_10(void) { // 0xA589B3 + Draygon_Func_3(); + Enemy_Draygon *E = Get_Draygon(0); + R44 = Abs16(E->draygon_var_02 - samus_x_pos); + R42 = 0; + R46 = varE26 >> 2; + R48 = 0; + EnemyFunc_B761(); + E->draygon_var_D = R44; + E->draygon_var_E = R42; + E->draygon_var_A = FUNC16(Draygon_Func_11); + E->base.current_instruction = addr_kDraygon_Ilist_97BB; + E->base.instruction_timer = 1; + E->draygon_var_20 = 0; + E->draygon_var_B = E->draygon_var_C; +} + +void Draygon_Func_11(void) { // 0xA58A00 + Draygon_Func_3(); + Draygon_Func_35(); + Enemy_Draygon *E = Get_Draygon(0); + uint16 draygon_var_B = E->draygon_var_B; + if (draygon_var_B == 104) { + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.current_instruction = addr_kDraygon_Ilist_9813; + E3->base.instruction_timer = 1; + } + Get_Draygon(cur_enemy_index)->base.y_pos = *(uint16 *)((char *)&g_word_7E9002 + draygon_var_B); + E->draygon_var_B -= 4; + if (E->draygon_var_B) { + uint16 x_subpos = E->base.x_subpos; + bool v6 = x_subpos < E->draygon_var_E; + E->base.x_subpos = x_subpos - E->draygon_var_E; + E->base.x_pos -= v6 + E->draygon_var_D; + } else { + E->draygon_var_A = FUNC16(Draygon_Func_12); + } +} + +void Draygon_Func_12(void) { // 0xA58A50 + int16 draygon_var_00; + + Draygon_Func_3(); + Enemy_Draygon *E = Get_Draygon(0); + draygon_var_00 = E->draygon_var_00; + uint16 v2; + if (draygon_var_00 < 0) + v2 = E->base.x_pos - draygon_var_00; + else + v2 = E->base.x_pos - E->draygon_var_00; + R44 = v2; + R42 = 0; + R46 = E->draygon_var_C >> 2; + R48 = 0; + EnemyFunc_B761(); + E->draygon_var_D = R44; + E->draygon_var_E = R42; + E->draygon_var_A = FUNC16(Draygon_Func_13); +} + +void Draygon_Func_13(void) { // 0xA58A90 + Draygon_Func_3(); + Draygon_Func_35(); + Enemy_Draygon *E = Get_Draygon(0); + uint16 draygon_var_B = E->draygon_var_B; + if (draygon_var_B == 104) { + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.current_instruction = addr_kDraygon_Ilist_97E7; + E3->base.instruction_timer = 1; + } + Get_Draygon(cur_enemy_index)->base.y_pos = *(uint16 *)((char *)&g_word_7E9002 + draygon_var_B); + ++E->draygon_var_B; + ++E->draygon_var_B; + ++E->draygon_var_B; + if (++E->draygon_var_B == E->draygon_var_C) { + if ((random_number & 1) != 0) { + E->draygon_var_A = FUNC16(Draygon_Func_4); + E->draygon_var_B = 0; + E->base.x_pos = E->draygon_var_00; + E->base.y_pos = E->draygon_var_01; + } else { + E->draygon_var_A = FUNC16(Draygon_Func_14); + E->base.x_pos = E->draygon_var_00; + } + } else { + uint16 x_subpos = E->base.x_subpos; + bool v6 = x_subpos < E->draygon_var_E; + E->base.x_subpos = x_subpos - E->draygon_var_E; + E->base.x_pos -= v6 + E->draygon_var_D; + } +} + +void Draygon_Func_14(void) { // 0xA58B0A + Draygon_Func_3(); + Enemy_Draygon *E = Get_Draygon(0); + E->base.x_pos = -80; + E->base.y_pos = 384; + E->draygon_var_E = 0; + E->draygon_var_D = 1; + E->draygon_var_0D = 0; + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.current_instruction = addr_kDraygon_Ilist_9C06; + E3->base.instruction_timer = 1; + E->draygon_var_A = FUNC16(Draygon_Func_15); + E->base.current_instruction = addr_kDraygon_Ilist_97D1; + E->base.instruction_timer = 1; + E->draygon_var_20 = 1; +} + +void Draygon_Func_15(void) { // 0xA58B52 + Draygon_Func_3(); + Draygon_Func_35(); + Enemy_Draygon *E = Get_Draygon(0); + uint16 v2 = Abs16(E->base.x_pos - samus_x_pos); + if (sign16(v2 - 208)) { + E->draygon_var_A = FUNC16(Draygon_Func_16); + E->draygon_var_03 = 16; + } else { + draw_enemy_layer = 32; + E->base.y_pos = CosineMult8bit(E->draygon_var_0D) + 384; + E->draygon_var_0D = (uint8)(E->draygon_var_0D + 1); + uint16 x_subpos = E->base.x_subpos; + bool v4 = __CFADD__uint16(E->draygon_var_E, x_subpos); + E->base.x_subpos = E->draygon_var_E + x_subpos; + E->base.x_pos += E->draygon_var_D + v4; + } +} + +void Draygon_Func_16(void) { // 0xA58BAE + Enemy_Draygon *E = Get_Draygon(0); + int16 v5; + + Draygon_Func_3(); + if (samus_x_speed_divisor) + goto LABEL_9; + if ((random_number & 0xF) == 0) { + uint16 v1 = E->draygon_var_03 - 1; + E->draygon_var_03 = v1; + if (!v1) + goto LABEL_8; + E->base.current_instruction = addr_kDraygon_Ilist_9C90; + E->base.instruction_timer = 1; + } + draw_enemy_layer = 32; + + E->base.y_pos = CosineMult8bit(E->draygon_var_0D) + 384; + E->draygon_var_0D = (uint8)(E->draygon_var_0D + 1); + uint16 x_subpos; + x_subpos = E->base.x_subpos; + bool v4; + v4 = __CFADD__uint16(E->draygon_var_E, x_subpos); + E->base.x_subpos = E->draygon_var_E + x_subpos; + v5 = E->draygon_var_D + v4 + E->base.x_pos; + E->base.x_pos = v5; + if (v5 >= 0 && !sign16(v5 - 672)) { +LABEL_8: + if (!samus_x_speed_divisor) { + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.current_instruction = addr_kDraygon_Ilist_9BDA; + E3->base.instruction_timer = 1; + E->draygon_var_A = FUNC16(Draygon_Func_17); + return; + } +LABEL_9: + E->draygon_var_A = FUNC16(Draygon_Func_22); + } +} + +void Draygon_Func_17(uint16 k) { // 0xA58C33 + int16 v4; + + Draygon_Func_35(); + draw_enemy_layer = 32; + Enemy_Draygon *E = Get_Draygon(0); + E->base.y_pos = CosineMult8bit(E->draygon_var_0D) + 384; + E->draygon_var_0D = (uint8)(E->draygon_var_0D + 1); + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->draygon_var_E, x_subpos); + E->base.x_subpos = E->draygon_var_E + x_subpos; + v4 = E->draygon_var_D + v3 + E->base.x_pos; + E->base.x_pos = v4; + if (v4 >= 0 && !sign16(v4 - 672)) { + E->draygon_var_A = FUNC16(Draygon_Func_10); + E->base.x_pos = 592; + E->base.y_pos = -80; + E->draygon_var_B = E->draygon_var_C; + } +} + +void Draygon_Func_18(void) { // 0xA58C8E + Enemy_Draygon *E = Get_Draygon(0); + E->base.x_pos = E->draygon_var_02; + E->base.y_pos = 384; + E->draygon_var_E = 0; + E->draygon_var_D = 1; + E->draygon_var_0D = 0; + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.current_instruction = addr_kDraygon_Ilist_9C06; + E3->base.instruction_timer = 1; + E->draygon_var_A = FUNC16(Draygon_Func_19); + E->base.current_instruction = addr_kDraygon_Ilist_97BB; + E->base.instruction_timer = 1; + E->draygon_var_20 = 0; +} + +void Draygon_Func_19(void) { // 0xA58CD4 + Draygon_Func_3(); + Draygon_Func_35(); + Enemy_Draygon *E = Get_Draygon(0); + uint16 v2 = Abs16(E->base.x_pos - samus_x_pos); + if (sign16(v2 - 208)) { + E->draygon_var_A = FUNC16(Draygon_Func_20); + E->draygon_var_03 = 16; + } else { + draw_enemy_layer = 32; + E->base.y_pos = CosineMult8bit(E->draygon_var_0D) + 384; + E->draygon_var_0D = (uint8)(E->draygon_var_0D + 1); + uint16 x_subpos = E->base.x_subpos; + bool v4 = x_subpos < E->draygon_var_E; + E->base.x_subpos = x_subpos - E->draygon_var_E; + E->base.x_pos -= v4 + E->draygon_var_D; + } +} + +void Draygon_Func_20(void) { // 0xA58D30 + Enemy_Draygon *E = Get_Draygon(0); + int16 v5; + + if (samus_x_speed_divisor) + goto LABEL_9; + if ((random_number & 0xF) == 0) { + uint16 v1 = E->draygon_var_03 - 1; + E->draygon_var_03 = v1; + if (!v1) + goto LABEL_8; + E->base.current_instruction = addr_kDraygon_Ilist_98FE; + E->base.instruction_timer = 1; + } + draw_enemy_layer = 32; + + E->base.y_pos = CosineMult8bit(E->draygon_var_0D) + 384; + E->draygon_var_0D = (uint8)(E->draygon_var_0D + 1); + uint16 x_subpos; + x_subpos = E->base.x_subpos; + bool v4; + v4 = x_subpos < E->draygon_var_E; + E->base.x_subpos = x_subpos - E->draygon_var_E; + v5 = E->base.x_pos - (v4 + E->draygon_var_D); + E->base.x_pos = v5; + if (v5 < 0 && sign16(v5 + 80)) { +LABEL_8: + if (!samus_x_speed_divisor) { + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.current_instruction = addr_kDraygon_Ilist_97E7; + E3->base.instruction_timer = 1; + Get_Draygon(0)->draygon_var_A = FUNC16(Draygon_Func_21); + return; + } +LABEL_9: + Get_Draygon(0)->draygon_var_A = FUNC16(Draygon_Func_22); + } +} + +void Draygon_Func_21(uint16 k) { // 0xA58DB2 + Enemy_Draygon *E = Get_Draygon(0); + int16 v4; + + Draygon_Func_35(); + if (samus_x_speed_divisor) { + E->draygon_var_A = FUNC16(Draygon_Func_22); + } else { + draw_enemy_layer = 32; + E->base.y_pos = CosineMult8bit(E->draygon_var_0D) + 384; + E->draygon_var_0D = (uint8)(E->draygon_var_0D + 1); + uint16 x_subpos = E->base.x_subpos; + bool v3 = x_subpos < E->draygon_var_E; + E->base.x_subpos = x_subpos - E->draygon_var_E; + v4 = E->base.x_pos - (v3 + E->draygon_var_D); + E->base.x_pos = v4; + if (v4 < 0) { + if (sign16(v4 + 80)) { + E->draygon_var_A = FUNC16(Draygon_Func_4); + E->base.x_pos = -80; + E->base.y_pos = -80; + E->draygon_var_B = E->draygon_var_C; + } + } + } +} + +void Draygon_Func_22(void) { // 0xA58E19 + Enemy_Draygon *E = Get_Draygon(0); + int16 v2; + uint16 v4; + + Draygon_Func_3(); + if (samus_x_speed_divisor) { + E->base.properties |= kEnemyProps_Tangible; + v2 = 8; + if (!E->draygon_var_20) + v2 = -8; + uint16 v3 = Abs16(E->base.x_pos + v2 - samus_x_pos); + if (sign16(v3 - 8) && (v4 = Abs16(E->base.y_pos - samus_y_pos), sign16(v4 - 8))) { + uint16 v5 = addr_kDraygon_Ilist_9845; + if (E->draygon_var_20) + v5 = addr_kDraygon_Ilist_9C38; + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.current_instruction = v5; + E3->base.instruction_timer = 1; + if (CallSomeSamusCode(0xDu)) { + E->draygon_var_A = FUNC16(Draygon_Func_23); + } else { + Samus_SetGrabbedByDraygonPose(E->draygon_var_20 != 0); + E->draygon_var_06 = 256; + E->draygon_var_07 = 384; + E->draygon_var_05 = 0; + E->draygon_var_09 = 0; + E->draygon_var_08 = 192; + E->draygon_var_0B = 2048; + E->draygon_var_A = FUNC16(Draygon_Func_24); + } + } else { + R18_ = samus_x_pos - E->base.x_pos; + R20_ = samus_y_pos - E->base.y_pos; + enemy_population_ptr = (uint8)(64 - CalculateAngleFromXY()); + R18_ = enemy_population_ptr; + R20_ = 2; + ConvertAngleToXy(); + varE24 = R22_; + varE26 = R24_; + varE28 = R26_; + varE2A = R28_; + EnemyFunc_B691(); + } + } else { + E->draygon_var_A = FUNC16(Draygon_Func_30); + } +} + +void Draygon_Func_23(void) { // 0xA58F10 + grapple_beam_function = FUNC16(GrappleBeam_Func2); + Get_Draygon(0)->draygon_var_A = FUNC16(Draygon_Func_29); +} + +void Draygon_Func_24(uint16 k) { // 0xA58F1E + Enemy_Draygon *E = Get_Draygon(0); + uint16 v5; + + if ((samus_grapple_flags & 1) != 0) { + E->base.flash_timer = get_EnemyDef_A2(E->base.enemy_ptr)->hurt_ai_time + 8; + E->base.ai_handler_bits |= 2u; + } else { + uint16 v4 = Abs16(E->base.x_pos - 256); + if (sign16(v4 - 2) && (v5 = Abs16(E->base.y_pos - 384), sign16(v5 - 2))) { + E->draygon_var_A = FUNC16(Draygon_Func_25); + uint16 v6 = addr_kDraygon_Ilist_9922; + if (E->draygon_var_20) + v6 = addr_kDraygon_Ilist_9CB4; + Enemy_Draygon *EK = Get_Draygon(k); + EK->base.current_instruction = v6; + EK->base.instruction_timer = 1; + E->base.properties |= kEnemyProps_Tangible; + } else { + R18_ = 256 - E->base.x_pos; + R20_ = 384 - E->base.y_pos; + enemy_population_ptr = (uint8)(64 - CalculateAngleFromXY()); + R18_ = enemy_population_ptr; + R20_ = 2; + ConvertAngleToXy(); + varE24 = R22_; + varE26 = R24_; + varE28 = R26_; + varE2A = R28_; + EnemyFunc_B691(); + Draygon_Func_40(k); + } + } +} + +void Draygon_Func_25(uint16 k) { // 0xA58FD6 + Enemy_Draygon *E = Get_Draygon(0); + uint16 v6; + + if ((samus_grapple_flags & 1) != 0) { + E->base.flash_timer = get_EnemyDef_A2(E->base.enemy_ptr)->hurt_ai_time + 8; + E->base.ai_handler_bits |= 2u; + } else if ((uint8)random_number) { + draw_enemy_layer = E->draygon_var_05; + E->base.x_pos = E->draygon_var_06 + CosineMult8bit(E->draygon_var_08); + draw_enemy_layer = E->draygon_var_05 >> 2; + E->base.y_pos = E->draygon_var_07 + SineMult8bitNegative(E->draygon_var_08); + if ((Get_Draygon(k)->base.frame_counter & 7) == 0) { + R18_ = E->base.x_pos - 32; + if (E->draygon_var_20) + R18_ = E->base.x_pos + 32; + R20_ = E->base.y_pos - 16; + R22_ = 61; + R24_ = 0; + CreateSpriteAtPos(); + } + uint16 draygon_var_09 = E->draygon_var_09; + E->draygon_var_09 = draygon_var_09 + 0x2000; + uint16 v5 = __CFADD__uint16(draygon_var_09, 0x2000) + E->draygon_var_05; + E->draygon_var_05 = v5; + uint16 draygon_var_0A, v8; + if (!sign16(v5 - 160) + || (v6 = E->draygon_var_0B - 1, + E->draygon_var_0B = v6, + E->draygon_var_08 = (uint8)(LOBYTE(E->draygon_var_08) + HIBYTE(v6)), + draygon_var_0A = E->draygon_var_0A, + E->draygon_var_0A = draygon_var_0A - 0x4000, + v8 = (__PAIR32__(E->draygon_var_07, draygon_var_0A) - 0x4000) >> 16, + E->draygon_var_07 = v8, + sign16(v8 - 64))) { + E->draygon_var_A = FUNC16(Draygon_Func_27); + } else { + Draygon_Func_40(k); + } + } else { + E->draygon_var_0C = 64; + E->draygon_var_A = FUNC16(Draygon_Func_26); + } +} + +void Draygon_Func_26(uint16 k) { // 0xA590D4 + uint16 v0 = k; + uint16 v3; + + Draygon_Func_40(v0); + Enemy_Draygon *E = Get_Draygon(0); + uint16 v2 = E->draygon_var_0C - 1; + E->draygon_var_0C = v2; + if (v2) { + if (v2 == 63) { + v3 = addr_kDraygon_Ilist_9AE8; + if (E->draygon_var_20) + v3 = addr_kDraygon_Ilist_9EA1; + Enemy_Draygon *E2 = Get_Draygon(0x80); + E2->base.current_instruction = v3; + E2->base.instruction_timer = 1; + } + } else { + E->draygon_var_A = FUNC16(Draygon_Func_25); + } +} + +void Draygon_Func_27(uint16 k) { // 0xA59105 + Draygon_Func_40(k); + uint16 v1 = addr_kDraygon_Ilist_9A68; + if (Get_Draygon(k)->draygon_var_20) + v1 = addr_kDraygon_Ilist_9E21; + Enemy_Draygon *E = Get_Draygon(0x80); + E->base.current_instruction = v1; + E->base.instruction_timer = 1; + Get_Draygon(0)->draygon_var_A = FUNC16(Draygon_Func_28); +} + +void Draygon_Func_28(uint16 k) { // 0xA59124 + Draygon_Func_40(k); +} + +void Draygon_Func_29(void) { // 0xA59128 + Samus_ReleaseFromDraygon_(); + samus_grapple_flags = 0; + Enemy_Draygon *E = Get_Draygon(0); + E->draygon_var_A = FUNC16(Draygon_Func_30); + E->base.properties &= ~kEnemyProps_Tangible; + uint16 v1 = addr_kDraygon_Ilist_9B5A; + if (E->draygon_var_20) + v1 = addr_kDraygon_Ilist_9F15; + Enemy_Draygon *E2 = Get_Draygon(0x80); + E2->base.current_instruction = v1; + E2->base.instruction_timer = 1; +} + +void Draygon_Func_30(void) { // 0xA59154 + int16 v1; + + Draygon_Func_3(); + Enemy_Draygon *E = Get_Draygon(0); + v1 = E->base.y_pos - 4; + E->base.y_pos = v1; + if (v1 < 0) { + E->base.properties &= ~kEnemyProps_Tangible; + E->draygon_var_A = FUNC16(Draygon_Func_4); + E->draygon_var_B = 0; + E->base.x_pos = E->draygon_var_00; + E->base.y_pos = E->draygon_var_01; + } +} + +void Draygon_Func_31(void) { // 0xA59185 + Enemy_Draygon *E = Get_Draygon(0); + if ((Get_Draygon(cur_enemy_index)->base.frame_counter & 0xF) == 0) { + R18_ = E->base.x_pos - 32; + if (E->draygon_var_20) + R18_ = E->base.x_pos + 32; + R20_ = E->base.y_pos - 16; + R22_ = 61; + R24_ = 0; + CreateSpriteAtPos(); + } + R18_ = E->base.x_pos >> 2; + R18_ = 64 - R18_; + R20_ = E->base.y_pos >> 2; + R20_ = 120 - R20_; + E->draygon_var_43 = (uint8)(64 - CalculateAngleFromXY()); + R20_ = 1; + R18_ = LOBYTE(E->draygon_var_43); + ConvertAngleToXy(); + varE24 = R22_; + varE26 = R24_; + varE28 = R26_; + varE2A = R28_; + enemy_population_ptr = LOBYTE(E->draygon_var_43); + EnemyFunc_B691(); + uint16 v3 = Abs16(E->base.x_pos - 256); + if (sign16(v3 - 4)) { + uint16 v4 = Abs16(E->base.y_pos - 480); + if (sign16(v4 - 4)) { + Draygon_Func_43(); + E->draygon_var_A = FUNC16(Draygon_Func_32); + QueueMusic_Delayed8(3u); + E->draygon_var_B = 416; + E->base.current_instruction = addr_kDraygon_Ilist_97B9; + E->base.instruction_timer = 1; + uint16 v5 = E->base.properties | kEnemyProps_Deleted; + Get_Draygon(0x80)->base.properties = v5; + Get_Draygon(0xC0u)->base.properties = v5; + uint16 v6 = addr_kDraygon_Ilist_999C; + if (E->draygon_var_20) + v6 = addr_kDraygon_Ilist_9D3E; + Enemy_Draygon *E1 = Get_Draygon(0x40u); + E1->base.current_instruction = v6; + E1->base.instruction_timer = 1; + E1->draygon_var_A = FUNC16(nullsub_169_A5); + } + } +} + +void Draygon_Func_32(void) { // 0xA59294 + Draygon_Func_34(); + Enemy_Draygon *E = Get_Draygon(0); + if (--E->draygon_var_B) + Draygon_Func_42(); + else + E->draygon_var_A = FUNC16(Draygon_Func_33); +} + +void Draygon_Func_33(void) { // 0xA592AB + Draygon_Func_34(); + Draygon_Func_42(); + Enemy_Draygon *E = Get_Draygon(0); + if (!sign16(++E->base.y_pos - 576)) { + E->base.current_instruction = addr_kDraygon_Ilist_98ED; + E->base.instruction_timer = 1; + uint16 v1 = E->base.properties | kEnemyProps_Deleted; + E->base.properties = v1; + Get_Draygon(0x40u)->base.properties = v1; + uint16 v2 = area_index; + *(uint16 *)&boss_bits_for_area[area_index] |= 1u; + Enemy_ItemDrop_Draygon(v2); + Draygon_Func_44(); + } +} + +void Draygon_Func_34(void) { // 0xA592EA + if ((nmi_frame_counter_word & 7) == 0) { + R18_ = (NextRandom() & 0x7F) + 192; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) + 400; + R22_ = 21; + R24_ = 0; + CreateSpriteAtPos(); + } +} + +void Draygon_Func_35(void) { // 0xA5931C + Enemy_Draygon *Draygon = Get_Draygon(cur_enemy_index); + + if ((Draygon->base.frame_counter & 0x7F) == 0) { + Draygon = Get_Draygon(0); + R18_ = Draygon->base.x_pos - 16; + R20_ = Draygon->base.y_pos - 16; + R22_ = 24; + R24_ = 0; + CreateSpriteAtPos(); + } +} + +void Draygon_Func_36(void) { // 0xA59342 + Enemy_Draygon *E = Get_Draygon(0); + reg_BG2HOFS = E->draygon_var_5E + layer1_x_pos - E->base.x_pos - 450; + reg_BG2VOFS = E->draygon_var_5F + layer1_y_pos - E->base.y_pos - 192; +} + +void Draygon_Func_37(void) { // 0xA59367 + Enemy_Draygon *E = Get_Draygon(0); + if ((joypad2_last & 0x40) != 0) + Draygon_Func_39(); + else + Draygon_Func_38(); + if ((joypad2_new_keys & 0x4000) != 0) { + uint16 v0 = addr_kDraygon_Ilist_98FE; + if (E->draygon_var_20) + v0 = addr_kDraygon_Ilist_9C90; + E->base.current_instruction = v0; + E->base.instruction_timer = 1; + } else if ((joypad2_new_keys & 0x8000u) == 0) { + if ((joypad2_new_keys & 0x80) != 0) { + uint16 v4 = addr_kDraygon_Ilist_9825; + if (E->draygon_var_20) + v4 = addr_kDraygon_Ilist_9C18; + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.current_instruction = v4; + E3->base.instruction_timer = 1; + } + } else { + uint16 v2 = addr_kDraygon_Ilist_99FC; + if (E->draygon_var_20) + v2 = addr_kDraygon_Ilist_9D9E; + Enemy_Draygon *E2 = Get_Draygon(0x80); + E2->base.current_instruction = v2; + E2->base.instruction_timer = 1; + } +} + +void Draygon_Func_38(void) { // 0xA593DA + Enemy_Draygon *E = Get_Draygon(0); + uint16 v0 = joypad2_last, v2; + if ((joypad2_last & 0x200) == 0 || (--E->base.x_pos, v0 == debug_enemy_population_pointer)) { + if ((v0 & 0x100) == 0) + goto LABEL_8; + ++E->base.x_pos; + if (v0 == debug_enemy_population_pointer) + goto LABEL_8; + debug_enemy_population_pointer = v0; + v2 = addr_kDraygon_Ilist_97D1; + E->draygon_var_20 = 1; + } else { + debug_enemy_population_pointer = v0; + v2 = addr_kDraygon_Ilist_97BB; + E->draygon_var_20 = 0; + } + E->base.current_instruction = v2; + E->base.instruction_timer = 1; +LABEL_8: + if ((joypad2_last & 0x800) != 0) { + --E->base.y_pos; + } else if ((joypad2_last & 0x400) != 0) { + ++E->base.y_pos; + } +} + +void Draygon_Func_39(void) { // 0xA59430 + Enemy_Draygon *E = Get_Draygon(0); + uint16 v0 = joypad2_last, v2; + if ((joypad2_last & 0x200) == 0 + || (E->base.x_pos -= 4, v0 = joypad2_last, joypad2_last == debug_enemy_population_pointer)) { + if ((v0 & 0x100) == 0) + goto LABEL_8; + E->base.x_pos += 4; + if (joypad2_last == debug_enemy_population_pointer) + goto LABEL_8; + debug_enemy_population_pointer = joypad2_last; + v2 = addr_kDraygon_Ilist_97D1; + E->draygon_var_20 = 1; + } else { + debug_enemy_population_pointer = joypad2_last; + v2 = addr_kDraygon_Ilist_97BB; + E->draygon_var_20 = 0; + } + E->base.current_instruction = v2; + E->base.instruction_timer = 1; +LABEL_8: + if ((joypad2_last & 0x800) != 0) { + E->base.y_pos -= 4; + } else if ((joypad2_last & 0x400) != 0) { + ++E->base.y_pos; + E->base.y_pos += 4; + } +} + +void Draygon_Func_40(uint16 k) { // 0xA594A9 + int16 v1; + + v1 = 8; + if (!Get_Draygon(k)->draygon_var_20) + v1 = -8; + Enemy_Draygon *E = Get_Draygon(0); + samus_x_pos = E->base.x_pos + v1; + samus_y_pos = E->base.y_pos + 40; + EnemyFunc_B7A1(); + if ((samus_grapple_flags & 2) != 0) { + samus_grapple_flags = 0; + E->draygon_var_A = FUNC16(Draygon_Func_30); + } +} + +uint16 Draygon_Instr_1(uint16 k, uint16 j) { // 0xA594DD + uint16 *v2 = (uint16 *)RomPtr_A5(j); + Get_Draygon(0)->base.current_instruction = *v2; + Get_Draygon(0x40u)->base.current_instruction = v2[1]; + Get_Draygon(0x80)->base.current_instruction = v2[2]; + Enemy_Draygon *E = Get_Draygon(0xC0u); + E->base.current_instruction = v2[3]; + Get_Draygon(0)->base.instruction_timer = 1; + Get_Draygon(0x40u)->base.instruction_timer = 1; + Get_Draygon(0x80)->base.instruction_timer = 1; + E->base.instruction_timer = 1; + return j + 8; +} + +void Draygon_Hurt(void) { // 0xA5954D + int16 v2; + int16 v7; + int16 v9; + + uint16 v0 = addr_kDraygon_MorePalettes2; + if ((Get_Draygon(cur_enemy_index)->base.flash_timer & 2) != 0) + v0 = addr_word_A5A297; + uint16 v1 = addr_kDraygon_BigSprmap_C08F__plus__17; + remaining_enemy_spritemap_entries = 16; + do { + v2 = *(uint16 *)RomPtr_A5(v0); + *(uint16 *)RomPtr_7E(v1) = v2; + v1 += 2; + v0 += 2; + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); + if ((Get_Draygon(cur_enemy_index)->base.flash_timer & 2) == 0) { + uint16 v3 = 4 * Get_Draygon(0)->draygon_var_0E; + for (int i = 0; i != 8; i += 2) { + palette_buffer[(i >> 1) + 89] = g_word_A596AF[v3 >> 1]; + v3 += 2; + } + } + uint16 v5 = addr_kDraygon_Palette; + if ((Get_Draygon(cur_enemy_index)->base.flash_timer & 2) != 0) + v5 = addr_word_A5A297; + uint16 v6 = addr_kDraygon_BigSprmap_C11B__plus__197; + remaining_enemy_spritemap_entries = 16; + do { + v7 = *(uint16 *)RomPtr_A5(v5); + *(uint16 *)RomPtr_7E(v6) = v7; + v6 += 2; + v5 += 2; + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); + if ((samus_grapple_flags & 1) != 0) { + Enemy_Draygon *E = Get_Draygon(0); + if ((E->base.frame_counter & 7) == 0) { + v9 = E->base.health - 256; + if (v9 < 0) + v9 = 0; + E->base.health = v9; + sub_A5960D(); + } + } +} + +void Draygon_Touch(void) { // 0xA595EA + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); + sub_A5960D(); +} + +void Draygon_Shot(void) { // 0xA595F0 + Enemy_Draygon *E = Get_Draygon(0); + if (sign16(E->draygon_var_0F - 152)) + E->draygon_var_0F += 8; + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + sub_A5960D(); +} + +void Draygon_Powerbomb(void) { // 0xA59607 + NormalEnemyPowerBombAiSkipDeathAnim_CurEnemy(); + sub_A5960D(); +} + +void sub_A5960D(void) { // 0xA5960D + if (Get_Draygon(cur_enemy_index)->base.health) { + Draygon_Func_41(); + } else { + grapple_beam_function = FUNC16(GrappleBeam_Func2); + uint16 v0 = addr_kDraygon_Ilist_9867; + Enemy_Draygon *E = Get_Draygon(0); + if (E->draygon_var_20) + v0 = addr_kDraygon_Ilist_9C5A; + E->base.current_instruction = v0; + E->base.instruction_timer = 1; + uint16 v3 = addr_kDraygon_Ilist_997A; + if (E->draygon_var_20) + v3 = addr_kDraygon_Ilist_9D1C; + Enemy_Draygon *E1 = Get_Draygon(0x40u); + E1->base.current_instruction = v3; + E1->base.instruction_timer = 1; + E1->draygon_var_A = FUNC16(nullsub_169_A5); + E->draygon_var_A = FUNC16(Draygon_Func_31); + Samus_ReleaseFromDraygon_(); + samus_grapple_flags = 0; + R18_ = 256 - E->base.x_pos; + R20_ = 480 - E->base.y_pos; + E->draygon_var_43 = (uint8)(64 - CalculateAngleFromXY()); + R20_ = 1; + R18_ = LOBYTE(E->draygon_var_43); + ConvertAngleToXy(); + E->draygon_var_28 = R22_; + E->draygon_var_29 = R24_; + E->draygon_var_2A = R26_; + E->draygon_var_2B = R28_; + } +} + +void Draygon_Func_41(void) { // 0xA59701 + int i; + uint16 j; + Enemy_Draygon *E = Get_Draygon(0); + for (i = 0; ; i += 2) { + if ((int16)(E->base.health - g_word_A596EF[i >> 1]) >= 0) + break; + } + if (i != E->draygon_var_0E) { + E->draygon_var_0E = i; + uint16 v2 = 4 * E->draygon_var_0E; + for (j = 0; j != 8; j += 2) { + palette_buffer[(j >> 1) + 89] = g_word_A596AF[v2 >> 1]; + v2 += 2; + } + } +} + +uint16 Draygon_Instr_13(uint16 k, uint16 j) { // 0xA59736 + uint16 v2 = *(uint16 *)RomPtr_A5(j); + Get_Draygon(k)->draygon_var_A = v2; + return j + 2; +} + +uint16 Draygon_Instr_8(uint16 k, uint16 j) { // 0xA5973F + Draygon_Func_47(); + R22_ = 21; + R24_ = 0; + CreateSpriteAtPos(); + return j; +} + +uint16 Draygon_Instr_7(uint16 k, uint16 j) { // 0xA59752 + Draygon_Func_47(); + R22_ = 3; + R24_ = 0; + CreateSpriteAtPos(); + return j; +} + +uint16 Draygon_Instr_6(uint16 k, uint16 j) { // 0xA59765 + Draygon_Func_47(); + R22_ = 29; + R24_ = 0; + CreateSpriteAtPos(); + return j; +} + +uint16 Draygon_Instr_9(uint16 k, uint16 j) { // 0xA59778 + Draygon_Func_47(); + R22_ = 24; + R24_ = 0; + CreateSpriteAtPos(); + return j; +} + +void Draygon_Func_47(void) { // 0xA5978B + NextRandom(); + R18_ = (random_number & 0x7F) - 64; + Enemy_Draygon *E = Get_Draygon(0); + R18_ += E->base.x_pos; + R20_ = ((uint16)(random_number & 0x7F00) >> 8) - 64; + R20_ += E->base.y_pos; +} + +uint16 Draygon_Instr_2(uint16 k, uint16 j) { // 0xA59895 + room_loading_irq_handler = 12; + return j; +} + +uint16 Draygon_Instr_11(uint16 k, uint16 j) { // 0xA598D3 + Enemy_Draygon *E2 = Get_Draygon(0x80); + E2->base.instruction_timer = 1; + E2->base.current_instruction = addr_kDraygon_Ilist_97B9; + + Enemy_Draygon *E3 = Get_Draygon(0xC0u); + E3->base.instruction_timer = 1; + E3->base.current_instruction = addr_kDraygon_Ilist_97B9; + return j; +} + +uint16 Draygon_Instr_5(uint16 k, uint16 j) { // 0xA598EF + Enemy_Draygon *E = Get_Draygon(0); + E->base.properties |= kEnemyProps_Tangible; + return j; +} + +uint16 Draygon_Instr_15(uint16 k, uint16 j) { // 0xA59B9A + Enemy_Draygon *E = Get_Draygon(0); + E->draygon_var_0F = 24; + uint8 *v3 = RomPtr_A0(E->base.enemy_ptr); + uint16 v4 = SuitDamageDivision(*((uint16 *)v3 + 3)); + Samus_DealDamage(v4); + earthquake_timer = 32; + earthquake_type = 7; + R18_ = samus_x_pos; + R20_ = samus_y_pos + 16; + R22_ = 21; + R24_ = 0; + CreateSpriteAtPos(); + return j; +} + +uint16 Draygon_Instr_17(uint16 k, uint16 j) { // 0xA59C8A + room_loading_irq_handler = 12; + return j; +} + +uint16 Draygon_Instr_14(uint16 k, uint16 j) { // 0xA59E0A + uint8 *v2 = RomPtr_A5(j); + Enemy_Draygon *E = Get_Draygon(0); + E->draygon_var_5E = *(uint16 *)v2; + E->draygon_var_5F = *((uint16 *)v2 + 1); + return j + 4; +} + +uint16 Draygon_Instr_16(uint16 k, uint16 j) { // 0xA59F57 + uint16 v2 = *(uint16 *)RomPtr_A5(j); + Get_Draygon(0)->draygon_var_A = v2; + return j + 2; +} + +uint16 Draygon_Instr_10(uint16 k, uint16 j) { // 0xA59F60 + uint16 *v2 = (uint16 *)RomPtr_A5(j); + QueueSfx2_Max6(*v2); + return j + 2; +} + +uint16 Draygon_Instr_4(uint16 k, uint16 j) { // 0xA59F6E + uint16 *v2 = (uint16 *)RomPtr_A5(j); + QueueSfx3_Max6(*v2); + return j + 2; +} + +uint16 Draygon_Instr_12(uint16 k, uint16 j) { // 0xA59F7C + Enemy_Draygon *E = Get_Draygon(0); + R18_ = E->base.x_pos - 28; + R20_ = E->base.y_pos - 16; + enemy_projectile_unk1995 = (NextRandom() & 0x3F) + 128; + SpawnEnemyProjectileWithGfx(2u, cur_enemy_index, addr_stru_868E50); + return j; +} + +uint16 Draygon_Instr_18(uint16 k, uint16 j) { // 0xA59FAE + Enemy_Draygon *E = Get_Draygon(0); + R18_ = E->base.x_pos + 24; + R20_ = E->base.y_pos - 16; + enemy_projectile_unk1995 = (NextRandom() & 0x3F) + 192; + SpawnEnemyProjectileWithGfx(2u, cur_enemy_index, addr_stru_868E50); + return j; +} + +void Draygon_Func_42(void) { // 0xA59FE0 + uint16 v0 = 62; + for (int i = 20; i >= 0; i -= 4) { + int v2 = i >> 1; + int v3 = v0 >> 1; + uint16 v4 = sprite_x_subpos[v3], v6; + if (((g_word_A5A1DF[v2] + 64) & 0x80) != 0) { + bool v5 = __CFADD__uint16(g_word_A5A1AF[v2], v4); + sprite_x_subpos[v3] = g_word_A5A1AF[v2] + v4; + v6 = v5 + sprite_x_pos[v3]; + } else { + bool v5 = v4 < g_word_A5A1AF[v2]; + sprite_x_subpos[v3] = v4 - g_word_A5A1AF[v2]; + v6 = sprite_x_pos[v3] - (v5 + varE24); + } + sprite_x_pos[v3] = v6; + int v7 = v0 >> 1; + uint16 v8 = sprite_y_subpos[v7], v9; + if (((g_word_A5A1DF[v2] + 128) & 0x80) != 0) { + bool v5 = __CFADD__uint16(g_word_A5A1AF[v2 + 1], v8); + sprite_y_subpos[v7] = g_word_A5A1AF[v2 + 1] + v8; + v9 = v5 + sprite_y_pos[v7]; + } else { + bool v5 = v8 < g_word_A5A1AF[v2 + 1]; + sprite_y_subpos[v7] = v8 - g_word_A5A1AF[v2 + 1]; + v9 = sprite_y_pos[v7] - v5; + } + sprite_y_pos[v7] = v9; + v0 -= 2; + } +} + +void Draygon_Func_43(void) { // 0xA5A06C + int16 v1; + int16 j; + + for (int i = 62; i >= 0; i -= 2) + sprite_instr_list_ptrs[i >> 1] = 0; + v1 = 2; + uint16 v2 = 20; + do { + int v3 = v2 >> 1; + R18_ = g_word_A5A1C7[v3]; + R20_ = g_word_A5A1C7[v3 + 1]; + R22_ = 59; + R24_ = 3584; + CreateSpriteAtPos(); + v2 -= 4; + --v1; + } while (v1 >= 0); + for (j = 2; j >= 0; --j) { + int v5 = v2 >> 1; + R18_ = g_word_A5A1C7[v5]; + R20_ = g_word_A5A1C7[v5 + 1]; + R22_ = 60; + R24_ = 3584; + CreateSpriteAtPos(); + v2 -= 4; + } +} + +void Draygon_Func_44(void) { // 0xA5A0C6 + for (int i = 62; i >= 0; i -= 2) + sprite_instr_list_ptrs[i >> 1] = 0; +} + +void Draygon_Func_45(void) { // 0xA5A0D9 + R18_ = 16; + R20_ = 384; + R22_ = 59; + R24_ = 3584; + CreateSpriteAtPos(); + R18_ = 16; + R20_ = 384; + R22_ = 59; + R24_ = 3584; + CreateSpriteAtPos(); + R18_ = 16; + R20_ = 384; + R22_ = 59; + R24_ = 3584; + CreateSpriteAtPos(); + R18_ = 16; + R20_ = 384; + R22_ = 59; + R24_ = 3584; + CreateSpriteAtPos(); +} + +void Draygon_Func_46(void) { // 0xA5A13E + uint16 v0 = 62; + do { + uint16 v1 = Get_Draygon(0)->draygon_var_46 + g_word_A5A19F[(uint16)(v0 - 56) >> 1]; + if ((v1 & 0x8000u) == 0) { + uint16 v2 = v1; + if (*(uint16 *)&g_byte_A5CE07[v1] == 0x8080) { + sprite_instr_list_ptrs[v0 >> 1] = 0; + } else { + int v3 = v0 >> 1; + sprite_x_pos[v3] += SignExtend8(g_byte_A5CE07[v1]); + sprite_y_pos[v3] += SignExtend8(g_byte_A5CE07[v2 + 1]); + } + } + v0 -= 2; + } while ((int16)(v0 - 56) >= 0); + Enemy_Draygon *E = Get_Draygon(0); + E->draygon_var_46 += 4; +} + +void DraygonsEye_Init(void) { // 0xA5C46B + Enemy_Draygon *E = Get_Draygon(cur_enemy_index); + E->base.current_instruction = addr_kDraygon_Ilist_9944; + E->draygon_var_A = FUNC16(nullsub_169_A5); +} + +uint16 Draygon_Instr_3(uint16 k, uint16 j) { // 0xA5C47B + uint16 v2 = *(uint16 *)RomPtr_A5(j); + Get_Draygon(0x40u)->draygon_var_A = v2; + return j + 2; +} + +void DraygonsEye_Main(void) { // 0xA5C486 + Enemy_Draygon *E = Get_Draygon(cur_enemy_index); + CallDraygonFunc(E->draygon_var_A | 0xA50000, cur_enemy_index); +} + +void Draygon_Func_48(uint16 k) { // 0xA5C48D + if ((Get_Draygon(k)->base.frame_counter & 0x7F) == 0) { + Enemy_Draygon *E1 = Get_Draygon(0x40u); + R18_ = E1->base.x_pos - 24; + R20_ = E1->base.y_pos - 32; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x18u); + } + Enemy_Draygon *E0 = Get_Draygon(0); + R18_ = E0->base.x_pos - 24; + R18_ = samus_x_pos - R18_; + R20_ = E0->base.y_pos - 32; + R20_ = samus_y_pos - R20_; + uint16 v4 = CalculateAngleFromXY(); + Enemy_Draygon *E = Get_Draygon(cur_enemy_index); + if (v4 != E->draygon_var_F) { + uint16 v6 = addr_kDraygon_Ilist_99BA; + if (!sign16(v4 - 32)) { + v6 = addr_kDraygon_Ilist_99B4; + if (!sign16(v4 - 96)) { + v6 = addr_kDraygon_Ilist_99C0; + if (!sign16(v4 - 160)) { + v6 = addr_kDraygon_Ilist_99AE; + if (!sign16(v4 - 224)) + v6 = addr_kDraygon_Ilist_99BA; + } + } + } + E->draygon_var_F = v4; + E->base.current_instruction = v6; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void Draygon_Func_49(uint16 k) { // 0xA5C513 + Enemy_Draygon *E0 = Get_Draygon(0); + + if ((Get_Draygon(k)->base.frame_counter & 0x7F) == 0) { + R18_ = E0->base.x_pos + 24; + R20_ = E0->base.y_pos - 32; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x18u); + } + + R18_ = E0->base.x_pos + 24; + R18_ = samus_x_pos - R18_; + R20_ = E0->base.y_pos - 32; + R20_ = samus_y_pos - R20_; + uint16 v4 = CalculateAngleFromXY(); + Enemy_Draygon *E = Get_Draygon(cur_enemy_index); + if (v4 != E->draygon_var_F) { + uint16 v6 = addr_kDraygon_Ilist_9D5C; + if (!sign16(v4 - 32)) { + v6 = addr_kDraygon_Ilist_9D50; + if (!sign16(v4 - 96)) { + v6 = addr_kDraygon_Ilist_9D62; + if (!sign16(v4 - 160)) { + v6 = addr_kDraygon_Ilist_9D56; + if (!sign16(v4 - 224)) + v6 = addr_kDraygon_Ilist_9D5C; + } + } + } + E->draygon_var_F = v4; + E->base.current_instruction = v6; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void DraygonsTail_Init(void) { // 0xA5C599 + EnemyData *v0 = gEnemyData(cur_enemy_index); + v0->current_instruction = addr_kDraygon_Ilist_99FC; + v0->palette_index = 3584; +} + +void DraygonsArms_Init(void) { // 0xA5C5AD + EnemyData *v0 = gEnemyData(cur_enemy_index); + v0->current_instruction = addr_kDraygon_Ilist_97E7; + v0->palette_index = 3584; + v0->layer = 2; +} + +uint16 Draygon_Instr_25(uint16 k, uint16 j) { // 0xA5E75F + Enemy_Draygon *E = Get_Draygon(0); + if (sign16(E->draygon_var_0B - 40)) + E->draygon_var_0B += 8; + return j; +} + +uint16 Draygon_Instr_24(uint16 k, uint16 j) { // 0xA5E771 + Get_Draygon(0)->draygon_var_2F = 0; + return j; +} + +void Draygon_Func_50(uint16 j) { // 0xA5E811 + uint8 *v1 = RomPtr_A5(j); + Enemy_Draygon *E = Get_Draygon(0); + E->draygon_var_0B = *(uint16 *)v1; + E->draygon_var_0C = *((uint16 *)v1 + 1); + E->draygon_var_0A = *((uint16 *)v1 + 2); +} + +uint16 Draygon_Instr_21(uint16 k, uint16 j) { // 0xA5E82D + uint8 *v2 = RomPtr_A5(j); + Enemy_Draygon *E = Get_Draygon(0); + E->draygon_var_0B = *(uint16 *)v2; + E->draygon_var_0C = *((uint16 *)v2 + 1); + return j + 4; +} + +void Draygon_Func_51(uint16 j) { // 0xA5E840 + uint16 v1 = *(uint16 *)RomPtr_A5(j); + Get_Draygon(0)->draygon_var_0B = v1; +} + +void Draygon_Func_52(uint16 j) { // 0xA5E84A + uint16 v1 = *(uint16 *)RomPtr_A5(j); + Get_Draygon(0)->draygon_var_0C = v1; +} + +uint16 Draygon_Instr_53(uint16 k, uint16 j) { // 0xA5E854 + Enemy_Draygon *E = Get_Draygon(0); + E->draygon_var_0B += *(uint16 *)RomPtr_A5(j); + return j + 2; +} + +uint16 Draygon_Instr_54(uint16 k, uint16 j) { // 0xA5E863 + Enemy_Draygon *E = Get_Draygon(0); + E->draygon_var_0C += *(uint16 *)RomPtr_A5(j); + return j + 2; +} + +uint16 Draygon_Instr_22(uint16 k, uint16 j) { // 0xA5E872 + kraid_unk9000 = *(uint16 *)RomPtr_A5(j); + return j + 2; +} + +uint16 Draygon_Instr_27(uint16 k, uint16 j) { // 0xA5E87C + Enemy_Draygon *E = Get_Draygon(0); + E->base.x_pos = 128; + E->base.y_pos = 624; + E->base.properties = E->base.properties & 0x5BFF | 0xA000; + return j; +} + +uint16 Draygon_Instr_23(uint16 k, uint16 j) { // 0xA5E895 + uint16 *v2 = (uint16 *)RomPtr_A5(j); + QueueSfx2_Max6(*v2); + return j + 2; +} + +uint16 Draygon_Instr_55(uint16 k, uint16 j) { // 0xA5E8A3 + uint16 *v2 = (uint16 *)RomPtr_A5(j); + QueueSfx3_Max6(*v2); + return j + 2; +} + +uint16 Draygon_Instr_30(uint16 k, uint16 j) { // 0xA5E8B1 + Enemy_ItemDrop_SporeSpawn(k); + return j; +} + +uint16 Draygon_Instr_20(uint16 k, uint16 j) { // 0xA5E8BA + uint16 v2 = *(uint16 *)RomPtr_A5(j); + Get_Draygon(cur_enemy_index)->draygon_var_A = v2; + return j + 2; +} + +uint16 Draygon_Instr_29(uint16 k, uint16 j) { // 0xA5E8CA + uint16 m; + uint16 n; + + R18_ = j; + uint16 v2 = *(uint16 *)RomPtr_A5(j); + for (int i = 0; i != 32; i += 2) { + palette_buffer[(i >> 1) + 144] = g_word_A5E3F9[v2 >> 1]; + v2 += 2; + } + uint16 v4 = *(uint16 *)RomPtr_A5(R18_); + for (m = 0; m != 32; m += 2) { + palette_buffer[(m >> 1) + 64] = g_word_A5E4F9[v4 >> 1]; + v4 += 2; + } + uint16 v6 = *(uint16 *)RomPtr_A5(R18_); + for (n = 0; n != 32; n += 2) { + palette_buffer[(n >> 1) + 112] = g_word_A5E5D9[v6 >> 1]; + v6 += 2; + } + return j + 2; +} + +uint16 Draygon_Instr_19(uint16 k, uint16 j) { // 0xA5E91C + uint16 m; + uint16 n; + + R18_ = j; + uint16 v2 = *(uint16 *)RomPtr_A5(j); + for (int i = 0; i != 32; i += 2) { + target_palettes[(i >> 1) + 144] = g_word_A5E3F9[v2 >> 1]; + v2 += 2; + } + uint16 v4 = *(uint16 *)RomPtr_A5(R18_); + for (m = 0; m != 32; m += 2) { + target_palettes[(m >> 1) + 64] = g_word_A5E4F9[v4 >> 1]; + v4 += 2; + } + uint16 v6 = *(uint16 *)RomPtr_A5(R18_); + for (n = 0; n != 32; n += 2) { + target_palettes[(n >> 1) + 112] = g_word_A5E5D9[v6 >> 1]; + v6 += 2; + } + return j + 2; +} + +uint16 Draygon_Instr_28(uint16 k, uint16 j) { // 0xA5E96E + NextRandom(); + R18_ = (random_number & 0x7F) - 64; + Enemy_Draygon *E = Get_Draygon(0); + R18_ += E->base.x_pos; + R20_ = ((uint16)(random_number & 0x7F00) >> 8) - 64; + R20_ += E->base.y_pos; + SpawnEnemyProjectileWithRoomGfx(0xE509u, 0x15u); + QueueSfx2_Max6(0x29u); + return j; +} + +uint16 Draygon_Instr_26(uint16 k, uint16 j) { // 0xA5E9B1 + NextRandom(); + R18_ = (random_number & 0x7F) - 64; + Enemy_Draygon *E = Get_Draygon(0); + R18_ += E->base.x_pos; + R20_ = ((uint16)(random_number & 0x3F00) >> 8) - 32; + R20_ += E->base.y_pos; + R22_ = 3; + R24_ = 0; + CreateSpriteAtPos(); + QueueSfx2_Max6(0x25u); + return j; +} + +void sub_A5E9F5(void) { // 0xA5E9F5 + if ((nmi_frame_counter_word & 0xF) == 0) { + NextRandom(); + R18_ = (random_number & 0x3F) + 96; + R20_ = ((uint16)(random_number & 0xF00) >> 8) + 480; + R22_ = 21; + R24_ = 0; + CreateSpriteAtPos(); + } +} + +void SporeSpawn_Init(void) { // 0xA5EA2A + static const SpawnHardcodedPlmArgs unk_A5EAB7 = { 0x07, 0x1e, 0xb793 }; + + uint16 v0 = 0; + for (int i = 0; i != 32; i += 2) { + target_palettes[(i >> 1) + 240] = kSporeSpawn_Palette[v0 >> 1]; + v0 += 2; + } + SpawnEnemyProjectileWithGfx(0, cur_enemy_index, addr_kEproj_SporeSpawnsStalk); + SpawnEnemyProjectileWithGfx(1u, cur_enemy_index, addr_kEproj_SporeSpawnsStalk); + SpawnEnemyProjectileWithGfx(2u, cur_enemy_index, addr_kEproj_SporeSpawnsStalk); + SpawnEnemyProjectileWithGfx(3u, cur_enemy_index, addr_kEproj_SporeSpawnsStalk); + Enemy_SporeSpawn *E = Get_SporeSpawn(cur_enemy_index); + Enemy_SporeSpawn *E0 = Get_SporeSpawn(0); + E->ssn_var_04 = E->base.x_pos; + E->ssn_var_05 = E->base.y_pos - 72; + E->ssn_var_C = E->base.x_pos; + E->ssn_var_D = E->base.y_pos; + E->ssn_var_F = 0; + if ((boss_bits_for_area[area_index] & 2) != 0) { + E0->base.current_instruction = addr_kDraygon_Ilist_E6B9; + E0->ssn_var_A = FUNC16(nullsub_223); + E0->base.properties |= 0x8000u; + SporeSpawn_Func_5(); + SpawnHardcodedPlm(&unk_A5EAB7); + scrolling_finished_hook = 0; + } else { + E0->base.current_instruction = addr_kDraygon_Ilist_E6C7; + flag_process_all_enemies = -1; + uint16 v5 = cur_enemy_index; + E->ssn_var_A = FUNC16(nullsub_223); + scrolling_finished_hook = FUNC16(Samus_ScrollFinishedHook_SporeSpawnFight); + E->base.y_pos -= 128; + SpawnEnemyProjectileWithGfx(0, v5, addr_kEproj_SporeSpawners); + SpawnEnemyProjectileWithGfx(1u, v5, addr_kEproj_SporeSpawners); + SpawnEnemyProjectileWithGfx(2u, v5, addr_kEproj_SporeSpawners); + SpawnEnemyProjectileWithGfx(3u, v5, addr_kEproj_SporeSpawners); + SporeSpawn_Func_5(); + } +} + +void CallSporeSpawnFunc(uint32 ea) { + switch (ea) { + case fnnullsub_223: return; + case fnSporeSpawn_Func_1: SporeSpawn_Func_1(); return; + case fnSporeSpawn_Func_2: SporeSpawn_Func_2(cur_enemy_index); return; + case fnSporeSpawn_Func_3: SporeSpawn_Func_3(); return; + case fnSporeSpawn_Func_4: SporeSpawn_Func_4(); return; + default: Unreachable(); + } +} + +void SporeSpawn_Main(void) { // 0xA5EB13 + Enemy_SporeSpawn *E = Get_SporeSpawn(cur_enemy_index); + CallSporeSpawnFunc(E->ssn_var_A | 0xA50000); +} + +void SporeSpawn_Func_1(void) { // 0xA5EB1B + SporeSpawn_Func_5(); + Enemy_SporeSpawn *E = Get_SporeSpawn(cur_enemy_index); + uint16 v1 = E->base.y_pos + 1; + E->base.y_pos = v1; + if (!sign16(v1 - 624)) { + E->base.current_instruction = addr_kDraygon_Ilist_E6D5; + E->base.instruction_timer = 1; + } + Enemy_SporeSpawn *E0 = Get_SporeSpawn(0); + E0->ssn_var_0B = 48; + E0->ssn_var_0C = 1; + E0->ssn_var_0A = 192; +} + +void SporeSpawn_Func_2(uint16 k) { // 0xA5EB52 + SporeSpawn_Func_5(); + Enemy_SporeSpawn *E0 = Get_SporeSpawn(0); + draw_enemy_layer = E0->ssn_var_0B; + uint16 v2 = CosineMult8bit(E0->ssn_var_0A); + Enemy_SporeSpawn *E = Get_SporeSpawn(k); + E->base.x_pos = E->ssn_var_C + v2; + draw_enemy_layer = E0->ssn_var_0B - 16; + E->base.y_pos = E->ssn_var_D + SineMult8bitNegative(2 * (E0->ssn_var_0A - 64)); + E0->ssn_var_0A = (uint8)(LOBYTE(E0->ssn_var_0C) + E0->ssn_var_0A); +} + +void SporeSpawn_Func_3(void) { // 0xA5EB9B + Enemy_SporeSpawn *E0 = Get_SporeSpawn(0); + R18_ = 128 - E0->base.x_pos; + R20_ = 624 - E0->base.y_pos; + E0->ssn_var_43 = (uint8)(64 - CalculateAngleFromXY()); + R20_ = 1; + R18_ = LOBYTE(E0->ssn_var_43); + ConvertAngleToXy(); + Enemy_SporeSpawn *E = Get_SporeSpawn(cur_enemy_index); + E->ssn_var_28 = R22_; + E->ssn_var_29 = R24_; + E->ssn_var_2A = R26_; + E->ssn_var_2B = R28_; +} + +void SporeSpawn_Func_4(void) { // 0xA5EBEE + Enemy_SporeSpawn *E = Get_SporeSpawn(cur_enemy_index); + varE24 = E->ssn_var_28; + varE26 = E->ssn_var_29; + varE28 = E->ssn_var_2A; + varE2A = E->ssn_var_2B; + Enemy_SporeSpawn *E0 = Get_SporeSpawn(0); + enemy_population_ptr = LOBYTE(E0->ssn_var_43); + EnemyFunc_B691(); + uint16 v2 = Abs16(E0->base.x_pos - 128); + if (sign16(v2 - 8)) { + uint16 v3 = Abs16(E0->base.y_pos - 624); + if (sign16(v3 - 8)) + E0->ssn_var_A = FUNC16(nullsub_223); + } + SporeSpawn_Func_5(); + sub_A5E9F5(); +} + +void SporeSpawn_Func_5(void) { // 0xA5EC49 + Enemy_SporeSpawn *E = Get_SporeSpawn(0); + uint16 v1 = E->base.x_pos - E->ssn_var_04, v2; + if ((v1 & 0x8000u) == 0) { + R18_ = v1 >> 1; + R20_ = v1 >> 2; + R22_ = (v1 >> 1) + (v1 >> 2); + enemy_projectile_x_pos[14] = 128; + enemy_projectile_x_pos[15] = E->ssn_var_04 + (v1 >> 2); + E->ssn_var_20 = enemy_projectile_x_pos[15]; + enemy_projectile_x_pos[16] = E->ssn_var_04 + R18_; + E->ssn_var_21 = enemy_projectile_x_pos[16]; + v2 = E->ssn_var_04 + R22_; + } else { + R18_ = (uint16)(E->ssn_var_04 - E->base.x_pos) >> 1; + R20_ = (uint16)-v1 >> 2; + R22_ = R18_ + R20_; + enemy_projectile_x_pos[14] = 128; + enemy_projectile_x_pos[15] = E->ssn_var_04 - R20_; + E->ssn_var_20 = enemy_projectile_x_pos[15]; + enemy_projectile_x_pos[16] = E->ssn_var_04 - R18_; + E->ssn_var_21 = enemy_projectile_x_pos[16]; + v2 = E->ssn_var_04 - R22_; + } + enemy_projectile_x_pos[17] = v2; + E->ssn_var_22 = v2; + uint16 v3 = E->base.y_pos - 40 - E->ssn_var_05, v4; + if ((v3 & 0x8000u) == 0) { + R18_ = v3 >> 1; + R20_ = v3 >> 2; + R22_ = (v3 >> 1) + (v3 >> 2); + enemy_projectile_y_pos[14] = 560; + enemy_projectile_y_pos[15] = E->ssn_var_05 + (v3 >> 2); + E->ssn_var_23 = enemy_projectile_y_pos[15]; + enemy_projectile_y_pos[16] = E->ssn_var_05 + R18_; + E->ssn_var_24 = enemy_projectile_y_pos[16]; + v4 = E->ssn_var_05 + R22_; + } else { + R18_ = (uint16)(E->ssn_var_05 - (E->base.y_pos - 40)) >> 1; + R20_ = (uint16)-v3 >> 2; + R22_ = R18_ + R20_; + enemy_projectile_y_pos[14] = 560; + enemy_projectile_y_pos[15] = E->ssn_var_05 - R20_; + E->ssn_var_23 = enemy_projectile_y_pos[15]; + enemy_projectile_y_pos[16] = E->ssn_var_05 - R18_; + E->ssn_var_24 = enemy_projectile_y_pos[16]; + v4 = E->ssn_var_05 - R22_; + } + enemy_projectile_y_pos[17] = v4; + E->ssn_var_25 = v4; +} + +void SporeSpawn_Shot(void) { // 0xA5ED5A + int16 v4; + + uint16 v0 = 2 * collision_detection_index; + uint16 v1 = projectile_type[collision_detection_index]; + if ((v1 & 0x700) != 0 || (v1 & 0x10) != 0) { + EnemyFunc_A6B4_UsedBySporeSpawn(); + v0 = cur_enemy_index; + Enemy_SporeSpawn *EK = Get_SporeSpawn(v0); + if (EK->base.flash_timer) { + Enemy_SporeSpawn *E = Get_SporeSpawn(0); + EK->ssn_var_A = FUNC16(SporeSpawn_Func_2); + v4 = 2; + if (sign16(EK->base.health - 400)) { + if ((E->ssn_var_0C & 0x8000u) != 0) + v4 = -2; + E->ssn_var_0C = v4; + } + if (!E->ssn_var_2F) { + E->ssn_var_0C = -E->ssn_var_0C; + E->ssn_var_2F = 1; + EK->base.current_instruction = addr_stru_A5E729; + EK->base.instruction_timer = 1; + uint16 v7 = 96; + uint16 health = EK->base.health; + if (!sign16(health - 70)) { + v7 = 64; + if (!sign16(health - 410)) { + v7 = 32; + if (!sign16(health - 770)) + v7 = 0; + } + } + if (health != E->ssn_var_40) { + E->ssn_var_40 = health; + SporeSpawn_Func_7(v7); + } + } + } + SporeSpawn_Func_6(); + } +} + +void SporeSpawn_Touch(void) { // 0xA5EDEC + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); + SporeSpawn_Func_6(); +} + +void SporeSpawn_Func_6(void) { // 0xA5EDF3 + static const SpawnHardcodedPlmArgs unk_A5EE45 = { 0x07, 0x1e, 0xb78f }; + + if (!Get_SporeSpawn(cur_enemy_index)->base.health) { + Enemy_SporeSpawn *E = Get_SporeSpawn(cur_enemy_index); + Enemy_SporeSpawn *E0 = Get_SporeSpawn(0); + E0->ssn_var_0E = 0; + E->base.invincibility_timer = 0; + E->base.flash_timer = 0; + E->base.ai_handler_bits = 0; + E->base.properties |= kEnemyProps_Tangible; + for (int i = 26; i >= 0; i -= 2) + *(uint16 *)((char *)enemy_projectile_id + (uint16)i) = 0; + E0->base.current_instruction = addr_kDraygon_Ilist_E77D; + E0->base.instruction_timer = 1; + *(uint16 *)&boss_bits_for_area[area_index] |= 2u; + scrolling_finished_hook = 0; + SpawnHardcodedPlm(&unk_A5EE45); + } +} + +void SporeSpawn_Func_7(uint16 a) { // 0xA5EE4A + R18_ = a; + uint16 v1 = a; + for (int i = 0; i != 32; i += 2) { + palette_buffer[(i >> 1) + 144] = g_word_A5E379[v1 >> 1]; + v1 += 2; + } +} diff --git a/src/sm_a6.c b/src/sm_a6.c new file mode 100644 index 0000000..81c45f4 --- /dev/null +++ b/src/sm_a6.c @@ -0,0 +1,5412 @@ +// Enemy AI - inc. Ridley & zebetites +#include "ida_types.h" +#include "variables.h" +#include "sm_rtl.h" +#include "funcs.h" +#include "enemy_types.h" + +int BabyMetroid_DBCB_DoubleRetEx(uint16 a); +uint8 Ridley_Func_40_Carry(); +uint8 Ridley_Func_40_Sign(); + +static const uint16 g_word_A686F1[2] = { 0x1000, 0x1800 }; +static const uint16 g_word_A68DBB = 5; +static const uint16 g_word_A68DBD = 0xa; +static const uint16 g_word_A68DBF = 0xf; +static const uint16 g_word_A68DC1 = 0x14; +static const uint16 g_word_A68DC3 = 0x19; +static const uint16 g_word_A68DC5 = 0x1e; +static const uint16 g_word_A68DC7 = 0x23; +static const uint16 g_word_A68DC9 = 0x28; +static const uint16 g_word_A68DCB = 0x2d; +static const uint16 g_word_A68DCD = 0x32; +static const uint16 g_word_A68DCF = 0x37; +static const uint16 g_word_A68DD1 = 0x3c; +static const uint16 g_word_A68DD3 = 0x41; +static const uint16 g_word_A68DD5 = 0x46; +static const uint16 g_word_A68DD7 = 0x4b; +static const uint16 g_word_A68DD9 = 0x50; +static const uint16 g_word_A68DDB = 0x55; +static const uint16 g_word_A68DDD = 0x5a; +static const uint16 g_word_A68DDF = 0x5f; +static const uint16 g_word_A68DE1 = 0x64; +static const uint16 g_word_A68DE3 = 0x69; +static const uint16 g_word_A68DE5 = 0x6e; +static const uint16 g_word_A68DE7 = 0x18; +static const uint16 g_word_A68DE9 = 0x18; +static const uint16 g_word_A68DEB = 0x18; +static const uint16 g_word_A68DED = 0x18; +static const uint16 g_word_A68DEF = 0x18; +static const uint16 g_word_A68DF1 = 0x18; +static const uint16 g_word_A68DF3 = 0x18; +static const uint16 g_word_A68DF5 = 0x18; +static const uint16 g_word_A68DF7 = 0x18; +static const uint16 g_word_A68DF9 = 0x18; +static const uint16 g_word_A68DFB = 0x18; +static const uint16 g_word_A68DFD = 0x18; +static const uint16 g_word_A68DFF = 0x18; +static const uint16 g_word_A68E01 = 0x18; +static const uint16 g_word_A68E03 = 0x18; +static const uint16 g_word_A68E05 = 0x18; +static const uint16 g_word_A68E07 = 0x18; +static const uint16 g_word_A68E09 = 0x18; +static const uint16 g_word_A68E0B = 0x14; +static const uint16 g_word_A68E0D = 0x10; +static const uint16 g_word_A68E0F = 0xc; +static const uint16 g_word_A68E11 = 8; +static const uint16 g_word_A695F6[4] = { 0x190, 0xf0, 0xf0, 0x190 }; +static const uint16 g_word_A695FE[4] = { 0xffe8, 0xfff4, 0x18, 0xc }; +static const uint16 g_word_A69606[4] = { 0x180, 0x100, 0x100, 0x180 }; +static const uint16 g_word_A69A48[8] = { 0xfe00, 0xfb00, 0xfc00, 0xfb00, 0x200, 0xfb00, 0x400, 0xfb00 }; + +#define g_byte_A6E269 ((uint8*)RomPtr(0xa6e269)) +#define g_word_A6E2AA ((uint16*)RomPtr(0xa6e2aa)) +#define g_word_A6E30A ((uint16*)RomPtr(0xa6e30a)) +#define g_word_A6E46A ((uint16*)RomPtr(0xa6e46a)) +#define g_off_A6A4EB ((uint16*)RomPtr(0xa6a4eb)) +#define g_off_A6A743 ((uint16*)RomPtr(0xa6a743)) +#define g_word_A6AE4D ((uint16*)RomPtr(0xa6ae4d)) +#define g_word_A6AF2F ((uint16*)RomPtr(0xa6af2f)) +#define g_word_A6B00F ((uint16*)RomPtr(0xa6b00f)) +#define g_off_A6ACDA ((uint16*)RomPtr(0xa6acda)) +#define g_off_A6AD45 ((uint16*)RomPtr(0xa6ad45)) +static const uint16 g_word_A6B288 = 8; +#define g_word_A6B60D ((uint16*)RomPtr(0xa6b60d)) +#define g_word_A6B63B ((uint16*)RomPtr(0xa6b63b)) +#define g_word_A6B6C8 ((uint16*)RomPtr(0xa6b6c8)) +#define g_word_A6B9D5 ((uint16*)RomPtr(0xa6b9d5)) +#define g_word_A6B9DB ((uint16*)RomPtr(0xa6b9db)) +#define g_off_A6B965 ((uint16*)RomPtr(0xa6b965)) +#define g_off_A6B96D ((uint16*)RomPtr(0xa6b96d)) +#define g_word_A6B9D5 ((uint16*)RomPtr(0xa6b9d5)) +#define g_word_A6B9DB ((uint16*)RomPtr(0xa6b9db)) +#define g_word_A6B94D ((uint16*)RomPtr(0xa6b94d)) +#define g_word_A6B959 ((uint16*)RomPtr(0xa6b959)) +#define g_word_A6BB48 ((uint16*)RomPtr(0xa6bb48)) +#define g_word_A6BB4E ((uint16*)RomPtr(0xa6bb4e)) +static const uint16 g_word_A6BBEB[3] = { 0x40, 0, 0xd0 }; +static const uint16 g_word_A6BC62[3] = { 0xb0, 0, 0x50 }; +#define g_word_A6C1DF ((uint16*)RomPtr(0xa6c1df)) +static const int16 g_word_A6C66E[20] = { -24, -24, -20, 20, 16, -30, 30, -3, 14, -13, -2, 18, -2, -32, -31, 8, -4, -10, 19, 19 }; +#define g_off_A6C7BA ((uint16*)RomPtr(0xa6c7ba)) +#define g_word_A6C804 ((uint16*)RomPtr(0xa6c804)) +#define g_off_A6C808 ((uint16*)RomPtr(0xa6c808)) +#define g_word_A6C836 ((uint16*)RomPtr(0xa6c836)) +#define g_off_A6C83A ((uint16*)RomPtr(0xa6c83a)) +#define g_word_A6C868 ((uint16*)RomPtr(0xa6c868)) +#define g_off_A6C86C ((uint16*)RomPtr(0xa6c86c)) +#define g_word_A6C89A ((uint16*)RomPtr(0xa6c89a)) +#define g_off_A6C89E ((uint16*)RomPtr(0xa6c89e)) +#define g_word_A6C8CC ((uint16*)RomPtr(0xa6c8cc)) +#define g_off_A6C8D0 ((uint16*)RomPtr(0xa6c8d0)) +#define g_word_A6C6CE ((uint16*)RomPtr(0xa6c6ce)) +#define g_off_A6C6E6 ((uint16*)RomPtr(0xa6c6e6)) +#define g_word_A6CC12 ((uint16*)RomPtr(0xa6cc12)) +#define g_word_A6CC18 ((uint16*)RomPtr(0xa6cc18)) +static const int16 g_word_A6CF54[3] = { 0x20, 0, -0x20 }; +static const uint8 g_byte_A6D61F[16] = { 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; +static const uint8 g_byte_A6D712[16] = { 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; +static const uint16 g_word_A6D9ED[8] = { 0xc, 0xe, 0x10, 0x12, 0x1c, 0x20, 0x28, 0x30 }; +#define g_off_A6DB02 ((uint16*)RomPtr(0xa6db02)) +#define kRidley_Ilist_DCBA ((uint16*)RomPtr(0xa6dcba)) +#define g_off_A6EFF5 ((uint16*)RomPtr(0xa6eff5)) +#define g_off_A6F001 ((uint16*)RomPtr(0xa6f001)) +#define g_off_A6F72B ((uint16*)RomPtr(0xa6f72b)) +#define g_off_A6F52C ((uint16*)RomPtr(0xa6f52c)) +#define g_word_A6F840 ((uint16*)RomPtr(0xa6f840)) +#define g_off_A6F900 ((uint16*)RomPtr(0xa6f900)) +#define g_word_A6FC03 ((uint16*)RomPtr(0xa6fc03)) +#define g_word_A6FC0B ((uint16*)RomPtr(0xa6fc0b)) +#define g_off_A6FC13 ((uint16*)RomPtr(0xa6fc13)) +#define g_word_A6FC1B ((uint16*)RomPtr(0xa6fc1b)) +#define g_word_A6FC23 ((uint16*)RomPtr(0xa6fc23)) +#define g_word_A6FC2B ((uint16*)RomPtr(0xa6fc2b)) +#define g_off_A6FD4A ((uint16*)RomPtr(0xa6fd4a)) +#define g_off_A6FD54 ((uint16*)RomPtr(0xa6fd54)) + +uint16 EnemyInstr_Sleep_A6(uint16 k, uint16 j) { // 0xA6812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + +void Enemy_GrappleReact_NoInteract_A6(void) { // 0xA68000 + SwitchEnemyAiToMainAi(); +} + +void Enemy_GrappleReact_CancelBeam_A6(void) { // 0xA6800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_NormalTouchAI_A6(void) { // 0xA68023 + NormalEnemyTouchAi(); +} + +void Enemy_NormalShotAI_A6(void) { // 0xA6802D + NormalEnemyShotAi(); +} + +void Enemy_NormalFrozenAI_A6(void) { // 0xA68041 + NormalEnemyFrozenAI(); +} + +uint16 EnemyInstr_Goto_A6(uint16 k, uint16 j) { // 0xA680ED + return *(uint16 *)RomPtr_A6(j); +} + + +void Boulder_Init(void) { // 0xA686F5 + int16 boulder_parameter_2_high; + + Enemy_Boulder *E = Get_Boulder(cur_enemy_index); + E->boulder_var_C = 0; + E->boulder_var_B = 0; + E->boulder_var_D = 2; + E->boulder_var_A = FUNC16(Boulder_Func_1); + E->boulder_var_04 = E->base.x_pos; + uint16 y_pos = E->base.y_pos; + E->boulder_var_05 = y_pos; + E->boulder_var_03 = y_pos; + E->boulder_var_02 = E->base.y_subpos; + boulder_parameter_2_high = HIBYTE(E->boulder_parameter_2); + if (!HIBYTE(E->boulder_parameter_2)) { + boulder_parameter_2_high = 1; + E->boulder_var_07 = 1; + } + E->base.y_pos = E->boulder_var_05 - boulder_parameter_2_high; + E->boulder_var_00 = -LOBYTE(E->boulder_parameter_2); + E->boulder_var_06 = LOBYTE(E->base.current_instruction); + E->base.current_instruction = addr_kBoulder_Ilist_86A7; + uint16 boulder_parameter_1_high = HIBYTE(E->boulder_parameter_1); + E->boulder_var_E = boulder_parameter_1_high; + if (!boulder_parameter_1_high) { + E->boulder_var_00 = -E->boulder_var_00; + E->base.current_instruction = addr_kBoulder_Ilist_86CB; + } + E->boulder_var_01 = 2; + if (LOBYTE(E->boulder_parameter_1)) + E->boulder_var_01 = 5; +} + +void CallBoulderFunc(uint32 ea) { + switch (ea) { + case fnBoulder_Func_1: Boulder_Func_1(); return; + case fnBoulder_Func_2: Boulder_Func_2(); return; + case fnBoulder_Func_3: Boulder_Func_3(); return; + case fnBoulder_Func_4: Boulder_Func_4(); return; + case fnBoulder_Func_5: Boulder_Func_5(); return; + case fnBoulder_Func_6: Boulder_Func_6(); return; + default: Unreachable(); + } +} + +void Boulder_Main(void) { // 0xA68793 + Enemy_Boulder *E = Get_Boulder(cur_enemy_index); + CallBoulderFunc(E->boulder_var_A | 0xA60000); +} + +void Boulder_Func_1(void) { // 0xA6879A + int16 SamusEnemyDelta_Y; + int16 v3; + int16 SamusEnemyDelta_X; + + SamusEnemyDelta_Y = GetSamusEnemyDelta_Y(cur_enemy_index); + if (SamusEnemyDelta_Y >= 0) { + Enemy_Boulder *E = Get_Boulder(cur_enemy_index); + if ((int16)(SamusEnemyDelta_Y - E->boulder_var_06) < 0) { + if (E->boulder_var_E) { + SamusEnemyDelta_X = GetSamusEnemyDelta_X(cur_enemy_index); + if (SamusEnemyDelta_X < 0 && (int16)(SamusEnemyDelta_X - E->boulder_var_00) >= 0) { + E->boulder_var_A = FUNC16(Boulder_Func_2); + if (E->boulder_var_07) + E->boulder_var_A = FUNC16(Boulder_Func_5); + } + } else { + v3 = GetSamusEnemyDelta_X(cur_enemy_index); + if (v3 >= 0 && (int16)(v3 - E->boulder_var_00) < 0) { + E->boulder_var_A = FUNC16(Boulder_Func_2); + if (E->boulder_var_07) + E->boulder_var_A = FUNC16(Boulder_Func_5); + } + } + } + } +} + +void Boulder_Func_2(void) { // 0xA687ED + Enemy_Boulder *E = Get_Boulder(cur_enemy_index); + Boulder_Func_9(8 * HIBYTE(E->boulder_var_C)); + if ((int16)(E->base.y_pos - E->boulder_var_05) < 0) { + uint16 v1 = E->boulder_var_C + 256; + E->boulder_var_C = v1; + if (!sign16(v1 - 20480)) + E->boulder_var_C = 20480; + } else { + E->base.y_pos = E->boulder_var_05; + E->boulder_var_A = FUNC16(Boulder_Func_3); + E->boulder_var_C = 0x2000; + } +} + +void Boulder_Func_3(void) { // 0xA68832 + int16 v1; + + Enemy_Boulder *E = Get_Boulder(cur_enemy_index); + Boulder_Func_9(8 * HIBYTE(E->boulder_var_C) + 4); + v1 = E->boulder_var_C - 256; + E->boulder_var_C = v1; + if (v1 >= 0) { + uint16 v2 = 8 * HIBYTE(E->boulder_var_B); + if (E->boulder_var_E) + v2 += 4; + Boulder_Func_7(v2); + uint16 v3 = E->boulder_var_B + 32; + E->boulder_var_B = v3; + if (!sign16(v3 - 20480)) + E->boulder_var_B = 20480; + } else { + E->boulder_var_C = 0; + E->boulder_var_A = FUNC16(Boulder_Func_4); + } +} + +void Boulder_Func_4(void) { // 0xA6888B + Enemy_Boulder *E = Get_Boulder(cur_enemy_index); + int v1 = (uint16)(8 * HIBYTE(E->boulder_var_C)) >> 1; + R18_ = kCommonEnemySpeeds_Quadratic[v1]; + R20_ = kCommonEnemySpeeds_Quadratic[v1 + 1]; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + QueueSfx2_Max6(0x42u); + if (E->boulder_var_E == 2) { + E->base.properties |= kEnemyProps_Deleted; + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x11u); + QueueSfx2_Max6(0x43u); + } else { + E->boulder_var_A = FUNC16(Boulder_Func_3); + E->boulder_var_C = g_word_A686F1[E->boulder_var_D - 1]; + if ((--E->boulder_var_D & 0x8000u) != 0) { + E->boulder_var_03 = E->base.y_pos; + E->boulder_var_02 = E->base.y_subpos; + E->boulder_var_A = FUNC16(Boulder_Func_5); + } + } + } else { + E->boulder_var_C += 256; + uint16 v3 = 8 * HIBYTE(E->boulder_var_B); + if (E->boulder_var_E) + v3 += 4; + Boulder_Func_7(v3); + uint16 v4 = E->boulder_var_B + 32; + E->boulder_var_B = v4; + if (!sign16(v4 - 20480)) + E->boulder_var_B = 20480; + } +} + +void Boulder_Func_5(void) { // 0xA68942 + Enemy_Boulder *E = Get_Boulder(cur_enemy_index); + uint16 v2 = 8 * HIBYTE(E->boulder_var_B); + int v3 = v2 >> 1; + R18_ = kCommonEnemySpeeds_Quadratic[v3]; + R20_ = E->boulder_var_01 + kCommonEnemySpeeds_Quadratic[v3 + 1]; + Enemy_MoveDown(cur_enemy_index); + E->base.y_pos -= E->boulder_var_01; + if (E->boulder_var_E) + v2 += 4; + int v4 = v2 >> 1; + R18_ = kCommonEnemySpeeds_Quadratic[v4]; + R20_ = kCommonEnemySpeeds_Quadratic[v4 + 1]; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->base.properties |= 0x300u; + E->boulder_var_A = FUNC16(Boulder_Func_6); + QueueSfx2_Max6(0x42u); + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x11u); + QueueSfx2_Max6(0x43u); + } else { + uint16 v5 = E->boulder_var_B + 64; + E->boulder_var_B = v5; + if (!sign16(v5 - 0x4000)) + E->boulder_var_B = 0x4000; + if (E->base.y_pos == E->boulder_var_03 && E->base.y_subpos == E->boulder_var_02) + E->boulder_var_01 = 0; + } + E->boulder_var_03 = E->base.y_pos; + E->boulder_var_02 = E->base.y_subpos; +} + +void Boulder_Func_6(void) { // 0xA689FC + ; +} + +void Boulder_Func_7(uint16 j) { // 0xA68A00 + Enemy_Boulder *E = Get_Boulder(cur_enemy_index); + uint16 x_subpos = E->base.x_subpos; + int v3 = j >> 1; + bool v4 = __CFADD__uint16(kCommonEnemySpeeds_Quadratic[v3], x_subpos); + uint16 v5 = kCommonEnemySpeeds_Quadratic[v3] + x_subpos; + if (v4) + ++E->base.x_pos; + E->base.x_subpos = v5; + E->base.x_pos += kCommonEnemySpeeds_Quadratic[v3 + 1]; +} + +void Boulder_Func_8(uint16 j) { // 0xA68A1D + Enemy_Boulder *E = Get_Boulder(cur_enemy_index); + uint16 x_subpos = E->base.x_subpos; + int v3 = j >> 1; + bool v4 = __CFADD__uint16(kCommonEnemySpeeds_Linear[v3 + 1], x_subpos); + uint16 v5 = kCommonEnemySpeeds_Linear[v3 + 1] + x_subpos; + if (v4) + ++E->base.x_pos; + E->base.x_subpos = v5; + E->base.x_pos += kCommonEnemySpeeds_Linear[v3]; +} + +void Boulder_Func_9(uint16 j) { // 0xA68A3A + Enemy_Boulder *E = Get_Boulder(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + int v3 = j >> 1; + bool v4 = __CFADD__uint16(kCommonEnemySpeeds_Quadratic[v3], y_subpos); + uint16 v5 = kCommonEnemySpeeds_Quadratic[v3] + y_subpos; + if (v4) + ++E->base.y_pos; + E->base.y_subpos = v5; + E->base.y_pos += kCommonEnemySpeeds_Quadratic[v3 + 1]; +} + + +void SpikeyPlatform_Init(void) { // 0xA68B2F + Enemy_SpikeyPlatform *E = Get_SpikeyPlatform(cur_enemy_index); + E->base.current_instruction = addr_kSpikeyPlatform_Ilist_8B29; + E->spm_var_A = FUNC16(SpikeyPlatform_Func_1); + uint16 v1 = 8 * LOBYTE(E->spm_parameter_1); + E->spm_var_02 = v1; + int v2 = v1 >> 1; + R18_ = kCommonEnemySpeeds_Linear[v2]; + R20_ = kCommonEnemySpeeds_Linear[v2 + 1]; + E->spm_var_E = R20_; + E->spm_var_F = R18_; + E->spm_var_D = E->base.y_pos + HIBYTE(E->spm_parameter_2); + E->spm_var_C = E->base.y_pos; + uint16 spm_parameter_2_low = LOBYTE(E->spm_parameter_2); + E->spm_var_00 = spm_parameter_2_low; + E->spm_var_B = spm_parameter_2_low; +} + +void SpikeyPlatform2ndEnemy_Init(void) { // 0xA68B85 + int v0 = cur_enemy_index >> 1; + EnemyData *v1 = gEnemyData(cur_enemy_index); + v1->x_pos = enemy_drawing_queue[v0 + 91]; + v1->y_pos = enemy_drawing_queue[v0 + 93] + 12; +} + +void SpikeyPlatform2ndEnemy_Main(void) { // 0xA68B99 + int v0 = cur_enemy_index >> 1; + EnemyData *v1 = gEnemyData(cur_enemy_index); + v1->x_pos = enemy_drawing_queue[v0 + 91]; + v1->y_pos = enemy_drawing_queue[v0 + 93] + 12; +} + +void CallSpikeyPlatformFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnSpikeyPlatform_Func_1: SpikeyPlatform_Func_1(); return; + case fnSpikeyPlatform_Func_2: SpikeyPlatform_Func_2(); return; + case fnSpikeyPlatform_Func_3: SpikeyPlatform_Func_3(k); return; + case fnSpikeyPlatform_Func_4: SpikeyPlatform_Func_4(); return; + default: Unreachable(); + } +} + +void SpikeyPlatform_Main(void) { // 0xA68BAD + Enemy_SpikeyPlatform *E = Get_SpikeyPlatform(cur_enemy_index); + CallSpikeyPlatformFunc(E->spm_var_A | 0xA60000, cur_enemy_index); +} + +void SpikeyPlatform_Func_1(void) { // 0xA68BB4 + Enemy_SpikeyPlatform *E = Get_SpikeyPlatform(cur_enemy_index); + if (!--E->spm_var_B) { + E->spm_var_B = E->spm_var_00; + E->spm_var_02 = 8 * LOBYTE(E->spm_parameter_1); + E->spm_var_A = FUNC16(SpikeyPlatform_Func_2); + } +} + +void SpikeyPlatform_Func_2(void) { // 0xA68BDC + int16 v4; + + Enemy_SpikeyPlatform *E = Get_SpikeyPlatform(cur_enemy_index); + E->spm_var_01 = E->base.y_pos; + int v1 = E->spm_var_02 >> 1; + R20_ = kCommonEnemySpeeds_Linear[v1]; + R18_ = kCommonEnemySpeeds_Linear[v1 + 1]; + Enemy_AddPos_Y(cur_enemy_index); + if ((int16)(E->base.y_pos - E->spm_var_D) >= 0) { + E->spm_var_03 = 64; + E->spm_var_A = FUNC16(SpikeyPlatform_Func_3); + E->base.y_pos = E->spm_var_D; + QueueSfx2_Max6(0x1Bu); + } + if (SpikeyPlatform_Func_5(cur_enemy_index)) + extra_samus_y_displacement += E->base.y_pos - E->spm_var_01; + v4 = E->spm_var_02 + 8; + if (!sign16(E->spm_var_02 - 504)) + v4 = 512; + E->spm_var_02 = v4; +} + +void SpikeyPlatform_Func_3(uint16 k) { // 0xA68C4A + Enemy_SpikeyPlatform *E = Get_SpikeyPlatform(k); + uint16 v2 = E->spm_var_03 - 1; + E->spm_var_03 = v2; + if (!v2) + E->spm_var_A = FUNC16(SpikeyPlatform_Func_4); +} + +void SpikeyPlatform_Func_4(void) { // 0xA68C5D + Enemy_SpikeyPlatform *E = Get_SpikeyPlatform(cur_enemy_index); + E->spm_var_01 = E->base.y_pos; + R18_ = FUNC16(Enemy_GrappleReact_NoInteract_A6); + R20_ = 0; + Enemy_SubPos_Y(cur_enemy_index); + if ((int16)(E->base.y_pos - E->spm_var_C) < 0) { + E->spm_var_A = FUNC16(SpikeyPlatform_Func_1); + E->base.y_pos = E->spm_var_C; + } + if (SpikeyPlatform_Func_5(cur_enemy_index)) + extra_samus_y_displacement += E->base.y_pos - E->spm_var_01; +} + +uint16 SpikeyPlatform_Func_5(uint16 k) { // 0xA68CA1 + Enemy_SpikeyPlatform *E = Get_SpikeyPlatform(k); + uint16 v2 = abs16(samus_x_pos - E->base.x_pos); + bool v3 = v2 < samus_x_radius; + uint16 v4 = v2 - samus_x_radius; + if (!v3 && v4 >= E->base.x_width) + return 0; + if ((int16)(samus_y_pos + 5 - E->base.y_pos) < 0) { + uint16 v6 = E->base.y_pos - (samus_y_pos + 5); + v3 = v6 < samus_y_radius; + uint16 v7 = v6 - samus_y_radius; + if (v3 || v7 == E->base.y_height || v7 < E->base.y_height) + return -1; + } + return 0; +} + +uint16 FireGeyser_Instr_1(uint16 k, uint16 j) { // 0xA68DAF + QueueSfx2_Max6(0x61u); + return j; +} + +uint16 FireGeyser_Instr_2(uint16 k, uint16 j) { // 0xA68E13 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DBB; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DE7; + E->base.x_width = 8; + return j; +} + +uint16 FireGeyser_Instr_3(uint16 k, uint16 j) { // 0xA68E2D + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DBD; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DE9; + return j; +} + +uint16 FireGeyser_Instr_4(uint16 k, uint16 j) { // 0xA68E41 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DBF; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DEB; + return j; +} + +uint16 FireGeyser_Instr_5(uint16 k, uint16 j) { // 0xA68E55 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DC1; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DED; + return j; +} + +uint16 FireGeyser_Instr_6(uint16 k, uint16 j) { // 0xA68E69 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DC3; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DEF; + return j; +} + +uint16 FireGeyser_Instr_7(uint16 k, uint16 j) { // 0xA68E7D + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DC5; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DF1; + return j; +} + +uint16 FireGeyser_Instr_8(uint16 k, uint16 j) { // 0xA68E91 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DC7; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DF3; + return j; +} + +uint16 FireGeyser_Instr_9(uint16 k, uint16 j) { // 0xA68EA5 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DC9; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DF5; + return j; +} + +uint16 FireGeyser_Instr_10(uint16 k, uint16 j) { // 0xA68EB9 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DCB; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DF7; + return j; +} + +uint16 FireGeyser_Instr_11(uint16 k, uint16 j) { // 0xA68ECD + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DCD; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DF9; + return j; +} + +uint16 FireGeyser_Instr_12(uint16 k, uint16 j) { // 0xA68EE1 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DCF; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DFB; + return j; +} + +uint16 FireGeyser_Instr_13(uint16 k, uint16 j) { // 0xA68EF5 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DD1; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DFD; + return j; +} + +uint16 FireGeyser_Instr_14(uint16 k, uint16 j) { // 0xA68F09 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DD3; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68DFF; + return j; +} + +uint16 FireGeyser_Instr_15(uint16 k, uint16 j) { // 0xA68F1D + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DD5; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68E01; + return j; +} + +uint16 FireGeyser_Instr_16(uint16 k, uint16 j) { // 0xA68F31 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DD7; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68E03; + return j; +} + +uint16 FireGeyser_Instr_17(uint16 k, uint16 j) { // 0xA68F45 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DD9; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68E05; + return j; +} + +uint16 FireGeyser_Instr_18(uint16 k, uint16 j) { // 0xA68F59 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DDB; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68E07; + return j; +} + +uint16 FireGeyser_Instr_19(uint16 k, uint16 j) { // 0xA68F6D + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DDD; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68E09; + return j; +} + +uint16 FireGeyser_Instr_20(uint16 k, uint16 j) { // 0xA68F81 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DDF; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68E0B; + return j; +} + +uint16 FireGeyser_Instr_21(uint16 k, uint16 j) { // 0xA68F95 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DE1; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68E0D; + return j; +} + +uint16 FireGeyser_Instr_22(uint16 k, uint16 j) { // 0xA68FA9 + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DE3; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68E0F; + return j; +} + +uint16 FireGeyser_Instr_23(uint16 k, uint16 j) { // 0xA68FBD + uint16 v2 = Get_FireGeyser(cur_enemy_index)->fgr_var_D - g_word_A68DE5; + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index + 64); + E->base.y_pos = v2; + E->base.y_height = g_word_A68E11; + return j; +} + +uint16 FireGeyser_Instr_24(uint16 k, uint16 j) { // 0xA68FD1 + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index); + E->fgr_var_C = 1; + Enemy_FireGeyser *E1 = Get_FireGeyser(cur_enemy_index + 64); + E1->base.x_width = 0; + E1->base.y_height = 0; + E->base.y_pos = E->fgr_var_D; + E->base.properties |= kEnemyProps_Invisible; + E1->base.properties |= 0x400u; + return j; +} + +void FireGeyser_Init(void) { // 0xA68FFC + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index); + E->base.current_instruction = addr_kFireGeyser_Ilist_8DA9; + if (!E->fgr_parameter_2) { + E->base.current_instruction = addr_kFireGeyser_Ilist_8D1B; + E->fgr_var_A = FUNC16(FireGeyser_Func_1); + E->fgr_var_D = E->base.y_pos; + E->base.x_width = 0; + } +} + +void CallFireGeyserFunc(uint32 ea) { + switch (ea) { + case fnFireGeyser_Func_1: FireGeyser_Func_1(); return; + case fnFireGeyser_Func_2: FireGeyser_Func_2(); return; + default: Unreachable(); + } +} + +void FireGeyser_Main(void) { // 0xA69023 + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index); + if (!E->fgr_parameter_2) + CallFireGeyserFunc(E->fgr_var_A | 0xA60000); +} + +void FireGeyser_Func_1(void) { // 0xA6902F + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index); + if ((--E->fgr_var_B & 0x8000u) != 0) { + E->fgr_var_A = FUNC16(FireGeyser_Func_2); + E->fgr_var_C = 0; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kFireGeyser_Ilist_8D1B; + E->base.properties &= ~kEnemyProps_Invisible; + Enemy_FireGeyser *E1 = Get_FireGeyser(cur_enemy_index + 64); + E1->base.properties &= ~0x400u; + } +} + +void FireGeyser_Func_2(void) { // 0xA69062 + Enemy_FireGeyser *E = Get_FireGeyser(cur_enemy_index); + if (E->fgr_var_C) { + E->fgr_var_B = E->fgr_parameter_1; + E->base.properties |= kEnemyProps_Invisible; + E->fgr_var_A = FUNC16(FireGeyser_Func_1); + } +} + +void NuclearWaffle_Init(void) { // 0xA694C4 + Enemy_NuclearWaffle *E = Get_NuclearWaffle(cur_enemy_index); + E->base.current_instruction = addr_kNuclearWaffle_Ilist_9490; + E->nwe_var_C = LOBYTE(E->nwe_parameter_1); + E->nwe_var_D = HIBYTE(E->nwe_parameter_1); + E->nwe_var_E = LOBYTE(E->nwe_parameter_2); + uint16 nwe_parameter_2_high = HIBYTE(E->nwe_parameter_2); + E->nwe_var_F = nwe_parameter_2_high; + E->nwe_var_B = nwe_parameter_2_high; + E->nwe_var_A = FUNC16(NuclearWaffle_Func_1); + int v2 = (uint16)(4 * E->nwe_var_E) >> 1; + uint16 v3 = g_word_A695F6[v2]; + E->nwe_var_23 = v3; + E->nwe_var_21 = v3; + E->nwe_var_2E = g_word_A695F6[v2 + 1]; + E->nwe_var_2B = g_word_A695FE[v2]; + E->nwe_var_2C = g_word_A695FE[v2 + 1]; + E->nwe_var_30 = g_word_A69606[v2]; + E->nwe_var_2F = g_word_A69606[v2 + 1]; + uint16 v4 = 8 * E->nwe_var_C; + if (!E->nwe_var_E) + v4 += 4; + int v5 = v4 >> 1; + E->nwe_var_25 = kCommonEnemySpeeds_Linear[v5]; + E->nwe_var_24 = kCommonEnemySpeeds_Linear[v5 + 1]; + E->nwe_var_26 = E->base.x_pos; + E->nwe_var_27 = E->base.y_pos; + draw_enemy_layer = E->nwe_var_D; + uint16 v6 = E->nwe_var_26 + CosineMult8bit(E->nwe_var_23); + E->nwe_var_28 = v6; + E->base.x_pos = v6; + draw_enemy_layer = E->nwe_var_D; + uint16 v7 = E->nwe_var_27 + SineMult8bitNegative(E->nwe_var_23); + E->nwe_var_29 = v7; + E->base.y_pos = v7; + uint16 v8 = 8; + E->nwe_var_2A = 8; + do { + SpawnEnemyProjectileWithGfx(v8, cur_enemy_index, addr_kEproj_NuclearWaffleBody); + v8 = E->nwe_var_2A - 2; + E->nwe_var_2A = v8; + } while (v8); + E->nwe_var_2A = 6; + uint16 v15; + do { + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + R22_ = 43; + uint16 v13 = E->base.vram_tiles_index | E->base.palette_index; + E->nwe_var_34 = v13; + R24_ = v13; + CreateSpriteAtPos(); + Get_NuclearWaffle(cur_enemy_index + E->nwe_var_2A)->nwe_var_10 = R18_; + v15 = E->nwe_var_2A - 2; + E->nwe_var_2A = v15; + } while (v15); +} + +void CallNuclearWaffleFunc(uint32 ea) { + switch (ea) { + case fnNuclearWaffle_Func_1: NuclearWaffle_Func_1(); return; + case fnNuclearWaffle_Func_2: NuclearWaffle_Func_2(); return; + default: Unreachable(); + } +} + +void NuclearWaffle_Main(void) { // 0xA6960E + Enemy_NuclearWaffle *E = Get_NuclearWaffle(cur_enemy_index); + CallNuclearWaffleFunc(E->nwe_var_A | 0xA60000); +} + +void NuclearWaffle_Func_1(void) { // 0xA69615 + Enemy_NuclearWaffle *E = Get_NuclearWaffle(cur_enemy_index); + if ((--E->nwe_var_B & 0x8000u) != 0) { + E->nwe_var_B = E->nwe_var_F; + E->nwe_var_21 = E->nwe_var_23; + E->nwe_var_A = FUNC16(NuclearWaffle_Func_2); + E->nwe_var_33 = 0; + E->nwe_var_08 = 0; + E->nwe_var_09 = 0; + E->nwe_var_0A = 0; + E->nwe_var_0B = 0; + E->nwe_var_0C = 0; + E->nwe_var_0D = 0; + E->nwe_var_0E = 0; + E->nwe_var_0F = 0; + E->nwe_var_18 = 0; + E->nwe_var_19 = 0; + E->nwe_var_1A = 0; + E->nwe_var_1B = 0; + E->nwe_var_1C = 0; + E->nwe_var_1D = 0; + E->nwe_var_1E = 0; + E->nwe_var_1F = 0; + E->base.properties |= kEnemyProps_ProcessedOffscreen; + } +} + +void NuclearWaffle_Func_2(void) { // 0xA69682 + Enemy_NuclearWaffle *E = Get_NuclearWaffle(cur_enemy_index); + draw_enemy_layer = E->nwe_var_D; + g_word_7E001E = NuclearWaffle_Func_6(E->nwe_var_21); + uint16 v8 = g_word_7E001E; + if (g_word_7E001E != E->nwe_var_33) { + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + R22_ = 46; + R24_ = E->nwe_var_34; + CreateSpriteAtPos(); + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + R22_ = R26_ + 44; + R24_ = E->nwe_var_34; + CreateSpriteAtPos(); + NuclearWaffle_Func_7(); + } + E->nwe_var_33 = v8; + uint16 v4 = NuclearWaffle_Func_5(E->nwe_var_21); + E->base.x_pos = E->nwe_var_26 + CosineMult8bit(v4); + uint16 v5 = NuclearWaffle_Func_5(E->nwe_var_21); + E->base.y_pos = E->nwe_var_27 + SineMult8bitNegative(v5); + NuclearWaffle_Func_3(); + NuclearWaffle_Func_4(); + uint16 nwe_var_20 = E->nwe_var_20; + bool v7 = __CFADD__uint16(E->nwe_var_24, nwe_var_20); + E->nwe_var_20 = E->nwe_var_24 + nwe_var_20; + E->nwe_var_21 += E->nwe_var_25 + v7; +} + +void NuclearWaffle_Func_3(void) { // 0xA69721 + Enemy_NuclearWaffle *E = Get_NuclearWaffle(cur_enemy_index); + uint16 v12; + E->nwe_var_2A = 8; + R36 = E->nwe_var_2C + E->nwe_var_21; + do { + R36 -= E->nwe_var_2B; + Enemy_NuclearWaffle *ET = Get_NuclearWaffle(cur_enemy_index + E->nwe_var_2A); + uint16 nwe_var_00 = ET->nwe_var_00; + g_word_7E001E = NuclearWaffle_Func_6(R36); + uint16 v13 = g_word_7E001E; + if (g_word_7E001E != ET->nwe_var_08) { + int v5 = nwe_var_00 >> 1; + R18_ = enemy_projectile_x_pos[v5]; + R20_ = enemy_projectile_y_pos[v5]; + R22_ = 46; + R24_ = E->nwe_var_34; + CreateSpriteAtPos(); + R18_ = enemy_projectile_x_pos[v5]; + R20_ = enemy_projectile_y_pos[v5]; + R22_ = R26_ + 44; + R24_ = E->nwe_var_34; + CreateSpriteAtPos(); + NuclearWaffle_Func_7(); + } + ET->nwe_var_08 = v13; + uint16 v7 = NuclearWaffle_Func_5(R36); + uint16 v8 = CosineMult8bit(v7); + int v10 = nwe_var_00 >> 1; + enemy_projectile_x_pos[v10] = E->nwe_var_26 + v8; + uint16 v11 = NuclearWaffle_Func_5(R36); + enemy_projectile_y_pos[v10] = E->nwe_var_27 + SineMult8bitNegative(v11); + v12 = E->nwe_var_2A - 2; + E->nwe_var_2A = v12; + } while (v12); + if (R28_) { + E->nwe_var_A = FUNC16(NuclearWaffle_Func_1); + E->base.properties &= ~kEnemyProps_ProcessedOffscreen; + } +} + +void NuclearWaffle_Func_4(void) { // 0xA697E9 + Enemy_NuclearWaffle *E = Get_NuclearWaffle(cur_enemy_index); + E->nwe_var_2A = 6; + R36 = E->nwe_var_21; + uint16 v12; + do { + R36 -= E->nwe_var_2B; + Enemy_NuclearWaffle *ET = Get_NuclearWaffle(cur_enemy_index + E->nwe_var_2A); + uint16 nwe_var_10 = ET->nwe_var_10; + g_word_7E001E = NuclearWaffle_Func_6(R36); + uint16 v13 = g_word_7E001E; + if (g_word_7E001E != ET->nwe_var_18) { + R38 = E->nwe_var_34; + int v5 = nwe_var_10 >> 1; + R18_ = sprite_x_pos[v5]; + R20_ = sprite_y_pos[v5]; + R22_ = 46; + R24_ = R38; + CreateSpriteAtPos(); + R18_ = sprite_x_pos[v5]; + R20_ = sprite_y_pos[v5]; + R22_ = R26_ + 44; + R24_ = R38; + CreateSpriteAtPos(); + NuclearWaffle_Func_7(); + } + ET->nwe_var_18 = v13; + uint16 v6 = NuclearWaffle_Func_5(R36); + uint16 v7 = CosineMult8bit(v6); + R32 = E->nwe_var_26 + v7; + uint16 v9 = NuclearWaffle_Func_5(R36); + R34 = E->nwe_var_27 + SineMult8bitNegative(v9); + sprite_x_pos[nwe_var_10 >> 1] = R32; + sprite_y_pos[nwe_var_10 >> 1] = R34; + v12 = E->nwe_var_2A - 2; + E->nwe_var_2A = v12; + } while (v12); +} + +uint16 NuclearWaffle_Func_5(uint16 a) { // 0xA698AD + R28_ = 0; + Enemy_NuclearWaffle *E = Get_NuclearWaffle(cur_enemy_index); + if (!E->nwe_var_E) { + if ((int16)(a - E->nwe_var_2E) >= 0) { + if ((int16)(a - E->nwe_var_23) < 0) + return a; + return E->nwe_var_23; + } +LABEL_8: + ++R28_; + return E->nwe_var_2E; + } + if ((int16)(a - E->nwe_var_2E) >= 0) + goto LABEL_8; + if ((int16)(a - E->nwe_var_23) < 0) + return E->nwe_var_23; + return a; +} + +uint16 NuclearWaffle_Func_6(uint16 a) { // 0xA698E7 + Enemy_NuclearWaffle *E = Get_NuclearWaffle(cur_enemy_index); + if (E->nwe_var_E) { + if ((int16)(a - E->nwe_var_2F) >= 0) { + R26_ = 1; + return 2; + } else if ((int16)(a - E->nwe_var_30) >= 0) { + R26_ = 0; + return 1; + } else { + return 0; + } + } else if ((int16)(a - E->nwe_var_2F) < 0) { + R26_ = 0; + return 2; + } else if ((int16)(a - E->nwe_var_30) < 0) { + R26_ = 1; + return 1; + } else { + return 0; + } +} + +void NuclearWaffle_Func_7(void) { // 0xA6993F + if (g_word_7E001E != 2) + QueueSfx2_Max6(0x5Eu); +} + +void FakeKraid_Init(void) { // 0xA69A58 + uint16 v0 = (random_number & 3) + 2; + Enemy_FakeKraid *E = Get_FakeKraid(cur_enemy_index); + E->fkd_var_D = v0; + E->fkd_var_E = v0; + v0 += 64; + E->fkd_var_03 = v0; + v0 += 32; + E->fkd_var_04 = v0; + E->fkd_var_05 = v0 - 48; + E->fkd_var_07 = 0; + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->fkd_var_B = -4; + E->fkd_var_C = -4; + uint16 v2 = addr_stru_A699AE; + if ((int16)(E->base.x_pos - samus_x_pos) < 0) { + E->fkd_var_B = 4; + E->fkd_var_C = 4; + v2 = addr_stru_A699FC; + } + E->base.current_instruction = v2; +} + +void FakeKraid_Main(void) { // 0xA69AC2 + Enemy_FakeKraid *E = Get_FakeKraid(cur_enemy_index); + uint16 fkd_var_07 = E->fkd_var_07; + uint16 v3 = fkd_var_07 + 2; + if (!sign16(fkd_var_07 - 4)) + v3 = 0; + E->fkd_var_07 = v3; + FakeKraid_Func_1(cur_enemy_index, fkd_var_07); +} + +void FakeKraid_Func_1(uint16 k, uint16 j) { // 0xA69ADC + R18_ = k; + Enemy_FakeKraid *ET = Get_FakeKraid(k + j); + uint16 fkd_var_03 = ET->fkd_var_03; + if (fkd_var_03) { + ET->fkd_var_03 = fkd_var_03 - 1; + } else { + ET->fkd_var_03 = (random_number & 0x3F) + 16; + Enemy_FakeKraid *E = Get_FakeKraid(k); + E->fkd_var_06 = j; + uint16 v6 = addr_kEproj_MiniKraidSpikesLeft; + int16 fkd_var_C = E->fkd_var_C; + if (fkd_var_C >= 0) + v6 = addr_kEproj_MiniKraidSpikesRight; + SpawnEnemyProjectileWithGfx(fkd_var_C, k, v6); + if (!CheckIfEnemyIsOnScreen()) + QueueSfx2_Max6(0x3Fu); + } +} + +uint16 FakeKraid_Instr_2(uint16 k, uint16 j) { // 0xA69B26 + Enemy_FakeKraid *E = Get_FakeKraid(cur_enemy_index); + if (E->fkd_var_E) + --E->fkd_var_E; + if (E->fkd_var_D-- == 1) { + E->fkd_var_D = (random_number & 3) + 7; + } else { + R20_ = E->fkd_var_B; + R18_ = 0; + if (!(Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1)) + goto LABEL_7; + } + E->fkd_var_B = -E->fkd_var_B; +LABEL_7: + E->fkd_var_C = -4; + if ((int16)(E->base.x_pos - samus_x_pos) < 0) + E->fkd_var_C = 4; + return j; +} + +uint16 FakeKraid_Instr_1(uint16 k, uint16 j) { // 0xA69B74 + Enemy_FakeKraid *E = Get_FakeKraid(cur_enemy_index); + uint16 result; + if (E->fkd_var_E) { + if ((E->fkd_var_C & 0x8000u) != 0) { + result = addr_stru_A699AE; + if ((Get_FakeKraid(cur_enemy_index)->fkd_var_B & 0x8000u) == 0) + return addr_stru_A699C6; + } else { + result = addr_stru_A699FC; + if ((E->fkd_var_B & 0x8000u) != 0) + return addr_stru_A69A14; + } + } else { + E->fkd_var_E = (random_number & 3) + 3; + result = addr_kFakeKraid_Ilist_9A2A; + if ((E->fkd_var_C & 0x8000u) != 0) + return addr_kFakeKraid_Ilist_99DC; + } + return result; +} + +uint16 FakeKraid_Instr_3(uint16 k, uint16 j) { // 0xA69BB2 + if (CheckIfEnemyIsOnScreen() == 0) + QueueSfx2_Max6(0x16u); + return j; +} + +uint16 FakeKraid_Instr_4(uint16 k, uint16 j) { // 0xA69BC4 + FakeKraid_InstrHelper_45(k, 0, 0xFFFCu); + return j; +} + +void FakeKraid_InstrHelper_45(uint16 k, uint16 j, uint16 a) { // 0xA69BCB + uint16 ka = cur_enemy_index; + Enemy_FakeKraid *E = Get_FakeKraid(cur_enemy_index); + E->fkd_var_02 = a; + int v5 = j >> 1; + E->fkd_var_00 = g_word_A69A48[v5]; + uint16 v6 = g_word_A69A48[v5 + 1]; + E->fkd_var_01 = v6; + SpawnEnemyProjectileWithGfx(v6, cur_enemy_index, addr_kEproj_MiniKraidSpit); + E->fkd_var_00 = g_word_A69A48[v5 + 2]; + uint16 v8 = g_word_A69A48[v5 + 3]; + E->fkd_var_01 = v8; + SpawnEnemyProjectileWithGfx(v8, ka, addr_kEproj_MiniKraidSpit); +} + +uint16 FakeKraid_Instr_5(uint16 k, uint16 j) { // 0xA69C02 + FakeKraid_InstrHelper_45(k, 8u, 4u); + return j; +} + +void sub_A69C0B(void) { // 0xA69C0B + EnemyData *v0 = gEnemyData(cur_enemy_index); + special_death_item_drop_x_origin_pos = v0->x_pos; + special_death_item_drop_y_origin_pos = v0->y_pos; + NormalEnemyPowerBombAiSkipDeathAnim_CurEnemy(); + FakeKraid_9C50(); +} + +void FakeKraid_Touch(void) { // 0xA69C22 + Enemy_FakeKraid *E = Get_FakeKraid(cur_enemy_index); + special_death_item_drop_x_origin_pos = E->base.x_pos; + special_death_item_drop_y_origin_pos = E->base.y_pos; + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); + FakeKraid_9C50(); +} + +void FakeKraid_Shot(void) { // 0xA69C39 + Enemy_FakeKraid *E = Get_FakeKraid(cur_enemy_index); + special_death_item_drop_x_origin_pos = E->base.x_pos; + special_death_item_drop_y_origin_pos = E->base.y_pos; + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + FakeKraid_9C50(); +} + +void FakeKraid_9C50(void) { // 0xA69C50 + if (!Get_FakeKraid(cur_enemy_index)->base.health) { + EnemyDeathAnimation(cur_enemy_index, 3u); + Enemy_ItemDrop_MiniKraid(cur_enemy_index); + } +} + +void CeresRidley_Init(void) { // 0xA6A0F5 + int16 v4; + int16 v8; + Enemy_CeresRidley *E = Get_CeresRidley(0); + + if ((boss_bits_for_area[area_index] & 1) != 0) { + E->base.properties |= kEnemyProps_Tangible | kEnemyProps_Deleted | kEnemyProps_Invisible; + } else { + for (int i = 4094; i >= 0; i -= 2) + tilemap_stuff[i >> 1] = 0; + DisableMinimapAndMarkBossRoomAsExplored(); + E->cry_parameter_1 = 0; + E->cry_parameter_2 = 0; + Ridley_Func_99(addr_kRidley_Ilist_E538); + E->base.palette_index = 3584; + E->cry_var_0C = 3584; + E->base.extra_properties |= 4u; + E->cry_var_01 = 0; + E->cry_var_0D = 0; + earthquake_type = 0; + earthquake_timer = 0; + Ridley_Func_92(); + Ridley_Func_117(); + if (area_index == 2) { + E->base.properties |= kEnemyProps_BlockPlasmaBeam | kEnemyProps_Tangible; + E->base.x_pos = 96; + E->base.y_pos = 394; + E->cry_var_A = FUNC16(CeresRidley_Func_3); + E->cry_var_B = 0; + E->cry_var_C = 0; + E->base.layer = 5; + E->cry_var_01 = 0; + E->cry_var_02 = 1; + E->cry_var_20 = 64; + E->cry_var_21 = 416; + E->cry_var_22 = 64; + E->cry_var_23 = 224; + E->cry_var_10 = 2; + E->cry_var_1C = 120; + WriteColorsToTargetPalette(0xa6, 0x140u, addr_word_A6E1CF, 0x20u); + uint16 v3 = 0; + v4 = 15; + do { + int v5 = v3 >> 1; + target_palettes[v5 + 113] = 0; + target_palettes[v5 + 241] = 0; + v3 += 2; + --v4; + } while (v4); + } else { + E->base.properties |= kEnemyProps_BlockPlasmaBeam | kEnemyProps_Tangible; + E->base.x_pos = 186; + E->base.y_pos = 169; + ceres_status = 0; + E->cry_var_10 = 0; + E->cry_var_02 = 0; + tilemap_stuff[1] = 1; + E->cry_var_1C = 15; + E->cry_var_A = FUNC16(CeresRidley_Func_3); + E->cry_var_B = 0; + E->cry_var_C = 0; + E->cry_var_20 = -32; + E->cry_var_21 = 176; + E->cry_var_22 = 40; + E->cry_var_23 = 224; + WriteColorsToTargetPalette(0xa6, 0x140u, addr_word_A6E16F, 0x20u); + uint16 v7 = 482; + v8 = 15; + do { + target_palettes[v7 >> 1] = 0; + v7 += 2; + --v8; + } while (v8); + E->cry_var_03 = addr_kBabyMetroid_Ilist_BF31; + E->cry_var_04 = 1; + gRam8800_Default(0)->var_40 = FUNC16(Ridley_Func_50); + E->cry_var_07 = 5; + QueueMusic_Delayed8(0); + } + } +} + +void CallRidleyFunc(uint32 ea) { + switch (ea) { + case fnCeresRidley_Func_2: CeresRidley_Func_2(); return; + case fnCeresRidley_Func_3: CeresRidley_Func_3(); return; + case fnCeresRidley_A377: CeresRidley_A377(); return; + case fnCeresRidley_Func_4: CeresRidley_Func_4(); return; + case fnCeresRidley_Func_5: CeresRidley_Func_5(); return; + case fnCeresRidley_Func_6: CeresRidley_Func_6(); return; + case fnCeresRidley_Func_7: CeresRidley_Func_7(); return; + case fnCeresRidley_Func_9: CeresRidley_Func_9(); return; + case fnCeresRidley_Func_10: CeresRidley_Func_10(); return; + case fnCeresRidley_Func_11: CeresRidley_Func_11(); return; + case fnCeresRidley_Func_13: CeresRidley_Func_13(); return; + case fnCeresRidley_A7F9: CeresRidley_A7F9(); return; + case fnCeresRidley_Func_14: CeresRidley_Func_14(); return; + case fnCeresRidley_Func_15: CeresRidley_Func_15(); return; + case fnCeresRidley_Func_16: CeresRidley_Func_16(); return; + case fnCeresRidley_Func_17: CeresRidley_Func_17(); return; + case fnCeresRidley_Func_18: CeresRidley_Func_18(); return; + case fnCeresRidley_Func_19: CeresRidley_Func_19(); return; + case fnCeresRidley_Func_20: CeresRidley_Func_20(); return; + case fnCeresRidley_Func_21: CeresRidley_Func_21(); return; + case fnCeresRidley_Func_22: CeresRidley_Func_22(); return; + case fnCeresRidley_Func_23: CeresRidley_Func_23(); return; + case fnCeresRidley_Func_24: CeresRidley_Func_24(); return; + case fnnullsub_233: return; + case fnCeresRidley_Func_26: CeresRidley_Func_26(); return; + case fnRidley_Func_3: Ridley_Func_3(); return; + case fnRidley_Func_3b: Ridley_Func_3b(); return; + case fnRidley_Func_5: Ridley_Func_5(); return; + case fnRidley_Func_6: Ridley_Func_6(); return; + case fnRidley_Func_8: Ridley_Func_8(); return; + case fnRidley_B455: Ridley_B455(); return; + case fnRidley_Func_9: Ridley_Func_9(); return; + case fnRidley_Func_10: Ridley_Func_10(); return; + case fnRidley_Func_11: Ridley_Func_11(); return; + case fnRidley_Func_12: Ridley_Func_12(); return; + case fnRidley_Func_13: Ridley_Func_13(); return; + case fnRidley_Func_14: Ridley_Func_14(); return; + case fnRidley_Func_15: Ridley_Func_15(); return; + case fnRidley_Func_16: Ridley_Func_16(); return; + case fnRidley_Func_19: Ridley_Func_19(); return; + case fnRidley_Func_20: Ridley_Func_20(); return; + case fnRidley_Func_21: Ridley_Func_21(); return; + case fnRidley_Func_22: Ridley_Func_22(); return; + case fnRidley_Func_33: Ridley_Func_33(); return; + case fnRidley_Func_33b: Ridley_Func_33b(); return; + case fnRidley_Func_34: Ridley_Func_34(); return; + case fnRidley_Func_35: Ridley_Func_35(); return; + case fnRidley_Func_36: Ridley_Func_36(); return; + case fnRidley_Func_43: Ridley_Func_43(); return; + case fnRidley_Func_44: Ridley_Func_44(); return; + case fnRidley_Func_45: Ridley_Func_45(); return; + case fnRidley_Func_46: Ridley_Func_46(); return; + case fnRidley_Func_47: Ridley_Func_47(); return; + case fnRidley_Func_54: Ridley_Func_54(); return; + case fnRidley_Func_63: Ridley_Func_63(); return; + case fnRidley_C53E: Ridley_C53E(); return; + case fnRidley_C551: Ridley_C551(); return; + case fnRidley_Func_64: Ridley_Func_64(); return; + case fnRidley_Func_65: Ridley_Func_65(); return; + case fnRidley_Func_66: Ridley_Func_66(); return; + case fnRidley_Func_67: Ridley_Func_67(); return; + case fnnullsub_349: return; + default: Unreachable(); + } +} +void CeresRidley_Main(void) { // 0xA6A288 + Enemy_CeresRidley *E = Get_CeresRidley(0); + E->base.health = 0x7FFF; + CallRidleyFunc(E->cry_var_A | 0xA60000); + if (!ceres_status) { + if (Get_CeresRidley(0)->cry_var_02) { + Ridley_Func_102(); + Ridley_Func_112(); + Ridley_Func_115(); + CeresRidley_Func_1(); + Ridley_Func_70(); + Ridley_Func_101(); + Ridley_Func_118(); + sub_A6DB2A(); + Ridley_Func_120(); + } + Ridley_A2DC(); + } +} + +void CeresRidley_Func_1(void) { // 0xA6A2BD + if (random_number >= 0xFF00u) + tilemap_stuff[15] = (random_number & 0xF) + 8; +} + +void CeresRidley_Hurt(void) { // 0xA6A2D3 + Ridley_Func_102(); + sub_A6DB2A(); + Ridley_Func_120(); + Ridley_A2DC(); +} + +void Ridley_A2DC(void) { // 0xA6A2DC + Ridley_Func_49(); + if (Get_CeresRidley(0)->cry_var_02) { + mov24(&enemy_gfx_drawn_hook, 0xA6A2F2u); + } else { + Ridley_A2F2(); + } +} + +void Ridley_A2F2(void) { // 0xA6A2F2 + if (!ceres_status) + DrawBabyMetroid_0(); + Enemy_CeresRidley *E = Get_CeresRidley(0x40u); + if (E->cry_var_B) { + // bug + static const int16 g_word_A6A321[4] = { 0, -1024, -4, -1 }; + + R20_ = E->base.x_pos + g_word_A6A321[(uint8)(earthquake_timer & 3)]; + R18_ = E->base.y_pos; + R22_ = 1024; + DrawSpritemap(0xA6u, addr_kCeresRidley_Sprmap_A329); + } +} + +void CeresRidley_Func_2(void) { // 0xA6A354 + Enemy_CeresRidley *E = Get_CeresRidley(0); + E->cry_var_B = 0; + E->cry_var_C = 0; +} + +void CeresRidley_Func_3(void) { // 0xA6A35B + int16 v1; + + if (door_transition_flag_enemies) { + } else { + Enemy_CeresRidley *E = Get_CeresRidley(0); + E->cry_var_A = FUNC16(CeresRidley_A377); + v1 = 512; + if (area_index == 2) + v1 = 170; + E->cry_var_F = v1; + CeresRidley_A377(); + } +} + +void CeresRidley_A377(void) { // 0xA6A377 + Enemy_CeresRidley *E = Get_CeresRidley(0); + if ((--E->cry_var_F & 0x8000u) != 0) { + E->cry_var_A = FUNC16(CeresRidley_Func_4); + E->cry_var_E = 0; + E->cry_var_F = 0; + } +} + +void CeresRidley_Func_4(void) { // 0xA6A389 + int16 v2; + + Enemy_CeresRidley *E = Get_CeresRidley(0); + if ((E->cry_var_E & 0x8000u) == 0) { + uint16 cry_var_E = E->cry_var_E; + if (++E->cry_var_F) { + E->cry_var_F = 0; + v2 = g_byte_A6E269[cry_var_E]; + if (v2 == 255) { + E->cry_var_E = 0; + E->cry_var_A = FUNC16(CeresRidley_Func_5); + E->cry_var_02 = 1; + } else { + R18_ = g_byte_A6E269[cry_var_E]; + E->cry_var_E = cry_var_E + 1; + int v3 = (uint16)(6 * v2) >> 1; + palette_buffer[252] = g_word_A6E2AA[v3]; + palette_buffer[253] = g_word_A6E2AA[v3 + 1]; + palette_buffer[254] = g_word_A6E2AA[v3 + 2]; + } + } + } +} + +void CeresRidley_Func_5(void) { // 0xA6A3DF + int16 v2; + int16 v5; + + Enemy_CeresRidley *E = Get_CeresRidley(0); + if (++E->cry_var_F >= 2u) { + E->cry_var_F = 0; + uint16 cry_var_E = E->cry_var_E; + R18_ = 290; + R20_ = 482; + v2 = 11; + do { + v5 = v2; + uint16 v3 = g_word_A6E30A[cry_var_E >> 1]; + palette_buffer[R18_ >> 1] = v3; + palette_buffer[R20_ >> 1] = v3; + cry_var_E += 2; + ++R18_; + ++R18_; + ++R20_; + ++R20_; + v2 = v5 - 1; + } while (v5 != 1); + if (cry_var_E >= 0x160u) { + if (area_index == 2) + E->base.layer = 2; + E->base.properties &= ~kEnemyProps_Tangible; + E->cry_var_E = 0; + E->cry_var_A = FUNC16(CeresRidley_Func_6); + E->cry_var_F = 4; + QueueMusic_Delayed8(5u); + } else { + E->cry_var_E = cry_var_E; + } + } +} + +void CeresRidley_Func_6(void) { // 0xA6A455 + Enemy_CeresRidley *E = Get_CeresRidley(0); + if ((--E->cry_var_F & 0x8000u) != 0) { + Ridley_Func_99(addr_kRidley_Ilist_E690); + E->cry_var_F = 0; + E->cry_var_A = FUNC16(CeresRidley_Func_7); + if (area_index != 2) + E->cry_var_F = 252; + } +} + +void CeresRidley_Func_7(void) { // 0xA6A478 + Enemy_CeresRidley *E = Get_CeresRidley(0); + + if (area_index == 2) { + bool v1 = (--E->cry_var_F & 0x8000u) != 0; + if (!v1) + return; + E->cry_var_F = 2; + uint16 v2 = E->cry_var_E + 1; + E->cry_var_E = v2; + if (!(CeresRidley_Func_8(v2 - 1) & 1)) + return; + fx_target_y_pos = 440; + fx_y_vel = -96; + fx_timer = 32; + } else { + bool v1 = (--E->cry_var_F & 0x8000u) != 0; + if (!v1) + return; + } + E->cry_var_E = 0; + Ridley_Func_99(addr_kRidley_Ilist_E91D); + E->cry_var_08 = 8; + E->cry_var_09 = 8; + Ridley_Func_95(); + tilemap_stuff[0] = 1; + E->cry_var_A = FUNC16(CeresRidley_Func_2); +} + +uint8 CeresRidley_Func_8(uint16 a) { // 0xA6A4D6 + uint16 v1 = g_off_A6A4EB[a]; + if (!v1) + return 1; + WriteColorsToPalette(0xE2u, 0xa6, v1, 0xEu); + return 0; +} + +void CeresRidley_Func_9(void) { // 0xA6A6AF + Enemy_CeresRidley *E = Get_CeresRidley(0); + E->cry_var_C -= 16; + if (sign16(E->base.y_pos - 112)) { + E->cry_var_A = FUNC16(CeresRidley_Func_10); + CeresRidley_Func_10(); + } +} + +void CeresRidley_Func_10(void) { // 0xA6A6C8 + Enemy_CeresRidley *E = Get_CeresRidley(0); + E->cry_var_C += 20; + if (sign16(E->base.y_pos - 80)) { + E->cry_var_A = FUNC16(CeresRidley_Func_11); + E->cry_var_01 = 1; + } +} + +void CeresRidley_Func_11(void) { // 0xA6A6E8 + uint16 v1; + + Enemy_CeresRidley *E = Get_CeresRidley(0); + if (E->cry_var_0D >= 0x64u) { + E->cry_var_01 = 0; + E->cry_var_A = FUNC16(Ridley_Func_44); + Ridley_Func_44(); + } else if (sign16(samus_health - 30)) { + E->cry_var_01 = 0; + E->cry_var_A = FUNC16(CeresRidley_Func_22); + CeresRidley_Func_22(); + } else if (!(CeresRidley_Func_12() & 1) + || (v1 = E->cry_var_00 + 1, E->cry_var_00 = v1, v1 >= 0x7Cu)) { + E->cry_var_A = g_off_A6A743[random_number & 0xF]; + E->cry_var_00 = 0; + } +} + +uint8 CeresRidley_Func_12(void) { // 0xA6A763 + R18_ = 192; + R20_ = 100; + Ridley_Func_106(0, 0); + R22_ = 8; + R24_ = 8; + return Shitroid_Func_2(0) & 1; +} + +void CeresRidley_Func_13(void) { // 0xA6A782 + Enemy_CeresRidley *E = Get_CeresRidley(0); + uint16 v1 = abs16(E->cry_var_C); + if (v1 < 0x80) + v1 = 128; + E->cry_var_C = sign16(E->cry_var_C) ? -v1 : v1; + R18_ = E->base.x_pos; + R20_ = 88; + Ridley_Func_106(0, 0); + if (sign16(E->base.y_pos - 80)) { + uint16 v3 = E->cry_var_00 + 1; + E->cry_var_00 = v3; + if (v3 >= 0x30u) + E->cry_var_A = FUNC16(CeresRidley_Func_16); + } else if (sign16(E->base.y_pos - 128)) { + E->cry_var_17 = E->base.x_pos; + E->cry_var_18 = E->base.y_pos; + Ridley_Func_99(addr_kRidley_Ilist_E73A); + E->cry_var_A = addr_loc_A6A7F9; + E->cry_var_00 = 224; + CeresRidley_A7F9(); + } +} + +void CeresRidley_A7F9(void) { // 0xA6A7F9 + unsigned int v3; // kr00_4 + int16 v4; + + R22_ = sign16(random_number) ? -(random_number & 7) : (random_number & 7); + Enemy_CeresRidley *E = Get_CeresRidley(0); + uint16 cry_var_17 = E->cry_var_17; + R18_ = R22_ + cry_var_17; + v3 = __PAIR32__(R22_, R22_) + __PAIR32__(E->cry_var_18, cry_var_17); + uint16 v2 = (__PAIR32__(R22_, R22_) + __PAIR32__(E->cry_var_18, cry_var_17)) >> 16; + R18_ = v3; + R20_ = v2; + Ridley_Func_106(0, 0); + v4 = E->cry_var_00 - 1; + E->cry_var_00 = v4; + if (v4 < 0) { + E->cry_var_00 = 0; + E->cry_var_A = FUNC16(CeresRidley_Func_11); + } +} + +void CeresRidley_Func_14(void) { // 0xA6A83C + Ridley_Func_99(addr_kRidley_Ilist_E548); + Enemy_CeresRidley *E = Get_CeresRidley(0); + E->cry_var_A = FUNC16(CeresRidley_Func_15); + E->cry_var_F = 64; + CeresRidley_Func_15(); +} + +void CeresRidley_Func_15(void) { // 0xA6A84E + bool v2; // sf + + Enemy_CeresRidley *E = Get_CeresRidley(0); + R18_ = samus_x_pos; + uint16 v0 = samus_y_pos - 68; + if (sign16(samus_y_pos - 132)) + v0 = 64; + R20_ = v0; + Ridley_Func_106(0, 0xDu); + R22_ = 2; + R24_ = 2; + if (!(Shitroid_Func_2(0) & 1) + || (v2 = (int16)(E->cry_var_F - 1) < 0, --E->cry_var_F, v2)) { + E->cry_var_00 = 0; + E->cry_var_A = FUNC16(CeresRidley_Func_11); + } +} + +void CeresRidley_Func_16(void) { // 0xA6A88D + Enemy_CeresRidley *E = Get_CeresRidley(0); + E->cry_var_A = FUNC16(CeresRidley_Func_17); + E->cry_var_F = 10; + E->cry_var_0A = 0; + tilemap_stuff[1] = 0; + CeresRidley_Func_17(); +} + +void CeresRidley_Func_17(void) { // 0xA6A8A4 + R18_ = 192; + R20_ = 80; + Ridley_Func_106(0, 1u); + Enemy_CeresRidley *E = Get_CeresRidley(0); + if (sign16(E->base.y_pos - 96)) { + E->cry_var_A = FUNC16(CeresRidley_Func_18); + E->cry_var_F = 10; + E->cry_var_0A = 0; + } +} + +void CeresRidley_Func_18(void) { // 0xA6A8D4 + R18_ = -32; + R20_ = -1024; + R22_ = 768; + Ridley_Func_111(); + Enemy_CeresRidley *E = Get_CeresRidley(0); + if ((--E->cry_var_F & 0x8000u) != 0) { + E->cry_var_A = FUNC16(CeresRidley_Func_19); + E->cry_var_F = 36; + } +} + +void CeresRidley_Func_19(void) { // 0xA6A8F8 + R18_ = -512; + R20_ = -16384; + R22_ = 768; + Ridley_Func_111(); + Enemy_CeresRidley *E = Get_CeresRidley(0); + if ((--E->cry_var_F & 0x8000u) != 0) { + E->cry_var_A = FUNC16(CeresRidley_Func_20); + E->cry_var_F = 28; + tilemap_stuff[2] = 1; + } +} + +void CeresRidley_Func_20(void) { // 0xA6A923 + R18_ = -512; + R20_ = -30720; + R22_ = 768; + Ridley_Func_111(); + Enemy_CeresRidley *E = Get_CeresRidley(0); + if ((--E->cry_var_F & 0x8000u) != 0) { + E->cry_var_A = FUNC16(CeresRidley_Func_21); + E->cry_var_F = 1; + } +} + +void CeresRidley_Func_21(void) { // 0xA6A947 + R18_ = -768; + R20_ = -30720; + R22_ = 768; + Ridley_Func_111(); + Enemy_CeresRidley *E = Get_CeresRidley(0); + if ((--E->cry_var_F & 0x8000u) != 0) { + E->cry_var_A = FUNC16(CeresRidley_Func_11); + E->cry_var_00 = 0; + tilemap_stuff[1] = 1; + } +} + +void CeresRidley_Func_22(void) { // 0xA6A971 + Enemy_CeresRidley *E = Get_CeresRidley(0); + E->cry_var_20 = -192; + R18_ = 192; + R20_ = -128; + Ridley_Func_106(0, 1u); + if (sign16(E->base.y_pos + 128)) + CeresRidley_A994(); +} + +void CeresRidley_A994(void) { // 0xA6A994 + Enemy_CeresRidley *E = Get_CeresRidley(0); + E->cry_var_A = FUNC16(CeresRidley_Func_23); + E->cry_var_F = 64; + CeresRidley_Func_23(); +} + +void CeresRidley_Func_23(void) { // 0xA6A9A0 + Enemy_CeresRidley *E = Get_CeresRidley(0); + if ((--E->cry_var_F & 0x8000u) != 0) { + CeresRidley_Func_25(); + E->cry_var_B = 0; + E->cry_var_C = 0; + tilemap_stuff[0] = 0; + E->cry_var_A = FUNC16(CeresRidley_Func_24); + WriteColorsToPalette(0xA2u, 0xa6, addr_word_A6A9E3, 0xFu); + WriteColorsToPalette(0x42u, 0xa6, addr_word_A6AA01, 8u); + WriteColorsToPalette(0x1E2u, 0xa6, addr_word_A6AA01, 8u); + } +} + +void CeresRidley_Func_24(void) { // 0xA6AA11 + Get_CeresRidley(0)->cry_var_A = FUNC16(nullsub_233); + ceres_status = 1; + CeresRidley_Func_27(); +} + +void CeresRidley_Func_25(void) { // 0xA6AA20 + SpawnEnemy(0xA6u, addr_stru_A6AA2F); + SpawnEnemy(0xA6u, addr_stru_A6AA3F); +} + +void CeresRidley_Func_26(void) { // 0xA6AA50 + Ridley_Func_61(); +} + +void CeresRidley_Func_27(void) { // 0xA6AA54 + reg_BGMODE_fake = 7; + irq_enable_mode7 = 1; + reg_M7SEL = 0x80; + reg_M7A = 256; + reg_M7B = 256; + reg_M7C = 256; + reg_M7D = 256; + reg_M7X = 64; + reg_M7Y = 64; + Enemy_CeresRidley *E = Get_CeresRidley(0); + E->cry_var_32 = 0; + E->cry_var_33 = 0; + E->cry_var_0A = 1; + E->cry_var_34 = -128; + reg_BG1HOFS = -128; + E->cry_var_35 = 32; + reg_BG1VOFS = 32; + E->cry_var_30 = 2048; + E->cry_var_31 = 1024; +} + +void HandleCeresRidleyGetawayCutscene(void) { // 0xA6AAAF + if (!Get_CeresRidley(0)->cry_var_32) + CeresRidley_Func_28(); +} + +void CeresRidley_Func_28(void) { // 0xA6AABD + Enemy_CeresRidley *E = Get_CeresRidley(0); + uint16 cry_var_33 = E->cry_var_33; + E->cry_var_33 = cry_var_33 + 2; + if (!cry_var_33) + QueueSfx2_Max6(0x4Eu); + if (cry_var_33 == 208) { + Samus_SetPushedOutOfCeresRidley(); + earthquake_type = 35; + earthquake_timer = 64; + } + int v2 = cry_var_33 >> 1; + if (g_word_A6AE4D[v2] == 0xFFFF) { + ++E->cry_var_32; + reg_BGMODE_fake = 9; + reg_M7SEL = 0; + reg_M7A = 0; + reg_M7B = 0; + reg_M7C = 0; + reg_M7D = 0; + reg_M7X = 0; + reg_M7Y = 0; + reg_BG1HOFS = 0; + reg_BG1VOFS = 0; + E->cry_var_A = FUNC16(Ridley_Func_54); + E->cry_var_F = 0; + } else { + E->cry_var_30 = g_word_A6AE4D[v2]; + uint16 v3 = g_word_A6AF2F[v2] + E->cry_var_35; + E->cry_var_35 = v3; + reg_BG1VOFS = v3; + uint16 v4 = E->cry_var_34 - g_word_A6B00F[v2]; + E->cry_var_34 = v4; + reg_BG1HOFS = v4; + CeresRidley_Func_35(E->cry_var_30); + E->cry_var_0A += 48; + CeresRidley_Func_29(); + CeresRidley_Func_33(); + CeresRidley_Func_34(); + } +} + +uint16 MaybeNegate(uint16 cond, uint16 value) { + return cond & 0x8000 ? -value : value; +} + +void CeresRidley_Func_29(void) { // 0xA6AB5F + Enemy_CeresRidley *E = Get_CeresRidley(0); + R18_ = HIBYTE(E->cry_var_0A); + R24_ = CeresRidley_Func_31(0x100u); + R38 = abs16(R24_); + R40 = E->cry_var_30; + CeresRidley_Func_32(); + reg_M7A = MaybeNegate(R24_, *(uint16 *)((char *)&R42 + 1)); + + R24_ = CeresRidley_Func_30(0x100u); + R38 = abs16(R24_); + R40 = E->cry_var_30; + CeresRidley_Func_32(); + reg_M7B = MaybeNegate(R24_, *(uint16 *)((char *)&R42 + 1)); + + R24_ = -CeresRidley_Func_30(0x100u); + R38 = abs16(R24_); + R40 = E->cry_var_30; + CeresRidley_Func_32(); + reg_M7C = MaybeNegate(R24_, *(uint16 *)((char *)&R42 + 1)); + + R24_ = CeresRidley_Func_31(0x100u); + R38 = abs16(R24_); + R40 = E->cry_var_30; + CeresRidley_Func_32(); + reg_M7D = MaybeNegate(R24_, *(uint16 *)((char *)&R42 + 1)); +} + +uint16 CeresRidley_Func_30(uint16 a) { // 0xA6AC0E + R20_ = a; + R38 = abs16(a); + return CeresRidley_AC30(R18_); +} + +uint16 CeresRidley_Func_31(uint16 a) { // 0xA6AC1E + R20_ = a; + R38 = abs16(a); + return CeresRidley_AC30(R18_ + 64); +} + +uint16 CeresRidley_AC30(uint16 a) { // 0xA6AC30 + int v1 = (uint16)((2 * a) & 0x1FE) >> 1; + uint16 result = kSinCosTable8bit_Sext[v1 + 64]; + if (result) { + R22_ = kSinCosTable8bit_Sext[v1 + 64]; + R40 = abs16(result); + CeresRidley_Func_32(); + if (((R22_ ^ R20_) & 0x8000u) != 0) + return -*(uint16 *)((char *)&R42 + 1); + else + return *(uint16 *)((char *)&R42 + 1); + } + return result; +} + +void CeresRidley_Func_32(void) { // 0xA6AC58 + uint32 t = (uint32)R38 * (uint32)R40; + R42 = (uint16)t; + R44 = (uint16)(t >> 16); +} + +void CeresRidley_Func_33(void) { // 0xA6ACBC + if ((nmi_frame_counter_word & 3) == 0) { + Enemy_CeresRidley *E = Get_CeresRidley(0); + uint16 v1 = ((uint8)E->cry_var_36 + 1) & 3; + E->cry_var_36 = v1; + QueueMode7Transfers(0xA6u, g_off_A6ACDA[v1]); + } +} + +void CeresRidley_Func_34(void) { // 0xA6AD27 + if ((nmi_frame_counter_word & 7) == 0) { + Enemy_CeresRidley *E = Get_CeresRidley(0); + uint16 v1 = ((uint8)E->cry_var_37 + 1) & 1; + E->cry_var_37 = v1; + QueueMode7Transfers(0xA6u, g_off_A6AD45[v1]); + } +} + +void CeresRidley_Func_35(uint16 a) { // 0xA6B0EF + WriteColorsToPalette(0xA2u, 0xa6, 32 * HIBYTE(a) - 0x4EF9, 0xFu); +} + +void Ridley_Main(void) { // 0xA6B227 + int16 v1; + + Enemy_Ridley *E = Get_Ridley(0); + v1 = E->ridley_var_24 - 4; + if (v1 < 0) + v1 = 0; + E->ridley_var_24 = v1; + Ridley_Func_39(); + Ridley_Func_42(); + CallRidleyFunc(E->ridley_var_A | 0xA60000); + if (E->ridley_var_02) { + Ridley_Func_102(); + Ridley_Func_112(); + Ridley_Func_115(); + Ridley_Func_70(); + Ridley_Func_129(); + sub_A6DB2A(); + Ridley_Func_120(); + Ridley_Func_118(); + if (E->ridley_var_1B) + Ridley_Func_30(); + } + Ridley_Func_100(); +} + +void Ridley_Func_1(void) { // 0xA6B26F + Enemy_Ridley *E = Get_Ridley(0); + if (!(E->ridley_var_1B | E->ridley_var_1E)) { + if (Ridley_Func_26(4u, 4u) & 1) + Ridley_Func_37(); + } +} + +void Ridley_Func_2(void) { // 0xA6B28A + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_24 = 0; + E->base.frame_counter = 1; + Ridley_Hurt(); +} + +void Ridley_Hurt(void) { // 0xA6B297 + Enemy_Ridley *E = Get_Ridley(0); + if ((E->base.frame_counter & 1) == 0) { + Ridley_Func_39(); + Ridley_Func_42(); + CallRidleyFunc(E->ridley_var_A | 0xA60000); + if (!Get_Ridley(0)->ridley_var_02) { +LABEL_7: + if (Get_Ridley(0)->ridley_var_1B) + Ridley_Func_30(); + return; + } + Ridley_Func_112(); + Ridley_Func_115(); + Ridley_Func_70(); + } + Ridley_Func_129(); + Ridley_Func_102(); + sub_A6DB2A(); + Ridley_Func_120(); + Ridley_Func_100(); + Ridley_Func_118(); + uint16 v2 = E->ridley_var_24 + 1; + if ((int16)(v2 - g_word_A6B288) >= 0) + v2 = g_word_A6B288; + E->ridley_var_24 = v2; + if ((int16)(E->ridley_var_24 - g_word_A6B288) >= 0) + goto LABEL_7; +} + +void Ridley_Func_3(void) { // 0xA6B2F3 + R18_ = 64; + R20_ = 256; + Ridley_Func_104_0(0, 14); + R22_ = 8; + R24_ = 8; + if (!(Shitroid_Func_2(0) & 1)) { + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_01 = 1; + E->ridley_var_A = FUNC16(Ridley_Func_3b); + Ridley_Func_3b(); + } +} + +void Ridley_Func_3b(void) { // 0xA6B321 + Ridley_Func_4(); + int v0 = (uint16)(2 * (NextRandom() & 7)); + uint16 v1 = *(uint16 *)&RomPtr_A6(R18_)[v0]; + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_A = v1; + CallRidleyFunc(E->ridley_var_A | 0xA60000); +} + +void Ridley_Func_4(void) { // 0xA6B335 + if (samus_movement_type == 3) { + R18_ = addr_off_A6B3CC; + } else { + Enemy_Ridley *E = Get_Ridley(0); + uint16 health = E->base.health; + if (health) { + if (sign16(health - 14400)) { + R18_ = addr_off_A6B38C; + } else if (Ridley_Func_41() & 1) { + R18_ = addr_off_A6B3BC; + } else if ((Ridley_Func_40_Carry() & 1) != 0) { + R18_ = addr_off_A6B3AC; + } else { + uint16 v2 = addr_off_A6B38C; + if (sign16(E->base.health - 9000)) + v2 = addr_off_A6B39C; + R18_ = v2; + } + } else { + R18_ = addr_off_A6B3DC; + ++E->ridley_var_25; + } + } +} + +void Ridley_Func_5(void) { // 0xA6B3EC + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_A = FUNC16(Ridley_Func_6); + E->ridley_var_F = 128; + Ridley_Func_6(); +} + +void Ridley_Func_6(void) { // 0xA6B3F8 + Enemy_Ridley *E = Get_Ridley(0); + if ((--E->ridley_var_F & 0x8000u) != 0) + goto LABEL_5; + uint16 v2; + v2 = 192; + if (E->ridley_var_10) + v2 = 96; + R18_ = v2; + R20_ = 256; + uint16 v3; + v3 = Ridley_Func_7(); + Ridley_Func_104_0(0, v3); + R22_ = 8; + R24_ = 8; + if (!(Shitroid_Func_2(0) & 1)) + LABEL_5: + E->ridley_var_A = FUNC16(Ridley_Func_3b); +} + +uint16 Ridley_Func_7(void) { // 0xA6B42E + static const uint16 g_word_A6B439[4] = { 4, 8, 0xa, 0xc }; + return g_word_A6B439[(uint16)(2 * Get_Ridley(0)->ridley_var_12) >> 1]; +} + +void Ridley_Func_8(void) { // 0xA6B441 + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_A = addr_loc_A6B455; + E->ridley_var_00 = 10; + E->ridley_var_0A = 0; + Ridley_B455(); +} + +void Ridley_B455(void) { // 0xA6B455 + Enemy_Ridley *E = Get_Ridley(0); + uint16 v1 = 192; + if (E->ridley_var_10) + v1 = 64; + R18_ = v1; + R20_ = 128; + Ridley_Func_104_0(0, 1u); + R22_ = 8; + R24_ = 8; + if (!(Shitroid_Func_2(0) & 1)) { + E->ridley_var_A = FUNC16(Ridley_Func_9); + E->ridley_var_00 = 32; + E->ridley_var_0A = 0; + } +} + +void Ridley_Func_9(void) { // 0xA6B493 + Enemy_Ridley *E = Get_Ridley(0); + if (E->ridley_var_10) { + R18_ = 32; + R20_ = 512; + } else { + R18_ = -32; + R20_ = -512; + } + R22_ = 1152; + Ridley_Func_111(); + uint16 ridley_var_00 = E->ridley_var_00; + if (ridley_var_00) { + E->ridley_var_00 = ridley_var_00 - 1; + } else { + E->ridley_var_A = FUNC16(Ridley_Func_10); + E->ridley_var_00 = 20; + } +} + +void Ridley_Func_10(void) { // 0xA6B4D1 + Enemy_Ridley *E = Get_Ridley(0); + if (E->ridley_var_10) { + R18_ = 320; + R20_ = 0x4000; + } else { + R18_ = -320; + R20_ = -16384; + } + R22_ = 1280; + Ridley_Func_111(); + uint16 ridley_var_00 = E->ridley_var_00; + if (ridley_var_00) { + E->ridley_var_00 = ridley_var_00 - 1; + } else { + E->ridley_var_A = FUNC16(Ridley_Func_11); + E->ridley_var_00 = 16; + tilemap_stuff[2] = 1; + } +} + +void Ridley_Func_11(void) { // 0xA6B516 + Enemy_Ridley *E = Get_Ridley(0); + if (E->ridley_var_10) { + R18_ = 512; + R20_ = 30720; + } else { + R18_ = -512; + R20_ = -30720; + } + R22_ = 768; + Ridley_Func_111(); + uint16 ridley_var_00 = E->ridley_var_00; + if (ridley_var_00) { + E->ridley_var_00 = ridley_var_00 - 1; + } else { + E->ridley_var_A = FUNC16(Ridley_Func_12); + E->ridley_var_00 = 32; + } +} + +void Ridley_Func_12(void) { // 0xA6B554 + Enemy_Ridley *E = Get_Ridley(0); + if (E->ridley_var_10) { + R18_ = 1024; + R20_ = 30720; + } else { + R18_ = -1024; + R20_ = -30720; + } + R22_ = 768; + Ridley_Func_111(); + uint16 ridley_var_00 = E->ridley_var_00; + if (ridley_var_00) { + E->ridley_var_00 = ridley_var_00 - 1; + } else { + E->ridley_var_A = FUNC16(Ridley_Func_13); + E->ridley_var_00 = 32; + Ridley_Func_114(); + } +} + +void Ridley_Func_13(void) { // 0xA6B594 + R18_ = 0; + R20_ = FUNC16(Enemy_GrappleReact_NoInteract_A6); + R22_ = 448; + Ridley_Func_111(); + Enemy_Ridley *E = Get_Ridley(0); + uint16 ridley_var_00 = E->ridley_var_00; + if (ridley_var_00) { + E->ridley_var_00 = ridley_var_00 - 1; + } else { + E->ridley_var_A = Ridley_Func_40_Carry() ? FUNC16(Ridley_Func_33) : FUNC16(Ridley_Func_3b);; + } +} + +void Ridley_Func_14(void) { // 0xA6B5C4 + tilemap_stuff[15] = 11; + tilemap_stuff[9] = 384; + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_A = FUNC16(Ridley_Func_15); + E->ridley_var_F = (random_number & 0x1F) + 32; + Ridley_Func_15(); +} + +void Ridley_Func_15(void) { // 0xA6B5E5 + Enemy_Ridley *E = Get_Ridley(0); + R18_ = g_word_A6B60D[E->ridley_var_10]; + if (Ridley_Func_17() & 1) { + Ridley_Func_18(); + } else if ((--E->ridley_var_F & 0x8000u) != 0) { + E->ridley_var_A = FUNC16(Ridley_Func_16); + E->ridley_var_F = 128; + Ridley_Func_114(); + } +} + +void Ridley_Func_16(void) { // 0xA6B613 + Enemy_Ridley *E = Get_Ridley(0); + R18_ = g_word_A6B63B[E->ridley_var_10]; + if (Ridley_Func_17() & 1) { + Ridley_Func_18(); + } else if ((--E->ridley_var_F & 0x8000u) != 0) { + E->ridley_var_A = FUNC16(Ridley_Func_15); + E->ridley_var_F = 128; + Ridley_Func_114(); + } +} + +uint8 Ridley_Func_17(void) { // 0xA6B641 + uint16 v0 = samus_y_pos; + if (!sign16(samus_y_pos - 352)) + v0 = 352; + R20_ = v0; + uint16 v1 = Ridley_Func_7(); + Ridley_Func_104_0(0, v1); + tilemap_stuff[2] = 1; + if (samus_movement_type != 3) + return 1; + if ((uint8)random_number >= 0x80) { + Enemy_Ridley *E = Get_Ridley(0); + if (!E->ridley_var_0F && E->ridley_var_10 != 1) + Ridley_Func_99(addr_kRidley_Ilist_E73A); + } + return 0; +} + +void Ridley_Func_18(void) { // 0xA6B68B + tilemap_stuff[9] = 240; + tilemap_stuff[15] = 16; + tilemap_stuff[0] = 1; + Get_Ridley(0)->ridley_var_A = FUNC16(Ridley_Func_19); +} + +void Ridley_Func_19(void) { // 0xA6B6A7 + Enemy_Ridley *E = Get_Ridley(0); + if (sign16(E->base.y_pos - 288)) { + Ridley_Func_114(); + E->ridley_var_A = FUNC16(Ridley_Func_20); + E->ridley_var_F = 32; + Ridley_Func_20(); + } else { + R18_ = g_word_A6B6C8[E->ridley_var_10]; + R20_ = 288; + Ridley_Func_104_0(0, 0); + } +} + +void Ridley_Func_20(void) { // 0xA6B6DD + Enemy_Ridley *E = Get_Ridley(0); + R18_ = E->base.x_pos; + R20_ = 288; + Ridley_Func_104_0(0, 0); + if ((--E->ridley_var_F & 0x8000u) != 0) { + Ridley_Func_71(); + Ridley_Func_29(); + E->ridley_var_A = FUNC16(Ridley_Func_21); + E->ridley_var_F = (random_number & 0x3F) + 128; + } +} + +void Ridley_Func_21(void) { // 0xA6B70E + int16 v1; + + if (Ridley_Func_25() & 1) { + Ridley_Func_24(); + Ridley_Func_27(); + } else { + Enemy_Ridley *E = Get_Ridley(0); + v1 = tilemap_stuff[6] + E->ridley_var_C; + if (!sign16(v1 - 1536)) + v1 = 1536; + E->ridley_var_C = v1; + if (Ridley_Func_23() & 1) { + R18_ = tilemap_stuff[82]; + R20_ = tilemap_stuff[83] + 12; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 9u); + QueueSfx2_Max6(0x76u); + earthquake_type = 13; + earthquake_timer = 4; + Ridley_Func_28(); + Ridley_Func_29(); + Ridley_Func_93(0x2026u, addr_word_A6D37C); + tilemap_stuff[20] = 3072; + tilemap_stuff[30] = 3072; + tilemap_stuff[40] = 3072; + tilemap_stuff[50] = 3072; + tilemap_stuff[60] = 3072; + tilemap_stuff[70] = 3072; + tilemap_stuff[80] = 3072; + tilemap_stuff[0] = 4; + uint16 v2 = E->ridley_var_26 + 1; + if (!sign16(E->ridley_var_26 - 1)) { + if (E->ridley_var_10 != 1) + Ridley_Func_99(addr_kRidley_Ilist_E73A); + v2 = 0; + } + E->ridley_var_26 = v2; + E->ridley_var_A = FUNC16(Ridley_Func_22); + } + } +} + +void Ridley_Func_22(void) { // 0xA6B7B9 + Enemy_Ridley *E = Get_Ridley(0); + bool v1; + if (!(Ridley_Func_41() & 1) + || (v1 = (int16)(E->ridley_var_F - 1) < 0, --E->ridley_var_F, v1)) { + Ridley_Func_24(); + E->ridley_var_A = FUNC16(Ridley_Func_3b); + } else { + uint16 ridley_var_C = E->ridley_var_C; + v1 = (int16)(tilemap_stuff[7] + ridley_var_C) < 0; + E->ridley_var_C = tilemap_stuff[7] + ridley_var_C; + if (!v1) { + E->ridley_var_C = 0; + E->ridley_var_A = FUNC16(Ridley_Func_21); + } + } +} + +uint8 Ridley_Func_23(void) { // 0xA6B7E7 + uint8 v0 = Ridley_Func_103(tilemap_stuff[82], tilemap_stuff[83] + 16) & 1; + if (!v0) { + v0 = Ridley_Func_103(tilemap_stuff[72], tilemap_stuff[73] + 18) & 1; + if (!v0) { + v0 = Ridley_Func_103(tilemap_stuff[62], tilemap_stuff[63] + 18) & 1; + if (!v0) { + v0 = Ridley_Func_103(tilemap_stuff[52], tilemap_stuff[53] + 18) & 1; + if (!v0) + return Ridley_Func_103(tilemap_stuff[42], tilemap_stuff[43] + 18) & 1; + } + } + } + return v0; +} + +void Ridley_Func_24(void) { // 0xA6B84D + tilemap_stuff[0] = 1; + tilemap_stuff[10] = 1; +} + +uint8 Ridley_Func_25(void) { // 0xA6B859 + if ((Ridley_Func_40_Carry() & 1) != 0) + return Ridley_Func_26(4u, 4u) & 1; + else + return 0; +} + +uint8 Ridley_Func_26(uint16 k, uint16 j) { // 0xA6B865 + R22_ = k; + R24_ = j; + Enemy_Ridley *E = Get_Ridley(0); + R18_ = E->base.x_pos + g_word_A6B9D5[E->ridley_var_10]; + R20_ = E->base.y_pos + g_word_A6B9DB[E->ridley_var_1D >> 1]; + return Ridley_Func_124() & 1; +} + +void Ridley_Func_27(void) { // 0xA6B889 + int16 ridley_var_C; + + Enemy_Ridley *E = Get_Ridley(0); + ridley_var_C = E->ridley_var_C; + if (ridley_var_C >= 0) + ridley_var_C = -ridley_var_C; + if (!sign16(ridley_var_C + 512)) + ridley_var_C = -512; + E->ridley_var_C = ridley_var_C; + Ridley_Func_24(); + E->ridley_var_A = FUNC16(Ridley_Func_33b); + Ridley_Func_33b(); +} + +void Ridley_Func_28(void) { // 0xA6B8A9 + Enemy_Ridley *E = Get_Ridley(0); + if (!E->ridley_var_B) + E->ridley_var_B = E->base.x_pos & 0x80 ? -0xc0 : 0xc0; + if (((E->ridley_var_B ^ (E->base.x_pos - samus_x_pos)) & 0x8000u) == 0) { + uint16 x_pos; + x_pos = E->base.x_pos; + if ((int16)(x_pos - E->ridley_var_22) >= 0) { + if ((int16)(x_pos - E->ridley_var_23) < 0) { + if (random_number < 0x555u) + return; + goto LABEL_7; + } + goto LABEL_15; + } +LABEL_13: + if ((E->ridley_var_B & 0x8000u) == 0) + return; +LABEL_7: + E->ridley_var_B = -E->ridley_var_B; + return; + } + uint16 v4; + v4 = E->base.x_pos; + if ((int16)(v4 - E->ridley_var_22) < 0) + goto LABEL_13; + if ((int16)(v4 - E->ridley_var_23) >= 0) { +LABEL_15: + if ((E->ridley_var_B & 0x8000u) != 0) + return; + goto LABEL_7; + } + if (random_number < 0x555u) + goto LABEL_7; +} + +void Ridley_Func_29(void) { // 0xA6B90F + int v0 = random_number & 3; + R18_ = g_off_A6B965[v0]; + R20_ = g_off_A6B96D[v0]; + Enemy_Ridley *E = Get_Ridley(0); + uint16 v2 = 2 * (E->ridley_var_12 + 2); + int v3 = v2 >> 1; + tilemap_stuff[7] = g_word_A6B94D[v3]; + tilemap_stuff[6] = g_word_A6B959[v3]; + E->ridley_var_C = *(uint16 *)&RomPtr_A6(R20_)[v2]; + uint8 *v4 = RomPtr_A6(R18_); + uint16 t = *(uint16 *)&v4[v2]; + E->ridley_var_B = sign16(E->ridley_var_B) ? -t : t; +} + +void Ridley_Func_30(void) { // 0xA6B9E1 + int16 v2; + int16 v5; + + Enemy_Ridley *E = Get_Ridley(0); + uint16 ridley_var_14 = E->ridley_var_14, v3, v6; + if (ridley_var_14) { + R18_ = E->ridley_var_14; + v2 = abs16(ridley_var_14) - 4; + if (v2 >= 0) + v3 = sign16(ridley_var_14) ? -v2 : v2; + else + v3 = 0; + E->ridley_var_14 = v3; + } + uint16 ridley_var_15 = E->ridley_var_15; + if (ridley_var_15) { + R18_ = E->ridley_var_15; + v5 = abs16(ridley_var_15) - 4; + if (v5 >= 0) + v6 = sign16(ridley_var_15) ? -v5 : v5; + else + v6 = 0; + E->ridley_var_15 = v6; + } + samus_x_pos = E->ridley_var_14 + + E->base.x_pos + + g_word_A6B9D5[E->ridley_var_10]; + samus_y_pos = E->ridley_var_15 + E->base.y_pos + g_word_A6B9DB[E->ridley_var_1D >> 1]; +} + +void Ridley_Func_31(void) { // 0xA6BA54 + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_14 = samus_x_pos + - (E->base.x_pos + + g_word_A6B9D5[E->ridley_var_10]); + E->ridley_var_15 = samus_y_pos - (E->base.y_pos + g_word_A6B9DB[E->ridley_var_1D >> 1]); +} + +void Ridley_Func_32(void) { // 0xA6BA85 + Enemy_Ridley *E = Get_Ridley(0); + if (sign16(E->ridley_var_25 - 10)) { + if (power_bomb_flag) { + E->ridley_var_A = FUNC16(Ridley_Func_43); + Ridley_Func_43(); + } else { + E->ridley_var_A = FUNC16(Ridley_Func_5); + tilemap_stuff[2] = 1; + } + } else { + Ridley_Func_126(); + E->ridley_var_A = FUNC16(Ridley_C53E); + Ridley_C53E(); + } +} + +void Ridley_Func_33(void) { // 0xA6BAB7 + Enemy_Ridley *E = Get_Ridley(0); + uint16 v1; + int16 v2; + + if ((Ridley_Func_40_Carry() & 1) != 0 + && (!E->ridley_var_1F) + && ((R18_ = g_word_A6BB48[E->ridley_var_10], + R20_ = E->base.x_pos - samus_x_pos, + ((R18_ ^ R20_) & 0x8000u) == 0) + || (v1 = abs16(R20_), sign16(v1 - 32))) + && (int16)(E->base.y_pos + 35 - samus_y_pos) < 0) { + v2 = -16; + if (E->ridley_var_10) + v2 = 16; + R18_ = samus_x_pos + v2; + R20_ = samus_y_pos - 4; + Ridley_Func_104_0(0, g_word_A6BB4E[E->ridley_var_12]); + R18_ = E->base.x_pos + g_word_A6B9D5[E->ridley_var_10]; + R20_ = E->base.y_pos + 35; + R22_ = 8; + R24_ = 12; + if (Ridley_Func_124() & 1) { + E->ridley_var_C = -E->ridley_var_C; + if (E->base.health) { + if (power_bomb_flag) { + Ridley_Func_37(); + E->ridley_var_A = FUNC16(Ridley_Func_43); + Ridley_Func_43(); + } else { + Ridley_Func_33b(); + } + } else { + if (!E->ridley_var_1B) + Ridley_Func_37(); + Ridley_Func_126(); + E->ridley_var_A = FUNC16(Ridley_Func_63); + Ridley_Func_63(); + } + } + } else { + Ridley_Func_32(); + } +} + +void Ridley_Func_33b(void) { // 0xA6BB8F + int16 v1; + + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_17 = g_word_A6BBEB[E->ridley_var_10]; + v1 = E->base.y_pos - 64; + if (sign16(E->base.y_pos - 320)) + v1 = 256; + E->ridley_var_18 = v1; + if (!E->ridley_var_1B) + Ridley_Func_37(); + E->ridley_var_A = FUNC16(Ridley_Func_34); + E->ridley_var_F = 32; + Ridley_Func_34(); +} + +void Ridley_Func_34(void) { // 0xA6BBC4 + Enemy_Ridley *E = Get_Ridley(0); + R18_ = E->ridley_var_17; + R20_ = E->ridley_var_18; + Ridley_Func_104_0(0, 0); + if ((--E->ridley_var_F & 0x8000u) != 0) { + E->ridley_var_A = FUNC16(Ridley_Func_35); + E->ridley_var_F = 32; + } +} + +void Ridley_Func_35(void) { // 0xA6BBF1 + Enemy_Ridley *E = Get_Ridley(0); + if ((--E->ridley_var_F & 0x8000u) != 0) { + tilemap_stuff[15] = 8; + tilemap_stuff[9] = 240; + Ridley_Func_38(); + E->ridley_var_A = FUNC16(Ridley_Func_36); + E->ridley_var_F = 64; + } else { + R18_ = E->ridley_var_17; + R20_ = 256; + Ridley_Func_104_0(0, 0); + } +} + +void Ridley_Func_36(void) { // 0xA6BC2E + Enemy_Ridley *E = Get_Ridley(0); + if ((--E->ridley_var_F & 0x8000u) != 0) { + tilemap_stuff[15] = 16; + tilemap_stuff[9] = 240; + E->ridley_var_A = FUNC16(Ridley_Func_3b); + } else { + R18_ = g_word_A6BC62[E->ridley_var_10]; + R20_ = 224; + Ridley_Func_104_0(0, 0); + } +} + +void Ridley_Func_37(void) { // 0xA6BC68 + Ridley_Func_31(); + Enemy_Ridley *E = Get_Ridley(0); + E->base.properties |= kEnemyProps_Tangible; + E->ridley_var_1B = 1; + CallSomeSamusCode(0); + Ridley_Func_119(1); +} + +void Ridley_Func_38(void) { // 0xA6BC84 + tilemap_stuff[2] = 1; + tilemap_stuff[0] = 1; + Enemy_Ridley *E = Get_Ridley(0); + if ((E->ridley_var_01 & 0x8000u) == 0) { + E->ridley_var_1E = Ridley_Func_40_Sign() ? 6 : 10; + } + E->ridley_var_1B = 0; + CallSomeSamusCode(1u); + Ridley_Func_119(0); +} + +void Ridley_Func_39(void) { // 0xA6BCB4 + int16 ridley_var_01; + + Enemy_Ridley *E = Get_Ridley(0); + ridley_var_01 = E->ridley_var_01; + if (ridley_var_01 >= 0) { + if (ridley_var_01) { + if (Ridley_Func_121() & 1) { + E->base.properties |= kEnemyProps_Tangible; + return; + } + E->base.properties &= ~kEnemyProps_Tangible; + } + uint16 ridley_var_1E = E->ridley_var_1E; + if (ridley_var_1E) { + uint16 v3 = ridley_var_1E - 1; + E->ridley_var_1E = v3; + if (!v3 && (E->ridley_var_01 & 0x8000u) == 0) + E->base.properties &= ~kEnemyProps_Tangible; + } + } +} + +static const uint8 byte_A6BD04[28] = { + 0x80, 0x80, 0x80, 0, 0xff, 0x80, 0x80, 0xff, 0xff, 0xff, 0x80, 0, 0, 0x80, 0x80, 0x80, + 0x80, 0xff, 0xff, 0xff, 0x80, 0x80, 0, 0x80, 0x80, 0, 0, 0x80, +}; + +uint8 Ridley_Func_40_Carry(void) { + return (byte_A6BD04[samus_movement_type] & 0x80) != 0; +} + +uint8 Ridley_Func_40_Sign(void) { + return (byte_A6BD04[samus_movement_type] & 0x40) != 0; +} + + +uint8 Ridley_Func_41(void) { // 0xA6BD20 + return sign16(samus_y_pos - 352) == 0; +} + +void Ridley_Func_42(void) { // 0xA6BD2C + int16 ridley_var_01; + + Enemy_Ridley *E = Get_Ridley(0); + ridley_var_01 = E->ridley_var_01; + if (ridley_var_01 > 0 && ridley_var_01 != 2 && power_bomb_flag && !E->ridley_var_1B) { + Ridley_Func_24(); + E->ridley_var_A = FUNC16(Ridley_Func_33); + } +} + +void Ridley_Func_43(void) { // 0xA6BD4E + if (power_bomb_flag) { + Get_Ridley(0)->ridley_var_01 = 2; + uint16 v0 = 80; + if (sign16(power_bomb_explosion_x_pos - 128)) + v0 = 192; + R18_ = v0; + uint16 v1 = 192; + if (sign16(power_bomb_explosion_y_pos - 256)) + v1 = 384; + R20_ = v1; + uint16 v2 = Ridley_Func_7(); + Ridley_Func_104_0(0, v2); + } else { + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_01 = 1; + E->ridley_var_A = E->ridley_var_1B ? FUNC16(Ridley_Func_33b) : FUNC16(Ridley_Func_3b); + } +} + +void Ridley_Func_44(void) { // 0xA6BD9A + R18_ = 192; + R20_ = 128; + Ridley_Func_106(0, 1u); + Enemy_Ridley *E = Get_Ridley(0); + if (!sign16(E->base.x_pos - 192)) + E->ridley_var_A = FUNC16(Ridley_Func_45); +} + +void Ridley_Func_45(void) { // 0xA6BDBC + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_20 = -192; + R18_ = 192; + R20_ = -128; + Ridley_Func_106(0, 1u); + if (sign16(E->base.y_pos - 32)) { + E->ridley_var_40 = FUNC16(Ridley_Func_52); + E->ridley_var_A = FUNC16(Ridley_Func_46); + E->ridley_var_F = 21; + } +} + +void Ridley_Func_46(void) { // 0xA6BDF2 + Enemy_Ridley *E = Get_Ridley(0); + if ((--E->ridley_var_F & 0x8000u) != 0) { + Ridley_Func_99(addr_kRidley_Ilist_E658); + E->ridley_var_A = FUNC16(Ridley_Func_47); + Ridley_Func_47(); + } +} + +void Ridley_Func_47(void) { // 0xA6BE03 + Enemy_Ridley *E = Get_Ridley(0); + R18_ = E->ridley_var_42 - 10; + R20_ = E->ridley_var_44 - 56; + Ridley_Func_104_0(0, 12); + R18_ = E->base.x_pos + 14; + R20_ = E->base.y_pos + 66; + R22_ = 4; + R24_ = 4; + if (Ridley_Func_48() & 1) { + E->ridley_var_1B = 1; + Ridley_Func_119(1); + E->ridley_var_C = -512; + E->ridley_var_40 = FUNC16(Ridley_Func_51); + E->ridley_var_A = FUNC16(CeresRidley_Func_22); + } +} + +uint8 Ridley_Func_48(void) { // 0xA6BE61 + Enemy_Ridley *E = Get_Ridley(0); + uint16 v1 = abs16(E->ridley_var_42 - R18_); + bool v2 = v1 < 4u; + uint16 v3 = v1 - 4; + uint8 result = 0; + if (v2 || v3 < R22_) { + uint16 v4 = abs16(E->ridley_var_44 - R20_); + v2 = v4 < 4u; + uint16 v5 = v4 - 4; + if (v2 || v5 < R24_) + return 1; + } + return result; +} + +void CallRidleyFunc_var40(uint32 ea) { + switch (ea) { + case fnRidley_Func_50: Ridley_Func_50(); return; + case fnRidley_Func_51: Ridley_Func_51(); return; // 0xa6beb3 + case fnRidley_Func_52: Ridley_Func_52(); return; // 0xa6beca + case fnRidley_Func_53: Ridley_Func_53(); return; // 0xa6bedc + case fnnullsub_348: return; // 0xa6bf19 + default: Unreachable(); + } +} + +void Ridley_Func_49(void) { // 0xA6BE93 + R18_ = Get_Ridley(0)->ridley_var_40; + CallRidleyFunc_var40(R18_ | 0xA60000); +} + +void Ridley_Func_50(void) { // 0xA6BE9C + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_42 = E->base.x_pos - 16; + E->ridley_var_44 = E->base.y_pos + 22; +} + +void Ridley_Func_51(void) { // 0xA6BEB3 + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_42 = E->base.x_pos + 14; + E->ridley_var_44 = E->base.y_pos + 66; +} + +void Ridley_Func_52(void) { // 0xA6BECA + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_45 = 0; + E->ridley_var_46 = 0; + E->ridley_var_40 = FUNC16(Ridley_Func_53); + Ridley_Func_53(); +} + +void Ridley_Func_53(void) { // 0xA6BEDC + int16 v2; + char v3; // t0 + + Enemy_Ridley *E = Get_Ridley(0); + uint16 v1 = E->ridley_var_46 + 8; + E->ridley_var_46 = v1; + LOBYTE(v1) = HIBYTE(E->ridley_var_43) + v1; + HIBYTE(E->ridley_var_43) = v1; + v1 &= 0xFF00u; + v3 = v1; + LOBYTE(v2) = HIBYTE(v1); + HIBYTE(v2) = v3; + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + uint16 v4 = E->ridley_var_44 + v2; + E->ridley_var_44 = v4; + if (!sign16(v4 - 192)) { + E->ridley_var_44 = 192; + E->ridley_var_40 = addr_locret_A6BF19; + } +} + +void DrawBabyMetroid_0(void) { // 0xA6BF1A + int v0 = BabyMetroid_DBCB_DoubleRetEx(ADDR16_OF_RAM(*enemy_ram7800) + 6); + if (v0 < 0) + return; + Enemy_Ridley *E = Get_Ridley(0); + R18_ = E->ridley_var_42; + R20_ = E->ridley_var_44; + R22_ = 0; + sub_A6DC13(v0); +} + +uint16 BabyMetroid_Instr_2(uint16 k) { // 0xA6BFC9 + if (!Get_Ridley(0)->ridley_var_46 && (random_number & 1) != 0) + return BabyMetroid_Instr_4(k); + QueueSfx3_Max6(0x24u); + return BabyMetroid_Incr2(k); +} + +uint16 BabyMetroid_Incr2(uint16 k) { // 0xA6BFDE + return k + 2; +} + +uint16 BabyMetroid_Instr_3(uint16 k) { // 0xA6BFE1 + uint16 v1 = *(uint16 *)RomPtr_A6(k); + WriteColorsToPalette(0x162u, 0xa6, v1, 0xFu); + return BabyMetroid_Incr2(k); +} + +uint16 BabyMetroid_Instr_1(uint16 k) { // 0xA6BFF2 + if (Get_Ridley(0)->ridley_var_46) + return BabyMetroid_Instr_4(k); + else + return BabyMetroid_Incr2(k); +} + +uint16 BabyMetroid_Instr_4(uint16 k) { // 0xA6BFF8 + return *(uint16 *)RomPtr_A6(k); +} + +void Ridley_Func_54(void) { // 0xA6C04E + uint16 ridley_var_F = Get_Ridley(0)->ridley_var_F; + if (ridley_var_F) { + switch (ridley_var_F) { + case 2u: + Ridley_C08E(); + break; + case 4u: + Ridley_C09F(); + break; + case 6u: + Ridley_Func_56(); + break; + case 8u: + Ridley_Func_57(); + break; + case 0xAu: + Ridley_C104(); + break; + case 0xCu: + Ridley_Func_58(); + break; + default: + Unreachable(); + while (1) + ; + } + } else { + Ridley_Func_55(); + } +} + +void Ridley_Func_55(void) { // 0xA6C062 + palette_buffer[97] = palette_buffer[1]; + palette_buffer[99] = palette_buffer[3]; + palette_buffer[81] = palette_buffer[17]; + palette_buffer[83] = palette_buffer[19]; + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_E = -15157; + ++E->ridley_var_F; + ++E->ridley_var_F; + Ridley_C08E(); +} + +void Ridley_C08E(void) { // 0xA6C08E + if (ProcessEscapeTimerTileTransfers() & 1) { + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_E = -15106; + ++E->ridley_var_F; + ++E->ridley_var_F; + Ridley_C09F(); + } +} + +void Ridley_C09F(void) { // 0xA6C09F + if (ProcessEscapeTimerTileTransfers() & 1) { + Enemy_Ridley *E = Get_Ridley(0); + ++E->ridley_var_F; + ++E->ridley_var_F; + Ridley_Func_59(); + E->ridley_var_E = 128; + QueueMusic_Delayed8(7u); + } +} + +void Ridley_Func_56(void) { // 0xA6C0BB + Ridley_Func_61(); + Enemy_Ridley *E = Get_Ridley(0); + if (E->ridley_var_E-- == 1) { + E->ridley_var_3B = -15280; + E->ridley_var_3C = 0; + E->ridley_var_3D = 0; + E->ridley_var_3E = 0; + E->ridley_var_3F = 0; + E->ridley_var_E = 32; + if (!japanese_text_flag) { + ++E->ridley_var_F; + ++E->ridley_var_F; + } + ++E->ridley_var_F; + ++E->ridley_var_F; + } +} + +void Ridley_Func_57(void) { // 0xA6C0F5 + Enemy_Ridley *E = Get_Ridley(0); + if (E->ridley_var_E-- == 1) { + ++E->ridley_var_F; + ++E->ridley_var_F; + Ridley_Func_62(); + } + Ridley_C104(); +} + +void Ridley_C104(void) { // 0xA6C104 + Ridley_Func_61(); + if (HandleTypewriterText_Ext(0x3582u) & 1) { + Enemy_Ridley *E = Get_Ridley(0); + ++E->ridley_var_F; + ++E->ridley_var_F; + } +} + +void Ridley_Func_58(void) { // 0xA6C117 + Ridley_Func_61(); + CeresRidley_Func_2(); + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_F = 0; + E->ridley_var_A = FUNC16(CeresRidley_Func_26); + timer_status = 1; + ceres_status = 2; + SetBossBitForCurArea(1u); +} + +void Ridley_Func_59(void) { // 0xA6C136 + VramWriteEntry *v2; + + uint16 v0 = vram_write_queue_tail; + uint8 *v1 = RomPtr_A6(addr_byte_A6C15D); + v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = *(uint16 *)v1; + *(VoidP *)((char *)&v2->src.addr + 1) = *(uint16 *)(v1 + 3); + v2->src.addr = *((uint16 *)v1 + 1); + v2->vram_dst = *(uint16 *)(v1 + 5); + vram_write_queue_tail = v0 + 7; +} + +void Ridley_Func_60(void) { // 0xA6C176 + int16 v1; + + Enemy_Ridley *E = Get_Ridley(0); + v1 = E->ridley_var_39 + 1; + if (!sign16(E->ridley_var_39 - 31)) + v1 = -31; + E->ridley_var_39 = v1; + palette_buffer[11] = abs16(E->ridley_var_39) & 0x1F; +} + +void Ridley_Func_61(void) { // 0xA6C19C + if (!(door_transition_flag_enemies | palette_change_num) && (nmi_frame_counter_word & 3) == 0) { + Enemy_Ridley *E = Get_Ridley(0); + uint16 v1 = E->ridley_var_38 + 1; + if (v1 >= 0x10u) + v1 = 0; + E->ridley_var_38 = v1; + int v2 = (uint16)(2 * (E->ridley_var_38 + 2 * v1)) >> 1; + palette_buffer[97] = g_word_A6C1DF[v2]; + palette_buffer[98] = g_word_A6C1DF[v2 + 1]; + palette_buffer[99] = g_word_A6C1DF[v2 + 2]; + } +} + +void SetupZebesEscapeTypewriter(void) { // 0xA6C23F + palette_buffer[157] = palette_buffer[125]; + palette_buffer[158] = palette_buffer[126]; + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_3B = addr_loc_A9C49C; + E->mbn_var_3C = 0; + E->mbn_var_3D = 0; + E->mbn_var_3E = 0; + E->mbn_var_3F = 0; + reg_BG2HOFS = 0; + reg_BG2VOFS = 0; +} + +uint8 ProcessEscapeTimerTileTransfers(void) { // 0xA6C26E + VramWriteEntry *v4; + + EnemyData *v0 = gEnemyData(0); + uint16 ai_var_E = v0->ai_var_E; + uint16 v2 = vram_write_queue_tail; + uint8 *v3 = RomPtr_A6(ai_var_E); + uint8 result = 1; + if (*(uint16 *)v3) { + v4 = gVramWriteEntry(vram_write_queue_tail); + v4->size = *(uint16 *)v3; + *(VoidP *)((char *)&v4->src.addr + 1) = *(uint16 *)(v3 + 3); + v4->src.addr = *((uint16 *)v3 + 1); + v4->vram_dst = *(uint16 *)(v3 + 5); + vram_write_queue_tail = v2 + 7; + v0->ai_var_E = ai_var_E + 7; + if (*(uint16 *)RomPtr_A6(v0->ai_var_E)) + return 0; + } + return result; +} + +uint8 HandleTypewriterText_Ext(uint16 a) { // 0xA6C2A7 + R18_ = a; + return HandleTypewriterText() & 1; +} + +uint8 HandleTypewriterText(void) { // 0xA6C2B1 + int16 v4; + VramWriteEntry *v12; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + uint16 mbn_var_3D = E->mbn_var_3D; + if (mbn_var_3D) { + E->mbn_var_3D = mbn_var_3D - 1; + return 0; + } else { + E->mbn_var_3D = E->mbn_var_3E; + int i, v7; + for (i = E->mbn_var_3B; ; i = v7 + 2) { + while (1) { + v4 = *(uint16 *)RomPtr_A6(i); + if (!v4) + return 1; + if (v4 != 1) + break; + uint16 v5 = i + 2; + uint16 v6 = *(uint16 *)RomPtr_A6(v5); + E->mbn_var_3E = v6; + i = v5 + 2; + } + if (v4 != 13) + break; + v7 = i + 2; + uint16 v8 = *(uint16 *)RomPtr_A6(v7); + E->mbn_var_3C = v8; + } + v4 = (uint8)v4; + if ((uint8)v4 == 32) { + ++E->mbn_var_3C; + E->mbn_var_3B = i + 1; + return 0; + } else { + if ((uint8)v4 == 33) + v4 = 91; + E->mbn_var_3B = i + 1; + uint16 v11 = vram_write_queue_tail; + v12 = gVramWriteEntry(vram_write_queue_tail); + v12->size = 2; + *(VoidP *)((char *)&v12->src.addr + 1) = 32256; + E->mbn_var_3A = R18_ + v4 - 65; + v12->src.addr = ADDR16_OF_RAM(*extra_enemy_ram8000) + 52; + uint16 mbn_var_3C = E->mbn_var_3C; + v12->vram_dst = mbn_var_3C; + E->mbn_var_3C = mbn_var_3C + 1; + vram_write_queue_tail = v11 + 7; + uint16 v14 = E->mbn_var_3F + 1; + E->mbn_var_3F = v14; + if (!sign16(v14 - 2)) { + E->mbn_var_3F = 0; + if (area_index == 6) + QueueSfx2_Max3(0x45u); + else + QueueSfx3_Max3(0xDu); + } + return 0; + } + } +} + +void Ridley_Func_62(void) { // 0xA6C383 + int i; + VramWriteEntry *v3; + + uint16 v0 = addr_stru_A6C3B8; + for (i = vram_write_queue_tail; ; i += 7) { + uint8 *v2 = RomPtr_A6(v0); + if (!*(uint16 *)v2) + break; + v3 = gVramWriteEntry(i); + v3->size = *(uint16 *)v2; + *(VoidP *)((char *)&v3->src.addr + 1) = *(uint16 *)(v2 + 3); + v3->src.addr = *((uint16 *)v2 + 1); + v3->vram_dst = *(uint16 *)(v2 + 5); + v0 += 7; + } + vram_write_queue_tail = i; +} + +void Ridley_Func_63(void) { // 0xA6C538 + if (!(Ridley_Func_68() & 1)) + Ridley_C53E(); +} + +void Ridley_C53E(void) { // 0xA6C53E + Ridley_Func_99(addr_kRidley_Ilist_E6C8); + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_A = FUNC16(Ridley_C551); + E->ridley_var_F = 32; +} + +void Ridley_C551(void) { // 0xA6C551 + Ridley_Func_68(); + Enemy_Ridley *E = Get_Ridley(0); + if ((--E->ridley_var_F & 0x8000u) != 0) { + E->ridley_var_B = 0; + E->ridley_var_C = 0; + fx_target_y_pos = 528; + fx_y_vel = 64; + fx_timer = 1; + E->ridley_var_27 = 0; + E->ridley_var_28 = 0; + E->ridley_var_A = FUNC16(Ridley_Func_64); + E->ridley_var_F = 160; + Ridley_Func_64(); + } +} + +void Ridley_Func_64(void) { // 0xA6C588 + Ridley_Func_69(); + Enemy_Ridley *E = Get_Ridley(0); + if ((--E->ridley_var_F & 0x8000u) != 0) { + if (E->ridley_var_1B) + Ridley_Func_38(); + E->ridley_var_A = FUNC16(Ridley_Func_65); + E->ridley_var_B = 0; + E->ridley_var_C = 0; + RidleysExplosion_Func_2(); + } +} + +void Ridley_Func_65(void) { // 0xA6C5A8 + Ridley_Func_69(); + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_02 = 0; + E->base.properties |= kEnemyProps_Invisible; + E->ridley_var_A = FUNC16(Ridley_Func_66); + E->ridley_var_F = 32; +} + +void Ridley_Func_66(void) { // 0xA6C5C8 + Enemy_Ridley *E = Get_Ridley(0); + if ((--E->ridley_var_F & 0x8000u) != 0) { + E->ridley_var_A = FUNC16(Ridley_Func_67); + E->ridley_var_F = 256; + } +} + +void Ridley_Func_67(void) { // 0xA6C5DA + Enemy_Ridley *E = Get_Ridley(0); + if ((--E->ridley_var_F & 0x8000u) != 0) { + uint16 k = 0; + printf("Warning: X undefined\n"); + SetBossBitForCurArea(1u); + Enemy_ItemDrop_Ridley(k); + QueueMusic_Delayed8(3u); + E->base.properties |= kEnemyProps_Deleted; + E->ridley_var_A = addr_locret_A6C600; + } +} + +uint8 Ridley_Func_68(void) { // 0xA6C601 + R18_ = 128; + R20_ = 328; + Ridley_Func_104(0, 0, 0x10u); + R22_ = 4; + R24_ = 4; + return Shitroid_Func_2(0) & 1; +} + +void Ridley_Func_69(void) { // 0xA6C623 + int16 v1; + + Enemy_Ridley *E = Get_Ridley(0); + v1 = E->ridley_var_27 - 1; + if (v1 < 0) { + E->ridley_var_27 = 4; + uint16 v2 = E->ridley_var_28 + 1; + if (!sign16(E->ridley_var_28 - 9)) + v2 = 0; + E->ridley_var_28 = v2; + int v3 = (uint16)(4 * v2) >> 1; + R18_ = E->base.x_pos + g_word_A6C66E[v3]; + R20_ = E->base.y_pos + g_word_A6C66E[v3 + 1]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 3u); + QueueSfx2_Max3(0x24u); + } else { + E->ridley_var_27 = v1; + } +} + +void RidleysExplosion_Init(void) { // 0xA6C696 + Enemy_Ridley *E = Get_Ridley(cur_enemy_index); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.vram_tiles_index = 0; + E->base.palette_index = 3584; + uint16 ridley_parameter_1 = E->ridley_parameter_1; + E->ridley_var_F = g_word_A6C6CE[ridley_parameter_1 >> 1]; + uint16 Random = NextRandom(); + E->ridley_var_B = sign16(Random) ? -(Random & 0x130) : (Random & 0x130); + E->ridley_var_C = 0; + if (ridley_parameter_1) { + switch (ridley_parameter_1) { + case 2u: + E->base.x_pos = tilemap_stuff[32]; + E->base.y_pos = tilemap_stuff[33]; + E->base.current_instruction = addr_kRidleysExplosion_Ilist_CA47; + break; + case 4u: + E->base.x_pos = tilemap_stuff[42]; + E->base.y_pos = tilemap_stuff[43]; + E->base.current_instruction = addr_kRidleysExplosion_Ilist_CA4D; + break; + case 6u: + E->base.x_pos = tilemap_stuff[52]; + E->base.y_pos = tilemap_stuff[53]; + E->base.current_instruction = addr_kRidleysExplosion_Ilist_CA4D; + break; + case 8u: + E->base.x_pos = tilemap_stuff[62]; + E->base.y_pos = tilemap_stuff[63]; + E->base.current_instruction = addr_kRidleysExplosion_Ilist_CA53; + break; + case 0xAu: + E->base.x_pos = tilemap_stuff[72]; + E->base.y_pos = tilemap_stuff[73]; + E->base.current_instruction = addr_kRidleysExplosion_Ilist_CA53; + break; + case 0xCu: + E->base.x_pos = tilemap_stuff[82]; + E->base.y_pos = tilemap_stuff[83]; + E->base.current_instruction = g_off_A6C7BA[(uint16)((uint8)((LOBYTE(tilemap_stuff[71]) + + LOBYTE(tilemap_stuff[81]) + + 8) & 0xF0) >> 3) >> 1]; + break; + case 0xEu: { + uint16 v10 = 0; + Enemy_Ridley *E0 = Get_Ridley(0); + if (E0->ridley_var_10) + v10 = 2; + int v13 = v10 >> 1; + uint16 v14 = E0->base.x_pos + g_word_A6C804[v13]; + E->base.x_pos = v14; + E->base.y_pos = E0->base.y_pos; + E->base.current_instruction = g_off_A6C808[v13]; + break; + } + case 0x10u: { + uint16 v16 = 0; + Enemy_Ridley *E0 = Get_Ridley(0); + if (E0->ridley_var_10) + v16 = 2; + int v19 = v16 >> 1; + uint16 v20 = E0->base.x_pos + g_word_A6C836[v19]; + E->base.x_pos = v20; + E->base.y_pos = E0->base.y_pos + 22; + E->base.current_instruction = g_off_A6C83A[v19]; + break; + } + case 0x12u: { + uint16 v22 = 0; + Enemy_Ridley *E0 = Get_Ridley(0); + if (E0->ridley_var_10) + v22 = 2; + int v25 = v22 >> 1; + uint16 v26 = E0->base.x_pos + g_word_A6C868[v25]; + E->base.x_pos = v26; + E->base.y_pos = E0->base.y_pos - 24; + E->base.current_instruction = g_off_A6C86C[v25]; + break; + } + case 0x14u: { + uint16 v28 = 0; + Enemy_Ridley *E0 = Get_Ridley(0); + if (E0->ridley_var_10) + v28 = 2; + int v31 = v28 >> 1; + uint16 v32 = E0->base.x_pos + g_word_A6C89A[v31]; + E->base.x_pos = v32; + E->base.y_pos = E0->base.y_pos; + E->base.current_instruction = g_off_A6C89E[v31]; + break; + } + case 0x16u: { + uint16 v34 = 0; + Enemy_Ridley *E0 = Get_Ridley(0); + if (E0->ridley_var_10) + v34 = 2; + int v37 = v34 >> 1; + uint16 v38 = E0->base.x_pos + g_word_A6C8CC[v37]; + E->base.x_pos = v38; + E->base.y_pos = E0->base.y_pos + 7; + E->base.current_instruction = g_off_A6C8D0[v37]; + break; + } + default: + Unreachable(); + while (1) + ; + } + } else { + E->base.x_pos = tilemap_stuff[22]; + E->base.y_pos = tilemap_stuff[23]; + E->base.current_instruction = addr_kRidleysExplosion_Ilist_CA47; + } +} + +void RidleysExplosion_Main(void) { // 0xA6C8D4 + int16 v2; + + RidleysExplosion_Func_1(cur_enemy_index); + Enemy_RidleysExplosion *E = Get_RidleysExplosion(cur_enemy_index); + v2 = abs16(E->ren_var_B) - 4; + if (v2 < 0) + v2 = 0; + E->ren_var_B = sign16(E->ren_var_B) ? -v2 : v2; + E->ren_var_C += 4; + MoveEnemyWithVelocity(); + if ((--E->ren_var_F & 0x8000u) != 0) + EnemyDeathAnimation(cur_enemy_index, 0); +} + +void RidleysExplosion_Func_1(uint16 k) { // 0xA6C913 + Enemy_RidleysExplosion *E = Get_RidleysExplosion(k); + uint16 v2 = E->base.frame_counter & 1, v3; + E->base.frame_counter = v2; + if (v2) + v3 = E->base.properties | kEnemyProps_Invisible; + else + v3 = E->base.properties & ~kEnemyProps_Invisible; + E->base.properties = v3; +} + +void RidleysExplosion_Func_2(void) { // 0xA6C932 + SpawnEnemy(0xA6u, addr_stru_A6C9E7); + SpawnEnemy(0xA6u, addr_stru_A6C9D7); + SpawnEnemy(0xA6u, addr_stru_A6C9C7); + SpawnEnemy(0xA6u, addr_stru_A6C9B7); + SpawnEnemy(0xA6u, addr_stru_A6C9A7); + SpawnEnemy(0xA6u, addr_stru_A6C997); + SpawnEnemy(0xA6u, addr_stru_A6C987); + SpawnEnemy(0xA6u, addr_stru_A6C9F7); + SpawnEnemy(0xA6u, addr_stru_A6CA07); + SpawnEnemy(0xA6u, addr_stru_A6CA27); + SpawnEnemy(0xA6u, addr_stru_A6CA17); + SpawnEnemy(0xA6u, addr_stru_A6CA37); +} + +void locret_A6CB20(void) {} +static Func_V *const off_A6CB21[9] = { locret_A6CB20, Ridley_CBC0, Ridley_Func_71, Ridley_Func_72, Ridley_CBC7, Ridley_CBCE, Ridley_Func_73, Ridley_Func_74, Ridley_CBD5 }; + +void Ridley_Func_70(void) { // 0xA6CAF5 + Ridley_Func_91(); + off_A6CB21[tilemap_stuff[0]](); + Ridley_Func_86(); + Ridley_Func_87(); + Enemy_Ridley *E = Get_Ridley(0); + if (!(E->ridley_var_1B | (uint16)(samus_invincibility_timer | E->base.properties & kEnemyProps_Tangible))) + Ridley_Func_127(); +} + +void Ridley_Func_71(void) { // 0xA6CB33 + tilemap_stuff[10] = 8; + Ridley_Func_75(); + tilemap_stuff[0] = 3; +} + +void Ridley_Func_72(void) { // 0xA6CB45 + tilemap_stuff[10] = 8; + Ridley_Func_75(); +} + +void Ridley_Func_73(void) { // 0xA6CB4E + tilemap_stuff[10] = 3; + Ridley_Func_75(); + tilemap_stuff[0] = 6; +} + +void Ridley_Func_74(void) { // 0xA6CB60 + tilemap_stuff[10] = 2; + Ridley_Func_75(); + tilemap_stuff[0] = 7; +} + +void Ridley_Func_75(void) { // 0xA6CB72 + if (Get_Ridley(0)->ridley_var_10) { + tilemap_stuff[13] = 0x4000; + tilemap_stuff[14] = -1; + } else { + tilemap_stuff[14] = 0x4000; + tilemap_stuff[13] = -1; + } + Ridley_CBC7(); + if (!(tilemap_stuff[76] | (uint16)(tilemap_stuff[66] | tilemap_stuff[56] | tilemap_stuff[46] | tilemap_stuff[36] | tilemap_stuff[26] | tilemap_stuff[16]))) + tilemap_stuff[0] = 4; +} + +void Ridley_CBC0(void) { // 0xA6CBC0 + R18_ = FUNC16(Ridley_Func_79); + Ridley_Func_79(); + Ridley_CBDC(); +} + +void Ridley_CBC7(void) { // 0xA6CBC7 + R18_ = FUNC16(Ridley_Func_83); + Ridley_Func_83(); + Ridley_CBDC(); +} + +void Ridley_CBCE(void) { // 0xA6CBCE + R18_ = FUNC16(Ridley_Func_84); + Ridley_Func_84(); + Ridley_CBDC(); +} + +void Ridley_CBD5(void) { // 0xA6CBD5 + R18_ = FUNC16(Ridley_Func_81); + Ridley_Func_81(); + Ridley_CBDC(); +} + +void Ridley_CBDC(void) { // 0xA6CBDC + int16 v0; + int16 v2; + + v0 = 7; + uint16 v1 = 0; + do { + v2 = v0; + Ridley_Func_88(v1); + v1 += 20; + v0 = v2 - 1; + } while (v2 != 1); +} + +void Ridley_Func_77(void) { // 0xA6CBFE + int v0 = (uint16)(2 * Get_Ridley(0)->ridley_var_10) >> 1; + tilemap_stuff[11] = g_word_A6CC12[v0]; + tilemap_stuff[12] = g_word_A6CC18[v0]; +} + +uint8 Ridley_Func_78(void) { // 0xA6CC1E + return (tilemap_stuff[76] & (uint16)(tilemap_stuff[66] & tilemap_stuff[56] & tilemap_stuff[46] & tilemap_stuff[36] & tilemap_stuff[26] & tilemap_stuff[16])) != 0; +} + +void Ridley_Func_79(void) { // 0xA6CC39 + Ridley_Func_77(); + if (Ridley_Func_78()) { + if (Ridley_Func_80_DoubleRet()) + return; + } + if (!(tilemap_stuff[76] | (uint16)(tilemap_stuff[66] | tilemap_stuff[56] | tilemap_stuff[46] | tilemap_stuff[36] | tilemap_stuff[26] | tilemap_stuff[16]))) { + tilemap_stuff[16] = FUNC16(Enemy_GrappleReact_NoInteract_A6); + tilemap_stuff[13] = -1; + tilemap_stuff[14] = -1; + uint16 v0 = 2; + if (samus_x_pos < 0x70u) + v0 = 1; + tilemap_stuff[10] = v0; + } +} + +uint8 Ridley_Func_80_DoubleRet(void) { // 0xA6CC7D + Enemy_Ridley *E = Get_Ridley(0); + bool retval = false; + uint16 v1; + if (tilemap_stuff[2] && (tilemap_stuff[13] & tilemap_stuff[14] & 0x8000u) != 0) + goto LABEL_7; + if (!tilemap_stuff[1]) + goto LABEL_9; + if ((uint8)random_number >= 0xF0u) { +LABEL_7: + v1 = tilemap_stuff[2] - 1; + goto LABEL_8; + } + if (abs16(samus_x_pos - E->base.x_pos) < 0x80) { + v1 = 0; +LABEL_8: + Ridley_Func_89(v1); + retval = true; + } +LABEL_9: + tilemap_stuff[2] = 0; + return retval; +} + +bool Ridley_Func_82_DoubleRet(); + +void Ridley_Func_81(void) { // 0xA6CCBD + Ridley_Func_77(); + if (Ridley_Func_78() & 1) { + if (Ridley_Func_82_DoubleRet()) + return; + } + if (!(tilemap_stuff[76] | (uint16)(tilemap_stuff[66] | tilemap_stuff[56] | tilemap_stuff[46] | tilemap_stuff[36] | tilemap_stuff[26] | tilemap_stuff[16]))) { + tilemap_stuff[16] = FUNC16(Enemy_GrappleReact_NoInteract_A6); + tilemap_stuff[13] = -1; + tilemap_stuff[14] = -1; + uint16 v0 = 2; + if (samus_x_pos < 0x70u) + v0 = 1; + tilemap_stuff[10] = v0; + } +} + +bool Ridley_Func_82_DoubleRet(void) { + if (tilemap_stuff[2]) { + if ((tilemap_stuff[13] & tilemap_stuff[14] & 0x8000u) != 0) { + Ridley_Func_89(1u); + tilemap_stuff[2] = 0; + return true; + } + } + return false; +} + +void Ridley_Func_83(void) { // 0xA6CD24 + Enemy_Ridley *E = Get_Ridley(0); + Ridley_Func_77(); + if (Ridley_Func_78() & 1 + && ((uint8)random_number >= 0xF0u + || (abs16(samus_x_pos - E->base.x_pos) < 0x80)) + && (tilemap_stuff[13] & tilemap_stuff[14] & 0x8000u) != 0) { + tilemap_stuff[13] = 16128; + tilemap_stuff[10] = 8; + } else if (!(tilemap_stuff[76] | (uint16)(tilemap_stuff[66] | tilemap_stuff[56] | tilemap_stuff[46] | tilemap_stuff[36] | tilemap_stuff[26] | tilemap_stuff[16]))) { + if ((Get_Ridley(0)->ridley_var_C & 0x8000u) == 0) + tilemap_stuff[0] = 5; + tilemap_stuff[13] = -1; + tilemap_stuff[14] = -1; + uint16 v1 = tilemap_stuff[8]; + if (!tilemap_stuff[8] || (v1 = tilemap_stuff[8] - 1, (tilemap_stuff[8] = v1) != 0)) { + tilemap_stuff[10] = v1; + } else { + tilemap_stuff[16] = FUNC16(Enemy_GrappleReact_NoInteract_A6); + Ridley_Func_85(); + tilemap_stuff[10] = 8; + } + } +} + +void Ridley_Func_84(void) { // 0xA6CDAA + Enemy_Ridley *E = Get_Ridley(0); + Ridley_Func_77(); + if (Ridley_Func_78() & 1 + && ((uint8)random_number >= 0xF0u + || (abs16(samus_x_pos - E->base.x_pos) < 0x80)) + && (tilemap_stuff[13] & tilemap_stuff[14] & 0x8000u) != 0) { + tilemap_stuff[13] = 16128; + tilemap_stuff[10] = 8; + } else if (!(tilemap_stuff[76] | (uint16)(tilemap_stuff[66] | tilemap_stuff[56] | tilemap_stuff[46] | tilemap_stuff[36] | tilemap_stuff[26] | tilemap_stuff[16]))) { + if ((E->ridley_var_C & 0x8000u) == 0) { + tilemap_stuff[0] = 6; + tilemap_stuff[20] = 2560; + tilemap_stuff[30] = 2560; + tilemap_stuff[40] = 2560; + tilemap_stuff[50] = 2560; + tilemap_stuff[60] = 2560; + tilemap_stuff[70] = 2560; + tilemap_stuff[80] = 2560; + tilemap_stuff[21] = 0x4000; + tilemap_stuff[31] = 0x4000; + tilemap_stuff[41] = 0x4000; + tilemap_stuff[51] = 0x4000; + tilemap_stuff[61] = 0x4000; + tilemap_stuff[71] = 0x4000; + tilemap_stuff[81] = 0x4000; + tilemap_stuff[16] = FUNC16(Enemy_GrappleReact_NoInteract_A6); + } + tilemap_stuff[13] = -1; + tilemap_stuff[14] = -1; + uint16 v1 = tilemap_stuff[8]; + if (tilemap_stuff[8]) { + v1 = tilemap_stuff[8] - 1; + tilemap_stuff[8] = v1; + if (!v1) { + tilemap_stuff[16] = FUNC16(Enemy_GrappleReact_NoInteract_A6); + Ridley_Func_85(); + v1 = 8; + } + } + tilemap_stuff[10] = v1; + } +} + +void Ridley_Func_85(void) { // 0xA6CE65 + tilemap_stuff[21] = LOBYTE(tilemap_stuff[21]) | 0x4000; + tilemap_stuff[31] = LOBYTE(tilemap_stuff[31]) | 0x4000; + tilemap_stuff[41] = LOBYTE(tilemap_stuff[41]) | 0x4000; + tilemap_stuff[51] = LOBYTE(tilemap_stuff[51]) | 0x4000; + tilemap_stuff[61] = tilemap_stuff[21] & 0x4FF | 0x4000; + tilemap_stuff[71] = LOBYTE(tilemap_stuff[71]) | 0x4000; + tilemap_stuff[81] = LOBYTE(tilemap_stuff[81]) | 0x4000; +} + +void Ridley_Func_86(void) { // 0xA6CEBA + int16 v1; + + Enemy_Ridley *E = Get_Ridley(0); + tilemap_stuff[23] = tilemap_stuff[25] + E->base.y_pos + 16; + tilemap_stuff[33] = tilemap_stuff[35] + tilemap_stuff[23]; + tilemap_stuff[43] = tilemap_stuff[45] + tilemap_stuff[35] + tilemap_stuff[23]; + tilemap_stuff[53] = tilemap_stuff[55] + tilemap_stuff[43]; + tilemap_stuff[63] = tilemap_stuff[65] + tilemap_stuff[55] + tilemap_stuff[43]; + tilemap_stuff[73] = tilemap_stuff[75] + tilemap_stuff[63]; + tilemap_stuff[83] = tilemap_stuff[85] + tilemap_stuff[75] + tilemap_stuff[63]; + v1 = E->ridley_var_10 - 1; + if (E->ridley_var_10 != 1) + v1 = tilemap_stuff[24] + g_word_A6CF54[E->ridley_var_10]; + tilemap_stuff[22] = E->base.x_pos + v1; + if (E->ridley_var_10 == 1) { + tilemap_stuff[32] = E->base.x_pos; + tilemap_stuff[42] = tilemap_stuff[32]; + tilemap_stuff[52] = tilemap_stuff[32]; + tilemap_stuff[62] = tilemap_stuff[32]; + tilemap_stuff[72] = tilemap_stuff[32]; + tilemap_stuff[82] = tilemap_stuff[32]; + } else { + tilemap_stuff[32] = tilemap_stuff[34] + tilemap_stuff[22]; + tilemap_stuff[42] = tilemap_stuff[44] + tilemap_stuff[34] + tilemap_stuff[22]; + tilemap_stuff[52] = tilemap_stuff[54] + tilemap_stuff[42]; + tilemap_stuff[62] = tilemap_stuff[64] + tilemap_stuff[54] + tilemap_stuff[42]; + tilemap_stuff[72] = tilemap_stuff[74] + tilemap_stuff[62]; + tilemap_stuff[82] = tilemap_stuff[84] + tilemap_stuff[74] + tilemap_stuff[62]; + } +} + +void Ridley_Func_87(void) { // 0xA6CF5A + if (tilemap_stuff[30]) { + if ((int16)(tilemap_stuff[30] - tilemap_stuff[29]) < 0) + tilemap_stuff[30] = 0; + uint16 v0 = tilemap_stuff[9] + tilemap_stuff[29]; + if (!sign16(tilemap_stuff[9] + tilemap_stuff[29] - 6144)) + v0 = 6144; + tilemap_stuff[29] = v0; + } else if ((int16)(2048 - tilemap_stuff[29]) < 0) { + tilemap_stuff[29] -= 128; + } + if (tilemap_stuff[40]) { + if ((int16)(tilemap_stuff[40] - tilemap_stuff[39]) < 0) + tilemap_stuff[40] = 0; + uint16 v1 = tilemap_stuff[9] + tilemap_stuff[39]; + if (!sign16(tilemap_stuff[9] + tilemap_stuff[39] - 6144)) + v1 = 6144; + tilemap_stuff[39] = v1; + } else if ((int16)(2048 - tilemap_stuff[39]) < 0) { + tilemap_stuff[39] -= 128; + } + if (tilemap_stuff[50]) { + if ((int16)(tilemap_stuff[50] - tilemap_stuff[49]) < 0) + tilemap_stuff[50] = 0; + uint16 v2 = tilemap_stuff[9] + tilemap_stuff[49]; + if (!sign16(tilemap_stuff[9] + tilemap_stuff[49] - 5632)) + v2 = 5632; + tilemap_stuff[49] = v2; + } else if ((int16)(2048 - tilemap_stuff[49]) < 0) { + tilemap_stuff[49] -= 128; + } + if (tilemap_stuff[60]) { + if ((int16)(tilemap_stuff[60] - tilemap_stuff[59]) < 0) + tilemap_stuff[60] = 0; + uint16 v3 = tilemap_stuff[9] + tilemap_stuff[59]; + if (!sign16(tilemap_stuff[9] + tilemap_stuff[59] - 5632)) + v3 = 5632; + tilemap_stuff[59] = v3; + } else if ((int16)(2048 - tilemap_stuff[59]) < 0) { + tilemap_stuff[59] -= 128; + } + if (tilemap_stuff[70]) { + if ((int16)(tilemap_stuff[70] - tilemap_stuff[69]) < 0) + tilemap_stuff[70] = 0; + uint16 v4 = tilemap_stuff[9] + tilemap_stuff[69]; + if (!sign16(tilemap_stuff[9] + tilemap_stuff[69] - 4608)) + v4 = 4608; + tilemap_stuff[69] = v4; + } else if ((int16)(2048 - tilemap_stuff[69]) < 0) { + tilemap_stuff[69] -= 128; + } + if (tilemap_stuff[80]) { + if ((int16)(tilemap_stuff[80] - tilemap_stuff[79]) < 0) + tilemap_stuff[80] = 0; + uint16 v5 = tilemap_stuff[9] + tilemap_stuff[79]; + if (!sign16(tilemap_stuff[9] + tilemap_stuff[79] - 1280)) + v5 = 1280; + tilemap_stuff[79] = v5; + } else if ((int16)(1280 - tilemap_stuff[79]) < 0) { + tilemap_stuff[79] -= 128; + } +} + +void Ridley_Func_88(uint16 k) { // 0xA6D09F + int16 v6; + uint16 v2; + int v1 = k >> 1; + if ((tilemap_stuff[v1 + 16] & 0x8000u) != 0) { + int v4 = k >> 1; + uint16 v5 = tilemap_stuff[v4 + 17]; + if (v5 < tilemap_stuff[15]) { + tilemap_stuff[(k >> 1) + 17] += tilemap_stuff[10]; + return; + } + if (v5 != 0xFFFF) { + tilemap_stuff[v4 + 17] = -1; + tilemap_stuff[v4 + 26] = FUNC16(Enemy_GrappleReact_NoInteract_A6); + tilemap_stuff[v4 + 28] = tilemap_stuff[v4 + 18]; + } + if ((tilemap_stuff[v4 + 18] & 0x8000u) == 0) { + if ((tilemap_stuff[14] & 0x8000u) != 0) { + v2 = tilemap_stuff[10] + tilemap_stuff[v4 + 21]; + if ((int16)(v2 - tilemap_stuff[12]) >= 0) { +LABEL_15: + tilemap_stuff[v4 + 18] = FUNC16(Enemy_GrappleReact_NoInteract_A6); + v2 = tilemap_stuff[12]; + } + } else { + tilemap_stuff[v4 + 20] = 3072; + v2 = tilemap_stuff[10] + tilemap_stuff[v4 + 21]; + if ((int16)(v2 - tilemap_stuff[14]) >= 0) { + if (!k || !tilemap_stuff[v4 + 6]) { + tilemap_stuff[v4 + 21] = tilemap_stuff[14]; +LABEL_3:; + int v3 = k >> 1; + tilemap_stuff[v3 + 16] = 0; + tilemap_stuff[v3 + 17] = 0; + tilemap_stuff[v3 + 18] ^= 0x8000u; + return; + } + goto LABEL_15; + } + } +LABEL_24: + tilemap_stuff[v4 + 21] = v2; + goto LABEL_25; + } + if ((tilemap_stuff[13] & 0x8000u) != 0) { + v6 = tilemap_stuff[v4 + 21] - tilemap_stuff[10] - 1; + if ((int16)(v6 - tilemap_stuff[11]) < 0) { +LABEL_22: + tilemap_stuff[v4 + 18] = 0; + v2 = tilemap_stuff[11]; + goto LABEL_24; + } + } else { + tilemap_stuff[v4 + 20] = 3072; + v6 = tilemap_stuff[v4 + 21] - tilemap_stuff[10] - 1; + if ((int16)(v6 - tilemap_stuff[13]) < 0) { + if (!k || !tilemap_stuff[v4 + 6]) { + tilemap_stuff[v4 + 21] = tilemap_stuff[13]; + goto LABEL_3; + } + goto LABEL_22; + } + } + v2 = v6 + 1; + goto LABEL_24; + } + v2 = tilemap_stuff[v1 + 21]; +LABEL_25: + R18_ = (uint8)v2; + if (k) + R18_ = (uint8)(LOBYTE(tilemap_stuff[(k >> 1) + 11]) + R18_); + int v7 = k >> 1; + tilemap_stuff[v7 + 24] = ComputeSinMult(HIBYTE(tilemap_stuff[v7 + 19])); + tilemap_stuff[v7 + 25] = ComputeCosMult(HIBYTE(tilemap_stuff[v7 + 19])); +} + +void Ridley_Func_89(uint16 a) { // 0xA6D19D + uint16 v1; + char v2; // t0 + char v4; // cf + + v2 = a; + LOBYTE(v1) = 0; + HIBYTE(v1) = v2; + tilemap_stuff[5] = v1; + Enemy_Ridley *E = Get_Ridley(0); + if (E->ridley_var_10 != 1 && E->ridley_var_01) { + v4 = Ridley_Func_90() & 1; + if (v4) { + R18_ -= !v4 + tilemap_stuff[22]; + R20_ -= tilemap_stuff[23]; + } else { + R18_ = samus_x_pos - tilemap_stuff[22]; + R20_ = samus_y_pos + 24 - tilemap_stuff[23]; + } + R18_ = (uint8)-(int8)(CalculateAngleFromXY() + 0x80); + if (E->ridley_var_10) { + uint16 v7 = R18_; + if (R18_ >= 0x18u && R18_ < 0xE8u) + v7 = 24; + uint16 v8 = tilemap_stuff[5] + v7 + 0x4000; + if (v8 >= tilemap_stuff[21]) { + tilemap_stuff[14] = v8; + tilemap_stuff[10] = 8; + } + } else { + uint16 v5 = R18_; + if (R18_ >= 0x18u && R18_ < 0xE8u) + v5 = 232; + uint16 v6 = v5 + 16128 - tilemap_stuff[5]; + if (v6 < tilemap_stuff[21]) { + tilemap_stuff[13] = v6; + tilemap_stuff[10] = 8; + } + } + } +} + +uint8 Ridley_Func_90(void) { // 0xA6D242 + R18_ = tilemap_stuff[82]; + R20_ = tilemap_stuff[83]; + R22_ = 64; + R24_ = 64; + if (!projectile_counter) + return 0; + uint16 v1 = 0; + while (1) { + int v2 = v1 >> 1; + if ((HIBYTE(projectile_type[v2]) & 0xF) == 1 || (HIBYTE(projectile_type[v2]) & 0xF) == 2) { + uint16 v3 = abs16(projectile_x_pos[v2] - R18_); + bool v4 = v3 < projectile_x_radius[v2]; + uint16 v5 = v3 - projectile_x_radius[v2]; + if (v4 || v5 < R22_) { + uint16 v6 = abs16(projectile_y_pos[v2] - R20_); + v4 = v6 < projectile_y_radius[v2]; + uint16 v7 = v6 - projectile_y_radius[v2]; + if (v4 || v7 < R24_) + break; + } + } + v1 += 2; + if ((int16)(v1 - 10) >= 0) + return 0; + } + int v8 = v1 >> 1; + R18_ = projectile_x_pos[v8]; + R20_ = projectile_y_pos[v8]; + return 1; +} + +void Ridley_Func_91(void) { // 0xA6D2AA + Enemy_Ridley *E = Get_Ridley(0); + if (!sign16(tilemap_stuff[10] - 8)) { + uint16 v1 = E->ridley_var_0E + 1; + E->ridley_var_0E = v1; + if (sign16(v1 - 16)) + return; + if (!E->ridley_var_0F) + QueueSfx3_Max6(0x21u); + } + E->ridley_var_0E = 0; +} + +void Ridley_Func_92(void) { // 0xA6D2D6 + tilemap_stuff[10] = 1; + tilemap_stuff[11] = 16368; + tilemap_stuff[12] = 16448; + tilemap_stuff[13] = -1; + tilemap_stuff[14] = -1; + tilemap_stuff[9] = 240; + tilemap_stuff[15] = 16; + tilemap_stuff[17] = 17; + tilemap_stuff[27] = 17; + tilemap_stuff[37] = 17; + tilemap_stuff[47] = 17; + tilemap_stuff[57] = 17; + tilemap_stuff[67] = 17; + tilemap_stuff[77] = 17; + Ridley_Func_93(0x2024u, addr_word_A6D36E); + Ridley_Func_93(0x2026u, addr_word_A6D37C); + Ridley_Func_93(0x202Au, addr_word_A6D38A); + Ridley_Func_93(0x202Cu, addr_word_A6D398); + Ridley_Func_93(0x202Eu, addr_word_A6D3A6); + tilemap_stuff[16] = 0; + tilemap_stuff[26] = 0; + tilemap_stuff[36] = 0; + tilemap_stuff[46] = 0; + tilemap_stuff[56] = 0; + tilemap_stuff[66] = 0; + tilemap_stuff[76] = 0; +} + +void Ridley_Func_93(uint16 j, uint16 k) { // 0xA6D3B4 + int16 v3; + int16 v5; + + R20_ = 126; + R18_ = j; + uint16 v2 = 0; + v3 = 7; + do { + v5 = v3; + uint16 *v4 = (uint16 *)RomPtr_A6(k); + IndirWriteWord(&R18_, v2, *v4); + k += 2; + v2 += 20; + --v3; + } while (v5 != 1); +} + +void Ridley_Func_94(void) { // 0xA6D3D4 + Ridley_Func_D3DC(0); +} + +void Ridley_Func_95(void) { // 0xA6D3D9 + Ridley_Func_D3DC(FUNC16(Enemy_GrappleReact_NoInteract_A6)); +} + +void Ridley_Func_D3DC(uint16 a) { // 0xA6D3DC + tilemap_stuff[16] = a; + tilemap_stuff[26] = a; + tilemap_stuff[36] = a; + tilemap_stuff[46] = a; + tilemap_stuff[56] = a; + tilemap_stuff[66] = a; + tilemap_stuff[76] = a; +} + +void Ridley_Func_96(void) { // 0xA6D3F9 + int16 v0; + + Ridley_Func_93(0x2026u, addr_word_A6D37C); + v0 = 7; + uint16 v1 = 0; + do { + int v2 = v1 >> 1; + tilemap_stuff[v2 + 21] = 0x8000 - tilemap_stuff[v2 + 21]; + tilemap_stuff[v2 + 18] |= 0x8000u; + v1 += 20; + --v0; + } while (v0); +} + +uint8 Ridley_Func_97(void) { // 0xA6D431 + return (tilemap_stuff[76] & (uint16)(tilemap_stuff[66] & tilemap_stuff[56] & tilemap_stuff[46] & tilemap_stuff[36] & tilemap_stuff[26] & tilemap_stuff[16])) != 0; +} + +void Ridley_Func_98(void) { // 0xA6D453 + uint16 enemy_ptr = Get_Ridley(cur_enemy_index)->base.enemy_ptr; + uint8 *v1 = RomPtr_A0(enemy_ptr); + uint16 v2 = SuitDamageDivision(*((uint16 *)v1 + 3)); + Samus_DealDamage(v2); +} + +void Ridley_Func_99(uint16 a) { // 0xA6D467 + Enemy_Ridley *E = Get_Ridley(0); + E->base.current_instruction = a; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void Ridley_Func_100(void) { // 0xA6D474 + int16 v0; + + v0 = 0; + Enemy_Ridley *E = Get_Ridley(0); + uint16 health = E->base.health; + if (health < 0x2328u) { + v0 = 1; + if (health < 0x1518u) { + v0 = 2; + if (health < 0x708u) + v0 = 3; + } + } + E->ridley_var_12 = v0; + R18_ = v0 - 1; + if ((int16)(v0 - 1) >= 0) + Ridley_D495(); +} + +void Ridley_D495(void) { // 0xA6D495 + if (!palette_change_num) + WriteColorsToPalette(0x1E2u, 0xa6, 28 * R18_ - 7062, 0xEu); +} + +void Ridley_Func_101(void) { // 0xA6D4B5 + Enemy_Ridley *E = Get_Ridley(0); + if (E->ridley_var_01 && E->ridley_var_0D >= 0x32u) { + uint16 v1 = 0; + if (E->ridley_var_0D >= 0x46u) + v1 = 2; + R18_ = v1; + Ridley_D495(); + } +} + +void Ridley_Func_102(void) { // 0xA6D4DA + int16 v0; + + v0 = 3584; + Enemy_Ridley *E = Get_Ridley(0); + if (E->base.flash_timer >= 2u && (((uint8)enemy_damage_routine_exec_count + 1) & 2) != 0) + v0 = 0; + E->ridley_var_0C = v0; +} + +uint8 Ridley_Func_103(uint16 k, uint16 j) { // 0xA6D4F9 + uint16 prod = Mult8x8(j >> 4, room_width_in_blocks); + return (level_data[prod + (k >> 4)] & 0xF000) != 0; +} + +void Ridley_Func_104_0(uint16 k, uint16 j) { // 0xA6D523 + Ridley_Func_104(k, j, 0); +} +void Ridley_Func_104(uint16 k, uint16 j, uint16 a) { // 0xA6D526 + int16 v4; + int16 v6; + int16 v8; + int16 v9; + int16 v11; + int16 ridley_var_C; + int16 v17; + + R26_ = a; + R24_ = g_byte_A6D61F[j]; + Ridley_Func_105(k); + Enemy_Ridley *E = Get_Ridley(k); + v4 = E->base.y_pos - R20_; + if (v4) { + if (v4 >= 0) { + uint16 RegWord = SnesDivide(v4, R24_); + if (!RegWord) + RegWord = 1; + R22_ = RegWord; + ridley_var_C = E->ridley_var_C; + bool v14 = 0; + if (ridley_var_C >= 0) { + uint16 v15 = ridley_var_C - R26_; + v15 -= 8; + uint16 v16 = R22_; + ridley_var_C = v15 - v16; + } + v17 = ridley_var_C - R22_; + if (sign16(v17 + 1280)) + v17 = -1280; + E->ridley_var_C = v17; + } else { + uint16 v5 = SnesDivide(R20_ - E->base.y_pos, R24_); + if (!v5) + v5 = 1; + R22_ = v5; + v6 = E->ridley_var_C; + bool v7 = 0; + if (v6 < 0) { + v8 = R26_ + v6; + v8 += 8; + v9 = v8; + v6 = R22_ + v9; + } + v11 = R22_ + v6; + if (!sign16(v11 - 1280)) + v11 = 1280; + E->ridley_var_C = v11; + } + } +} + +void Ridley_Func_105(uint16 k) { // 0xA6D5A9 + int16 v2; + int16 v4; + int16 v6; + int16 v7; + int16 v9; + int16 ridley_var_B; + int16 v15; + + Enemy_Ridley *E = Get_Ridley(k); + v2 = E->base.x_pos - R18_; + if (v2) { + if (v2 >= 0) { + uint16 RegWord = SnesDivide(v2, R24_); + if (!RegWord) + RegWord = 1; + R22_ = RegWord; + ridley_var_B = E->ridley_var_B; + bool v12 = 0; + if (ridley_var_B >= 0) { + uint16 v13 = ridley_var_B - R26_; + v13 -= 8; + uint16 v14 = R22_; + ridley_var_B = v13 - v14; + } + v15 = ridley_var_B - R22_; + if (sign16(v15 + 1280)) + v15 = -1280; + E->ridley_var_B = v15; + } else { + uint16 v3 = SnesDivide(R18_ - E->base.x_pos, R24_); + if (!v3) + v3 = 1; + R22_ = v3; + v4 = E->ridley_var_B; + if (v4 < 0) { + v6 = R26_ + v4; + v6 += 8; + v7 = v6; + v4 = R22_ + v7; + } + v9 = R22_ + v4; + if (!sign16(v9 - 1280)) + v9 = 1280; + E->ridley_var_B = v9; + } + } +} + +void Ridley_Func_106(uint16 k, uint16 j) { // 0xA6D62F + int16 v3; + int16 v5; + int16 v6; + int16 ridley_var_C; + int16 v9; + + R24_ = g_byte_A6D712[j]; + Ridley_Func_107(k); + Enemy_Ridley *E = Get_Ridley(k); + v3 = E->base.y_pos - R20_; + if (v3) { + if (v3 >= 0) { + uint16 RegWord = SnesDivide(v3, R24_); + if (!RegWord) + RegWord = 1; + R22_ = RegWord; + ridley_var_C = E->ridley_var_C; + if (ridley_var_C >= 0) + ridley_var_C = ridley_var_C - R22_ - R22_; + v9 = ridley_var_C - R22_; + if (sign16(v9 + 1280)) + v9 = -1280; + E->ridley_var_C = v9; + } else { + uint16 v4 = SnesDivide(R20_ - E->base.y_pos, R24_); + if (!v4) + v4 = 1; + R22_ = v4; + v5 = E->ridley_var_C; + if (v5 < 0) + v5 += R22_ + R22_; + v6 = R22_ + v5; + if (!sign16(v6 - 1280)) + v6 = 1280; + E->ridley_var_C = v6; + } + } +} + +void Ridley_Func_107(uint16 k) { // 0xA6D6A6 + Enemy_Ridley *E = Get_Ridley(k); + int16 v2 = E->base.x_pos - R18_; + if (!v2) + return; + if (v2 >= 0) { + uint16 RegWord = SnesDivide(v2, R24_); + R22_ = RegWord = RegWord ? RegWord : 1; + int16 s = E->ridley_var_B; + if (s >= 0) + s -= 2 * RegWord; + s -= RegWord; + E->ridley_var_B = sign16(s + 1280) ? -1280 : s; + } else { + uint16 v3 = SnesDivide(R18_ - E->base.x_pos, R24_); + R22_ = v3 ? v3 : 1; + int16 s = E->ridley_var_B; + if (s < 0) + s += 2 * R22_; + s += R22_; + E->ridley_var_B = !sign16(s - 1280) ? 1280 : s; + } +} + +void Ridley_Func_108(uint16 k) { // 0xA6D722 + R22_ = 512; + R28_ = 0; + Ridley_Func_110(k); + Ridley_Func_109(k); + R28_ >>= 1; + R28_ >>= 1; +} + +void Ridley_Func_109(uint16 k) { // 0xA6D734 + int16 v2; + int16 v6; + int16 v10; + + Enemy_Ridley *E = Get_Ridley(k); + if ((int16)(E->base.y_pos - R20_) >= 0) { + v6 = E->ridley_var_C - R22_; + if (sign16(v6 + 1280)) + v6 = -1280; + E->ridley_var_C = v6; + v10 = E->base.y_pos + (int8)(E->ridley_var_C >> 8); + if ((int16)(v10 - R20_) <= 0) { + E->ridley_var_C = 0; + E->base.y_pos = R20_; + ++R28_; + } + } else { + v2 = E->ridley_var_C + R22_; + if (!sign16(v2 - 1280)) + v2 = 1280; + E->ridley_var_C = v2; + v10 = E->base.y_pos + (int8)(E->ridley_var_C >> 8); + if (!sign16(v10 - R20_)) { + E->ridley_var_C = 0; + E->base.y_pos = R20_; + ++R28_; + } + } +} + +void Ridley_Func_110(uint16 k) { // 0xA6D798 + int16 v2; + int16 v6; + int16 v10; + + Enemy_Ridley *E = Get_Ridley(k); + if ((int16)(E->base.x_pos - R18_) >= 0) { + v6 = E->ridley_var_B - R22_; + if (sign16(v6 + 1280)) + v6 = -1280; + E->ridley_var_B = v6; + v10 = E->base.x_pos + (int8)(E->ridley_var_B >> 8); + if ((int16)(v10 - R18_) <= 0) { + E->ridley_var_B = 0; + E->base.x_pos = R18_; + ++R28_; + } + } else { + v2 = R22_ + E->ridley_var_B; + if (!sign16(v2 - 1280)) + v2 = 1280; + E->ridley_var_B = v2; + if (!sign16(E->base.x_pos + (int8)(E->ridley_var_B >> 8) - R18_)) { + E->ridley_var_B = 0; + E->base.x_pos = R18_; + ++R28_; + } + } +} + +void Ridley_Func_111(void) { // 0xA6D800 + Enemy_Ridley *E = Get_Ridley(0); + if (R22_ != E->ridley_var_0B) { + if ((int16)(R22_ - E->ridley_var_0B) >= 0) { + uint16 v2 = E->ridley_var_0B + 32; + if (!sign16(v2 - R22_)) + v2 = R22_; + E->ridley_var_0B = v2; + } else { + uint16 v1 = E->ridley_var_0B - 32; + if (sign16(v1 - R22_)) + v1 = R22_; + E->ridley_var_0B = v1; + } + } + uint16 v3; + if ((R18_ & 0x8000u) != 0) { + v3 = E->ridley_var_0A + R18_; + if (sign16(v3 - R20_)) + LABEL_13: + v3 = R20_; + } else { + v3 = E->ridley_var_0A + R18_; + if (!sign16(v3 - R20_)) + goto LABEL_13; + } + E->ridley_var_0A = v3; + R18_ = HIBYTE(v3); + E->ridley_var_B = Math_MultBySin(E->ridley_var_0B); + E->ridley_var_C = Math_MultByCos(E->ridley_var_0B); +} + +void Ridley_Func_112(void) { // 0xA6D86B + Enemy_Ridley *Ridley; + uint16 v1; + Enemy_Ridley *v2; + uint16 ridley_var_23; + uint16 ridley_var_21; + + Ridley = Get_Ridley(0); + Ridley->ridley_var_1F = 0; + v1 = cur_enemy_index; + v2 = Get_Ridley(cur_enemy_index); + + int with_carry = HIBYTE(v2->base.x_subpos) + LOBYTE(v2->ridley_var_B); + HIBYTE(v2->base.x_subpos) = with_carry; + ridley_var_23 = v2->base.x_pos + (int8)(v2->ridley_var_B >> 8) + (with_carry >> 8); + if ((int16)(ridley_var_23 - Ridley->ridley_var_22) >= 0) { + if ((int16)(ridley_var_23 - Ridley->ridley_var_23) >= 0) { + v2->ridley_var_B = 0; + Ridley->ridley_var_1F = 2; + ridley_var_23 = Ridley->ridley_var_23; + } + v2->base.x_pos = ridley_var_23; + } else { + Ridley_Func_113(v1); + v2->base.x_pos = Ridley->ridley_var_22; + v2->ridley_var_B = 0; + Ridley->ridley_var_1F = 1; + } + + with_carry = HIBYTE(v2->base.y_subpos) + LOBYTE(v2->ridley_var_C); + HIBYTE(v2->base.y_subpos) = with_carry; + + ridley_var_21 = v2->base.y_pos + (int8)(v2->ridley_var_C >> 8) + (with_carry >> 8); + if ((int16)(ridley_var_21 - Ridley->ridley_var_20) >= 0) { + if ((int16)(ridley_var_21 - Ridley->ridley_var_21) >= 0) { + v2->ridley_var_C = 0; + Ridley->ridley_var_1F = 8; + ridley_var_21 = Ridley->ridley_var_21; + } + v2->base.y_pos = ridley_var_21; + } else { + v2->base.y_pos = Ridley->ridley_var_20; + v2->ridley_var_C = 0; + Ridley->ridley_var_1F = 4; + } +} + +void Ridley_Func_113(uint16 k) { // 0xA6D914 + if (area_index != 2) { + Enemy_Ridley *E = Get_Ridley(k); + R18_ = abs16(E->ridley_var_B); + uint16 v2 = abs16(E->ridley_var_C); + if (v2 < R18_) + v2 = R18_; + if (v2 >= 0x280u) { + uint16 v3; + if (area_index == 2) + v3 = 24; + else + v3 = 33; + earthquake_type = v3; + earthquake_timer = 12; + } + } +} + +void Ridley_Func_114(void) { // 0xA6D955 + Enemy_Ridley *E = Get_Ridley(0); + uint16 ridley_var_10 = E->ridley_var_10, v2; + if (!ridley_var_10) { + if (*(int16 *)((char *)&E->base.enemy_ptr + 1) < 0) + return; + v2 = addr_kRidley_Ilist_E6F0; + goto LABEL_7; + } + if (ridley_var_10 != 1 && *(int16 *)((char *)&E->base.enemy_ptr + 1) < 0) { + v2 = addr_kRidley_Ilist_E706; +LABEL_7: + E->base.current_instruction = v2; + E->base.instruction_timer = 2; + E->base.timer = 0; + } +} + +void Ridley_Func_115(void) { // 0xA6D97D + int16 v1; + + Ridley_Func_116(); + Enemy_Ridley *E = Get_Ridley(0); + v1 = E->ridley_var_09 - E->ridley_var_08; + E->ridley_var_09 = v1; + if (v1 < 0) { + E->ridley_var_09 = 32; + uint16 v2 = E->ridley_var_07 + 1; + if (v2 >= 0xAu) + v2 = 0; + E->ridley_var_07 = v2; + } +} + +void Ridley_Func_116(void) { // 0xA6D9A8 + int16 v1; + int16 v3; + char v4; // t0 + + Enemy_Ridley *E = Get_Ridley(0); + R18_ = abs16(E->ridley_var_B); + v1 = R18_ + abs16(E->ridley_var_C); + if (v1) { + uint16 v2 = v1 - R18_; + if (sign16(v2 - R18_)) + v2 = R18_; + v3 = (4 * v2) & 0xF00; + v4 = v3; + LOBYTE(v3) = HIBYTE(v3); + HIBYTE(v3) = v4; + uint16 v5 = 2 * v3; + if (v5 >= 0xEu) + v5 = 14; + uint16 v6 = g_word_A6D9ED[v5 >> 1]; + if ((E->ridley_var_C & 0x8000u) == 0) + v6 >>= 1; + E->ridley_var_08 = v6; + } else { + E->ridley_var_08 = 0; + } +} + +void Ridley_Func_117(void) { // 0xA6D9FD + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_05 = addr_word_A6DA71; + E->ridley_var_06 = 1; +} + +void Ridley_Func_118(void) { // 0xA6DA0C + VramWriteEntry *v7; + + Enemy_Ridley *E = Get_Ridley(0); + uint16 v1 = E->ridley_var_06 - 1; + E->ridley_var_06 = v1; + if (!v1) { + int i; + uint16 v3, *v4; + for (i = E->ridley_var_05; ; E->ridley_var_05 = i) { + v3 = i; + v4 = (uint16 *)RomPtr_A6(i); + i = *v4; + if ((*v4 & 0x8000u) == 0) + break; + } + E->ridley_var_06 = i; + uint16 v6 = vram_write_queue_tail; + v7 = gVramWriteEntry(vram_write_queue_tail); + *(VoidP *)((char *)&v7->src.addr + 1) = -20480; + *(VoidP *)((char *)&v7[1].src.addr + 1) = -20480; + v7->src.addr = v4[1]; + v7[1].src.addr = v4[2]; + v7->vram_dst = 29216; + v7[1].vram_dst = 29472; + v7->size = 64; + v7[1].size = 64; + vram_write_queue_tail = v6 + 14; + gVramWriteEntry(v6 + 14)->size = 0; + E->ridley_var_05 = v3 + 6; + } +} + +void Ridley_Func_119(uint8 carry) { // 0xA6DA8B + VramWriteEntry *v3; + + uint16 v1 = addr_off_A6DAD0; + if (carry) + v1 = addr_off_A6DAD4; + uint16 v2 = vram_write_queue_tail; + v3 = gVramWriteEntry(vram_write_queue_tail); + *(VoidP *)((char *)&v3->src.addr + 1) = -20480; + *(VoidP *)((char *)&v3[1].src.addr + 1) = -20480; + uint8 *v4 = RomPtr_A6(v1); + v3->src.addr = *(uint16 *)v4; + v3[1].src.addr = *((uint16 *)v4 + 1); + v3->vram_dst = 31424; + v3[1].vram_dst = 31680; + v3->size = 128; + v3[1].size = 128; + vram_write_queue_tail = v2 + 14; + gVramWriteEntry(v2 + 14)->size = 0; +} + +void Ridley_Func_120(void) { // 0xA6DAD8 + int16 ridley_var_10; + + Enemy_Ridley *E = Get_Ridley(0); + ridley_var_10 = E->ridley_var_10; + if (ridley_var_10) { + if (ridley_var_10 == 1) + return; + ridley_var_10 = 10; + } + uint16 v2 = g_off_A6DB02[E->ridley_var_07 + ridley_var_10]; + R22_ = E->ridley_var_0C; + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + sub_A6DC13(v2); +} + +void sub_A6DB2A(void) { // 0xA6DB2A + if ((gEnemyData(0)->properties & kEnemyProps_Invisible) == 0) { + R18_ = tilemap_stuff[82]; + R20_ = tilemap_stuff[83]; + sub_A6DBC2(kRidley_Ilist_DCBA[(uint16)((uint8)((LOBYTE(tilemap_stuff[71]) + + LOBYTE(tilemap_stuff[81]) + + 8) & 0xF0) >> 3) >> 1]); + R20_ = tilemap_stuff[73]; + R18_ = tilemap_stuff[72]; + sub_A6DBC2(0xDC9Eu); + R18_ = tilemap_stuff[62]; + R20_ = tilemap_stuff[63]; + sub_A6DBC2(0xDC9Eu); + R18_ = tilemap_stuff[52]; + R20_ = tilemap_stuff[53]; + sub_A6DBC2(0xDC97u); + R18_ = tilemap_stuff[42]; + R20_ = tilemap_stuff[43]; + sub_A6DBC2(0xDC97u); + R18_ = tilemap_stuff[32]; + R20_ = tilemap_stuff[33]; + sub_A6DBC2(0xDC90u); + R18_ = tilemap_stuff[22]; + R20_ = tilemap_stuff[23]; + sub_A6DBC2(0xDC90u); + } +} + +void sub_A6DBC2(uint16 j) { // 0xA6DBC2 + R22_ = Get_Ridley(0)->ridley_var_0C; + sub_A6DC13(j); +} +uint16 CallBabyMetroidInstr(uint32 ea, uint16 k) { + switch (ea) { + case fnBabyMetroid_Instr_2: return BabyMetroid_Instr_2(k); + case fnBabyMetroid_Instr_3: return BabyMetroid_Instr_3(k); + case fnBabyMetroid_Instr_1: return BabyMetroid_Instr_1(k); + case fnBabyMetroid_Instr_4: return BabyMetroid_Instr_4(k); + default: return Unreachable(); + } +} +int BabyMetroid_DBCB_DoubleRetEx(uint16 a) { + int16 v3; + + R0_.addr = a; + R3_.addr = a + 2; + R0_.bank = 126; + R3_.bank = 126; + + uint16 *instr_ptr = (uint16 *)IndirPtr(&R0_, 0); + uint16 *timer_ptr = (uint16 *)IndirPtr(&R3_, 0); + + if ((*instr_ptr & 0x8000u) == 0) + return -1; // double ret + + uint16 v2 = *instr_ptr; + v3 = *(uint16 *)RomPtr_A6(v2); + if (v3 < 0) + goto LABEL_7; + if (*timer_ptr != v3) { + (*timer_ptr)++; + return *((uint16 *)RomPtr_A6(v2) + 1); + } + v2 += 4; + for (; ; ) { + v3 = *(uint16 *)RomPtr_A6(v2); + if (v3 >= 0) + break; +LABEL_7: + R6_ = v3; + v2 = CallBabyMetroidInstr((uint16)v3 | 0xA60000, v2 + 2); + } + *timer_ptr = 1; + *instr_ptr = v2; + return *((uint16 *)RomPtr_A6(v2) + 1); +} + +void sub_A6DC13(uint16 j) { // 0xA6DC13 + int16 *v5; + int16 v6; + int16 v7; + char v8; // t0 + int16 v9; + int16 v10; + OamEnt *v11; + int16 v13; + int16 v15; + + uint16 *v1 = (uint16 *)RomPtr_A6(j); + uint16 v2 = j + 2; + R24_ = *v1; + uint16 v3 = oam_next_ptr; + do { + uint8 *v4 = RomPtr_A6(v2); + v5 = (int16 *)v4; + v6 = v4[2] << 8; + if ((v4[2] & 0x80) != 0) + v6 |= 0xFFu; + v8 = v6; + LOBYTE(v7) = HIBYTE(v6); + HIBYTE(v7) = v8; + v9 = R20_ + v7 - layer1_y_pos; + if (v9 >= 0 && sign16(v9 - 224)) { + R26_ = v9; + v10 = R18_ + *(uint16 *)v4 - layer1_x_pos; + v11 = gOamEnt(v3); + *(uint16 *)&v11->xcoord = v10; + if ((v10 & 0x100) != 0) { + int v12 = v3 >> 1; + R28_ = kOamExtra_Address_And_X8Large[v12]; + v13 = kOamExtra_X8Small_And_Large[v12] | *(uint16 *)RomPtr_RAM(R28_); + *(uint16 *)RomPtr_RAM(R28_) = v13; + } + if (*v5 < 0) { + int v14 = v3 >> 1; + R28_ = kOamExtra_Address_And_X8Large[v14]; + v15 = kOamExtra_X8Small_And_Large[v14 + 1] | *(uint16 *)RomPtr_RAM(R28_); + *(uint16 *)RomPtr_RAM(R28_) = v15; + } + *(uint16 *)&v11->ycoord = R26_; + *(uint16 *)&v11->charnum = R22_ | *(int16 *)((char *)v5 + 3); + v3 = (v3 + 4) & 0x1FF; + } + v2 += 5; + --R24_; + } while (R24_); + oam_next_ptr = v3; +} + +uint8 Ridley_Func_121(void) { // 0xA6DE7A + int16 y_pos; + int16 v2; + int16 x_pos; + int16 v4; + + Enemy_Ridley *E = Get_Ridley(0); + y_pos = E->base.y_pos; + uint8 result = 1; + if (y_pos >= 0) { + v2 = y_pos + 32 - layer1_y_pos; + if (v2 >= 0) { + if (sign16(v2 - 288)) { + x_pos = E->base.x_pos; + if (x_pos >= 0) { + v4 = x_pos + 32 - layer1_x_pos; + if (v4 >= 0) { + if (sign16(v4 - 320)) + return 0; + } + } + } + } + } + return result; +} + +uint16 Ridley_Func_122(void) { // 0xA6DEA6 + int16 v2; + + if (!projectile_counter) + return 0xffff; + uint16 result = 0; + while (1) { + int v1 = result >> 1; + v2 = projectile_type[v1]; + if (v2 < 0) { + if (sign16((HIBYTE(v2) & 0xF) - 3)) { + uint16 v3 = abs16(projectile_x_pos[v1] - R18_); + bool v4 = v3 < projectile_x_radius[v1]; + uint16 v5 = v3 - projectile_x_radius[v1]; + if (v4 || v5 < R22_) { + uint16 v6 = abs16(projectile_y_pos[v1] - R20_); + v4 = v6 < projectile_y_radius[v1]; + uint16 v7 = v6 - projectile_y_radius[v1]; + if (v4 || v7 < R24_) + break; + } + } + } + result += 2; + if ((int16)(result - 10) >= 0) + return 0xffff; + } + int v8 = result >> 1; + projectile_x_pos[v8] = R18_; + projectile_y_pos[v8] = R20_; + projectile_dir[v8] |= 0x10u; + return result; +} + +void Ridley_Func_123(uint16 j) { // 0xA6DF08 + int v1 = j >> 1; + uint16 v2; + if ((projectile_dir[v1] & 0xF) == 7) { + v2 = 1; + } else if ((projectile_dir[v1] & 0xF) == 2) { + v2 = 8; + } else { + v2 = 5; + } + projectile_dir[v1] = v2; +} + +uint8 Ridley_Func_124(void) { // 0xA6DF29 + uint16 v0 = abs16(samus_x_pos - R18_); + bool v1 = v0 < samus_x_radius; + uint16 v2 = v0 - samus_x_radius; + uint8 result = 0; + if (v1 || v2 < R22_) { + uint16 v3 = abs16(samus_y_pos - R20_); + v1 = v3 < samus_y_radius; + uint16 v4 = v3 - samus_y_radius; + if (v1 || v4 < R24_) + return 1; + } + return result; +} + +void sub_A6DF59(void) { // 0xA6DF59 + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); +} + +void sub_A6DF60(void) { // 0xA6DF60 + Ridley_Func_125(); +} + +void Ridley_Func_125(void) { // 0xA6DF66 + Ridley_Func_98(); + samus_invincibility_timer = 96; + samus_knockback_timer = 5; + knockback_x_dir = (int16)(samus_x_pos - Get_Ridley(cur_enemy_index)->base.x_pos) >= 0; +} + +void Ridley_Shot(void) { // 0xA6DF8A + int16 v0; + + if (area_index == 2) { + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + } else { + v0 = 13; + Enemy_Ridley *E = Get_Ridley(0); + uint16 flash_timer = E->base.flash_timer; + if (flash_timer) { + if (flash_timer & 1) + v0 = 14; + } + E->base.flash_timer = v0; + ++E->ridley_var_0D; + } +} + +void Ridley_Powerbomb(void) { // 0xA6DFB2 + NormalEnemyPowerBombAiSkipDeathAnim_CurEnemy(); +} + +void Ridley_Func_126(void) { // 0xA6DFB7 + Enemy_Ridley *E = Get_Ridley(0); + if (!E->base.health && (E->ridley_var_01 & 0x8000u) == 0) { + E->ridley_var_01 = -1; + E->base.properties |= kEnemyProps_Tangible; + E->ridley_var_A = FUNC16(Ridley_Func_63); + } +} + +void Ridley_Func_127(void) { // 0xA6DFD9 + R22_ = 14; + R24_ = 14; + R18_ = tilemap_stuff[82]; + R20_ = tilemap_stuff[83]; + if (Ridley_Func_124() & 1) { + Enemy_Ridley *E = Get_Ridley(0); + uint16 v1 = SuitDamageDivision(E->ridley_var_1C); + Samus_DealDamage(v1); + samus_invincibility_timer = 96; + samus_knockback_timer = 5; + knockback_x_dir = (int16)(samus_x_pos - tilemap_stuff[82]) >= 0; + } +} + +void Ridley_Func_128(void) { // 0xA6E01B + Enemy_Ridley *E = Get_Ridley(cur_enemy_index); + R18_ = projectile_x_pos[0] - E->base.x_pos; + R20_ = projectile_y_pos[0] - E->base.y_pos; + R18_ = (uint8)-CalculateAngleFromXY(); + uint16 v1 = 4 * projectile_damage[collision_detection_index]; + if (v1 >= 0x300u) + v1 = 768; + uint16 a = v1; + R18_ = Math_MultBySin(v1); + if (((E->ridley_var_B ^ R18_) & 0x8000u) != 0) + E->ridley_var_B += R18_; + R18_ = Math_MultByCos(a); + if (((E->ridley_var_C ^ R18_) & 0x8000u) != 0) + E->ridley_var_C += R18_; +} + +void Ridley_Func_129(void) { // 0xA6E088 + if ((Get_Ridley(0)->base.properties & kEnemyProps_Tangible) == 0) { + R22_ = 14; + R24_ = 14; + R18_ = tilemap_stuff[82]; + R20_ = tilemap_stuff[83]; + uint16 v0 = Ridley_Func_122(); + if (!sign16(v0) + || (R22_ = 10, R24_ = 10, R18_ = tilemap_stuff[72], R20_ = tilemap_stuff[73], !sign16(v0 = Ridley_Func_122()))) { + int v1 = v0 >> 1; + R18_ = projectile_x_pos[v1]; + R20_ = projectile_y_pos[v1]; + uint16 v2 = 12; + if ((HIBYTE(projectile_type[v1]) & 0xF) == 1) { + QueueSfx1_Max6(0x3Du); + v2 = 6; + } + SpawnEnemyProjectileWithRoomGfx(0xE509u, v2); + } + } +} + +uint16 Ridley_Instr_5(uint16 k, uint16 j) { // 0xA6E4BE + Get_Ridley(0)->ridley_var_0F = 89; + QueueSfx2_Max6(0x59u); + return j; +} + +uint16 Ridley_Instr_6(uint16 k, uint16 j) { // 0xA6E4CA + Get_Ridley(0)->ridley_var_0F = 0; + return j; +} + +uint16 Ridley_Instr_10(uint16 k, uint16 j) { // 0xA6E4D2 + if (area_index == 2 || !sign16(samus_health - 30)) + return sub_A6E514(j); + Get_Ridley(0)->ridley_var_00 = 8; + return sub_A6E4E9(j); +} + +uint16 sub_A6E4E9(uint16 j) { // 0xA6E4E9 + return *(uint16 *)RomPtr_A6(j); +} + +uint16 Ridley_Instr_4(uint16 k, uint16 j) { // 0xA6E4EE + if (Get_Ridley(0)->ridley_var_1B) + return sub_A6E4E9(j); + else + return sub_A6E4E9(j + 2); +} + +uint16 Ridley_Instr_3(uint16 k, uint16 j) { // 0xA6E4F8 + if (Get_Ridley(0)->ridley_var_1B) + return j + 2; + else + return sub_A6E4E9(j); +} + +uint16 Ridley_Instr_2(uint16 k, uint16 j) { // 0xA6E501 + samus_prev_x_pos = samus_x_pos; + samus_prev_y_pos = samus_y_pos; + uint16 v2 = *(uint16 *)RomPtr_A6(j); + Get_Ridley(0)->ridley_var_1D = v2; + return sub_A6E514(j); +} + +uint16 sub_A6E514(uint16 j) { // 0xA6E514 + return j + 2; +} + +uint16 Ridley_Instr_1(uint16 k, uint16 j) { // 0xA6E517 + if (Get_Ridley(0)->ridley_var_10) + return sub_A6E4E9(j); + else + return sub_A6E514(j); +} + +uint16 Ridley_Instr_14(uint16 k, uint16 j) { // 0xA6E51F + uint8 *v2 = RomPtr_A6(j); + Enemy_Ridley *E = Get_Ridley(0); + E->base.x_pos += *(uint16 *)v2; + E->base.y_pos += *((uint16 *)v2 + 1); + return j + 4; +} + +uint16 Ridley_Instr_9(uint16 k, uint16 j) { // 0xA6E71C + Get_Ridley(0)->ridley_var_10 = 0; + Ridley_Func_96(); + return j; +} + +uint16 Ridley_Instr_7(uint16 k, uint16 j) { // 0xA6E727 + Get_Ridley(0)->ridley_var_10 = 1; + return j; +} + +uint16 Ridley_Instr_8(uint16 k, uint16 j) { // 0xA6E72F + Get_Ridley(0)->ridley_var_10 = 2; + Ridley_Func_96(); + return j; +} + +void Ridley_Func_131(uint16 k) { // 0xA6E828 + Ridley_Func_132(k, 0); + Ridley_Func_132(k, 1u); + Ridley_Func_132(k, 2u); + Ridley_Func_132(k, 3u); +} + +void Ridley_Func_132(uint16 k, uint16 a) { // 0xA6E840 + Get_Ridley(0)->ridley_parameter_1 = a; + SpawnEnemyProjectileWithGfx(a, k, addr_stru_869634); +} + +uint16 Ridley_Instr_11(uint16 k, uint16 j) { // 0xA6E84D + Enemy_Ridley *E = Get_Ridley(0); + if (E->ridley_var_10) { + R18_ = E->base.x_pos + 25; + R18_ = samus_x_pos - R18_; + R20_ = E->base.y_pos - 43; + R20_ = samus_y_pos - R20_; + uint16 v4 = (uint8)-(int8)(CalculateAngleFromXY() + 0x80); + if (v4 < 0x50u) { + if (v4 >= 0x15u) + goto LABEL_13; + } else if (v4 < 0xC0u) { + v4 = 80; +LABEL_13: + R18_ = v4; + goto LABEL_14; + } + v4 = 21; + goto LABEL_13; + } + R18_ = E->base.x_pos - 25; + R18_ = samus_x_pos - R18_; + R20_ = E->base.y_pos - 43; + R20_ = samus_y_pos - R20_; + uint16 v3; + v3 = (uint8)-(int8)(CalculateAngleFromXY() + 0x80); + if (v3 >= 0xB0u) { + if (v3 < 0xEBu) + goto LABEL_7; +LABEL_6: + v3 = 235; + goto LABEL_7; + } + if (v3 < 0x40u) + goto LABEL_6; + v3 = 176; +LABEL_7: + R18_ = v3; +LABEL_14: + E->ridley_var_19 = Math_MultBySin(0x500u); + E->ridley_var_1A = Math_MultByCos(0x500u); + return j; +} + +uint16 Ridley_Instr_12(uint16 k, uint16 j) { // 0xA6E904 + return Ridley_E90C(k, j, 0); +} + +uint16 Ridley_Instr_13(uint16 k, uint16 j) { // 0xA6E909 + return Ridley_E90C(k, j, 0xe); +} + +uint16 Ridley_E90C(uint16 k, uint16 j, uint16 a) { // 0xA6E90C + enemy_projectile_unk1995 = a; + Enemy_Ridley *E = Get_Ridley(0); + SpawnEnemyProjectileWithRoomGfx(0x9642u, E->ridley_var_10); + return j; +} + + +uint16 Ridley_Instr_15(uint16 k, uint16 j) { // 0xA6E969 + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_A = FUNC16(CeresRidley_Func_9); + E->ridley_var_C = -352; + return j; +} + +uint16 Ridley_Instr_16(uint16 k, uint16 j) { // 0xA6E976 + Enemy_Ridley *E = Get_Ridley(0); + E->ridley_var_A = FUNC16(Ridley_Func_3); + E->ridley_var_C = -352; + return j; +} + +void CeresSteam_Init(void) { // 0xA6EFB1 + Enemy_CeresSteam *E = Get_CeresSteam(cur_enemy_index); + E->base.vram_tiles_index = 0; + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.extra_properties |= 4u; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.palette_index = 2560; + E->csm_var_D = (NextRandom() & 0x1F) + 1; + int v1 = (uint16)(2 * E->csm_parameter_1) >> 1; + E->base.current_instruction = g_off_A6EFF5[v1]; + E->csm_var_A = g_off_A6F001[v1]; +} + +void CallCeresSteamFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnnullsub_350: return; // 0xa6eff4 + case fnCeresSteam_Func_1: CeresSteam_Func_1(k); return; // 0xa6f019 + default: Unreachable(); + } +} + +void CeresSteam_Main(void) { // 0xA6F00D + Enemy_CeresSteam *E = Get_CeresSteam(cur_enemy_index); + E->base.health = 0x7FFF; + CallCeresSteamFunc(E->csm_var_A | 0xA60000, cur_enemy_index); +} + +void CeresSteam_Func_1(uint16 k) { // 0xA6F019 + EnemySpawnData *v3; + + Enemy_CeresSteam *E = Get_CeresSteam(k); + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + CalcCeresSteamPos_Mode7(); + v3 = gEnemySpawnData(cur_enemy_index); + v3->xpos2 = R18_ - E->base.x_pos; + v3->ypos2 = R20_ - E->base.y_pos; +} + +void CeresSteam_Touch(void) { // 0xA6F03F + Get_CeresSteam(cur_enemy_index)->base.health = 0x7FFF; + NormalEnemyTouchAi(); +} + +uint16 CeresSteam_Instr_1(uint16 k, uint16 j) { // 0xA6F11D + Enemy_CeresSteam *E = Get_CeresSteam(k); + E->base.properties |= kEnemyProps_Tangible | kEnemyProps_Invisible; + return j; +} + +uint16 CeresSteam_Instr_2(uint16 k, uint16 j) { // 0xA6F127 + Enemy_CeresSteam *E = Get_CeresSteam(k); + if (E->csm_var_D-- != 1) + return *(uint16 *)RomPtr_A6(j); + uint8 *v5 = RomPtr_A6(j); + return CeresSteam_Instr_3(k, *((uint16 *)v5 + 1)); +} + +uint16 CeresSteam_Instr_3(uint16 k, uint16 j) { // 0xA6F135 + Enemy_CeresSteam *E = Get_CeresSteam(k); + E->base.properties &= 0xFAFFu; + return j; +} + +uint16 CeresDoor_Instr_6(uint16 k, uint16 j) { // 0xA6F63E + Enemy_CeresDoor *E = Get_CeresDoor(k); + if (abs16(E->base.x_pos - samus_x_pos) >= 0x30u || abs16(E->base.y_pos - samus_y_pos) >= 0x30u) + return CeresDoor_Goto(j); + else + return CeresDoor_Incr(j); +} + +uint16 CeresDoor_Incr(uint16 j) { // 0xA6F662 + return j + 2; +} + +uint16 CeresDoor_Goto(uint16 j) { // 0xA6F665 + return *(uint16 *)RomPtr_A6(j); +} + +uint16 CeresDoor_Instr_4(uint16 k, uint16 j) { // 0xA6F66A + if (*(uint16 *)&boss_bits_for_area[area_index] & 1) + return CeresDoor_Incr(j); + else + return CeresDoor_Goto(j); +} + +uint16 CeresDoor_Instr_8(uint16 k, uint16 j) { // 0xA6F678 + if (ceres_status) + return CeresDoor_Incr(j); + else + return CeresDoor_Goto(j); +} + +void CeresDoor_Func_6b(void) { // 0xA6F67F + if (ceres_status) + ceres_status = FUNC16(Enemy_GrappleReact_NoInteract_A6); +} + +uint16 CeresSteam_Instr_4(uint16 k, uint16 j) { // 0xA6F68B + Enemy_CeresSteam *E = Get_CeresSteam(k); + E->base.properties |= kEnemyProps_Tangible; + return j; +} + +uint16 CeresDoor_Instr_1(uint16 k, uint16 j) { // 0xA6F695 + Enemy_CeresDoor *E = Get_CeresDoor(k); + E->base.properties &= ~kEnemyProps_Tangible; + return j; +} + +uint16 CeresDoor_Instr_3(uint16 k, uint16 j) { // 0xA6F69F + Get_CeresDoor(k)->cdr_var_B = 1; + return j; +} + +uint16 CeresSteam_Instr_5(uint16 k, uint16 j) { // 0xA6F6A6 + Enemy_CeresSteam *E = Get_CeresSteam(k); + E->base.properties |= kEnemyProps_Invisible; + return j; +} + +uint16 CeresDoor_Instr_5(uint16 k, uint16 j) { // 0xA6F6B0 + Get_CeresDoor(k)->cdr_var_B = 0; + return CeresDoor_Instr_2(k, j); +} + +uint16 CeresDoor_Instr_2(uint16 k, uint16 j) { // 0xA6F6B3 + Enemy_CeresDoor *E = Get_CeresDoor(k); + E->base.properties &= ~kEnemyProps_Invisible; + return j; +} + +uint16 CeresDoor_Instr_7(uint16 k, uint16 j) { // 0xA6F6BD + QueueSfx3_Max6(0x2Cu); + return j; +} + +void CeresDoor_Init(void) { // 0xA6F6C5 + Enemy_CeresDoor *E = Get_CeresDoor(cur_enemy_index); + E->base.spritemap_pointer = addr_kCeresDoor_Sprmap_FAC7; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.vram_tiles_index = 0; + E->base.palette_index = 1024; + int v2 = (uint16)(2 * E->cdr_parameter_1) >> 1; + E->cdr_var_A = g_off_A6F72B[v2]; + E->base.current_instruction = g_off_A6F52C[v2]; + E->cdr_var_B = 0; + CeresDoor_Func_1(cur_enemy_index); + uint16 v3; + if (ceres_status) { + v3 = addr_word_A6F50C__plus__2; + } else { + if (E->cdr_parameter_1 == 3) { + WriteColorsToTargetPalette(0xa6, 0x142u, addr_kCeresDoor_Palette__plus__2, 0xFu); + return; + } + v3 = addr_kCeresDoor_Palette__plus__2; + } + Get_CeresDoor(cur_enemy_index)->base.palette_index = 3584; + WriteColorsToTargetPalette(0xa6, 0x1E2u, v3, 0xFu); +} + +void CeresDoor_Func_1(uint16 k) { // 0xA6F739 + VramWriteEntry *v2; + + if (Get_CeresDoor(k)->cdr_parameter_1 == 2) { + uint16 v1 = vram_write_queue_tail; + v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 1024; + *(VoidP *)((char *)&v2->src.addr + 1) = -20480; + v2->src.addr = -15360; + v2->vram_dst = 28672; + vram_write_queue_tail = v1 + 7; + } +} + +void CallCeresDoor(uint32 ea) { + uint16 k = cur_enemy_index; + switch (ea) { + case fnCeresDoor_Func_2: CeresDoor_Func_2(); return; // 0xa6f76b + case fnCeresDoor_Func_3: CeresDoor_Func_3(); return; // 0xa6f770 + case fnCeresDoor_Func_4: CeresDoor_Func_4(); return; // 0xa6f7a5 + case fnCeresDoor_Func_5: CeresDoor_Func_5(k); return; // 0xa6f7bd + case fnCeresDoor_Func_6: CeresDoor_Func_6(k); return; // 0xa6f7dc + case fnCeresDoor_Func_7: CeresDoor_Func_7(); return; // 0xa6f850 + default: Unreachable(); + } +} + +void CeresDoor_Main(void) { // 0xA6F765 + Enemy_CeresDoor *E = Get_CeresDoor(cur_enemy_index); + CallCeresDoor(E->cdr_var_A | 0xA60000); +} + +void CeresDoor_Func_2(void) { // 0xA6F76B + CeresDoor_F773(0x14u); +} + +void CeresDoor_Func_3(void) { // 0xA6F770 + CeresDoor_F773(0x1Du); +} + +void CeresDoor_F773(uint16 j) { // 0xA6F773 + if (ceres_status >= 2u && !earthquake_timer) { + if ((random_number & 0xFFFu) < 0x80) { + earthquake_timer = 4; + earthquake_type = j + 6; + } else { + earthquake_timer = 2; + earthquake_type = j; + } + } +} + +void CeresDoor_Func_4(void) { // 0xA6F7A5 + CeresSteam_Instr_5(cur_enemy_index, 0); + if (ceres_status & 1) { + Get_CeresDoor(cur_enemy_index)->base.palette_index = 3584; + CeresDoor_Instr_2(cur_enemy_index, 0); + } +} + +void CeresDoor_Func_5(uint16 k) { // 0xA6F7BD + CeresDoor_Func_7(); + if (ceres_status >= 2u) { + Enemy_CeresDoor *E = Get_CeresDoor(k); + E->cdr_var_A = FUNC16(CeresDoor_Func_6); + E->cdr_var_D = 48; + Enemy_CeresDoor *E0 = Get_CeresDoor(0); + E0->cdr_var_E = 0; + E0->cdr_var_F = 0; + } +} + +void CeresDoor_Func_6(uint16 k) { // 0xA6F7DC + Enemy_CeresDoor *E = Get_CeresDoor(k); + bool v3 = (--E->cdr_var_D & 0x8000u) != 0; + if (v3) { + E->base.properties |= kEnemyProps_Invisible; + E->cdr_var_A = FUNC16(CeresDoor_Func_7); + CeresDoor_Func_6b(); + } else { + Enemy_CeresDoor *E0 = Get_CeresDoor(0); + v3 = (--E0->cdr_var_E & 0x8000u) != 0; + if (v3) { + E0->cdr_var_E = 4; + v3 = (--E0->cdr_var_F & 0x8000u) != 0; + if (v3) + E0->cdr_var_F = 3; + int v5 = (uint16)(4 * E0->cdr_var_F) >> 1; + R18_ = E->base.x_pos + g_word_A6F840[v5]; + R20_ = E->base.y_pos + g_word_A6F840[v5 + 1]; + uint16 v6 = 3; + if (NextRandom() < 0x4000u) + v6 = 12; + SpawnEnemyProjectileWithRoomGfx(0xE509u, v6); + QueueSfx2_Max6(0x25u); + } + } +} + +void CeresDoor_Func_7(void) { // 0xA6F850 + CeresDoor_Func_8(); + if (!palette_change_num) + WriteColorsToPalette( + 0x52u, + 0xa6, 2 * (nmi_frame_counter_word & 0x38) - 0x78F, + 6u); +} + +void CeresDoor_Func_8(void) { // 0xA6F8F1 + QueueMode7Transfers(0xA6u, g_off_A6F900[(uint8)(nmi_frame_counter_word & 2) >> 1]); +} + +void Zebetites_Init(void) { // 0xA6FB72 + Enemy_Zebetites *E = Get_Zebetites(cur_enemy_index); + E->base.properties |= 0xA000u; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.palette_index = 1024; + E->base.vram_tiles_index = 128; + E->zebet_var_C = 0; + uint16 v1 = FUNC16(Zebetites_Func_1); + if (E->zebet_parameter_1) + v1 = FUNC16(Zebetites_Func_2); + E->zebet_var_A = v1; + R18_ = 0; + R18_ = (R18_ << 1) | CheckEventHappened(5u); + R18_ = (R18_ << 1) | CheckEventHappened(4u); + R18_ = (R18_ << 1) | CheckEventHappened(3u); + uint16 v2 = R18_; + E->zebet_var_D = R18_; + if (sign16(v2 - 4)) { + int v3 = v2; + E->zebet_var_F = g_word_A6FC03[v3]; + E->base.y_height = g_word_A6FC0B[v3]; + E->base.current_instruction = g_off_A6FC13[v3]; + E->base.x_pos = g_word_A6FC1B[v3]; + uint16 v4; + if (E->zebet_parameter_1) + v4 = g_word_A6FC2B[v3]; + else + v4 = g_word_A6FC23[v3]; + E->base.y_pos = v4; + } else { + E->base.properties |= kEnemyProps_Deleted; + } +} + +void CallZebetitesFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnZebetites_Func_1: Zebetites_Func_1(k); return; + case fnZebetites_Func_2: Zebetites_Func_2(k); return; + case fnZebetites_Func_3: Zebetites_Func_3(); return; + default: Unreachable(); + } +} + +void Zebetites_Main(void) { // 0xA6FC33 + if (!earthquake_timer) + Get_Zebetites(cur_enemy_index)->base.shake_timer = 0; + Enemy_Zebetites *E = Get_Zebetites(cur_enemy_index); + CallZebetitesFunc(E->zebet_var_A | 0xA60000, cur_enemy_index); +} + +void Zebetites_Func_1(uint16 k) { // 0xA6FC41 + Enemy_Zebetites *E = Get_Zebetites(k); + if ((E->zebet_var_F & 0x8000u) != 0) { + uint16 new_k = Zebetites_Func_9(); + Get_Zebetites(new_k)->zebet_parameter_2 = k; + Get_Zebetites(k)->zebet_parameter_2 = new_k; + } + Get_Zebetites(k)->zebet_var_A = FUNC16(Zebetites_Func_2); + Zebetites_Func_2(k); +} + +void Zebetites_Func_2(uint16 k) { // 0xA6FC5B + if (!door_transition_flag_elevator_zebetites) { + Get_Zebetites(k)->zebet_var_A = FUNC16(Zebetites_Func_3); + Zebetites_Func_3(); + } +} + +void Zebetites_Func_3(void) { // 0xA6FC67 + int16 v3; + + Zebetites_Func_4(); + Zebetites_Func_5(); + Enemy_Zebetites *E = Get_Zebetites(cur_enemy_index); + uint16 health = E->base.health; + if (health) { + v3 = health + 1; + if (!sign16(v3 - 1000)) + v3 = 1000; + E->base.health = v3; + } else if (E->zebet_parameter_1 + || (Zebetites_Func_6(), !sign16(E->zebet_var_D - 4))) { + EnemyDeathAnimation(cur_enemy_index, 0); + } else { + EnemyDeathAnimation(cur_enemy_index, 0); + Zebetites_Func_8(); + } +} + +void Zebetites_Func_6(void) { // 0xA6FCAA + int16 v1; + + Enemy_Zebetites *E = Get_Zebetites(cur_enemy_index); + v1 = E->zebet_var_D + 1; + E->zebet_var_D = v1; + R18_ = v1; + Zebetites_Func_7(3u, (R18_ >> 0) & 1); + Zebetites_Func_7(4u, (R18_ >> 1) & 1); + Zebetites_Func_7(5u, (R18_ >> 2) & 1); +} + +void Zebetites_Func_7(uint16 j, uint8 a) { // 0xA6FCCB + if (a) + SetEventHappened(j); + else + ClearEventHappened(j); +} + +void Zebetites_Func_8(void) { // 0xA6FCD9 + SpawnEnemy(0xA6u, addr_stru_A6FCE1); +} + +uint16 Zebetites_Func_9(void) { // 0xA6FCF1 + return SpawnEnemy(0xA6u, addr_stru_A6FCF9); +} + +void Zebetites_Func_5(void) { // 0xA6FD09 + uint16 v0 = 0; + Enemy_Zebetites *E = Get_Zebetites(cur_enemy_index); + uint16 health = E->base.health; + if (sign16(health - 800)) { + v0 = 2; + if (sign16(health - 600)) { + v0 = 4; + if (sign16(health - 400)) { + v0 = 6; + if (sign16(health - 200)) + v0 = 8; + } + } + } + int v3 = v0 >> 1; + uint16 v4 = g_off_A6FD4A[v3]; + if ((E->zebet_var_F & 0x8000u) != 0) + v4 = g_off_A6FD54[v3]; + E->base.current_instruction = v4; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void Zebetites_Func_4(void) { // 0xA6FD5E + if (!palette_change_num && !Get_Zebetites(cur_enemy_index)->zebet_parameter_1) { + Enemy_Zebetites *E = Get_Zebetites(0); + uint16 v1 = ((uint8)E->zebet_var_C + 1) & 7; + E->zebet_var_C = v1; + WriteColorsToPalette(0x158u, 0xa6, 4 * v1 - 0x279, 2u); + } +} + +void Zebetites_Touch(void) { // 0xA6FDA7 + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); +} + +void Zebetites_Shot(void) { // 0xA6FDAC + QueueSfx3_Max6(9u); + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + Enemy_Zebetites *E = Get_Zebetites(cur_enemy_index); + Enemy_Zebetites *G = Get_Zebetites(E->zebet_parameter_2); + G->base.health = E->base.health; + G->base.flash_timer = E->base.flash_timer; +} diff --git a/src/sm_a7.c b/src/sm_a7.c new file mode 100644 index 0000000..4992fb4 --- /dev/null +++ b/src/sm_a7.c @@ -0,0 +1,4196 @@ +// Enemy AI - inc. Kraid (complete) & Phantoon +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" +#include "sm_rtl.h" + + + +#define kKraid_Palette2 ((uint16*)RomPtr(0xa786c7)) +#define kKraid_Palette2 ((uint16*)RomPtr(0xa786c7)) +#define kKraid_BgTargetPalette3 ((uint16*)RomPtr(0xa7aaa6)) +#define g_word_A7ACB3 ((uint16*)RomPtr(0xa7acb3)) +#define g_off_A7ACC5 ((uint16*)RomPtr(0xa7acc5)) + +static const uint16 g_word_A7A916 = 0x120; +static const uint16 g_word_A7A918 = 0xa0; +static const uint16 g_word_A7A91A = 0x40; +static const uint16 g_word_A7A91C = 3; +static const uint16 g_word_A7A920 = 3; +static const uint16 g_word_A7A922 = 4; +static const uint16 g_word_A7A926 = 0x8000; +static const uint16 g_word_A7A928 = 3; + +#define g_stru_A796D2 (*(KraidInstrList*)RomPtr(0xa796d2)) +#define g_stru_A796DA (*(KraidInstrList*)RomPtr(0xa796da)) +#define g_word_A7B161 ((uint16*)RomPtr(0xa7b161)) + +#define kKraid_BgPalette7 ((uint16*)RomPtr(0xa7b3d3)) +#define kKraid_BgPalette7_KraidDeath ((uint16*)RomPtr(0xa7b4f3)) +#define kKraid_SprPalette7_KraidDeath ((uint16*)RomPtr(0xa7b513)) +#define g_stru_A7974A ((KraidInstrList*)RomPtr(0xa7974a)) +#define g_stru_A79764 ((KraidInstrList*)RomPtr(0xa79764)) +#define g_stru_A792B7 (*(Hitbox*)RomPtr(0xa792b7)) +#define g_word_A7BA7D ((uint16*)RomPtr(0xa7ba7d)) +#define g_word_A7BC65 ((uint16*)RomPtr(0xa7bc65)) +#define kKraid_Ilist_8B0A (*(SpriteDrawInstr*)RomPtr(0xa78b0a)) +#define g_off_A7BE3E ((uint16*)RomPtr(0xa7be3e)) +#define g_off_A7BE46 ((uint16*)RomPtr(0xa7be46)) +#define g_word_A7BF1D ((uint16*)RomPtr(0xa7bf1d)) +#define kKraidSinkEntry ((KraidSinkTable*)RomPtr(0xa7c5e7)) +#define g_off_A7CE8E ((uint16*)RomPtr(0xa7ce8e)) +#define g_word_A7CDED ((uint16*)RomPtr(0xa7cded)) +#define g_stru_A7902D ((ExtendedSpriteMap*)RomPtr(0xa7902d)) +#define g_byte_A7CFC2 ((uint8*)RomPtr(0xa7cfc2)) +#define g_off_A7CCFD ((uint16*)RomPtr(0xa7ccfd)) +#define g_word_A7CD41 ((uint16*)RomPtr(0xa7cd41)) +#define g_word_A7CD53 ((uint16*)RomPtr(0xa7cd53)) +#define g_word_A7CD63 ((uint16*)RomPtr(0xa7cd63)) +static const uint16 g_word_A7CD73 = 0x600; +static const uint16 g_word_A7CD75 = 0; +static const uint16 g_word_A7CD77 = 0x1000; +static const uint16 g_word_A7CD79 = 0; +static const uint16 g_word_A7CD7B = 2; +static const uint16 g_word_A7CD7D = 7; +static const uint16 g_word_A7CD7F = 0; +static const uint16 g_word_A7CD81 = 0x600; +static const uint16 g_word_A7CD83 = 0; +static const uint16 g_word_A7CD85 = 0x1000; +static const uint16 g_word_A7CD87 = 0; +static const uint16 g_word_A7CD89 = 0xfffe; +static const uint16 g_word_A7CD8B = 0xfff9; +static const uint16 g_word_A7CD8D = 0; +#define g_off_A7D40D ((uint16*)RomPtr(0xa7d40d)) +static const uint16 g_word_A7CD9B = 0x40; +static const uint16 g_word_A7CD9D = 0xc00; +static const uint16 g_word_A7CD9F = 0x100; +static const uint16 g_word_A7CDA1 = 0xf000; +static const uint16 g_word_A7CDA3 = 8; +static const uint8 g_byte_A7CDA5[8] = { 6, 6, 8, 8, 6, 8, 6, 8 }; +#define g_word_A7CDAD ((uint16*)RomPtr(0xa7cdad)) +#define g_byte_A7DA1D ((uint8*)RomPtr(0xa7da1d)) +#define g_off_A7DC4A ((uint16*)RomPtr(0xa7dc4a)) +static const uint16 g_word_A7E900 = 0xfffd; +static const uint16 g_word_A7E902 = 0; +static const uint16 g_word_A7E906 = 0; +static const uint16 g_word_A7E904 = 0xfffc; +static const uint16 g_word_A7E908 = 2; +static const uint16 g_word_A7E90A = 0; +static const uint16 g_word_A7E90C = 0xfffe; +static const uint16 g_word_A7E90E = 0; +static const uint16 g_word_A7E910 = 0x40; + +static const uint16 g_word_A7F4C9 = 0x60; +static const uint16 g_word_A7F4CD = 0x78; +static const uint16 g_word_A7F4CF = 0x3c; +static const uint16 g_word_A7F4D1 = 1; +static const uint16 g_word_A7F4D3 = 8; +static const uint16 g_word_A7F4D5 = 8; +static const uint16 g_word_A7F4D7 = 0; +static const uint16 g_word_A7F4D9 = 0; +static const uint16 g_word_A7F4DB = 0x1000; +#define g_off_A7F787 ((uint16*)RomPtr(0xa7f787)) +#define g_off_A7F92D ((uint16*)RomPtr(0xa7f92d)) +#define g_word_A7CA41 ((uint16*)RomPtr(0xa7ca41)) +#define g_word_A7CA61 ((uint16*)RomPtr(0xa7ca61)) + +uint16 EnemyInstr_Goto_A7(uint16 k, uint16 j) { // 0xA780ED + return *(uint16 *)RomPtr_A7(j); +} + +uint16 EnemyInstr_DecTimerAndGoto2_A7(uint16 k, uint16 j) { // 0xA78110 + EnemyData *v2 = gEnemyData(k); + if (v2->timer-- == 1) + return j + 2; + else + return EnemyInstr_Goto_A7(k, j); +} + +void CallEnemyInstrExtFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnPhantoon_Func_1: Phantoon_Func_1(); return; + case fnPhantoon_Func_4: Phantoon_Func_4(k); return; + case fnPhantoon_StartTrackingSamusAndInitEyeTimer: Phantoon_StartTrackingSamusAndInitEyeTimer(); return; + case fnPhantoon_PickPatternForRound2: Phantoon_PickPatternForRound2(); return; + default: Unreachable(); + } +} + +uint16 EnemyInstr_Call_A7(uint16 k, uint16 j) { // 0xA7808A + R18_ = *(uint16 *)RomPtr_A7(j); + CallEnemyInstrExtFunc(R18_ | 0xA70000, k); + return j + 2; +} +uint16 EnemyInstr_SetTimer_A7(uint16 k, uint16 j) { // 0xA78123 + uint16 v2 = *(uint16 *)RomPtr_A7(j); + gEnemyData(k)->timer = v2; + return j + 2; +} +uint16 EnemyInstr_Sleep_A7(uint16 k, uint16 j) { // 0xA7812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + + +void Enemy_GrappleReact_NoInteract_A7(void) { // 0xA78000 + SwitchEnemyAiToMainAi(); +} + +void Enemy_GrappleReact_CancelBeam_A7(void) { // 0xA7800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_NormalShotAI_A7(void) { // 0xA7802D + NormalEnemyShotAi(); +} + +void Enemy_NormalPowerBombAI_SkipDeathAnim_A7(void) { // 0xA7803C + NormalEnemyPowerBombAiSkipDeathAnim_CurEnemy(); +} + +void Enemy_NormalFrozenAI_A7(void) { // 0xA78041 + NormalEnemyFrozenAI(); +} + +uint16 Kraid_Instr_9(uint16 k, uint16 j) { // 0xA78A8F + Enemy_Kraid *E = Get_Kraid(0); + if ((int16)(E->base.health - E->kraid_healths_8ths[3]) < 0) { + Enemy_Kraid *E1 = Get_Kraid(0x40u); + if (sign16(E1->base.current_instruction + 0x75BF)) + return addr_kKraid_Ilist_8A41; + } + return j; +} + +void Kraid_Touch_ArmFoot(void) { // 0xA7948B + NormalEnemyTouchAi(); +} + +void KraidsArm_Touch(void) { // 0xA79490 + if (!samus_invincibility_timer) { + Kraid_Func_1(); + gEnemyData(0)[4].ai_var_A = FUNC16(KraidLint_FireLint); + Kraid_Touch(); + } +} + +void Kraid_Touch(void) { // 0xA7949F + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); +} + +void Kraid_Func_1(void) { // 0xA794A4 + extra_samus_x_displacement = 4; + extra_samus_y_displacement = -8; +} + +void Kraid_Shot(void) { // 0xA794B1 + NormalEnemyShotAi(); +} + +void Kraid_Arm_Shot(uint16 j) { // 0xA794B6 + Kraid_SpawnExplosionEproj(j); + projectile_dir[j >> 1] |= 0x10u; +} + +void sub_A7A92A(void) { // 0xA7A92A + Kraid_CheckIfDead(); +} + +uint16 Kraid_CheckIfDead(void) { // 0xA7A92C + return (*(uint16 *)&boss_bits_for_area[area_index] & 1) != 0; +} + +void Kraid_SetEnemyPropsToDead(void) { // 0xA7A943 + Enemy_Kraid *E = Get_Kraid(cur_enemy_index); + E->base.properties = E->base.properties & 0x50FF | 0x700; +} + +void Kraid_Init(void) { // 0xA7A959 + VramWriteEntry *v5; + uint16 j; + + unpause_hook.bank = -89; + pause_hook.bank = -89; + unpause_hook.addr = FUNC16(UnpauseHook_Kraid_IsAlive); + pause_hook.addr = FUNC16(PauseHook_Kraid); + if (Kraid_CheckIfDead()) { + uint16 v0 = 192; + uint16 v1 = 0; + do { + target_palettes[v0 >> 1] = kKraid_Palette2[v1 >> 1]; + v0 += 2; + v1 += 2; + } while ((int16)(v1 - 32) < 0); + for (int i = 2046; i >= 0; i -= 2) + tilemap_stuff[i >> 1] = 824; + Enemy_Kraid *E = Get_Kraid(0); + E->field_4 = 0; + uint16 v4 = vram_write_queue_tail; + v5 = gVramWriteEntry(vram_write_queue_tail); + v5->size = 512; + v5->src.addr = addr_kKraidsRoomBg; + v5->src.bank = -89; + v5->vram_dst = ((reg_BG12NBA & 0xF) << 8) + 16128; + vram_write_queue_tail = v4 + 7; + Kraid_SpawnPlmToClearCeiling(); + Kraid_ClearSomeSpikes(); + E->kraid_var_A = FUNC16(Kraid_FadeInBg_ClearBg2TilemapTopHalf); + } else { + reg_BG2SC = 67; + camera_distance_index = 2; + *(uint16 *)scrolls = 0; + *(uint16 *)&scrolls[2] = 1; + Enemy_Kraid *E = Get_Kraid(0); + E->kraid_min_y_pos_eject = 324; + uint16 v7 = 0; + uint16 v8 = E->base.health >> 3; + R18_ = v8; + do { + Get_Kraid(v7)->kraid_healths_8ths[0] = v8; + v8 += R18_; + v7 += 2; + } while ((int16)(v7 - 16) < 0); + R18_ = -8193; + Kraid_SetupGfxWithTilePrioClear(); + uint16 v10 = E->base.health >> 2; + E->kraid_healths_4ths[0] = v10; + uint16 v11 = E->kraid_healths_4ths[0] + v10; + E->kraid_healths_4ths[1] = v11; + uint16 v12 = E->kraid_healths_4ths[0] + v11; + E->kraid_healths_4ths[2] = v12; + E->kraid_healths_4ths[3] = E->kraid_healths_4ths[0] + v12; + E->field_2E[8] = 0; + E->base.x_pos = 176; + E->base.y_pos = 592; + E->base.properties |= kEnemyProps_Tangible; + E->kraid_var_A = FUNC16(Kraid_RestrictSamusXtoFirstScreen); + E->kraid_var_F = 300; + E->kraid_next = FUNC16(Kraid_RaiseKraidThroughFloor); + E->kraid_var_C = 64; + DisableMinimapAndMarkBossRoomAsExplored(); + for (j = 62; (j & 0x8000u) == 0; j -= 2) + tilemap_stuff[(j >> 1) + 2016] = 824; + earthquake_type = 5; + uint16 v14 = 0; + do { + target_palettes[(v14 >> 1) + 176] = kKraid_BgTargetPalette3[v14 >> 1]; + v14 += 2; + } while ((int16)(v14 - 32) < 0); + } +} + +void Kraid_SetupGfxWithTilePrioClear(void) { // 0xA7AAC6 + decompress_src.addr = addr_byte_B9FA38; + decompress_src.bank = -71; + decompress_dst.addr = 0x4000; + DecompressToMem(); + decompress_src.addr = addr_byte_B9FE3E; + decompress_src.bank = -71; + decompress_dst.addr = 0x2000; + DecompressToMem(); + Enemy_Kraid *E = Get_Kraid(0); + E->kraid_hurt_frame = 0; + E->kraid_hurt_frame_timer = 0; + uint16 v1 = 0; + do { + tilemap_stuff[(v1 >> 1) + 1024] = tilemap_stuff[v1 >> 1] & 0xDFFF; + v1 += 2; + } while ((int16)(v1 - 1536) < 0); + uint16 v2 = 0; + do { + tilemap_stuff[v2] = R18_ & ram4000.xray_tilemaps[v2]; + ++v2; + } while ((int16)(v2 * 2 - 2048) < 0); +} + +void KraidsArm_Init(void) { // 0xA7AB43 + if (Kraid_CheckIfDead()) { + Kraid_SetEnemyPropsToDead(); + } else { + EnemyData *v0 = gEnemyData(0); + v0[1].palette_index = v0->palette_index; + v0[1].ai_var_A = FUNC16(nullsub_234); + v0[1].current_instruction = addr_kKraid_Ilist_8AA4; + v0[1].instruction_timer = 1; + v0[1].ai_var_B = 0; + } +} + +void KraidsTopLint_Init(void) { // 0xA7AB68 + if (Kraid_CheckIfDead()) { + Kraid_SetEnemyPropsToDead(); + } else { + EnemyData *v0 = gEnemyData(0); + v0[2].palette_index = v0->palette_index; + v0[2].instruction_timer = 0x7FFF; + v0[2].current_instruction = addr_kKraid_Ilist_8AFE; + v0[2].spritemap_pointer = addr_kKraid_Sprmap_A5DF; + v0[2].ai_var_A = addr_locret_A7B831; + v0[2].ai_preinstr = 0x7FFF; + v0[2].ai_var_C = 0; + } +} + +void KraidsMiddleLint_Init(void) { // 0xA7AB9C + if (Kraid_CheckIfDead()) { + Kraid_SetEnemyPropsToDead(); + } else { + EnemyData *v0 = gEnemyData(0); + v0[3].palette_index = v0->palette_index; + v0[3].instruction_timer = 0x7FFF; + v0[3].current_instruction = addr_kKraid_Ilist_8AFE; + v0[3].spritemap_pointer = addr_kKraid_Sprmap_A5DF; + v0[3].ai_var_A = addr_locret_A7B831; + v0[3].ai_var_C = -16; + } +} + +void KraidsBottomLint_Init(void) { // 0xA7ABCA + if (Kraid_CheckIfDead()) { + Kraid_SetEnemyPropsToDead(); + } else { + EnemyData *v0 = gEnemyData(0); + v0[4].palette_index = v0->palette_index; + v0[4].instruction_timer = 0x7FFF; + v0[4].current_instruction = addr_kKraid_Ilist_8AFE; + v0[4].spritemap_pointer = addr_kKraid_Sprmap_A5DF; + v0[4].ai_var_A = addr_locret_A7B831; + v0[4].ai_var_C = -16; + } +} + +void KraidsFoot_Init(void) { // 0xA7ABF8 + if (Kraid_CheckIfDead()) { + Kraid_SetEnemyPropsToDead(); + } else { + uint16 palette_index = Get_Kraid(0)->base.palette_index; + Enemy_Kraid *E = Get_Kraid(0x140u); + E->base.palette_index = palette_index; + E->base.current_instruction = addr_kKraid_Ilist_86E7; + E->base.instruction_timer = 1; + E->kraid_var_A = FUNC16(nullsub_234); + E->kraid_next = 0; + } +} + +void CallKraidFunc(uint32 ea) { + uint16 k = cur_enemy_index; + switch (ea) { + case fnKraid_GetsBig_BreakCeilingPlatforms: Kraid_GetsBig_BreakCeilingPlatforms(); return; // 0x9bc35 + case fnKraid_GetsBig_SetBG2TilemapPrioBits: Kraid_GetsBig_SetBG2TilemapPrioBits(); return; // 0x9bde6 + case fnKraid_GetsBig_FinishUpdateBg2Tilemap: Kraid_GetsBig_FinishUpdateBg2Tilemap(); return; // 0x9be51 + case fnKraid_GetsBig_DrawRoomBg: Kraid_GetsBig_DrawRoomBg(); return; // 0x9bee5 + case fnKraid_GetsBig_FadeInRoomBg: Kraid_GetsBig_FadeInRoomBg(); return; // 0x9c08c + case fnKraid_Mainloop_Thinking: Kraid_Mainloop_Thinking(); return; // 0x9c1b8 + case fnKraid_GetsBig_Thinking: Kraid_GetsBig_Thinking(); return; // 0x9c207 + case fnKraid_Shot_MouthIsOpen: Kraid_Shot_MouthIsOpen(); return; // 0x9c256 + case fnKraid_InitEyeGlowing: Kraid_InitEyeGlowing(); return; // 0x9cf64 + case fnKraid_Shot_GlowHisEye: Kraid_Shot_GlowHisEye(); return; // 0x9cf9f + case fnKraid_Shot_UnglowEye: Kraid_Shot_UnglowEye(); return; // 0x9d0b4 + case fnKraidLint_ProduceLint: KraidLint_ProduceLint(k); return; // 0x9d371 + case fnKraidLint_FireLint: KraidLint_FireLint(k); return; // 0x9d44f + case fnKraidFingernail_WaitForLintXpos: KraidFingernail_WaitForLintXpos(k); return; // 0x9d556 + case fnKraid_AlignEnemyToKraid: Kraid_AlignEnemyToKraid(k); return; // 0x9d5b5 + case fnKraidEnemy_HandleFunctionTimer: KraidEnemy_HandleFunctionTimer(k); return; // 0x9d5e5 + case fnKraidEnemy_DecrementEnemyFunctionTimer: KraidEnemy_DecrementEnemyFunctionTimer(); return; // 0x9d61c + case fnKraidFoot_FirstPhase_Thinking: KraidFoot_FirstPhase_Thinking(k); return; // 0x9d66a + case fnKraidEnemy_ProcessInstrEnemyTimer: KraidEnemy_ProcessInstrEnemyTimer(k); return; // 0x9d67d + case fnKraidsFoot_SecondPhase_Thinking: KraidsFoot_SecondPhase_Thinking(); return; // 0x9d8b2 + case fnKraidsFoot_SecondPhase_WalkingBackwards: KraidsFoot_SecondPhase_WalkingBackwards(); return; // 0x9da2d + case fnKraidsFoot_SecondPhaseSetup_WalkToStartPt: KraidsFoot_SecondPhaseSetup_WalkToStartPt(); return; // 0x9daa2 + case fnKraidsFoot_SecondPhase_Init: KraidsFoot_SecondPhase_Init(); return; // 0x9db2a + case fnKraidsFoot_SecondPhase_WalkForward: KraidsFoot_SecondPhase_WalkForward(); return; // 0x9db40 + case fnKraid_Main_AttackWithMouthOpen: Kraid_Main_AttackWithMouthOpen(); return; // 0x9dbe0 + case fnKraidsFingernail_Init: KraidsFingernail_Init(); return; // 0x9df94 + case fnKraidsFingernail_Fire: KraidsFingernail_Fire(k); return; // 0x9e1ac + case fnKraidsFoot_PrepareToLungeForward: KraidsFoot_PrepareToLungeForward(); return; // 0x9e312 + case fnKraidsFoot_FirstPhase_RetreatFromLunge: KraidsFoot_FirstPhase_RetreatFromLunge(); return; // 0x9e43a + case fnKraid_GetsBig_ReleaseCamera: Kraid_GetsBig_ReleaseCamera(); return; // 0x9e6a7 + case fnKraid_Death_Init: Kraid_Death_Init(); return; // 0x9ec0b + case fnKraid_Death_Fadeout: Kraid_Death_Fadeout(); return; // 0x9ed75 + case fnKraid_Death_UpdateBG2TilemapTopHalf: Kraid_Death_UpdateBG2TilemapTopHalf(); return; // 0x9ef19 + case fnKraid_Death_UpdateBG2TilemapBottomHalf: Kraid_Death_UpdateBG2TilemapBottomHalf(); return; // 0x9ef92 + case fnKraid_Death_SinkThroughFloor: Kraid_Death_SinkThroughFloor(); return; // 0x9f074 + case fnKraid_FadeInBg_ClearBg2TilemapTopHalf: Kraid_FadeInBg_ClearBg2TilemapTopHalf(); return; // 0x9f369 + case fnKraid_FadeInBg_ClearBg2TilemapBottomHalf: Kraid_FadeInBg_ClearBg2TilemapBottomHalf(); return; // 0x9f3ed + case fnKraid_FadeInBg_LoadBg3Tiles1of4: Kraid_FadeInBg_LoadBg3Tiles1of4(); return; // 0x9f448 + case fnKraid_FadeInBg_LoadBg3Tiles2of4: Kraid_FadeInBg_LoadBg3Tiles2of4(); return; // 0x9f4ad + case fnKraid_FadeInBg_LoadBg3Tiles3of4: Kraid_FadeInBg_LoadBg3Tiles3of4(); return; // 0x9f507 + case fnKraid_FadeInBg_LoadBg3Tiles4of4: Kraid_FadeInBg_LoadBg3Tiles4of4(); return; // 0x9f561 + case fnKraid_FadeInBg_FadeInBp6: Kraid_FadeInBg_FadeInBp6(); return; // 0x9f5bb + case fnKraid_FadeInBg_SetEnemyDead_KraidWasAlive: Kraid_FadeInBg_SetEnemyDead_KraidWasAlive(); return; // 0x9f62d + case fnKraid_FadeInBg_SetEnemyDead_KraidWasDead: Kraid_FadeInBg_SetEnemyDead_KraidWasDead(); return; // 0x9f65b + case fnKraid_RestrictSamusXtoFirstScreen: Kraid_RestrictSamusXtoFirstScreen(k); return; // 0x9f694 + case fnKraid_RaiseKraidThroughFloor: Kraid_RaiseKraidThroughFloor(k); return; // 0x9f6a7 + case fnKraid_Raise_LoadTilemapBottomAndShake: Kraid_Raise_LoadTilemapBottomAndShake(); return; // 0x9f71f + case fnKraid_Raise_SpawnRandomEarthquakeProjs16: Kraid_Raise_SpawnRandomEarthquakeProjs16(); return; // 0x9f7b8 + case fnKraid_Raise_SpawnRandomEarthquakeProjs8: Kraid_Raise_SpawnRandomEarthquakeProjs8(); return; // 0x9f805 + case fnKraid_Raise_Handler: Kraid_Raise_Handler(); return; // 0x9f852 + case fnKraidLint_ChargeLint: KraidLint_ChargeLint(k); return; // 0xa7b868 + case fnnullsub_234: return; // 0xa7ba2d + case fnKraidsFoot_FirstPhase_LungeForward: KraidsFoot_FirstPhase_LungeForward(); return; // 0xa7bf5d + case fnnullsub_347: return; + default: Unreachable(); + } +} +void Kraid_Main(void) { // 0xA7AC21 + Kraid_Shot_Mouth(); + Kraid_Palette_Handling(); + Kraid_Shot_Body(); + Kraid_Enemy_Touch(); + Enemy_Kraid *E = Get_Kraid(0); + printf("E Carry crap!\n"); + reg_BG2HOFS = E->base.x_width + reg_BG1HOFS - bg1_x_offset - E->base.x_pos; + reg_BG2VOFS = layer1_y_pos - E->base.y_pos + 152; + CallKraidFunc(E->kraid_var_A | 0xA70000); +} + +void Kraid_GetsBig_BreakCeilingPlatforms(void) { // 0xA7AC4D + uint16 kraid_var_F; + + if ((nmi_frame_counter_word & 7) == 0) + Kraid_SpawnRandomQuakeProjs(); + uint16 v0 = 1; + Enemy_Kraid *E = Get_Kraid(0); + if ((E->base.y_pos & 2) != 0) + v0 = -1; + R18_ = v0; + E->base.x_pos += v0; + --E->base.y_pos; + if ((E->base.y_pos & 3) != 0 || (kraid_var_F = E->kraid_var_F, (int16)(kraid_var_F - 18) >= 0)) { + + } else { + static const SpawnHardcodedPlmArgs unk_A7ACDB = { 0x02, 0x12, 0xb7a3 }; + static const SpawnHardcodedPlmArgs unk_A7ACE6 = { 0x03, 0x12, 0xb7ab }; + static const SpawnHardcodedPlmArgs unk_A7ACF1 = { 0x04, 0x12, 0xb7b3 }; + static const SpawnHardcodedPlmArgs unk_A7ACFC = { 0x05, 0x12, 0xb7ab }; + static const SpawnHardcodedPlmArgs unk_A7AD07 = { 0x06, 0x12, 0xb7b3 }; + static const SpawnHardcodedPlmArgs unk_A7AD12 = { 0x0a, 0x12, 0xb7b3 }; + static const SpawnHardcodedPlmArgs unk_A7AD1D = { 0x0b, 0x12, 0xb7ab }; + static const SpawnHardcodedPlmArgs unk_A7AD28 = { 0x0c, 0x12, 0xb7b3 }; + static const SpawnHardcodedPlmArgs unk_A7AD33 = { 0x0d, 0x12, 0xb7ab }; + + SpawnEnemyProjectileWithGfx(g_word_A7ACB3[kraid_var_F >> 1], cur_enemy_index, addr_kEproj_RocksFallingKraidCeiling); + R18_ = g_off_A7ACC5[E->kraid_var_F >> 1]; + switch (E->kraid_var_F >> 1) { + case 0: + SpawnHardcodedPlm(&unk_A7AD07); + break; + case 1: + SpawnHardcodedPlm(&unk_A7AD33); + break; + case 2: + SpawnHardcodedPlm(&unk_A7ACDB); + break; + case 3: + SpawnHardcodedPlm(&unk_A7AD12); + break; + case 4: + SpawnHardcodedPlm(&unk_A7ACFC); + break; + case 5: + SpawnHardcodedPlm(&unk_A7AD28); + break; + case 6: + SpawnHardcodedPlm(&unk_A7ACE6); + break; + case 7: + SpawnHardcodedPlm(&unk_A7AD1D); + break; + case 8: + SpawnHardcodedPlm(&unk_A7ACF1); + break; + } + E->kraid_var_F += 2; + } + if (sign16(E->base.y_pos - 296)) + E->kraid_var_A = FUNC16(Kraid_GetsBig_SetBG2TilemapPrioBits); +} + +void Kraid_GetsBig_SetBG2TilemapPrioBits(void) { // 0xA7AD3A + uint16 v0 = 0; + do { + tilemap_stuff[v0 >> 1] |= 0x2000u; + v0 += 2; + } while ((int16)(v0 - 4096) < 0); + Enemy_Kraid *E = Get_Kraid(0x40u); + E->base.properties &= ~0x400u; + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_GetsBig_FinishUpdateBg2Tilemap); + Kraid_UpdateBg2TilemapTopHalf(); +} + +void Kraid_GetsBig_FinishUpdateBg2Tilemap(void) { // 0xA7AD61 + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_GetsBig_DrawRoomBg); + Enemy_Kraid *E5 = Get_Kraid(0x140u); + E5->base.instruction_timer = 1; + E5->base.current_instruction = addr_kKraid_Ilist_86ED; + Enemy_Kraid *E2 = Get_Kraid(0x80); + E2->base.current_instruction = addr_kKraid_Ilist_8B04; + Enemy_Kraid *E3 = Get_Kraid(0xC0u); + E3->base.current_instruction = addr_kKraid_Ilist_8B04; + Enemy_Kraid *E = Get_Kraid(0x100u); + E->base.current_instruction = addr_kKraid_Ilist_8B04; + E2->base.spritemap_pointer = addr_kKraid_Sprmap_8C6C; + E3->base.spritemap_pointer = addr_kKraid_Sprmap_8C6C; + E->base.spritemap_pointer = addr_kKraid_Sprmap_8C6C; + Kraid_UpdateBG2TilemapBottomHalf(); +} + +void Kraid_GetsBig_DrawRoomBg(void) { // 0xA7AD8E + Enemy_Kraid *E = Get_Kraid(0); + E->kraid_var_A = FUNC16(Kraid_GetsBig_FadeInRoomBg); + E->kraid_var_E = 0; + E->kraid_var_F = 0; + Kraid_DrawRoomBg(); +} + +void Kraid_DrawRoomBg(void) { // 0xA7AD9A + VramWriteEntry *v3; + + uint16 v0 = 192; + uint16 v1 = 0; + do { + target_palettes[v0 >> 1] = kKraid_Palette2[v1 >> 1]; + v0 += 2; + v1 += 2; + } while ((int16)(v1 - 32) < 0); + palette_change_num = 0; + uint16 v2 = vram_write_queue_tail; + v3 = gVramWriteEntry(vram_write_queue_tail); + v3->size = 512; + v3->src.addr = addr_kKraidsRoomBg; + v3->src.bank = -89; + v3->vram_dst = ((reg_BG12NBA & 0xF) << 8) + 16128; + vram_write_queue_tail = v2 + 7; +} + +void Kraid_GetsBig_Thinking_Setup(void) { // 0xA7ADE1 + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_GetsBig_Thinking); + Kraid_SetLintYAndRandomThinkTimer(); +} + +void Kraid_Mainloop_Thinking_Setup(void) { // 0xA7ADE9 + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_Mainloop_Thinking); + Kraid_SetLintYAndRandomThinkTimer(); +} + +void Kraid_SetLintYAndRandomThinkTimer(void) { // 0xA7ADEF + int16 v1; + + Enemy_Kraid *E = Get_Kraid(0); + Get_Kraid(0x80)->base.y_pos = E->base.y_pos - 20; + Get_Kraid(0xC0u)->base.y_pos = E->base.y_pos + 46; + Get_Kraid(0x100u)->base.y_pos = E->base.y_pos + 112; + v1 = random_number & 7; + if ((random_number & 7) == 0) + v1 = 2; + E->kraid_thinking = v1 << 6; +} + +void Kraid_GetsBig_FadeInRoomBg(void) { // 0xA7AE23 + if (AdvancePaletteFade_BgPalette6() & 1) { + Kraid_GetsBig_Thinking_Setup(); + Kraid_Lints_Enable(0x80, g_word_A7A916); + Kraid_Lints_Enable(0xc0, g_word_A7A918); + Kraid_Lints_Enable(0x100, g_word_A7A91A); + Enemy_Kraid *E6 = Get_Kraid(0x180u); + E6->kraid_next = FUNC16(KraidsFingernail_Init); + Enemy_Kraid *E7 = Get_Kraid(0x1C0u); + E7->kraid_next = FUNC16(KraidsFingernail_Init); + E6->kraid_var_A = FUNC16(KraidEnemy_HandleFunctionTimer); + E7->kraid_var_A = FUNC16(KraidEnemy_HandleFunctionTimer); + E6->kraid_var_F = 64; + E7->kraid_var_F = 128; + Get_Kraid(0x40u)->kraid_var_C = 1; + Enemy_Kraid *E0 = Get_Kraid(0); + E0->kraid_var_B = addr_stru_A796DA; + E0->kraid_target_x = 288; + Enemy_Kraid *E5 = Get_Kraid(0x140u); + E5->kraid_var_A = FUNC16(KraidsFoot_SecondPhaseSetup_WalkToStartPt); + E5->base.instruction_timer = 1; + E5->base.current_instruction = addr_kKraid_Ilist_8887; + } +} + +void Kraid_Lints_Enable(uint16 k, uint16 a) { // 0xA7AE90 + Enemy_Kraid *E = Get_Kraid(k); + E->kraid_var_F = a; + E->kraid_var_A = FUNC16(Kraid_AlignEnemyToKraid); + E->kraid_next = FUNC16(KraidLint_ProduceLint); + E->kraid_var_B = 0; +} + +void Kraid_Mainloop_Thinking(void) { // 0xA7AEA4 + Enemy_Kraid *E = Get_Kraid(0); + uint16 kraid_thinking = E->kraid_thinking; + if (kraid_thinking) { + uint16 v2 = kraid_thinking - 1; + E->kraid_thinking = v2; + if (!v2) { + E->kraid_var_A = FUNC16(Kraid_Main_AttackWithMouthOpen); + E->kraid_var_B = addr_stru_A796DA; + E->kraid_var_C = g_stru_A796D2.timer; + } + } +} + +void Kraid_GetsBig_Thinking(void) { // 0xA7AEC4 + Enemy_Kraid *E = Get_Kraid(0); + uint16 kraid_thinking = E->kraid_thinking; + if (kraid_thinking) { + uint16 v2 = kraid_thinking - 1; + E->kraid_thinking = v2; + if (!v2) { + E->kraid_var_A = FUNC16(Kraid_Shot_MouthIsOpen); + E->kraid_var_B = addr_stru_A796DA; + E->kraid_var_C = g_stru_A796D2.timer; + } + } +} + +void Kraid_Shot_MouthIsOpen(void) { // 0xA7AEE4 + uint16 v2; + Enemy_Kraid *E = Get_Kraid(0); + + if (Kraid_ProcessKraidInstr() == 0xFFFF) { + E->kraid_var_A = FUNC16(Kraid_Mainloop_Thinking); + E->kraid_var_C = 90; + uint16 kraid_mouth_flags = E->kraid_mouth_flags; + if ((kraid_mouth_flags & 4) != 0 + && (v2 = kraid_mouth_flags - 256, E->kraid_mouth_flags = v2, (v2 & 0xFF00) != 0)) { + E->kraid_var_A = FUNC16(KraidEnemy_HandleFunctionTimer); + E->kraid_var_F = 64; + E->kraid_next = FUNC16(Kraid_InitEyeGlowing); + E->field_2 = 2; + } else { + E->kraid_mouth_flags = 0; + } + } +} + +uint16 Kraid_ProcessKraidInstr(void) { // 0xA7AF32 + Enemy_Kraid *E = Get_Kraid(0); + uint16 result = E->kraid_var_C; + if (result) { + if (E->kraid_var_C-- == 1) + return Kraid_ExecuteInstr(); + } + return result; +} + +void CallKraidInstr(uint32 ea) { + switch (ea) { + case fnKraidInstr_PlayRoarSfx: KraidInstr_PlayRoarSfx(); return; + case fnKraidInstr_PlayDyingSfx: KraidInstr_PlayDyingSfx(); return; + default: Unreachable(); + } +} + +uint16 Kraid_ExecuteInstr(void) { // 0xA7AF3D + Enemy_Kraid *E = Get_Kraid(0); +RESTART:; + uint16 kraid_var_B = E->kraid_var_B; + uint16 *v2 = (uint16 *)RomPtr_A7(kraid_var_B); + uint16 result = *v2; + if (*v2 != 0xFFFF) { + if ((int16)(*v2 + 1) < 0) { + R18_ = *v2; + CallKraidInstr(result | 0xA70000); + E->kraid_var_B += 2; + goto RESTART; + } else { + E->kraid_var_C = result; + E->kraid_var_B = kraid_var_B + 8; + uint16 v4 = v2[1]; + uint16 v5 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 704; + v5 += 2; + gVramWriteEntry(v5)->size = v4; + v5 += 2; + LOBYTE(gVramWriteEntry(v5++)->size) = -89; + gVramWriteEntry(v5)->size = (reg_BG2SC & 0xFC) << 8; + vram_write_queue_tail = v5 + 2; + return 1; + } + } + return result; +} + +void KraidInstr_PlayRoarSfx(void) { // 0xA7AF94 + QueueSfx2_Max6(0x2Du); +} + +void KraidInstr_PlayDyingSfx(void) { // 0xA7AF9F + QueueSfx2_Max15(0x2Eu); +} + +void Kraid_Shot_Mouth(void) { // 0xA7AFAA + int16 v3; + + Enemy_Kraid *E = Get_Kraid(0); + if (!sign16(E->kraid_var_A + 0x3AC9)) + return; + uint8 *v2 = RomPtr_A7(E->kraid_var_B - 8); + if (*((uint16 *)v2 + 3) == 0xFFFF) { + v3 = 0; + goto LABEL_14; + } + uint16 v4; + v4 = *((uint16 *)v2 + 3); + E->kraid_var_E = 1; + v3 = 0; + uint8 *v5; + v5 = RomPtr_A7(v4); + R22_ = E->base.x_pos + *(uint16 *)v5; + R20_ = E->base.y_pos + *((uint16 *)v5 + 1); + R18_ = E->base.y_pos + *((uint16 *)v5 + 3); + if (projectile_counter) { + uint16 v6 = 2 * projectile_counter; + while (1) { + int v7; + v7 = v6 >> 1; + if (!sign16(projectile_y_pos[v7] - projectile_y_radius[v7] - 1 - R18_) + || sign16(projectile_y_radius[v7] + projectile_y_pos[v7] - R20_) + || sign16(projectile_x_radius[v7] + projectile_x_pos[v7] - R22_)) { + goto LABEL_13; + } + uint16 v8; + v8 = projectile_type[v7]; + if ((v8 & 0xF00) != 0) + goto LABEL_12; + if ((v8 & 0x10) != 0) + break; +LABEL_13: + v6 -= 2; + if ((v6 & 0x8000u) != 0) + goto LABEL_14; + } + E->kraid_mouth_flags |= 1u; +LABEL_12: + collision_detection_index = v6 >> 1; + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + projectile_dir[v6 >> 1] |= 0x10u; + v3 = 1; + goto LABEL_13; + } +LABEL_14: + if (v3) { + E->kraid_hurt_frame = 6; + E->kraid_hurt_frame_timer = 2; + uint16 kraid_mouth_flags = E->kraid_mouth_flags; + if ((kraid_mouth_flags & 2) != 0) + E->kraid_mouth_flags = kraid_mouth_flags | 4; + if (sign16(E->base.health - 1) && sign16(E->kraid_var_A + 0x3CA0)) { + E->kraid_var_A = FUNC16(Kraid_Death_Init); + E->kraid_mouth_flags = 0; + E->base.properties |= kEnemyProps_Tangible; + R18_ = -8193; + Kraid_SetupGfxWithTilePrioClear(); + uint16 v12 = 0; + do { + Enemy_Kraid *EL = Get_Kraid(v12); + EL->base.properties |= kEnemyProps_Tangible; + v12 += 64; + } while ((int16)(v12 - 384) < 0); + if (sign16(E->kraid_var_B + 0x68F2)) + E->kraid_var_B += 60; + } + } +} + +void Kraid_SpawnExplosionEproj(uint16 k) { // 0xA7B0CB + int v1 = k >> 1; + R18_ = projectile_x_pos[v1]; + R20_ = projectile_y_pos[v1]; + uint16 v2 = 29; + if ((projectile_type[v1] & 0x200) == 0) + v2 = 6; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, v2); + QueueSfx1_Max6(0x3Du); +} + +void Kraid_Enemy_Touch(void) { // 0xA7B0F3 + int16 v1; + + Enemy_Kraid *E = Get_Kraid(0); + if (sign16(E->kraid_var_A + 0x3CA0)) { + R18_ = samus_x_radius + samus_x_pos; + v1 = samus_y_pos - E->base.y_pos; + int i; + for (i = 0; ; i += 4) { + int v3 = i >> 1; + if ((int16)(v1 - g_word_A7B161[v3]) >= 0 || (int16)(v1 - g_word_A7B161[v3 + 2]) >= 0) + break; + } + if ((int16)(E->base.x_pos + g_word_A7B161[(i >> 1) + 1] - R18_) < 0) { + if (!sign16(samus_x_pos - 40)) { + samus_x_pos -= 8; + samus_prev_x_pos = samus_x_pos; + } + uint16 kraid_min_y_pos_eject = samus_y_pos - 8; + if ((int16)(samus_y_pos - 8 - E->kraid_min_y_pos_eject) < 0) + kraid_min_y_pos_eject = E->kraid_min_y_pos_eject; + samus_y_pos = kraid_min_y_pos_eject; + samus_prev_y_pos = kraid_min_y_pos_eject; + Kraid_Func_1(); + if (!samus_invincibility_timer) + NormalEnemyTouchAi(); + } + } +} + +void Kraid_Shot_Body(void) { // 0xA7B181 + int16 v11; + uint16 j; + + Enemy_Kraid *E = Get_Kraid(0); + if (sign16(E->kraid_var_A + 0x3AC9)) { + E->kraid_var_E = 0; + E->kraid_mouth_flags &= ~1u; + R48 = 0; + uint8 *v2 = RomPtr_A7(E->kraid_var_B - 8); + uint8 *v3 = RomPtr_A7(*((uint16 *)v2 + 2)); + R22_ = E->base.x_pos + *(uint16 *)v3; + R20_ = E->base.y_pos + *((uint16 *)v3 + 1); + R18_ = E->base.y_pos + *((uint16 *)v3 + 3); + if (projectile_counter) { + for (int i = 2 * projectile_counter; i >= 0; i -= 2) { + int v5 = i >> 1; + if (sign16(projectile_y_pos[v5] - projectile_y_radius[v5] - 1 - R18_)) { + if (!sign16(projectile_y_radius[v5] + projectile_y_pos[v5] - R20_) + && !sign16(projectile_x_radius[v5] + projectile_x_pos[v5] - R22_)) { + goto LABEL_7; + } + } else { + int v10; + v10 = i >> 1; + R18_ = projectile_x_radius[v10] + projectile_x_pos[v10]; + v11 = projectile_y_pos[v10] - E->base.y_pos; + for (j = 0; ; j += 4) { + int v13 = j >> 1; + if ((int16)(v11 - g_word_A7B161[v13]) >= 0 || (int16)(v11 - g_word_A7B161[v13 + 2]) >= 0) + break; + } + if ((int16)(E->base.x_pos + g_word_A7B161[(j >> 1) + 1] - R18_) < 0) { +LABEL_7: + Kraid_SpawnExplosionEproj(i); + int v6 = i >> 1; + projectile_dir[v6] |= 0x10u; + if ((projectile_type[v6] & 0x10) != 0) { + E->kraid_mouth_flags |= 1u; + } + ++R48; + } + } + } + } + if (R48) { + if (E->kraid_var_A == (uint16)FUNC16(Kraid_Mainloop_Thinking)) { + E->kraid_var_A = FUNC16(Kraid_InitEyeGlowing); + uint16 kraid_mouth_flags = E->kraid_mouth_flags; + if ((kraid_mouth_flags & 1) != 0) + E->kraid_mouth_flags = kraid_mouth_flags | 0x302; + } + } + } +} + +void Kraid_Palette_Handling(void) { // 0xA7B337 + Enemy_Kraid *E = Get_Kraid(0); + if (sign16(E->base.health - 1)) { + E->kraid_hurt_frame = E->base.health; +LABEL_6: + Kraid_HurtFlash_Handling(); + Kraid_HealthBasedPaletteHandling(); + return; + } + if (E->kraid_hurt_frame) { + uint16 v1 = E->kraid_hurt_frame_timer - 1; + E->kraid_hurt_frame_timer = v1; + if (!v1) { + E->kraid_hurt_frame_timer = 2; + --E->kraid_hurt_frame; + goto LABEL_6; + } + } +} + +void Kraid_HurtFlash_Handling(void) { // 0xA7B371 + uint16 v0 = 0; + if ((Get_Kraid(0)->kraid_hurt_frame & 1) == 0) + v0 = 32; + uint16 v1 = 0; + do { + palette_buffer[(v1 >> 1) + 240] = kKraid_SprPalette7_KraidDeath[v0 >> 1]; + v1 += 2; + v0 += 2; + } while ((int16)(v1 - 32) < 0); +} + +void Kraid_HealthBasedPaletteHandling(void) { // 0xA7B394 + uint16 v0 = 0; + Enemy_Kraid *E = Get_Kraid(0); + if ((E->kraid_hurt_frame & 1) == 0) { + uint16 v2 = 14; + uint16 health = E->base.health; + do { + if ((int16)(health - Get_Kraid(v2)->kraid_healths_8ths[0]) >= 0) + break; + v2 -= 2; + } while (v2); + v0 = 16 * (v2 + 2); + } + uint16 v4 = 0; + do { + int v5 = v0 >> 1; + int v6 = v4 >> 1; + palette_buffer[v6 + 112] = kKraid_BgPalette7[v5]; + palette_buffer[v6 + 240] = kKraid_SprPalette7_KraidDeath[v5]; + v0 += 2; + v4 += 2; + } while ((int16)(v4 - 32) < 0); +} + +uint16 Kraid_Instr_1(uint16 k, uint16 j) { // 0xA7B633 + return j; +} + +uint16 Kraid_Instr_DecYpos(uint16 k, uint16 j) { // 0xA7B636 + Enemy_Kraid *E = Get_Kraid(0); + --E->base.y_pos; + return j; +} + +uint16 Kraid_Instr_IncrYpos_Shake(uint16 k, uint16 j) { // 0xA7B63C + Enemy_Kraid *E = Get_Kraid(0); + ++E->base.y_pos; + earthquake_type = 1; + earthquake_timer = 10; + return j; +} + +uint16 Kraid_Instr_PlaySound_0x76(uint16 k, uint16 j) { // 0xA7B64E + QueueSfx2_Max6(0x76u); + return j; +} + +uint16 Kraid_Instr_XposMinus3(uint16 k, uint16 j) { // 0xA7B65A + Enemy_Kraid *E = Get_Kraid(0); + E->base.x_pos -= g_word_A7A91C; + return j; +} + +uint16 Kraid_Instr_XposMinus3b(uint16 k, uint16 j) { // 0xA7B667 + Enemy_Kraid *E = Get_Kraid(0); + E->base.x_pos -= g_word_A7A91C; + return j; +} + +uint16 Kraid_Instr_XposPlus3(uint16 k, uint16 j) { // 0xA7B674 + Enemy_Kraid *E = Get_Kraid(0); + E->base.x_pos += g_word_A7A920; + return j; +} + +uint16 Kraid_Instr_MoveHimRight(uint16 k, uint16 j) { // 0xA7B683 + uint16 v3; + + Enemy_Kraid *E = Get_Kraid(0); + if (sign16(E->base.x_pos - 320) || (v3 = E->kraid_target_x - 1, (E->kraid_target_x = v3) == 0)) { + R18_ = 0; + R20_ = g_word_A7A922; + if (Enemy_MoveRight_IgnoreSlopes(0) & 1) { + earthquake_type = 0; + earthquake_timer = 7; + uint16 x_pos = Get_Kraid(0)->base.x_pos; + Get_Kraid(0x140u)->base.x_pos = x_pos; + } + } + return j; +} + +void Kraid_InitEyeGlowing(void) { // 0xA7B6BF + Enemy_Kraid *E = Get_Kraid(0); + E->kraid_var_A = FUNC16(Kraid_Shot_MouthIsOpen); + E->kraid_var_A = FUNC16(Kraid_Shot_GlowHisEye); + E->kraid_var_B = addr_stru_A7974A__plus__8; + E->kraid_var_C = g_stru_A7974A[0].timer; + Kraid_Shot_GlowHisEye(); +} + +void Kraid_Shot_GlowHisEye(void) { // 0xA7B6D7 + int16 v1; + + Kraid_ProcessKraidInstr(); + uint16 v0 = 226; + v1 = 0; + do { + int v2 = v0 >> 1; + uint16 v3 = (palette_buffer[v2] & 0x1F) + 1; + if (!sign16((palette_buffer[v2] & 0x1F) - 30)) { + ++v1; + v3 = 31; + } + R18_ = v3; + uint16 v4 = (palette_buffer[v2] & 0x3E0) + 32; + if (!sign16((palette_buffer[v2] & 0x3E0) - 960)) { + ++v1; + v4 = 992; + } + R20_ = v4; + palette_buffer[v2] = v4 | R18_ | palette_buffer[v2] & 0xFC00; + v0 += 2; + } while ((int16)(v0 - 232) < 0); + if ((int16)(v1 - 6) >= 0) + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_Shot_UnglowEye); +} +// 9CBFB: ignored the value written to the shadow area of the succeeding call + +void Kraid_Shot_UnglowEye(void) { // 0xA7B73D + Enemy_Kraid *E = Get_Kraid(0); + uint16 v0 = 14; + uint16 health = E->base.health; + do { + if ((int16)(health - Get_Kraid(v0)->kraid_healths_8ths[0]) >= 0) + break; + v0 -= 2; + } while (v0); + uint16 v2 = 16 * (v0 + 2); + uint16 v3 = 226; + R20_ = 0; + do { + int v4 = v3 >> 1; + R18_ = palette_buffer[v4] & 0x1F; + int v5 = v2 >> 1; + if ((kKraid_BgPalette7[v5 + 1] & 0x1F) != R18_) { + ++R20_; + --palette_buffer[v4]; + } + R18_ = palette_buffer[v4] & 0x3E0; + if ((kKraid_BgPalette7[v5 + 1] & 0x3E0) != R18_) { + ++R20_; + palette_buffer[v4] -= 32; + } + v3 += 2; + v2 += 2; + } while ((int16)(v3 - 232) < 0); + if (!R20_) { + E->kraid_var_A = FUNC16(Kraid_Shot_MouthIsOpen); + E->kraid_var_B = addr_stru_A796DA; + E->kraid_var_C = g_stru_A796D2.timer; + } +} + +void KraidsArm_Main(void) { // 0xA7B7BD + R18_ = layer1_y_pos + 224; + Enemy_Kraid *E = Get_Kraid(0); + uint16 v1 = E->base.y_pos - 44; + Enemy_Kraid *E1 = Get_Kraid(0x40u); + E1->base.y_pos = v1; + uint16 v3 = v1; + uint16 v4 = E1->base.properties | 0x100; + if ((int16)(v3 - layer1_y_pos) >= 0 && (int16)(v3 - R18_) < 0) + v4 = E1->base.properties & 0xFEFF; + E1->base.properties = v4; + E1->base.x_pos = E->base.x_pos; + if (HIBYTE(E->kraid_mouth_flags)) + ++E1->base.instruction_timer; +} + +void KraidsTopLint_Main(void) { // 0xA7B801 + gEnemyData(0x80)->instruction_timer = 0x7FFF; + KraidLintCommon_Main(0x80); +} + +void KraidsMiddleLint_Main(void) { // 0xA7B80D + gEnemyData(0xC0u)->instruction_timer = 0x7FFF; + KraidLintCommon_Main(0xC0u); +} + +void KraidsBottomLint_Main(void) { // 0xA7B819 + gEnemyData(0x100u)->instruction_timer = 0x7FFF; + KraidLintCommon_Main(0x100u); +} + +void KraidLintCommon_Main(uint16 k) { // 0xA7B822 + Kraid_EnemyTouch_Lint(k); + R18_ = layer1_y_pos + 224; + EnemyData *v1 = gEnemyData(k); + CallKraidFunc(v1->ai_var_A | 0xA70000); +} + +void KraidLint_ProduceLint(uint16 k) { // 0xA7B832 + EnemyData *v1 = gEnemyData(k); + v1->properties &= 0xFAFFu; + v1->x_pos = v1->ai_var_C + gEnemyData(0)->x_pos - v1->ai_var_B; + uint16 v2 = v1->ai_var_B + 1; + v1->ai_var_B = v2; + if (!sign16(v2 - 32)) { + v1->ai_var_A = FUNC16(KraidLint_ChargeLint); + v1->ai_preinstr = 30; + } +} + +void KraidLint_ChargeLint(uint16 k) { // 0xA7B868 + int16 v1; + + v1 = 0; + EnemyData *v2 = gEnemyData(k); + EnemyData *v3 = v2; + if ((v2->ai_preinstr & 1) != 0) + v1 = 3584; + v2->palette_index = v1; + v2->x_pos = v2->ai_var_C + gEnemyData(0)->x_pos - v2->ai_var_B; + if (v3->ai_preinstr-- == 1) { + v3->ai_var_A = FUNC16(KraidLint_FireLint); + QueueSfx3_Max6(0x1Fu); + } +} + +void KraidLint_FireLint(uint16 k) { // 0xA7B89B + Enemy_Kraid *E = Get_Kraid(k); + uint16 x_subpos = E->base.x_subpos; + bool v3 = x_subpos < g_word_A7A926; + E->base.x_subpos = x_subpos - g_word_A7A926; + uint16 v4 = E->base.x_pos - (v3 + g_word_A7A928); + E->base.x_pos = v4; + if (sign16(v4 - 56)) + E->base.properties |= kEnemyProps_Tangible; + if (sign16(v4 - 32)) { + E->base.properties |= kEnemyProps_Invisible; + E->kraid_var_A = FUNC16(Kraid_AlignEnemyToKraid); + E->kraid_var_F = 300; + E->kraid_next = FUNC16(KraidLint_ProduceLint); + E->kraid_var_B = 0; + } + if (CheckIfEnemyTouchesSamus(k)) { + uint16 v5 = (__PAIR32__(extra_samus_x_displacement, extra_samus_x_subdisplacement) + - __PAIR32__(g_word_A7A928, g_word_A7A926)) >> 16; + extra_samus_x_subdisplacement -= g_word_A7A926; + if (sign16(v5 + 16)) + v5 = -16; + extra_samus_x_displacement = v5; + } +} + +void KraidFingernail_WaitForLintXpos(uint16 k) { // 0xA7B907 + Enemy_Kraid *E2 = Get_Kraid(0x80); + if (!sign16(E2->base.x_pos - 256)) { + Enemy_Kraid *E = Get_Kraid(k); + E->kraid_var_A = E->kraid_next; + E->base.properties &= 0xFAFFu; + } +} + +void Kraid_AlignEnemyToKraid(uint16 k) { // 0xA7B923 + uint16 x_pos = Get_Kraid(0)->base.x_pos; + Enemy_Kraid *E = Get_Kraid(k); + E->base.x_pos = x_pos - E->base.x_width; + KraidEnemy_HandleFunctionTimer(k); +} + +void KraidEnemy_HandleFunctionTimer(uint16 k) { // 0xA7B92D + Enemy_Kraid *E = Get_Kraid(k); + if (E->kraid_var_F) { + if (E->kraid_var_F-- == 1) + E->kraid_var_A = E->kraid_next; + } +} + +void KraidEnemy_DecrementEnemyFunctionTimer(void) { // 0xA7B93F + Enemy_Kraid *E = Get_Kraid(cur_enemy_index); + if (E->kraid_var_F) { + if (E->kraid_var_F-- == 1) { + E->kraid_var_A = E->kraid_next; + E->base.current_instruction = addr_kKraid_Ilist_8887; + E->base.instruction_timer = 1; + } + } +} + +void KraidFoot_FirstPhase_Thinking(uint16 k) { // 0xA7B960 + Kraid_HandleFirstPhase(); + KraidEnemy_HandleFunctionTimer(k); +} + +void KraidEnemy_ProcessInstrEnemyTimer(uint16 k) { // 0xA7B965 + Kraid_ProcessKraidInstr(); + KraidEnemy_HandleFunctionTimer(k); +} + +void Kraid_EnemyTouch_Lint(uint16 k) { // 0xA7B96A + Enemy_Kraid *E = Get_Kraid(k); + if ((E->base.properties & kEnemyProps_Tangible) == 0 && !samus_invincibility_timer) { + R18_ = g_stru_A792B7.left + E->base.x_pos - 2; + if (!sign16(samus_x_radius + samus_x_pos - R18_)) { + if (sign16(samus_x_pos - samus_x_radius - R18_)) { + R22_ = g_stru_A792B7.top + E->base.y_pos + 2; + if (!sign16(samus_y_radius + samus_y_pos - R22_)) { + R24_ = g_stru_A792B7.bottom + E->base.y_pos - 2; + if (sign16(samus_y_pos - samus_y_radius - R24_)) { + uint16 v2 = extra_samus_x_displacement + ~(samus_x_radius + 16); + if (!sign16(v2 - 16)) + v2 = 16; + extra_samus_x_displacement = v2; + NormalEnemyTouchAi(); + E->base.properties |= kEnemyProps_Tangible; + } + } + } + } + } +} + +void KraidsFoot_Main(void) { // 0xA7B9F6 + int16 v3; + + EnemyData *v0 = gEnemyData(0); + v0[5].x_pos = v0->x_pos; + uint16 v1 = v0->y_pos + 100; + v0[5].y_pos = v1; + uint16 v2 = v1; + v3 = v1 - 224; + uint16 v4 = v0[5].properties & 0xFEFF; + if ((int16)(v2 - layer1_y_pos) >= 0) { + if ((int16)(v3 - layer1_y_pos) >= 0) + v4 |= 0x100u; + } else { + v4 |= 0x100u; + } + v0[5].properties = v4; + CallKraidFunc(v0[5].ai_var_A | 0xA70000); +} + +void KraidsFoot_SecondPhase_Thinking(void) { // 0xA7BA2E + int16 v4; + + Enemy_Kraid *E5 = Get_Kraid(0x140u); + uint16 v1 = E5->kraid_next - 1; + E5->kraid_next = v1; + if (!v1) { + uint16 v2 = 0; + Enemy_Kraid *E0; + while (1) { + E0 = Get_Kraid(0); + if (E0->base.x_pos == g_word_A7BA7D[v2 >> 1]) + break; + v2 += 4; + if ((int16)(v2 - 24) >= 0) { + v2 = 4; + break; + } + } + v4 = random_number & 0x1C; + if (!sign16(v4 - 16)) + v4 = 16; + uint16 *v5 = (uint16 *)RomPtr_A7(g_word_A7BA7D[(v2 >> 1) + 1] + v4); + uint16 v6 = v5[1]; + if ((int16)(*v5 - E0->base.x_pos) >= 0) + Kraid_SetWalkingBackwards(v6, *v5); + else + Kraid_SetWalkingForwards(v6, *v5); + } +} + +void Kraid_SetWalkingBackwards(uint16 j, uint16 a) { // 0xA7BB0D + Get_Kraid(0)->kraid_target_x = a; + Enemy_Kraid *E = Get_Kraid(0x140u); + E->kraid_next = j; + E->kraid_var_A = FUNC16(KraidsFoot_SecondPhase_WalkingBackwards); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kKraid_Ilist_8887; +} + +void Kraid_SetWalkingForwards(uint16 j, uint16 a) { // 0xA7BB29 + Get_Kraid(0)->kraid_target_x = a; + Enemy_Kraid *E = Get_Kraid(0x140u); + E->kraid_next = j; + E->kraid_var_A = FUNC16(KraidsFoot_SecondPhase_WalkForward); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kKraid_Ilist_86F3; +} + +void KraidsFoot_SecondPhase_WalkingBackwards(void) { // 0xA7BB45 + Enemy_Kraid *E0 = Get_Kraid(0); + uint16 kraid_target_x = E0->kraid_target_x; + if (kraid_target_x != E0->base.x_pos) { + if ((int16)(kraid_target_x - E0->base.x_pos) >= 0) + return; + E0->base.x_pos = kraid_target_x; + } + Enemy_Kraid *E5 = Get_Kraid(0x140u); + if (!sign16(E5->base.current_instruction + 0x76C7)) { + E5->kraid_var_A = FUNC16(KraidsFoot_SecondPhase_Thinking); + E5->base.instruction_timer = 1; + E5->base.current_instruction = addr_kKraid_Ilist_86ED; + } +} + +void KraidsFoot_SecondPhaseSetup_WalkToStartPt(void) { // 0xA7BB6E + Enemy_Kraid *E0 = Get_Kraid(0); + uint16 kraid_target_x = E0->kraid_target_x; + if (kraid_target_x != E0->base.x_pos) { + if ((int16)(kraid_target_x - E0->base.x_pos) >= 0) + return; + E0->base.x_pos = kraid_target_x; + } + Enemy_Kraid *E5 = Get_Kraid(0x140u); + if (!sign16(E5->base.current_instruction + 0x76C7)) { + E5->kraid_var_A = FUNC16(KraidEnemy_HandleFunctionTimer); + E5->kraid_var_F = 180; + E5->kraid_next = FUNC16(KraidsFoot_SecondPhase_Init); + E5->base.instruction_timer = 1; + E5->base.current_instruction = addr_kKraid_Ilist_86ED; + } +} + +void KraidsFoot_SecondPhase_Init(void) { // 0xA7BBA4 + Kraid_SetWalkingBackwards(0xB4u, 0x160u); +} + +void KraidsFoot_SecondPhase_WalkForward(void) { // 0xA7BBAE + Enemy_Kraid *E0 = Get_Kraid(0); + uint16 kraid_target_x = E0->kraid_target_x; + if ((int16)(kraid_target_x - E0->base.x_pos) < 0) { + Enemy_Kraid *E5 = Get_Kraid(0x140u); + if (E5->base.current_instruction == (uint16)addr_off_A787BB) { + E5->base.current_instruction = addr_kKraid_Ilist_86F3; + E5->base.instruction_timer = 1; + } + } else { + E0->base.x_pos = kraid_target_x; + Enemy_Kraid *E5 = Get_Kraid(0x140u); + if (E5->base.current_instruction == (uint16)addr_off_A787BB) { + E5->kraid_var_A = FUNC16(KraidsFoot_SecondPhase_Thinking); + E5->base.instruction_timer = 1; + E5->base.current_instruction = addr_kKraid_Ilist_86ED; + } + } +} + +void Kraid_Main_AttackWithMouthOpen(void) { // 0xA7BBEA + uint16 v3; + Enemy_Kraid *E = Get_Kraid(0); + + if (Kraid_ProcessKraidInstr() == 0xFFFF) { + Kraid_Mainloop_Thinking_Setup(); + E->kraid_var_C = 90; + uint16 kraid_mouth_flags = E->kraid_mouth_flags; + if ((kraid_mouth_flags & 4) != 0 + && (v3 = kraid_mouth_flags - 256, E->kraid_mouth_flags = v3, (v3 & 0xFF00) != 0)) { + E->kraid_var_A = FUNC16(KraidEnemy_HandleFunctionTimer); + E->kraid_var_F = 64; + E->kraid_next = FUNC16(Kraid_InitEyeGlowing); + E->field_2 = 2; + } else { + E->kraid_mouth_flags = 0; + } + } else { + if (*((uint16 *)RomPtr_A7(E->kraid_var_B - 8) + 1) == (uint16)addr_kKraidTilemaps_3 + && (E->kraid_var_C & 0xF) == 0) { + SpawnEnemyProjectileWithGfx( + g_word_A7BC65[(uint8)(random_number & 0xE) >> 1], + random_number & 0xE, + addr_kEproj_RocksKraidSpits); + QueueSfx3_Max6(0x1Eu); + } + } +} + +void KraidsGoodFingernail_Touch(void) { // 0xA7BCCF + uint16 v0 = 0; + printf("X undefined\n"); + NormalEnemyTouchAi(); + EnemyDeathAnimation(cur_enemy_index, v0); +} + +void KraidsBadFingernail_Touch(void) { // 0xA7BCDE + uint16 v0 = 0; + + printf("X undefined\n"); + NormalEnemyTouchAi(); + EnemyDeathAnimation(cur_enemy_index, v0); +} + +void KraidsGoodFingernail_Init(void) { // 0xA7BCEF + KraidFingernailInit(cur_enemy_index); +} + +void KraidFingernailInit(uint16 k) { // 0xA7BCF2 + uint16 palette_index = Get_Kraid(0)->base.palette_index; + Enemy_Kraid *E = Get_Kraid(k); + E->base.palette_index = palette_index; + E->kraid_var_B = 40; + E->base.properties |= kEnemyProps_Invisible; + E->base.instruction_timer = 0x7FFF; + E->base.current_instruction = addr_kKraid_Ilist_8B0A; + E->base.spritemap_pointer = kKraid_Ilist_8B0A.field_2; + E->kraid_next = FUNC16(KraidsFingernail_Init); + E->kraid_var_A = FUNC16(KraidEnemy_HandleFunctionTimer); + E->kraid_var_F = 64; +} + +void KraidsBadFingernail_Init(void) { // 0xA7BD2D + KraidFingernailInit(cur_enemy_index); +} + +void KraidsGoodFingernail_Main(void) { // 0xA7BD32 + EnemyData *v0 = gEnemyData(0); + if (sign16(v0->health - 1)) { + EnemyData *v1 = gEnemyData(0); + v1[6].properties |= kEnemyProps_Deleted | kEnemyProps_Invisible; + } else { + CallKraidFunc(v0[6].ai_var_A | 0xA70000); + } +} + +void KraidsBadFingernail_Main(void) { // 0xA7BD49 + EnemyData *v0 = gEnemyData(0); + if (sign16(v0->health - 1)) { + EnemyData *v1 = gEnemyData(0); + v1[7].properties |= kEnemyProps_Deleted | kEnemyProps_Invisible; + } else { + CallKraidFunc(v0[7].ai_var_A | 0xA70000); + } +} + +void KraidsFingernail_Init(void) { // 0xA7BD60 + uint16 v2; + + uint16 kraid_var_E = Get_Kraid(0x180u)->kraid_var_E; + if (cur_enemy_index == 384) + kraid_var_E = Get_Kraid(0x1C0u)->kraid_var_E; + if (sign16(kraid_var_E)) + v2 = g_off_A7BE3E[(uint8)(random_number & 6) >> 1]; + else + v2 = g_off_A7BE46[(uint8)(random_number & 6) >> 1]; + uint8 *v3 = RomPtr_A7(v2); + Enemy_Kraid *E = Get_Kraid(cur_enemy_index); + E->kraid_var_B = *(uint16 *)v3; + E->kraid_var_C = *((uint16 *)v3 + 1); + E->kraid_var_D = *((uint16 *)v3 + 2); + E->kraid_var_E = *((uint16 *)v3 + 3); + E->kraid_parameter_1 = 1; + E->base.properties &= ~(kEnemyProps_Tangible | kEnemyProps_Invisible); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kKraid_Ilist_8B0A; + E->kraid_var_A = FUNC16(KraidsFingernail_Fire); + if ((random_number & 1) == 0) + goto LABEL_7; + uint16 v7; + v7 = Get_Kraid(0x180u)->kraid_healths_8ths[1]; + if (cur_enemy_index != 448) + v7 = Get_Kraid(0x1C0u)->kraid_healths_8ths[1]; + if (v7 == 1) { +LABEL_7: + E->kraid_healths_8ths[1] = 0; + Enemy_Kraid *E0 = Get_Kraid(0); + E->base.x_pos = (E0->base.x_pos - E0->base.x_width - E->base.x_width) & 0xFFF0; + E->base.y_pos = Get_Kraid(0x40u)->base.y_pos + 128; + } else { + E->kraid_healths_8ths[1] = 1; + E->base.x_pos = 50; + E->base.y_pos = 240; + E->kraid_var_B = 0; + E->kraid_var_C = 1; + E->kraid_var_D = 0; + E->kraid_var_E = 0; + E->kraid_var_A = FUNC16(KraidFingernail_WaitForLintXpos); + E->kraid_next = FUNC16(KraidsFingernail_Fire); + E->base.properties |= kEnemyProps_Tangible | kEnemyProps_Invisible; + } +} + +void KraidsFingernail_Fire(uint16 k) { // 0xA7BE8E + EnemyData *v1 = gEnemyData(k); + R18_ = v1->ai_var_B; + R20_ = v1->ai_var_C; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + v1->ai_var_B = -v1->ai_var_B; + v1->ai_var_C = -v1->ai_var_C; + } else { + int i; + EnemyData *v3, *v4; + for (i = 0; ; i += 4) { + v3 = gEnemyData(0); + v4 = gEnemyData(k); + if ((int16)(g_word_A7BF1D[(i >> 1) + 1] + v3->y_pos - v4->y_pos) < 0) + break; + } + R18_ = g_word_A7BF1D[i >> 1] + v3->x_pos; + if (!sign16(v4->x_width + v4->x_pos - R18_) && (v4->ai_var_C & 0x8000u) == 0) { + v4->ai_var_B = -v4->ai_var_B; + v4->ai_var_C = -v4->ai_var_C; + } + } + EnemyData *v5 = gEnemyData(k); + R18_ = v5->ai_var_D; + R20_ = v5->ai_var_E; + if (Enemy_MoveDown(k) & 1) { + Negate32(&v5->ai_var_E, &v5->ai_var_D, &v5->ai_var_E, &v5->ai_var_D); + } +} + +void KraidsFoot_PrepareToLungeForward(void) { // 0xA7BF2D + Kraid_HandleFirstPhase(); + EnemyData *v0 = gEnemyData(0); + if (!sign16(v0[1].current_instruction + 0x75C9)) { + v0[1].current_instruction = addr_kKraid_Ilist_8AF0; + v0[1].instruction_timer = 1; + v0[5].instruction_timer = 1; + v0[5].current_instruction = addr_kKraid_Ilist_87BD; + v0[5].ai_var_A = FUNC16(KraidsFoot_FirstPhase_LungeForward); + v0[5].ai_preinstr = 0; + } +} + +void KraidsFoot_FirstPhase_LungeForward(void) { // 0xA7BF5D + Kraid_HandleFirstPhase(); + Enemy_Kraid *E = Get_Kraid(0); + if (sign16(E->base.x_pos - 92)) + E->base.x_pos = 92; + Enemy_Kraid *E5 = Get_Kraid(0x140u); + if (E5->base.current_instruction == (uint16)addr_off_A78885) { + if (E->base.x_pos == 92) { + E5->kraid_next = FUNC16(KraidsFoot_FirstPhase_RetreatFromLunge); + E5->kraid_var_A = FUNC16(KraidEnemy_DecrementEnemyFunctionTimer); + E5->kraid_var_F = 1; + E5->base.instruction_timer = 1; + E5->base.current_instruction = addr_kKraid_Ilist_86ED; + } else { + E5->base.instruction_timer = 1; + E5->base.current_instruction = addr_kKraid_Ilist_87BD; + } + } +} + +void KraidsFoot_FirstPhase_RetreatFromLunge(void) { // 0xA7BFAB + Kraid_HandleFirstPhase(); + Enemy_Kraid *E0 = Get_Kraid(0); + if (!sign16(E0->base.x_pos - 176)) + E0->base.x_pos = 176; + Enemy_Kraid *E5 = Get_Kraid(0x140u); + if (!sign16(E5->base.current_instruction + 0x76C7)) { + if (E0->base.x_pos == 176) { + Enemy_Kraid *E1 = Get_Kraid(0x40u); + E1->base.current_instruction = addr_kKraid_Ilist_89F3; + E1->base.instruction_timer = 1; + E5->base.instruction_timer = 1; + E5->base.current_instruction = addr_kKraid_Ilist_86ED; + E5->kraid_var_A = FUNC16(KraidFoot_FirstPhase_Thinking); + E5->kraid_var_F = 300; + E5->kraid_next = FUNC16(KraidsFoot_PrepareToLungeForward); + } else { + printf("X undefined\n"); + Enemy_Kraid *E = Get_Kraid(cur_enemy_index); + E->base.current_instruction = addr_kKraid_Ilist_8887; + E->base.instruction_timer = 1; + } + } +} + +void Kraid_HandleFirstPhase(void) { // 0xA7C005 + Enemy_Kraid *E0 = Get_Kraid(0); + if ((int16)(E0->base.health - E0->kraid_healths_8ths[6]) < 0) { + E0->kraid_var_A = FUNC16(KraidEnemy_ProcessInstrEnemyTimer); + E0->kraid_var_F = 180; + E0->kraid_next = FUNC16(Kraid_GetsBig_ReleaseCamera); + uint16 v2 = *((uint16 *)RomPtr_A7(E0->kraid_var_B) + 1); + uint16 v3 = 50; + if (v2 != (uint16)addr_kKraidTilemaps_0) { + v3 = 42; + if (v2 != (uint16)addr_kKraidTilemaps_1) { + v3 = 34; + if (v2 != (uint16)addr_kKraidTilemaps_2) + v3 = 26; + } + } + E0->kraid_var_B = v3 - 26918; + E0->kraid_var_C = *(uint16 *)((char *)&g_stru_A796D2.timer + v3); + earthquake_type = 4; + earthquake_timer = 340; + Enemy_Kraid *E5 = Get_Kraid(0x140u); + E5->base.current_instruction = addr_kKraid_Ilist_86E7; + E5->base.instruction_timer = 1; + E5->kraid_var_A = FUNC16(nullsub_234); + Enemy_Kraid *E1 = Get_Kraid(0x40u); + E1->base.current_instruction = addr_kKraid_Ilist_89F3; + E1->base.instruction_timer = 1; + Enemy_Kraid *E2 = Get_Kraid(0x80); + E2->base.properties |= 0x100u; + Enemy_Kraid *E3 = Get_Kraid(0xC0u); + E3->base.properties |= 0x100u; + Enemy_Kraid *E4 = Get_Kraid(0x100u); + E4->base.properties |= 0x100u; + E1->base.properties |= 0x400u; + } +} + +void Kraid_GetsBig_ReleaseCamera(void) { // 0xA7C0A1 + Enemy_Kraid *E = Get_Kraid(0); + E->kraid_var_A = FUNC16(Kraid_GetsBig_BreakCeilingPlatforms); + *(uint16 *)scrolls = 514; + *(uint16 *)&scrolls[2] = 257; + E->kraid_min_y_pos_eject = 164; +} +static const SpawnHardcodedPlmArgs unk_A7C16C = { 0x02, 0x12, 0xb7b7 }; +static const SpawnHardcodedPlmArgs unk_A7C175 = { 0x05, 0x1b, 0xb7bb }; +void Kraid_SpawnPlmToClearCeiling(void) { // 0xA7C168 + SpawnHardcodedPlm(&unk_A7C16C); +} + +void Kraid_ClearSomeSpikes(void) { // 0xA7C171 + SpawnHardcodedPlm(&unk_A7C175); +} + +void UnpauseHook_Kraid_IsDead(void) { // 0xA7C1FB + static const StartDmaCopy unk_A7C21E = { 1, 1, 0x18, LONGPTR(0xa7a716), 0x0200 }; + static const StartDmaCopy unk_A7C23E = { 1, 1, 0x18, LONGPTR(0x9ab200), 0x0800 }; + ScreenOff(); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 16 * (reg_BG12NBA & 0xF) + 63); + WriteReg(VMAIN, 0x80); + SetupDmaTransfer(&unk_A7C21E); + WriteReg(MDMAEN, 2u); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, 0x40u); + WriteReg(VMAIN, 0x80); + SetupDmaTransfer(&unk_A7C23E); + WriteReg(MDMAEN, 2u); + Kraid_TransferTopHalfToVram(); +} + +static const StartDmaCopy unk_A7C26B = { 1, 1, 0x18, LONGPTR(0x7e5000), 0x0400 }; +static const StartDmaCopy unk_A7C28D = { 1, 1, 0x18, LONGPTR(0x7e2000), 0x0800 }; + +void UnpauseHook_Kraid_IsAlive(void) { // 0xA7C24E + ScreenOff(); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, reg_BG12NBA + 62); + WriteReg(VMAIN, 0x80); + SetupDmaTransfer(&unk_A7C26B); + WriteReg(MDMAEN, 2u); + Kraid_TransferTopHalfToVram(); +} + +void Kraid_TransferTopHalfToVram(void) { // 0xA7C278 + WriteReg(VMADDL, 0); + WriteReg(VMADDH, reg_BG2SC & 0xFC); + WriteReg(VMAIN, 0x80); + SetupDmaTransfer(&unk_A7C28D); + WriteReg(MDMAEN, 2u); + ScreenOn(); +} + +static const StartDmaCopy unk_A7C2BD = { 1, 1, 0x18, LONGPTR(0x7e5000), 0x0400 }; + +void WaitForNMI_Kraid(void) { + printf("WaitForNMI_Kraid Unimpl!\n"); +} + +void Kraid_UnpauseHook_IsSinking(void) { // 0xA7C2A0 + VramWriteEntry *v2; + + ScreenOff(); + WriteReg(VMADDL, 0); + WriteReg(VMADDH, reg_BG12NBA + 62); + WriteReg(VMAIN, 0x80); + SetupDmaTransfer(&unk_A7C2BD); + WriteReg(MDMAEN, 2u); + if ((int16)(Get_Kraid(0)->base.y_pos - kKraidSinkEntry[0].field_0) >= 0) { + uint16 v0 = 0; + uint16 v1 = vram_write_queue_tail; + while (kKraidSinkEntry[v0].field_0 != 0xFFFF + && (int16)(Get_Kraid(0)->base.y_pos - kKraidSinkEntry[v0].field_0) >= 0) { + v2 = gVramWriteEntry(v1); + v2->size = 64; + v2->src.addr = 12224; + *(uint16 *)&v2->src.bank = 126; + v2->vram_dst = kKraidSinkEntry[v0].field_2 + ((reg_BG2SC & 0xFC) << 8); + vram_write_queue_tail = v1 + 7; + WaitForNMI_Kraid(); + ++v0; + } + } + ScreenOff(); +} + +void PauseHook_Kraid(void) { // 0xA7C325 + unsigned int v1; + + uint16 v0 = vram_read_queue_tail; + v1 = vram_read_queue_tail; + *(uint16 *)((char *)&vram_read_queue[0].vram_target + vram_read_queue_tail) = ((reg_BG12NBA & 0xFC) << 8) + 15872; + *(uint16 *)((char *)&vram_read_queue[0].dma_parameters + v1) = 129; + *(uint16 *)((char *)&vram_read_queue[0].dma_parameters + v0 + 1) = 57; + *(VoidP *)((char *)&vram_read_queue[0].src.addr + v0) = 20480; + *(uint16 *)(&vram_read_queue[0].src.bank + v0) = 126; + *(uint16 *)((char *)&vram_read_queue[0].size + v0) = 1024; + vram_read_queue_tail = v0 + 9; +} + +void Kraid_Death_Init(void) { // 0xA7C360 + Enemy_Kraid *E0 = Get_Kraid(0); + if (!E0->kraid_hurt_frame) { + uint16 v0 = 192; + do { + target_palettes[v0 >> 1] = 0; + v0 += 2; + } while ((int16)(v0 - 224) < 0); + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 112] = kKraid_BgPalette7_KraidDeath[i >> 1]; + Enemy_Kraid *E1 = Get_Kraid(0x40u); + E1->base.current_instruction = addr_kKraid_Ilist_8AF0; + E1->base.instruction_timer = 1; + E0->kraid_var_A = FUNC16(Kraid_Death_Fadeout); + E0->kraid_var_B = addr_stru_A79764__plus__8; + E0->kraid_var_C = g_stru_A79764[0].timer; + uint16 v4 = cur_enemy_index; + uint16 v7 = cur_enemy_index; + Enemy_Kraid *E6 = Get_Kraid(0x180u); + E6->base.properties &= ~0x4000u; + cur_enemy_index = 384; + EnemyDeathAnimation(v4, 0x180u); + Enemy_Kraid *E7 = Get_Kraid(0x1C0u); + E7->base.properties &= ~0x4000u; + cur_enemy_index = 448; + EnemyDeathAnimation(v4, 0x1C0u); + cur_enemy_index = 128; + EnemyDeathAnimation(v4, 0x80); + cur_enemy_index = 192; + EnemyDeathAnimation(v4, 0xC0u); + cur_enemy_index = 256; + EnemyDeathAnimation(v4, 0x100u); + cur_enemy_index = v7; + static const SpawnHardcodedPlmArgs unk_A7C3F4 = { 0x05, 0x1b, 0xb7bf }; + SpawnHardcodedPlm(&unk_A7C3F4); + } +} + +void Kraid_Death_Fadeout(void) { // 0xA7C3F9 + VramWriteEntry *v3; + + Kraid_ProcessKraidInstr(); + if (AdvancePaletteFade_BgPalette6() & 1) { + Enemy_Kraid *E = Get_Kraid(0); + E->kraid_var_A = FUNC16(Kraid_Death_UpdateBG2TilemapTopHalf); + E->kraid_hurt_frame_timer = 1; + E->kraid_hurt_frame = 1; + Kraid_Palette_Handling(); + uint16 v1 = 0; + do { + ram4000.xray_tilemaps[v1] = 0; + ram4000.xray_tilemaps[v1 + 1] = 0; + v1 += 2; + } while ((int16)(v1 * 2 - 512) < 0); + uint16 v2 = vram_write_queue_tail; + v3 = gVramWriteEntry(vram_write_queue_tail); + v3->size = 512; + v3->src.addr = 0x4000; + v3->src.bank = 126; + v3->vram_dst = ((reg_BG12NBA & 0xF) << 8) + 16128; + vram_write_queue_tail = v2 + 7; + } +} + +void Kraid_Death_UpdateBG2TilemapTopHalf(void) { // 0xA7C4A4 + Kraid_ProcessKraidInstr(); + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_Death_UpdateBG2TilemapBottomHalf); + Enemy_Kraid *E2 = Get_Kraid(0x80); + E2->kraid_var_A = FUNC16(Kraid_AlignEnemyToKraid); + E2->kraid_var_F = 0x7FFF; + Enemy_Kraid *E3 = Get_Kraid(0xC0u); + E3->kraid_var_A = FUNC16(Kraid_AlignEnemyToKraid); + E3->kraid_var_F = 0x7FFF; + Enemy_Kraid *E4 = Get_Kraid(0x100u); + E4->kraid_var_A = FUNC16(Kraid_AlignEnemyToKraid); + E4->kraid_var_F = 0x7FFF; + Kraid_UpdateBg2TilemapTopHalf(); +} + +void Kraid_Death_UpdateBG2TilemapBottomHalf(void) { // 0xA7C4C8 + Kraid_ProcessKraidInstr(); + unpause_hook.bank = -89; + unpause_hook.addr = FUNC16(Kraid_UnpauseHook_IsSinking); + Enemy_Kraid *E = Get_Kraid(0); + E->kraid_var_A = FUNC16(Kraid_Death_SinkThroughFloor); + kraid_unk9000 = 43; + E->base.properties |= 0x8000u; + earthquake_type = 1; + earthquake_timer = 256; + Enemy_Kraid *E1 = Get_Kraid(0x40u); + E1->base.current_instruction = addr_kKraid_Ilist_8AA4; + E1->base.instruction_timer = 1; + Enemy_Kraid *E5 = Get_Kraid(0x140u); + E5->base.current_instruction = addr_kKraid_Ilist_86E7; + E5->base.instruction_timer = 1; + E5->kraid_var_A = FUNC16(nullsub_234); + Kraid_UpdateBG2TilemapBottomHalf(); +} + +void Kraid_PlaySoundEveryHalfSecond(void) { // 0xA7C51D + if (!--kraid_unk9000) { + QueueSfx3_Max6(0x1Eu); + kraid_unk9000 = 30; + } +} + +void Kraid_Death_SinkThroughFloor(void) { // 0xA7C537 + Kraid_ProcessKraidInstr(); + Kraid_PlaySoundEveryHalfSecond(); + Kraid_HandleSinking(); + Enemy_Kraid *E0 = Get_Kraid(0); + if (!sign16(++E0->base.y_pos - 608)) { + E0->base.properties &= ~kEnemyProps_Tangible; + enemy_bg2_tilemap_size = 2; + uint16 enemy_ptr = Get_Kraid(cur_enemy_index)->base.enemy_ptr; + get_EnemyDef_A2(enemy_ptr)->shot_ai = FUNC16(nullsub_170_A7); + Enemy_Kraid *E1 = Get_Kraid(0x40u); + uint16 v3 = E1->base.properties | kEnemyProps_Tangible | kEnemyProps_Deleted; + E1->base.properties = v3; + uint16 v4 = v3 & 0x51FF | 0x600; + Get_Kraid(0x80)->base.properties = v4; + Get_Kraid(0xC0u)->base.properties = v4; + Get_Kraid(0x100u)->base.properties = v4; + Get_Kraid(0x140u)->base.properties = v4; + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_FadeInBg_ClearBg2TilemapTopHalf); + camera_distance_index = 0; + Enemy_ItemDrop_Kraid(enemy_ptr); + Kraid_DrawRoomBg(); + } +} + +void CallKraidSinkTableFunc(uint32 ea) { + switch (ea) { + case fnKraid_CrumbleLeftPlatform_Left: Kraid_CrumbleLeftPlatform_Left(); return; + case fnnullsub_356: return; + case fnKraid_CrumbleRightPlatform_Middle: Kraid_CrumbleRightPlatform_Middle(); return; + case fnKraid_CrumbleRightPlatform_Left: Kraid_CrumbleRightPlatform_Left(); return; + case fnKraid_CrumbleLeftPlatform_Right: Kraid_CrumbleLeftPlatform_Right(); return; + case fnKraid_CrumbleLeftPlatform_Middle: Kraid_CrumbleLeftPlatform_Middle(); return; + case fnKraid_CrumbleRightPlatform_Right: Kraid_CrumbleRightPlatform_Right(); return; + default: Unreachable(); + } +} + +void Kraid_HandleSinking(void) { // 0xA7C59F + int16 v1; + VramWriteEntry *v3; + + for (int i = 0; ; ++i) { + v1 = kKraidSinkEntry[i].field_0; + if (v1 < 0) + break; + if (v1 == Get_Kraid(0)->base.y_pos) { + if ((kKraidSinkEntry[i].field_2 & 0x8000u) == 0) { + uint16 v2 = vram_write_queue_tail; + v3 = gVramWriteEntry(vram_write_queue_tail); + v3->size = 64; + v3->src.addr = 12224; + v3->src.bank = 126; + v3->vram_dst = kKraidSinkEntry[i].field_2 + ((reg_BG2SC & 0xFC) << 8); + vram_write_queue_tail = v2 + 7; + } + CallKraidSinkTableFunc(kKraidSinkEntry[i].field_4 | 0xA70000); + return; + } + } +} + +static const SpawnHardcodedPlmArgs unk_A7C6A2 = { 0x07, 0x12, 0xb7a7 }; +static const SpawnHardcodedPlmArgs unk_A7C6B8 = { 0x0f, 0x12, 0xb7a7 }; +static const SpawnHardcodedPlmArgs unk_A7C6CE = { 0x0e, 0x12, 0xb7af }; +static const SpawnHardcodedPlmArgs unk_A7C6E4 = { 0x09, 0x12, 0xb7a7 }; +static const SpawnHardcodedPlmArgs unk_A7C6FA = { 0x08, 0x12, 0xb7af }; +static const SpawnHardcodedPlmArgs unk_A7C710 = { 0x10, 0x12, 0xb7af }; + +void Kraid_CrumbleLeftPlatform_Left(void) { // 0xA7C691 + SpawnEnemyProjectileWithGfx(0x70u, cur_enemy_index, addr_kEproj_RocksFallingKraidCeiling); + SpawnHardcodedPlm(&unk_A7C6A2); +} + +void Kraid_CrumbleRightPlatform_Middle(void) { // 0xA7C6A7 + SpawnEnemyProjectileWithGfx(0xF0u, cur_enemy_index, addr_kEproj_RocksFallingKraidCeiling); + SpawnHardcodedPlm(&unk_A7C6B8); +} + +void Kraid_CrumbleRightPlatform_Left(void) { // 0xA7C6BD + SpawnEnemyProjectileWithGfx(0xE0u, cur_enemy_index, addr_kEproj_RocksFallingKraidCeiling); + SpawnHardcodedPlm(&unk_A7C6CE); +} + +void Kraid_CrumbleLeftPlatform_Right(void) { // 0xA7C6D3 + SpawnEnemyProjectileWithGfx(0x90u, cur_enemy_index, addr_kEproj_RocksFallingKraidCeiling); + SpawnHardcodedPlm(&unk_A7C6E4); +} + +void Kraid_CrumbleLeftPlatform_Middle(void) { // 0xA7C6E9 + SpawnEnemyProjectileWithGfx(0x80, cur_enemy_index, addr_kEproj_RocksFallingKraidCeiling); + SpawnHardcodedPlm(&unk_A7C6FA); +} + +void Kraid_CrumbleRightPlatform_Right(void) { // 0xA7C6FF + SpawnEnemyProjectileWithGfx(0x100u, cur_enemy_index, addr_kEproj_RocksFallingKraidCeiling); + SpawnHardcodedPlm(&unk_A7C710); +} + +void Kraid_FadeInBg_ClearBg2TilemapTopHalf(void) { // 0xA7C715 + VramWriteEntry *v2; + + reg_BG2SC = 72; + for (int i = 2046; i >= 0; i -= 2) + tilemap_stuff[i >> 1] = 824; + uint16 v1 = vram_write_queue_tail; + v2 = gVramWriteEntry(vram_write_queue_tail); + v2->size = 1024; + v2->src.addr = 0x2000; + *(uint16 *)&v2->src.bank = 126; + v2->vram_dst = 18432; + vram_write_queue_tail = v1 + 7; + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_FadeInBg_ClearBg2TilemapBottomHalf); +} + +void Kraid_FadeInBg_ClearBg2TilemapBottomHalf(void) { // 0xA7C751 + VramWriteEntry *v1; + + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 1024; + v1->src.addr = 0x2000; + *(uint16 *)&v1->src.bank = 126; + v1->vram_dst = 18944; + vram_write_queue_tail = v0 + 7; + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_FadeInBg_LoadBg3Tiles1of4); +} + +void Kraid_FadeInBg_LoadBg3Tiles1of4(void) { // 0xA7C777 + VramWriteEntry *v1; + + unpause_hook.addr = FUNC16(UnpauseHook_Kraid_IsDead); + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_FadeInBg_LoadBg3Tiles2of4); + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 1024; + v1->src.addr = -19968; + *(uint16 *)&v1->src.bank = 154; + v1->vram_dst = 0x4000; + vram_write_queue_tail = v0 + 7; +} + +void Kraid_FadeInBg_LoadBg3Tiles2of4(void) { // 0xA7C7A3 + VramWriteEntry *v1; + + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_FadeInBg_LoadBg3Tiles3of4); + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 1024; + v1->src.addr = -18944; + *(uint16 *)&v1->src.bank = 154; + v1->vram_dst = 16896; + vram_write_queue_tail = v0 + 7; +} + +void Kraid_FadeInBg_LoadBg3Tiles3of4(void) { // 0xA7C7C9 + VramWriteEntry *v1; + + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_FadeInBg_LoadBg3Tiles4of4); + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 1024; + v1->src.addr = -17920; + *(uint16 *)&v1->src.bank = 154; + v1->vram_dst = 17408; + vram_write_queue_tail = v0 + 7; +} + +void Kraid_FadeInBg_LoadBg3Tiles4of4(void) { // 0xA7C7EF + VramWriteEntry *v1; + + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_FadeInBg_FadeInBp6); + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 1024; + v1->src.addr = -16896; + *(uint16 *)&v1->src.bank = 154; + v1->vram_dst = 17920; + vram_write_queue_tail = v0 + 7; +} + +void Kraid_FadeInBg_FadeInBp6(void) { // 0xA7C815 + int16 v0; + + if (AdvancePaletteFade_BgPalette6() & 1) { + QueueMusic_Delayed8(3u); + v0 = *(uint16 *)&boss_bits_for_area[area_index]; + if ((v0 & 1) != 0) { + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_FadeInBg_SetEnemyDead_KraidWasDead); + } else { + *(uint16 *)&boss_bits_for_area[area_index] = v0 | 1; + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_FadeInBg_SetEnemyDead_KraidWasAlive); + } + } +} + +void Kraid_FadeInBg_SetEnemyDead_KraidWasAlive(void) { // 0xA7C843 + if (!Kraid_CheckIfDead() || layer1_x_pos) + Kraid_SetEnemyPropsToDead(); +} + +void Kraid_FadeInBg_SetEnemyDead_KraidWasDead(void) { // 0xA7C851 + if (!Kraid_CheckIfDead() || layer1_x_pos) + Kraid_SetEnemyPropsToDead(); + previous_layer1_x_block = -1; +} + +void Kraid_RestrictSamusXtoFirstScreen(uint16 k) { // 0xA7C865 + Kraid_RestrictSamusXtoFirstScreen_2(); + KraidEnemy_HandleFunctionTimer(k); +} + +void Kraid_RaiseKraidThroughFloor(uint16 k) { // 0xA7C86B + Kraid_RestrictSamusXtoFirstScreen_2(); + Get_Kraid(0)->kraid_var_A = FUNC16(Kraid_Raise_LoadTilemapBottomAndShake); + Kraid_UpdateBg2TilemapTopHalf(); +} + +void Kraid_UpdateBg2TilemapTopHalf(void) { // 0xA7C874 + VramWriteEntry *v1; + + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 2048; + v1->src.addr = 0x2000; + v1->src.bank = 126; + v1->vram_dst = (reg_BG2SC & 0xFC) << 8; + vram_write_queue_tail = v0 + 7; +} + +void Kraid_Raise_LoadTilemapBottomAndShake(void) { // 0xA7C89A + Kraid_RestrictSamusXtoFirstScreen_2(); + Enemy_Kraid *E = Get_Kraid(0); + E->kraid_var_A = FUNC16(Kraid_Raise_SpawnRandomEarthquakeProjs16); + E->kraid_var_F = 120; + earthquake_timer = 496; + QueueMusic_Delayed8(5u); + Kraid_UpdateBG2TilemapBottomHalf(); +} + +void Kraid_UpdateBG2TilemapBottomHalf(void) { // 0xA7C8B6 + VramWriteEntry *v1; + + uint16 v0 = vram_write_queue_tail; + v1 = gVramWriteEntry(vram_write_queue_tail); + v1->size = 2048; + v1->src.addr = 10240; + v1->src.bank = 126; + v1->vram_dst = ((reg_BG2SC & 0xFC) << 8) + 2048; + vram_write_queue_tail = v0 + 7; +} + +void Kraid_Raise_SpawnRandomEarthquakeProjs16(void) { // 0xA7C8E0 + Kraid_RestrictSamusXtoFirstScreen_2(); + Enemy_Kraid *E = Get_Kraid(0); + uint16 v1 = E->kraid_var_F - 1; + E->kraid_var_F = v1; + if (v1) { + if ((v1 & 0xF) == 0) + Kraid_SpawnRandomQuakeProjs(); + } else { + E->kraid_var_A = FUNC16(Kraid_Raise_SpawnRandomEarthquakeProjs8); + E->kraid_var_F = 96; + } +} + +void Kraid_Raise_SpawnRandomEarthquakeProjs8(void) { // 0xA7C902 + Kraid_RestrictSamusXtoFirstScreen_2(); + Enemy_Kraid *E = Get_Kraid(0); + uint16 v1 = E->kraid_var_F - 1; + E->kraid_var_F = v1; + if (v1) { + if ((v1 & 7) == 0) + Kraid_SpawnRandomQuakeProjs(); + } else { + E->kraid_var_A = FUNC16(Kraid_Raise_Handler); + E->kraid_var_F = 288; + } +} + +void Kraid_Raise_Handler(void) { // 0xA7C924 + Kraid_RestrictSamusXtoFirstScreen_2(); + if ((earthquake_timer & 5) == 0) + Kraid_SpawnRandomQuakeProjs(); + uint16 v0 = 1; + Enemy_Kraid *E0 = Get_Kraid(0); + if ((E0->base.y_pos & 2) == 0) + v0 = -1; + R18_ = v0; + E0->base.x_pos += v0; + uint16 y_subpos = E0->base.y_subpos; + E0->base.y_subpos = y_subpos + 0x8000; + E0->base.y_pos = (__PAIR32__(E0->base.y_pos, y_subpos) - 0x8000) >> 16; + if (sign16(E0->base.y_pos - 457)) { + E0->base.x_pos = 176; + Enemy_Kraid *E5 = Get_Kraid(0x140u); + E5->kraid_var_A = FUNC16(KraidFoot_FirstPhase_Thinking); + E5->kraid_var_F = 300; + E5->kraid_next = FUNC16(KraidsFoot_PrepareToLungeForward); + E0->kraid_var_B = addr_stru_A796DA; + Kraid_Mainloop_Thinking_Setup(); + Enemy_Kraid *E1 = Get_Kraid(0x40u); + E1->base.current_instruction = addr_kKraid_Ilist_89F3; + E1->base.instruction_timer = 1; + } +} + +void Kraid_SpawnRandomQuakeProjs(void) { // 0xA7C995 + int16 v0; + + v0 = random_number & 0x3F; + if ((random_number & 2) == 0) + v0 = ~v0; + R18_ = Get_Kraid(0)->base.x_pos + v0; + R20_ = (uint16)(random_number & 0x3F00) >> 8; + R20_ = 448 - R20_; + R22_ = 21; + R24_ = 0; + CreateSpriteAtPos(); + uint16 v1 = addr_kEproj_RocksWhenKraidRisesLeft; + if ((random_number & 0x10) != 0) + v1 = addr_kEproj_RocksWhenKraidRisesRight; + SpawnEnemyProjectileWithGfx(random_number & 0x3F0, cur_enemy_index, v1); +} + +void Kraid_RestrictSamusXtoFirstScreen_2(void) { // 0xA7C9EE + if ((int16)(samus_x_pos - 256) >= 0) { + samus_x_pos = 256; + samus_prev_x_pos = 256; + } +} + +void Phantoon_Init(void) { // 0xA7CDF3 + int16 j; + uint16 k; + + for (int i = 4094; i >= 0; i -= 2) + tilemap_stuff[i >> 1] = 824; + for (j = 2046; j >= 0; j -= 2) + *(uint16 *)((char *)&kraid_unk9000 + (uint16)j) = 0; + for (k = 30; (k & 0x8000u) == 0; k -= 2) + target_palettes[(k >> 1) + 112] = 0; + enemy_bg2_tilemap_size = 864; + DisableMinimapAndMarkBossRoomAsExplored(); + Enemy_Phantoon *E = Get_Phantoon(cur_enemy_index); + E->phant_var_E = 120; + E->phant_var_A = 0; + E->phant_var_B = 0; + g_word_7E9032 = 0; + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->phant_parameter_1 = 0; + E1->phant_parameter_2 = 0; + Enemy_Phantoon *E0 = Get_Phantoon(0); + E0->base.properties |= kEnemyProps_Tangible; + static const SpawnHdmaObject_Args unk_A7CE51 = { 0x01, 0x14, 0xce96 }; + SpawnHdmaObject(0xa7, &unk_A7CE51); + Phantoon2_Init(); +} + +void Phantoon2_Init(void) { // 0xA7CE55 + EnemyData *v6 = gEnemyData(cur_enemy_index); + v6->spritemap_pointer = addr_kSpritemap_Nothing_A7; + v6->instruction_timer = 1; + v6->timer = 0; + EnemyData *v7 = gEnemyData(0); + v6->palette_index = v7->palette_index; + v6->vram_tiles_index = v7->vram_tiles_index; + v6->current_instruction = g_off_A7CE8E[v6->parameter_2]; + v6->ai_preinstr = FUNC16(Phantoon_Spawn8FireballsInCircleAtStart); + v7[3].parameter_1 = 0; + v7[3].ai_var_C = -1; +} + +void Phantoon_Main(void) { // 0xA7CEA6 + Phantoon_Func_2(cur_enemy_index); + Enemy_Phantoon *EK = Get_Phantoon(cur_enemy_index); + CallEnemyPreInstr(EK->phant_var_F | 0xA70000); + printf("What is X?\n"); + uint16 tt = cur_enemy_index; // wtf bug + if (!tt) { + Enemy_Phantoon *E0 = Get_Phantoon(0); + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + Enemy_Phantoon *E2 = Get_Phantoon(0x80); + Enemy_Phantoon *E3 = Get_Phantoon(0xC0u); + uint16 x_pos = E0->base.x_pos; + E1->base.x_pos = x_pos; + E2->base.x_pos = x_pos; + E3->base.x_pos = x_pos; + uint16 y_pos = E0->base.y_pos; + E1->base.y_pos = y_pos; + E2->base.y_pos = y_pos; + E3->base.y_pos = y_pos; + if (!E1->phant_parameter_1) { + reg_BG2HOFS = layer1_x_pos - E0->base.x_pos + 40; + reg_BG2VOFS = layer1_y_pos - E0->base.y_pos + 40; + } + } + + + +} + +void Phantoon_Func_1(void) { // 0xA7CEED + QueueSfx2_Max6(g_word_A7CDED[g_word_7E9032]); + uint16 v0 = g_word_7E9032 + 1; + if (!sign16(g_word_7E9032 - 2)) + v0 = 0; + g_word_7E9032 = v0; +} + +void Phantoon_Func_2(uint16 k) { // 0xA7CF0C + if (!k && (joypad1_newkeys & 0x4000) != 0) + *(uint16 *)((char *)&g_stru_A7902D[0].ypos + 1) = *(uint16 *)((char *)&g_stru_A7902D[0].ypos + 1) == 0; +} + +uint8 Phantoon_Func_3(void) { // 0xA7CF27 + char v2; // t1 + + Enemy_Phantoon *E = Get_Phantoon(0xC0u); + if (E->phant_var_E) { + uint16 phant_var_D = E->phant_var_D; + bool v4 = phant_var_D < R18_; + E->phant_var_D = phant_var_D - R18_; + if (v4) { + E->phant_var_D = 0; + return 1; + } + } else { + R22_ = (uint8)((uint16)(R20_ & 0xFF00) >> 8); + uint16 v1 = R18_ + E->phant_var_D; + E->phant_var_D = v1; + v1 &= 0xFF00u; + v2 = v1; + LOBYTE(v1) = HIBYTE(v1); + HIBYTE(v1) = v2; + if (!sign16(v1 - R22_)) + E->phant_var_D = R20_; + } + return 0; +} + +void Phantoon_Func_4(uint16 k) { // 0xA7CF5E + SpawnEnemyProjectileWithGfx(0, k, addr_kEproj_DestroyableFireballs); + QueueSfx3_Max6(0x1Du); +} + +void Phantoon_Func_5(uint16 k) { // 0xA7CF70 + for (int i = 7; i >= 0; --i) + SpawnEnemyProjectileWithGfx(i | 0x600, k, addr_kEproj_DestroyableFireballs); + QueueSfx3_Max6(0x28u); +} + +void Phantoon_Func_6(uint16 k, uint16 a) { // 0xA7CF8B + int16 v2; + int16 v3; + + v2 = g_byte_A7CFC2[a]; + R18_ = 7; + R20_ = 16; + do { + v3 = v2; + SpawnEnemyProjectileWithGfx(R20_ | v2++ | 0x400, k, addr_kEproj_DestroyableFireballs); + if ((int16)(v3 - 8) >= 0) + v2 = 0; + R20_ += 16; + --R18_; + } while ((R18_ & 0x8000u) == 0); +} + +void Phantoon_Func_7(uint16 k) { // 0xA7CFCA + Enemy_Phantoon *E = Get_Phantoon(k + 192); + bool v3 = E->phant_var_B == 1; + bool v4 = (--E->phant_var_B & 0x8000u) != 0; + if (v3 || v4) { + if ((E->phant_var_C & 0x8000u) == 0) { + v3 = E->phant_var_C == 1; + bool v8 = (--E->phant_var_C & 0x8000u) != 0; + if (v3 || v8) { + E->phant_var_C = -1; + E->phant_var_B = *((uint16 *)RomPtr_A7(g_off_A7CCFD[E->phant_var_A]) + + 1); + } else { + R18_ = 2 * E->phant_var_C; + E->phant_var_B = *((uint16 *)RomPtr_A7(R18_ + g_off_A7CCFD[E->phant_var_A]) + + 1); + } + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kKraid_Ilist_CCEB; + } else { + uint16 v5 = NextRandom() & 3; + E->phant_var_A = v5; + uint16 v6 = g_off_A7CCFD[v5]; + uint16 v7 = *(uint16 *)RomPtr_A7(v6); + E->phant_var_C = v7; + R18_ = 2 * v7; + E->phant_var_B = *((uint16 *)RomPtr_A7(2 * v7 + v6) + 1); + } + } +} + +void Phantoon_StartTrackingSamusAndInitEyeTimer(void) { // 0xA7D03F + Get_Phantoon(0x80)->phant_var_A = 0; + Enemy_Phantoon *E = Get_Phantoon(0); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kKraid_Ilist_CC4D; + E->base.properties &= ~kEnemyProps_Tangible; + E->phant_var_E = g_word_A7CD41[NextRandom() & 7]; + E->phant_var_F = FUNC16(Phantoon_EyeFollowsSamusUntilTimerRunsOut); + + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->base.instruction_timer = 1; + E1->base.current_instruction = addr_kKraid_Ilist_CC9D; +} + +void Phantoon_PickPatternForRound2(void) { // 0xA7D076 + int16 v4; + + Enemy_Phantoon *E = Get_Phantoon(0); + E->phant_var_E = 60; + uint16 v1 = g_word_A7CD53[NextRandom() & 7]; + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->phant_var_A = v1; + if ((nmi_frame_counter_word & 1) != 0) { + if (!E1->phant_var_C) { + v4 = E->phant_var_A - 1; + E->phant_var_A = v4; + if (v4 < 0) + E->phant_var_A = 533; + } + E->phant_var_C = 0; + E->phant_var_B = 0; + E->phant_var_D = 0; + E1->phant_var_C = 1; + } else { + if (E1->phant_var_C) { + uint16 v3 = E->phant_var_A + 1; + E->phant_var_A = v3; + if (!sign16(v3 - 534)) + E->phant_var_A = 0; + } + E->phant_var_C = 1; + E->phant_var_B = 0; + E->phant_var_D = 0; + E1->phant_var_C = 0; + } + if (E->phant_parameter_2) { + E1->phant_var_F = 0; + E->phant_var_F = FUNC16(Phantoon_FadeOutBeforeFirstFireballRain); + } else { + E->phant_var_F = FUNC16(Phantoon_MovePhantoonInFigure8ThenOpenEye); + } +} + +void Phantoon_AdjustSpeedAndMoveInFigure8(void) { // 0xA7D0F1 + if (Get_Phantoon(0x40u)->phant_var_C) { + Phantoon_AdjustSpeedRightSideClockwise(); + R20_ = 533; + Phantoon_MoveInFigure8_RightSideClockwise(addr_kPhantoonMoveData); + } else { + Phantoon_AdjustSpeedLeftSideClockwise(); + R20_ = 534; + Phantoon_MoveInFigure8_LeftSideClockwise(addr_kPhantoonMoveData); + } +} + +void Phantoon_AdjustSpeedLeftSideClockwise(void) { // 0xA7D114 + Enemy_Phantoon *E = Get_Phantoon(0); + uint16 phant_var_D = E->phant_var_D; + if (phant_var_D) { + if ((phant_var_D & 1) != 0) { + uint16 phant_var_B = E->phant_var_B; + bool v3 = __CFADD__uint16(g_word_A7CD77, phant_var_B); + E->phant_var_B = g_word_A7CD77 + phant_var_B; + uint16 v6 = g_word_A7CD79 + v3 + E->phant_var_C; + E->phant_var_C = v6; + if ((int16)(v6 - g_word_A7CD7D) >= 0) { + E->phant_var_C = g_word_A7CD7D; + E->phant_var_B = 0; + ++E->phant_var_D; + } + } else { + uint16 v7 = E->phant_var_B; + bool v3 = v7 < g_word_A7CD77; + E->phant_var_B = v7 - g_word_A7CD77; + uint16 v8 = E->phant_var_C - (v3 + g_word_A7CD79); + E->phant_var_C = v8; + if (v8 == g_word_A7CD7F || (int16)(v8 - g_word_A7CD7F) < 0) { + E->phant_var_C = g_word_A7CD7F + 1; + E->phant_var_B = 0; + E->phant_var_D = 0; + } + } + } else { + uint16 v2 = E->phant_var_B; + bool v3 = __CFADD__uint16(g_word_A7CD73, v2); + E->phant_var_B = g_word_A7CD73 + v2; + uint16 v4 = g_word_A7CD75 + v3 + E->phant_var_C; + E->phant_var_C = v4; + if ((int16)(v4 - g_word_A7CD7B) >= 0) { + E->phant_var_C = g_word_A7CD7B - 1; + E->phant_var_B = 0; + ++E->phant_var_D; + } + } +} + +void Phantoon_AdjustSpeedRightSideClockwise(void) { // 0xA7D193 + Enemy_Phantoon *E = Get_Phantoon(0); + uint16 phant_var_D = E->phant_var_D; + if (phant_var_D) { + if ((phant_var_D & 1) != 0) { + uint16 phant_var_B = E->phant_var_B; + bool v3 = phant_var_B < g_word_A7CD85; + E->phant_var_B = phant_var_B - g_word_A7CD85; + uint16 v6 = E->phant_var_C - (v3 + g_word_A7CD87); + E->phant_var_C = v6; + if (v6 == g_word_A7CD8B || (int16)(v6 - g_word_A7CD8B) < 0) { + E->phant_var_C = g_word_A7CD8B + 1; + E->phant_var_B = 0; + ++E->phant_var_D; + } + } else { + uint16 v7 = E->phant_var_B; + bool v3 = __CFADD__uint16(g_word_A7CD85, v7); + E->phant_var_B = g_word_A7CD85 + v7; + uint16 v8 = g_word_A7CD87 + v3 + E->phant_var_C; + E->phant_var_C = v8; + if ((int16)(v8 - g_word_A7CD8D) >= 0) { + E->phant_var_C = g_word_A7CD8D; + E->phant_var_B = 0; + E->phant_var_D = 0; + } + } + } else { + uint16 v2 = E->phant_var_B; + bool v3 = v2 < g_word_A7CD81; + E->phant_var_B = v2 - g_word_A7CD81; + uint16 v4 = E->phant_var_C - (v3 + g_word_A7CD83); + E->phant_var_C = v4; + if (v4 == g_word_A7CD89 || (int16)(v4 - g_word_A7CD89) < 0) { + E->phant_var_C = (uint16)(g_word_A7CD89 + 2); + E->phant_var_B = 0; + ++E->phant_var_D; + } + } +} + +void Phantoon_MoveInFigure8_LeftSideClockwise(uint16 j) { // 0xA7D215 + Enemy_Phantoon *E = Get_Phantoon(0); + for (R22_ = E->phant_var_C; R22_; --R22_) { + R18_ = 2 * E->phant_var_A; + uint8 *v2 = RomPtr_A7(R18_ + j); + uint16 v3 = *v2; + if ((v3 & 0x80) != 0) + v3 |= 0xFF00u; + R18_ = v3; + E->base.x_pos += v3; + uint16 v4 = v2[1]; + if ((v4 & 0x80) != 0) + v4 |= 0xFF00u; + R18_ = v4; + E->base.y_pos += v4; + uint16 v5 = E->phant_var_A + 1; + E->phant_var_A = v5; + if (!sign16(v5 - R20_)) + E->phant_var_A = 0; + } +} + +void Phantoon_MoveInFigure8_RightSideClockwise(uint16 j) { // 0xA7D271 + int16 v7; + + Enemy_Phantoon *E = Get_Phantoon(0); + bool v2 = E->phant_var_C == 0; + R22_ = -E->phant_var_C; + if (!v2) { + do { + R18_ = 2 * E->phant_var_A; + uint8 *v4 = RomPtr_A7(R18_ + j); + uint16 v5 = *v4; + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + R18_ = v5; + E->base.x_pos -= v5; + uint16 v6 = v4[1]; + if ((v6 & 0x80) != 0) + v6 |= 0xFF00u; + R18_ = v6; + E->base.y_pos -= v6; + v7 = E->phant_var_A - 1; + E->phant_var_A = v7; + if (v7 < 0) + E->phant_var_A = R20_; + --R22_; + } while (R22_); + } +} + +void Phantoon_MoveInSwoopingPattern(uint16 k) { // 0xA7D2D1 + Enemy_Phantoon *Phantoon; + Enemy_Phantoon *v2; + int16 phant_var_E; + uint16 v4; + uint16 v5; + uint16 v6; + Enemy_Phantoon *v7; + Enemy_Phantoon *v8; + uint16 v9; + uint16 x_subpos; + bool v11; // cf + uint16 v12; + int16 v13; + uint16 v14; + uint16 y_subpos; + uint16 v16; + + Phantoon = Get_Phantoon(0x80); + v2 = Phantoon; + phant_var_E = Phantoon->phant_var_E; + if (phant_var_E < 0) { + v6 = phant_var_E - 2; + Phantoon->phant_var_E = v6; + v4 = v6 & 0x7FFF; + if (!v4) { + v4 = 0; + Phantoon->phant_var_E = 0; + } + } else { + v4 = phant_var_E + 2; + Phantoon->phant_var_E = v4; + if (!sign16(v4 - 256)) { + v5 = v4 | 0x8000; + Phantoon->phant_var_E = v5; + v4 = v5 & 0x7FFF; + } + } + v7 = Get_Phantoon(0); + v8 = v7; + if ((int16)(v4 - v7->base.x_pos) < 0) { + if (!sign16(v2->phant_var_C + 2047)) + v2->phant_var_C -= 32; + } else if (sign16(v2->phant_var_C - 2048)) { + v2->phant_var_C += 32; + } + LOBYTE(v9) = HIBYTE(v2->phant_var_C); + HIBYTE(v9) = v2->phant_var_C; + R20_ = v9 & 0xFF00; + v9 = (uint8)v9; + if ((v9 & 0x80) != 0) + v9 |= 0xFF00u; + R18_ = v9; + x_subpos = v7->base.x_subpos; + v11 = __CFADD__uint16(R20_, x_subpos); + v7->base.x_subpos = R20_ + x_subpos; + v12 = R18_ + v11 + v7->base.x_pos; + v7->base.x_pos = v12; + if (sign16(v12 + 64)) { + v7->base.x_pos = -64; + } else if (!sign16(v12 - 448)) { + v7->base.x_pos = 448; + } + if (Get_Phantoon(k)->phant_var_F == (uint16)FUNC16(Phantoon_CompleteSwoopAfterFatalShot)) + v13 = 112; + else + v13 = samus_y_pos - 48; + if ((int16)(v13 - v8->base.y_pos) < 0) { + if (!sign16(v2->phant_var_D + 1535)) + v2->phant_var_D -= 64; + } else if (sign16(v2->phant_var_D - 1536)) { + v2->phant_var_D += 64; + } + LOBYTE(v14) = HIBYTE(v2->phant_var_D); + HIBYTE(v14) = v2->phant_var_D; + R20_ = v14 & 0xFF00; + v14 = (uint8)v14; + if ((v14 & 0x80) != 0) + v14 |= 0xFF00u; + R18_ = v14; + y_subpos = v8->base.y_subpos; + v11 = __CFADD__uint16(R20_, y_subpos); + v8->base.y_subpos = R20_ + y_subpos; + v16 = R18_ + v11 + v8->base.y_pos; + v8->base.y_pos = v16; + if (sign16(v16 - 64)) { + v8->base.y_pos = 64; + } else if (!sign16(v16 - 216)) { + v8->base.y_pos = 216; + } +} + +void Phantoon_BeginSwoopingPattern(uint16 k) { // 0xA7D3E1 + Enemy_Phantoon *E2 = Get_Phantoon(0x80); + E2->phant_var_C = 1024; + E2->phant_var_D = 1024; + E2->phant_var_E = 0; + Enemy_Phantoon *E = Get_Phantoon(k); + E->phant_var_F = FUNC16(Phantoon_IsSwooping); + E->phant_var_E = 360; +} + +void Phantoon_ChangeEyeSpriteBasedOnSamusDist(void) { // 0xA7D3FA + uint16 v0 = 2 * DetermineDirectionOfSamusFromEnemy(); + Enemy_Phantoon *E = Get_Phantoon(0x40u); + E->base.instruction_timer = 1; + E->base.current_instruction = g_off_A7D40D[v0 >> 1]; +} + +void Phantoon_StartDeathSequence(uint16 k) { // 0xA7D421 + int16 v3; + + Enemy_Phantoon *E = Get_Phantoon(k); + if (E->phant_var_F == (uint16)FUNC16(Phantoon_IsSwooping) + || E->phant_var_F == (uint16)FUNC16(Phantoon_FadeoutWithSwoop)) { + E->phant_var_F = FUNC16(Phantoon_CompleteSwoopAfterFatalShot); + } else { + E->phant_var_F = FUNC16(Phantoon_DyingPhantoonFadeInOut); + } + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->phant_var_C = 0; + E1->phant_var_F = 0; + Phantoon_ChangeEyeSpriteBasedOnSamusDist(); + v3 = 510; + uint16 v4 = reg_BG2HOFS; + do { + *(uint16 *)((char *)&g_word_7E9100 + (uint16)v3) = v4; + v3 -= 2; + } while (v3 >= 0); + phantom_related_layer_flag |= 0x4000u; + Get_Phantoon(0xC0u)->phant_parameter_2 = 1; +} + +void Phantoon_FadeOut(uint16 a) { // 0xA7D464 + R18_ = a; + if ((nmi_frame_counter_word & 1) == 0) { + Enemy_Phantoon *E = Get_Phantoon(0x40u); + if (!E->phant_var_F) { + E->phant_var_D = R18_; + if (Phantoon_Func_8() & 1) + E->phant_var_F = 1; + } + } +} + +void Phantoon_FadeIn(uint16 a) { // 0xA7D486 + R18_ = a; + if ((nmi_frame_counter_word & 1) == 0) { + Enemy_Phantoon *E = Get_Phantoon(0x40u); + if (!E->phant_var_F) { + E->phant_var_D = R18_; + if (Phantoon_SetColorBasedOnHp() & 1) + E->phant_var_F = 1; + } + } +} + +void Phantoon_Spawn8FireballsInCircleAtStart(uint16 k) { // 0xA7D4A9 + Enemy_Phantoon *EK = Get_Phantoon(k); + bool v2 = EK->phant_var_E == 1; + bool v3 = (--EK->phant_var_E & 0x8000u) != 0; + if (v2 || v3) { + Enemy_Phantoon *E0 = Get_Phantoon(0); + SpawnEnemyProjectileWithGfx(E0->phant_var_A, k, addr_kEproj_StartingFireballs); + QueueSfx3_Max6(0x1Du); + EK->phant_var_E = 30; + uint16 v5 = E0->phant_var_A + 1; + E0->phant_var_A = v5; + if (!sign16(v5 - 8)) { + E0->phant_var_A = 0; + Get_Phantoon(k + 128)->phant_var_B = 0; + EK->phant_var_F = FUNC16(Phantoon_WaitBetweenSpawningAndSpinningFireballs); + EK->phant_var_E = 30; + static const SpawnHardcodedPlmArgs unk_A7D4E9 = { 0x00, 0x06, 0xb781 }; + SpawnHardcodedPlm(&unk_A7D4E9); + } + } +} + +void Phantoon_WaitBetweenSpawningAndSpinningFireballs(uint16 k) { // 0xA7D4EE + Enemy_Phantoon *E = Get_Phantoon(k); + bool v2 = E->phant_var_E == 1; + bool v3 = (--E->phant_var_E & 0x8000u) != 0; + if (v2 || v3) { + E->phant_var_E = 240; + E->phant_var_B = 1; + E->phant_var_F = FUNC16(Phantoon_SpawnFireballsBeforeFight); + } +} + +void Phantoon_SpawnFireballsBeforeFight(uint16 k) { // 0xA7D508 + Enemy_Phantoon *EK = Get_Phantoon(k); + bool v3 = EK->phant_var_E == 1; + bool v4 = (--EK->phant_var_E & 0x8000u) != 0; + if (v3 || v4) { + EK->phant_var_B = 0; + phantom_related_layer_flag |= 0x4000u; + EK->phant_var_F = FUNC16(Phantoon_WavyFadeIn); + Enemy_Phantoon *E3 = Get_Phantoon(0xC0u); + E3->phant_parameter_1 = -32767; + EK->phant_var_E = 120; + R22_ = g_word_A7CDA3; + sub_88E487(2u); + E3->phant_var_D = g_word_A7CD9D; + Get_Phantoon(0x40u)->phant_var_F = 0; + QueueMusic_Delayed8(5u); + } +} + +void Phantoon_WavyFadeIn(uint16 k) { // 0xA7D54A + Phantoon_FadeIn(0xCu); + R18_ = g_word_A7CD9B; + R20_ = g_word_A7CD9D; + if (Phantoon_Func_3() & 1) { + Enemy_Phantoon *E = Get_Phantoon(k); + E->phant_var_F = FUNC16(Phantoon_PickPatternForRound1); + Get_Phantoon(0xC0u)->phant_parameter_1 = 1; + E->phant_var_E = 30; + } else { + Enemy_Phantoon *E = Get_Phantoon(k); + bool v2 = E->phant_var_E == 1; + bool v3 = (--E->phant_var_E & 0x8000u) != 0; + if (v2 || v3) + Get_Phantoon(0xC0u)->phant_var_E = 1; + } +} + +void Phantoon_PickPatternForRound1(uint16 k) { // 0xA7D596 + Enemy_Phantoon *EK = Get_Phantoon(k); + bool v2 = EK->phant_var_E == 1; + bool v3 = (--EK->phant_var_E & 0x8000u) != 0; + if (v2 || v3) { + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->phant_parameter_1 = 0; + EK->phant_var_F = FUNC16(Phantoon_MovePhantoonInFigure8ThenOpenEye); + E1->phant_var_A = g_word_A7CD53[(nmi_frame_counter_word >> 1) & 3]; + if ((NextRandom() & 1) != 0) { + Enemy_Phantoon *E = Get_Phantoon(0); + E->phant_var_C = 0; + E->phant_var_B = 0; + E->phant_var_D = 0; + E1->phant_var_C = 1; + E->phant_var_A = 533; + } else { + Enemy_Phantoon *E = Get_Phantoon(0); + E->phant_var_C = 1; + E->phant_var_B = 0; + E->phant_var_D = 0; + E1->phant_var_C = 0; + E->phant_var_A = 0; + } + } +} + +void Phantoon_MovePhantoonInFigure8ThenOpenEye(uint16 k) { // 0xA7D5E7 + Phantoon_AdjustSpeedAndMoveInFigure8(); + Phantoon_Func_7(k); + Enemy_Phantoon *E = Get_Phantoon(0x40u); + bool v2 = E->phant_var_A == 1; + bool v3 = (--E->phant_var_A & 0x8000u) != 0; + if (v2 || v3) { + Get_Phantoon(k)->phant_var_F = FUNC16(nullsub_237); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kKraid_Ilist_CC53; + Get_Phantoon(0)->phant_parameter_2 = 0; + Phantoon_Func_5(k); + } +} + +void Phantoon_EyeFollowsSamusUntilTimerRunsOut(uint16 k) { // 0xA7D60D + Enemy_Phantoon *EK = Get_Phantoon(k); + bool v2 = EK->phant_var_E == 1; + bool v3 = (--EK->phant_var_E & 0x8000u) != 0; + if (v2 || v3) { + Get_Phantoon(k + 128)->phant_var_B = 0; + Enemy_Phantoon *E2 = Get_Phantoon(0x80); + if (!E2->phant_var_A) { + EK->phant_var_F = FUNC16(nullsub_237); + Enemy_Phantoon *E0 = Get_Phantoon(0); + E0->base.instruction_timer = 1; + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->base.instruction_timer = 1; + E0->base.current_instruction = addr_kKraid_Ilist_CC41; + E1->base.current_instruction = addr_kKraid_Ilist_CC81; + E0->base.properties |= kEnemyProps_Tangible; + E0->phant_parameter_2 = 1; + return; + } + E2->phant_var_A = 0; + EK->phant_var_E = 60; + EK->phant_var_F = FUNC16(Phantoon_BecomesSolidAndBodyVuln); + } + Phantoon_ChangeEyeSpriteBasedOnSamusDist(); +} + +void Phantoon_BecomesSolidAndBodyVuln(uint16 v0) { // 0xA7D65C + Phantoon_ChangeEyeSpriteBasedOnSamusDist(); + phantom_related_layer_flag &= ~0x4000u; + Phantoon_BeginSwoopingPattern(v0); + Enemy_Phantoon *E = Get_Phantoon(0); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kKraid_Ilist_CC47; +} + +void Phantoon_IsSwooping(uint16 k) { // 0xA7D678 + Phantoon_ChangeEyeSpriteBasedOnSamusDist(); + Phantoon_MoveInSwoopingPattern(k); + Enemy_Phantoon *EK = Get_Phantoon(k); + bool v2 = EK->phant_var_E == 1; + bool v3 = (--EK->phant_var_E & 0x8000u) != 0; + if (v2 || v3) { + EK->phant_var_F = FUNC16(Phantoon_FadeoutWithSwoop); + phantom_related_layer_flag |= 0x4000u; + Enemy_Phantoon *E0 = Get_Phantoon(0); + E0->base.instruction_timer = 1; + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->base.instruction_timer = 1; + E0->base.current_instruction = addr_kKraid_Ilist_CC41; + E1->base.current_instruction = addr_kKraid_Ilist_CC91; + E0->base.properties |= kEnemyProps_Tangible; + E1->phant_var_F = 0; + Get_Phantoon(k + 128)->phant_var_B = 0; + } +} + +void Phantoon_FadeoutWithSwoop(uint16 k) { // 0xA7D6B9 + Phantoon_MoveInSwoopingPattern(k); + Phantoon_FadeOut(0xCu); + if (Get_Phantoon(0x40u)->phant_var_F) { + Enemy_Phantoon *E = Get_Phantoon(k); + E->phant_var_F = FUNC16(Phantoon_WaitAfterFadeOut); + E->phant_var_E = 120; + } +} + +void Phantoon_WaitAfterFadeOut(uint16 k) { // 0xA7D6D4 + Enemy_Phantoon *E = Get_Phantoon(k); + bool v2 = E->phant_var_E == 1; + bool v3 = (--E->phant_var_E & 0x8000u) != 0; + if (v2 || v3) + E->phant_var_F = FUNC16(Phantoon_MoveLeftOrRightAndPickEyeOpenPatt); +} + +void Phantoon_MoveLeftOrRightAndPickEyeOpenPatt(uint16 k) { // 0xA7D6E2 + Enemy_Phantoon *E = Get_Phantoon(0); + if ((NextRandom() & 1) != 0) { + E->phant_var_A = 136; + E->base.x_pos = 208; + } else { + E->phant_var_A = 399; + E->base.x_pos = 48; + } + E->base.y_pos = 96; + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->phant_var_C = 0; + E->phant_var_C = 1; + E->phant_var_B = 0; + E->phant_parameter_2 = 0; + Phantoon_PickPatternForRound2(); + Get_Phantoon(k)->phant_var_F = FUNC16(Phantoon_FadeInBeforeFigure8); + E1->phant_var_F = 0; +} + +void Phantoon_FadeInBeforeFigure8(uint16 k) { // 0xA7D72D + Phantoon_FadeIn(0xCu); + if (Get_Phantoon(0x40u)->phant_var_F) + Get_Phantoon(0)->phant_var_F = FUNC16(Phantoon_MovePhantoonInFigure8ThenOpenEye); +} + +void Phantoon_BecomeSolidAfterRainingFireballs(uint16 k) { // 0xA7D73F + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->phant_var_F = 0; + phantom_related_layer_flag &= ~0x4000u; + Enemy_Phantoon *E = Get_Phantoon(0); + E->base.instruction_timer = 1; + E1->base.instruction_timer = 1; + E->base.current_instruction = addr_kKraid_Ilist_CC47; + E1->base.current_instruction = addr_kKraid_Ilist_CC9D; + Get_Phantoon(k)->phant_var_F = FUNC16(Phantoon_FadeInDuringFireballRain); +} + +void Phantoon_FadeInDuringFireballRain(uint16 k) { // 0xA7D767 + Phantoon_FadeIn(1u); + if (Get_Phantoon(0x40u)->phant_var_F) { + Enemy_Phantoon *E = Get_Phantoon(0); + E->base.properties &= ~kEnemyProps_Tangible; + Get_Phantoon(k)->phant_var_F = FUNC16(Phantoon_FollowSamusWithEyeDuringFireballRain); + E->phant_var_E = 90; + } +} + +void Phantoon_FollowSamusWithEyeDuringFireballRain(uint16 k) { // 0xA7D788 + Enemy_Phantoon *EK = Get_Phantoon(k); + bool v2 = EK->phant_var_E == 1; + bool v3 = (--EK->phant_var_E & 0x8000u) != 0; + if (v2 || v3) { + Get_Phantoon(k + 128)->phant_var_B = 0; + Enemy_Phantoon *E2 = Get_Phantoon(0x80); + if (E2->phant_var_A) { + E2->phant_var_A = 0; + Get_Phantoon(0)->phant_parameter_2 = 1; + Phantoon_BeginSwoopingPattern(k); + } else { + EK->phant_var_F = FUNC16(Phantoon_FadeOutDuringFireballRain); + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->phant_var_F = 0; + Enemy_Phantoon *E0 = Get_Phantoon(0); + E0->base.instruction_timer = 1; + E1->base.instruction_timer = 1; + E0->base.current_instruction = addr_kKraid_Ilist_CC41; + E1->base.current_instruction = addr_kKraid_Ilist_CC91; + E0->base.properties |= kEnemyProps_Tangible; + phantom_related_layer_flag |= 0x4000u; + } + } +} + +void Phantoon_FadeOutDuringFireballRain(uint16 k) { // 0xA7D7D5 + Phantoon_FadeOut(0xCu); + if (Get_Phantoon(0x40u)->phant_var_F) { + Enemy_Phantoon *E = Get_Phantoon(k); + E->phant_var_F = FUNC16(Phantoon_SpawnRainingFireballs); + E->phant_var_E = g_word_A7CD63[NextRandom() & 7]; + } +} + +void Phantoon_SpawnRainingFireballs(uint16 k) { // 0xA7D7F7 + Enemy_Phantoon *EK = Get_Phantoon(k); + bool v2 = EK->phant_var_E == 1; + bool v3 = (--EK->phant_var_E & 0x8000u) != 0; + if (v2 || v3) { + uint16 a = NextRandom() & 7; + int v4 = (uint16)(8 * a) >> 1; + Enemy_Phantoon *E0 = Get_Phantoon(0); + E0->phant_var_A = g_word_A7CDAD[v4]; + E0->base.x_pos = g_word_A7CDAD[v4 + 1]; + E0->base.y_pos = g_word_A7CDAD[v4 + 2]; + Get_Phantoon(0x40u)->phant_var_C = 0; + EK->phant_var_F = FUNC16(Phantoon_BecomeSolidAfterRainingFireballs); + Phantoon_Func_6(k, a); + } +} + +void Phantoon_FadeOutBeforeFirstFireballRain(uint16 k) { // 0xA7D82A + Phantoon_FadeOut(0xCu); + Phantoon_AdjustSpeedAndMoveInFigure8(); + Phantoon_Func_7(k); + Enemy_Phantoon *E = Get_Phantoon(0x40u); + bool v2 = E->phant_var_A == 1; + bool v3 = (--E->phant_var_A & 0x8000u) != 0; + if (v2 || v3) { + Get_Phantoon(0x80)->phant_var_A = 0; + Get_Phantoon(k)->phant_var_F = FUNC16(Phantoon_BecomeSolidAfterRainingFireballs); + if (sign16(Get_Phantoon(0)->base.x_pos - 128)) + Phantoon_Func_6(k, 0); + else + Phantoon_Func_6(k, 2u); + } +} + +void Phantoon_FadeOutBeforeEnrage(uint16 k) { // 0xA7D85C + Phantoon_FadeOut(0xCu); + if (Get_Phantoon(0x40u)->phant_var_F) { + Enemy_Phantoon *E = Get_Phantoon(k); + E->phant_var_F = FUNC16(Phantoon_MoveEnragedPhantoonToTopCenter); + E->phant_var_E = 120; + } +} + +void Phantoon_MoveEnragedPhantoonToTopCenter(uint16 k) { // 0xA7D874 + Enemy_Phantoon *E = Get_Phantoon(k); + bool v2 = E->phant_var_E == 1; + bool v3 = (--E->phant_var_E & 0x8000u) != 0; + if (v2 || v3) { + E->phant_var_F = FUNC16(Phantoon_FadeInEnragedPhantoon); + Enemy_Phantoon *E = Get_Phantoon(0); + E->base.x_pos = 128; + E->base.y_pos = 32; + Get_Phantoon(0x40u)->phant_var_F = 0; + } +} + +void Phantoon_FadeInEnragedPhantoon(uint16 k) { // 0xA7D891 + Phantoon_FadeIn(0xCu); + Enemy_Phantoon *E = Get_Phantoon(0x40u); + if (E->phant_var_F) { + Get_Phantoon(0)->phant_var_F = FUNC16(Phantoon_Enraged); + Get_Phantoon(k)->phant_var_E = 4; + E->phant_var_F = 0; + } +} + +void Phantoon_Enraged(uint16 k) { // 0xA7D8AC + int16 v5; + int16 v8; + + Enemy_Phantoon *E = Get_Phantoon(k); + bool v2 = E->phant_var_E == 1; + bool v3 = (--E->phant_var_E & 0x8000u) != 0; + if (v2 || v3) { + if ((Get_Phantoon(0x40u)->phant_var_F & 1) != 0) { + v5 = 15; + do { + v8 = v5; + SpawnEnemyProjectileWithGfx(v5-- | 0x200, k, addr_kEproj_DestroyableFireballs); + } while ((int16)(v8 - 9) >= 0); + } else { + for (int i = 6; i >= 0; --i) + SpawnEnemyProjectileWithGfx(i | 0x200, k, addr_kEproj_DestroyableFireballs); + } + QueueSfx3_Max6(0x29u); + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + uint16 v7 = E1->phant_var_F + 1; + E1->phant_var_F = v7; + if (sign16(v7 - 8)) { + Get_Phantoon(k)->phant_var_E = 128; + } else { + E1->base.instruction_timer = 1; + E1->base.current_instruction = addr_kKraid_Ilist_CC91; + E1->phant_var_F = 0; + Get_Phantoon(k)->phant_var_F = FUNC16(Phantoon_FadeoutAfterEnrage); + } + } +} + +void Phantoon_FadeoutAfterEnrage(uint16 k) { // 0xA7D916 + Phantoon_FadeOut(0xCu); + if (Get_Phantoon(0x40u)->phant_var_F) { + Enemy_Phantoon *E = Get_Phantoon(k); + E->phant_var_F = FUNC16(Phantoon_WaitAfterFadeOut); + E->phant_var_E = 120; + } +} + +void Phantoon_CompleteSwoopAfterFatalShot(uint16 k) { // 0xA7D92E + Phantoon_ChangeEyeSpriteBasedOnSamusDist(); + Phantoon_MoveInSwoopingPattern(k); + uint16 x_pos = Get_Phantoon(0)->base.x_pos; + if (!sign16(x_pos - 96)) { + if (sign16(x_pos - 160)) + Get_Phantoon(k)->phant_var_F = FUNC16(Phantoon_DyingPhantoonFadeInOut); + } +} + +void Phantoon_DyingPhantoonFadeInOut(uint16 k) { // 0xA7D948 + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + if ((E1->phant_var_C & 1) != 0) { + Phantoon_FadeIn(0xCu); + if (!E1->phant_var_F) + return; + } else { + Phantoon_FadeOut(0xCu); + if (!E1->phant_var_F) + return; + } + E1->phant_var_F = 0; + uint16 v2 = E1->phant_var_C + 1; + E1->phant_var_C = v2; + if (!sign16(v2 - 10)) { + Enemy_Phantoon *E = Get_Phantoon(k); + E->phant_var_F = FUNC16(Phantoon_DyingPhantoonExplosions); + E->phant_var_E = 15; + Get_Phantoon(0x80)->phant_var_F = 0; + Get_Phantoon(0)->phant_var_A = 0; + } +} + +void Phantoon_DyingPhantoonExplosions(uint16 k) { // 0xA7D98B + Enemy_Phantoon *EK = Get_Phantoon(k); + bool v2 = EK->phant_var_E == 1; + bool v3 = (--EK->phant_var_E & 0x8000u) != 0; + if (v2 || v3) { + Enemy_Phantoon *E2 = Get_Phantoon(0x80); + uint16 v5 = 4 * E2->phant_var_F; + uint16 v6 = g_byte_A7DA1D[v5]; + if ((v6 & 0x80) != 0) + v6 |= 0xFF00u; + R18_ = v6; + Enemy_Phantoon *E0 = Get_Phantoon(0); + R18_ = v6 + E0->base.x_pos; + uint16 v8 = g_byte_A7DA1D[v5 + 1]; + if ((v8 & 0x80) != 0) + v8 |= 0xFF00u; + R20_ = v8; + R20_ = v8 + E0->base.y_pos; + uint16 v11 = g_byte_A7DA1D[v5 + 2]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, v11); + if (v11 == 29) + QueueSfx2_Max6(0x24u); + else + QueueSfx2_Max6(0x2Bu); + EK->phant_var_E = g_byte_A7DA1D[v5 + 3]; + uint16 v9 = E2->phant_var_F + 1; + E2->phant_var_F = v9; + if (!sign16(v9 - 13)) { + E2->phant_var_F = 5; + uint16 v10 = E0->phant_var_A + 1; + E0->phant_var_A = v10; + if (!sign16(v10 - 3)) + EK->phant_var_F = FUNC16(Phantoon_WavyDyingPhantoonAndCry); + } + } +} + +void Phantoon_WavyDyingPhantoonAndCry(uint16 k) { // 0xA7DA51 + Enemy_Phantoon *Phantoon; // r10 + + R22_ = g_word_A7CDA3; + sub_88E487(1u); + Get_Phantoon(0xC0u)->phant_var_D = 0; + Get_Phantoon(k)->phant_var_F = FUNC16(Phantoon_DyingFadeOut); + Phantoon = Get_Phantoon(0x40u); + Phantoon->phant_var_C = 2; + uint16 v2 = Get_Phantoon(0)->base.properties & ~(kEnemyProps_DisableSamusColl | kEnemyProps_Tangible | kEnemyProps_Invisible) | kEnemyProps_Tangible | kEnemyProps_Invisible; + Phantoon->base.properties = v2; + Get_Phantoon(0x80)->base.properties = v2; + Get_Phantoon(0xC0u)->base.properties = v2; + QueueSfx2_Max6(0x7Eu); +} + +void Phantoon_DyingFadeOut(uint16 k) { // 0xA7DA86 + R18_ = g_word_A7CD9F; + R20_ = g_word_A7CDA1; + Phantoon_Func_3(); + Enemy_Phantoon *E = Get_Phantoon(0x40u); + if (E->phant_var_C == 0xFFFF) { + Phantoon_FadeOut(0xCu); + if (E->phant_var_F) + Get_Phantoon(k)->phant_var_F = FUNC16(Phantoon_AlmostDead); + } else if ((nmi_frame_counter_word & 0xF) == 0) { + if (LOBYTE(E->phant_var_C) == 0xF2) { + E->phant_var_C = -1; + E->phant_var_F = 0; + } else { + uint8 v2 = LOBYTE(E->phant_var_C) + 16; + LOBYTE(E->phant_var_C) = v2; + reg_MOSAIC = v2; + } + } +} + +void Phantoon_AlmostDead(uint16 k) { // 0xA7DAD7 + reg_MOSAIC = 0; + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->phant_parameter_1 = 0; + phantom_related_layer_flag &= ~0x4000u; + Get_Phantoon(0xC0u)->phant_parameter_1 = -1; + Enemy_Phantoon *EK = Get_Phantoon(k); + EK->phant_var_F = FUNC16(Phantoon_Dead); + EK->phant_var_E = 60; + E1->phant_var_F = 0; + Enemy_Phantoon *E0 = Get_Phantoon(0); + E0->base.x_pos = 384; + E0->base.y_pos = 128; + for (int i = 1022; i >= 0; i -= 2) + tilemap_stuff[i >> 1] = 824; + uint16 v5 = vram_write_queue_tail; + gVramWriteEntry(vram_write_queue_tail)->size = 1024; + v5 += 2; + gVramWriteEntry(v5)->size = 0x2000; + v5 += 2; + LOBYTE(gVramWriteEntry(v5++)->size) = 126; + gVramWriteEntry(v5)->size = 18432; + vram_write_queue_tail = v5 + 2; +} + +void Phantoon_Dead(uint16 k) { // 0xA7DB3D + Enemy_Phantoon *EK = Get_Phantoon(k); + if (EK->phant_var_E) { + --EK->phant_var_E; + } else if ((nmi_frame_counter_word & 3) == 0) { + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->phant_var_D = 12; + if (Phantoon_Func_9() & 1) { + reg_TM |= 2u; + Enemy_ItemDrop_Phantoon(k); + Enemy_Phantoon *E0 = Get_Phantoon(0); + uint16 v4 = E0->base.properties | kEnemyProps_Deleted; + E0->base.properties = v4; + E1->base.properties = v4; + Get_Phantoon(0x80)->base.properties = v4; + Get_Phantoon(0xC0u)->base.properties = v4; + *(uint16 *)&boss_bits_for_area[area_index] |= 1u; + static const SpawnHardcodedPlmArgs unk_A7DB8D = { 0x00, 0x06, 0xb78b }; + SpawnHardcodedPlm(&unk_A7DB8D); + QueueMusic_Delayed8(3u); + } + } +} + +uint8 Phantoon_Func_8(void) { // 0xA7DB9A + Enemy_Phantoon *E = Get_Phantoon(0x40u); + if ((uint16)(E->phant_var_D + 1) >= E->phant_var_E) { + for (int i = 0; i < 0x20u; i += 2) { + palette_buffer[(i >> 1) + 112] = + Phantoon_Func_10_CalculateNthTransitionColorFromXtoY(E->phant_var_E, + palette_buffer[(i >> 1) + 112], + g_word_A7CA41[i >> 1]); + } + ++E->phant_var_E; + return 0; + } else { + E->phant_var_E = 0; + return 1; + } +} + +uint8 Phantoon_SetColorBasedOnHp(void) { // 0xA7DBD5 + PairU16 Entry; + + Enemy_Phantoon *E = Get_Phantoon(0x40u); + if ((uint16)(E->phant_var_D + 1) >= E->phant_var_E) { + uint16 v2 = 0, v7; + do { + v7 = v2; + Entry = Phantoon_SetColorBasedOnHp_FindEntry(v2); + uint16 j = Entry.j; + uint16 v5 = palette_buffer[(Entry.k >> 1) + 112]; + palette_buffer[(v7 >> 1) + 112] = Phantoon_Func_10_CalculateNthTransitionColorFromXtoY(E->phant_var_E, v5, j); + v2 = v7 + 2; + } while ((uint16)(v7 + 2) < 0x20u); + ++E->phant_var_E; + return 0; + } else { + E->phant_var_E = 0; + return 1; + } +} + +PairU16 Phantoon_SetColorBasedOnHp_FindEntry(uint16 k) { // 0xA7DC0F + R24_ = k; + R18_ = 312; + R20_ = 312; + R22_ = 0; + do { + if ((int16)(R20_ - Get_Phantoon(cur_enemy_index)->base.health) >= 0) + break; + R20_ += R18_; + ++R22_; + } while (sign16(R22_ - 7)); + uint16 *v1 = (uint16 *)RomPtr_A7(R24_ + g_off_A7DC4A[R22_]); + return MakePairU16(R24_, *v1); +} + +uint8 Phantoon_Func_9(void) { // 0xA7DC5A + Enemy_Phantoon *E = Get_Phantoon(0x40u); + if ((uint16)(E->phant_var_D + 1) >= E->phant_var_E) { + for (int i = 0; i < 0xE0u; i += 2) { + palette_buffer[i >> 1] = Phantoon_Func_10_CalculateNthTransitionColorFromXtoY( + E->phant_var_E, + palette_buffer[i >> 1], + g_word_A7CA61[i >> 1]); + } + ++E->phant_var_E; + return 0; + } else { + E->phant_var_E = 0; + return 1; + } +} + +uint16 Phantoon_Func_10_CalculateNthTransitionColorFromXtoY(uint16 a, uint16 k, uint16 j) { // 0xA7DC95 + int16 v3; + char v4; // t0 + int16 v8; + + uint16 v7 = Phantoon_CalculateNthTransitionColorComponentFromXtoY(a, k & 0x1F, j & 0x1F); + v8 = v7 | (32 * Phantoon_CalculateNthTransitionColorComponentFromXtoY(a, (k >> 5) & 0x1F, (j >> 5) & 0x1F)); + v3 = 4 + * Phantoon_CalculateNthTransitionColorComponentFromXtoY( + a, + ((uint16)(k >> 2) >> 8) & 0x1F, + ((uint16)(j >> 2) >> 8) & 0x1F); + v4 = v3; + LOBYTE(v3) = HIBYTE(v3); + HIBYTE(v3) = v4; + return v8 | v3; +} + +uint16 Phantoon_CalculateNthTransitionColorComponentFromXtoY(uint16 a, uint16 k, uint16 j) { // 0xA7DCF1 + int16 v4; + int16 v9; + + if (!a) + return k; + v4 = a - 1; + Enemy_Phantoon *E = Get_Phantoon(0x40u); + if (v4 == E->phant_var_D) + return j; + R20_ = v4 + 1; + R18_ = j - k; + uint8 v6 = abs16(R18_); + uint16 RegWord = SnesDivide(v6 << 8, LOBYTE(E->phant_var_D) - R20_ + 1); + R18_ = sign16(R18_) ? -RegWord : RegWord; + LOBYTE(v9) = HIBYTE(k); + HIBYTE(v9) = k; + return (uint16)(R18_ + v9) >> 8; +} + +void Phantoon_Hurt(void) { // 0xA7DD3F + PairU16 Entry; + + Enemy_Phantoon *E0 = Get_Phantoon(0); + if (E0->base.flash_timer == 8) { +LABEL_4:; + uint16 v1 = 30; + do { + Entry = Phantoon_SetColorBasedOnHp_FindEntry(v1); + palette_buffer[(Entry.k >> 1) + 112] = Entry.j; + v1 = Entry.k - 2; + } while ((int16)(Entry.k - 2) >= 0); + Enemy_Phantoon *E3 = Get_Phantoon(0x80); + E3->phant_parameter_2 = LOBYTE(E3->phant_parameter_2); + return; + } + if ((E0->base.frame_counter & 2) == 0) { + if (!HIBYTE(Get_Phantoon(0x80)->phant_parameter_2)) + return; + goto LABEL_4; + } + if (!HIBYTE(Get_Phantoon(0x80)->phant_parameter_2)) { + for (int i = 30; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 112] = 0x7FFF; + Enemy_Phantoon *E3 = Get_Phantoon(0x80); + E3->phant_parameter_2 |= 0x100u; + } +} + +void Phantoon_Touch(void) { // 0xA7DD95 + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); +} + +void Phantoon_Shot(void) { // 0xA7DD9B + + Enemy_Phantoon *E0 = Get_Phantoon(0); + if (sign16(E0->phant_var_F + 0x26B8)) { + uint16 v1 = cur_enemy_index; + Enemy_Phantoon *EK = Get_Phantoon(cur_enemy_index); + uint16 health = EK->base.health; + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + R18_ = health; + if (!EK->base.health) { + QueueSfx2_Max6(0x73u); + Get_Phantoon(0x80)->phant_parameter_2 = 1; + E0->base.properties |= kEnemyProps_Tangible; + Phantoon_StartDeathSequence(v1); + return; + } + if ((EK->base.ai_handler_bits & 2) != 0) { + QueueSfx2_Max6(0x73u); + uint16 phanto_var_F = EK->phant_var_F; + if (phanto_var_F != (uint16)FUNC16(Phantoon_EyeFollowsSamusUntilTimerRunsOut) + && phanto_var_F != (uint16)FUNC16(Phantoon_FollowSamusWithEyeDuringFireballRain)) { + if (phanto_var_F != (uint16)FUNC16(Phantoon_IsSwooping)) { +LABEL_20: + Get_Phantoon(0x80)->phant_parameter_2 = 2; + return; + } + R18_ -= EK->base.health; + if (sign16(R18_ - 300) + || (projectile_type[collision_detection_index] & 0xF00) != 512) { + Enemy_Phantoon *E2 = Get_Phantoon(v1 + 0x80); + uint16 v7 = R18_ + E2->phant_var_B; + E2->phant_var_B = v7; + if (!sign16(v7 - 300)) + EK->phant_var_E = 1; + goto LABEL_20; + } + goto LABEL_23; + } + R18_ -= EK->base.health; + if (!sign16(R18_ - 300) + && (projectile_type[collision_detection_index] & 0xF00) == 512) { +LABEL_23: + EK->phant_var_F = FUNC16(Phantoon_FadeOutBeforeEnrage); + goto LABEL_22; + } + Enemy_Phantoon *E2; + E2 = Get_Phantoon(v1 + 0x80); + uint16 v9; + v9 = R18_ + E2->phant_var_B; + E2->phant_var_B = v9; + if (!sign16(v9 - 300)) { + EK->phant_var_F = FUNC16(Phantoon_FadeoutWithSwoop); +LABEL_22: + EK->phant_var_E = 0; + Get_Phantoon(0x80)->phant_var_A = 0; + E2->phant_var_B = 0; + phantom_related_layer_flag |= 0x4000u; + E0->base.instruction_timer = 1; + Enemy_Phantoon *E1 = Get_Phantoon(0x40u); + E1->base.instruction_timer = 1; + E0->base.current_instruction = addr_kKraid_Ilist_CC41; + E1->base.current_instruction = addr_kKraid_Ilist_CC91; + E0->base.properties |= kEnemyProps_Tangible; + E1->phant_var_F = 0; + goto LABEL_20; + } + uint16 v10 = NextRandom() & 7; + Get_Phantoon(0x40u)->phant_var_B = *(g_byte_A7CDA5 + v10); + Get_Phantoon(0xC0u)->phant_parameter_2 = v10; + Enemy_Phantoon *E2x = Get_Phantoon(0x80); + E2x->phant_parameter_2 = 1; + if (!E2x->phant_var_A) { + E2x->phant_var_A = 1; + if (!sign16(EK->phant_var_E - 16)) + EK->phant_var_E = 16; + } + } + } +} + +void Etecoon_Init(void) { // 0xA7E912 + Enemy_Etecoon *E = Get_Etecoon(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A7; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kEtecoon_Ilist_E8CE; + E->etecoon_var_F = FUNC16(Etecoon_Func_4); + E->etecoon_var_E = -1; +} + +void Etecoon_Main(void) { // 0xA7E940 + Enemy_Etecoon *E = Get_Etecoon(cur_enemy_index); + if (HIBYTE(E->etecoon_parameter_2)) + E->etecoon_parameter_2 -= 256; + else + CallEnemyPreInstr(E->etecoon_var_F | 0xA70000); +} + +void Etecoon_Func_1(uint16 k) { // 0xA7E958 + if (earthquake_timer) { + Enemy_Etecoon *E = Get_Etecoon(k); + E->etecoon_parameter_2 = LOBYTE(E->etecoon_parameter_2) | 0x8000; + E->base.instruction_timer += 128; + } +} + +uint8 Etecoon_Func_2(uint16 k) { // 0xA7E974 + Enemy_Etecoon *E = Get_Etecoon(k); + R20_ = E->etecoon_var_C; + R18_ = E->etecoon_var_D; + return Enemy_MoveRight_IgnoreSlopes(k) & 1; +} + +uint8 Etecoon_Func_3(uint16 k) { // 0xA7E983 + Enemy_Etecoon *E = Get_Etecoon(k); + R20_ = E->etecoon_var_A; + R18_ = E->etecoon_var_B; + if (sign16(E->etecoon_var_A - 5)) { + uint16 etecoo_var_B = E->etecoon_var_B; + bool v3 = __CFADD__uint16(samus_y_subaccel, etecoo_var_B); + E->etecoon_var_B = samus_y_subaccel + etecoo_var_B; + E->etecoon_var_A += samus_y_accel + v3; + } + return Enemy_MoveDown(k) & 1; +} + +void Etecoon_Func_4(uint16 k) { // 0xA7E9AF + if (!door_transition_flag_enemies) { + Enemy_Etecoon *E = Get_Etecoon(k); + if ((E->etecoon_var_E & 0x8000u) == 0) { + bool v2 = E->etecoon_var_E == 1; + bool v3 = (--E->etecoon_var_E & 0x8000u) != 0; + if (v2 || v3) { + E->base.current_instruction = addr_kEtecoon_Ilist_E854; + E->etecoon_var_F = FUNC16(Etecoon_Func_5); + E->etecoon_var_E = 11; + } + } else if (IsSamusWithinEnemy_Y(k, 0x80)) { + if ((E->etecoon_parameter_2 & 3) == 0) + QueueSfx2_Max15(0x35u); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kEtecoon_Ilist_E8D6; + E->etecoon_var_E = 256; + } + } +} + +void Etecoon_Func_5(uint16 k) { // 0xA7EA00 + Enemy_Etecoon *E = Get_Etecoon(k); + bool v2 = E->etecoon_var_E == 1; + bool v3 = (--E->etecoon_var_E & 0x8000u) != 0; + if (v2 || v3) { + E->etecoon_var_A = g_word_A7E900; + E->etecoon_var_B = g_word_A7E902; + E->base.current_instruction += 2; + E->base.instruction_timer = 1; + E->etecoon_var_F = FUNC16(Etecoon_Func_6); + if (!sign16(samus_x_pos - 256)) + QueueSfx2_Max6(0x33u); + } +} + +void Etecoon_Func_6(uint16 k) { // 0xA7EA37 + if (Etecoon_Func_3(k) & 1) { + Enemy_Etecoon *E = Get_Etecoon(k); + if ((E->etecoon_var_A & 0x8000u) == 0) { + if (IsSamusWithinEnemy_Y(k, 0x40u) && IsSamusWithinEnemy_X(k, g_word_A7E910)) { + uint16 v2 = DetermineDirectionOfSamusFromEnemy(); + if (sign16(v2 - 5)) { + E->base.current_instruction = addr_kEtecoon_Ilist_E81E; + E->etecoon_parameter_1 = 0; + } else { + E->base.current_instruction = addr_kEtecoon_Ilist_E876; + E->etecoon_parameter_1 = 1; + } + E->etecoon_var_E = 32; + E->base.instruction_timer = 1; + E->etecoon_var_F = FUNC16(Etecoon_Func_7); + } else { + E->etecoon_var_E = 11; + E->etecoon_var_F = FUNC16(Etecoon_Func_5); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kEtecoon_Ilist_E854; + } + } else { + E->etecoon_var_A = 0; + E->etecoon_var_B = 0; + E->base.instruction_timer = 3; + E->base.current_instruction = addr_stru_A7E862; + } + } +} + +void Etecoon_Func_7(uint16 k) { // 0xA7EAB5 + Enemy_Etecoon *E = Get_Etecoon(k); + bool v2 = E->etecoon_var_E == 1; + bool v3 = (--E->etecoon_var_E & 0x8000u) != 0; + if (v2 || v3) { + E->base.current_instruction += 2; + E->base.instruction_timer = 1; + if (E->etecoon_parameter_1) { + E->etecoon_var_C = g_word_A7E908; + E->etecoon_var_D = g_word_A7E90A; + E->etecoon_var_F = FUNC16(Etecoon_Func_9); + } else { + E->etecoon_var_C = g_word_A7E90C; + E->etecoon_var_D = g_word_A7E90E; + E->etecoon_var_F = FUNC16(Etecoon_Func_8); + } + E->etecoon_var_A = g_word_A7E900; + E->etecoon_var_B = g_word_A7E902; + } +} + +void Etecoon_Func_8(uint16 k) { // 0xA7EB02 + if (Etecoon_Func_2(k) & 1) { + Enemy_Etecoon *E = Get_Etecoon(k); + E->etecoon_var_C = g_word_A7E908; + E->etecoon_var_D = g_word_A7E90A; + E->etecoon_var_F = FUNC16(Etecoon_Func_9); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_stru_A7E880; + E->etecoon_parameter_1 = 1; + } +} + +void Etecoon_Func_9(uint16 k) { // 0xA7EB2C + R20_ = 32; + R18_ = 0; + if (EnemyFunc_BBBF(k) & 1) { + Enemy_Etecoon *E = Get_Etecoon(k); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_stru_A7E898; + E->etecoon_var_F = FUNC16(Etecoon_Func_10); + } else { + Etecoon_Func_2(k); + } +} + +void Etecoon_Func_10(uint16 k) { // 0xA7EB50 + Etecoon_Func_1(k); + if (Etecoon_Func_2(k) & 1) { + Enemy_Etecoon *E = Get_Etecoon(k); + if (E->etecoon_parameter_1) { + E->base.current_instruction = addr_kEtecoon_Ilist_E870; + E->etecoon_parameter_1 = 0; + } else { + E->base.current_instruction = addr_kEtecoon_Ilist_E8C8; + E->etecoon_parameter_1 = 1; + } + E->base.instruction_timer = 1; + E->etecoon_var_F = FUNC16(Etecoon_Func_11); + E->etecoon_var_E = 8; + if (!sign16(samus_x_pos - 256)) + QueueSfx2_Max6(0x32u); + } else if (Etecoon_Func_3(k) & 1) { + Enemy_Etecoon *E = Get_Etecoon(k); + if (E->etecoon_parameter_1) + E->base.current_instruction = addr_kEtecoon_Ilist_E854; + else + E->base.current_instruction = addr_kEtecoon_Ilist_E8AC; + E->base.instruction_timer = 1; + E->etecoon_var_E = 11; + E->etecoon_var_F = FUNC16(Etecoon_Func_12); + E->etecoon_var_A = g_word_A7E900; + E->etecoon_var_B = g_word_A7E902; + } +} + +void Etecoon_Func_11(uint16 k) { // 0xA7EBCD + Etecoon_Func_1(k); + Enemy_Etecoon *E = Get_Etecoon(k); + bool v2 = E->etecoon_var_E == 1; + bool v3 = (--E->etecoon_var_E & 0x8000u) != 0; + if (v2 || v3) { + if (E->etecoon_parameter_1) { + E->base.current_instruction = addr_kEtecoon_Ilist_E894; + E->etecoon_var_C = g_word_A7E908; + E->etecoon_var_D = g_word_A7E90A; + } else { + E->base.current_instruction = addr_kEtecoon_Ilist_E83C; + E->etecoon_var_C = g_word_A7E90C; + E->etecoon_var_D = g_word_A7E90E; + } + E->base.instruction_timer = 1; + E->etecoon_var_F = FUNC16(Etecoon_Func_10); + E->etecoon_var_A = g_word_A7E900; + E->etecoon_var_B = g_word_A7E902; + } +} + +static Func_Y_V *const funcs_A2A79[3] = { Etecoon_Func_13, Etecoon_Func_14, Etecoon_Func_15 }; + +void Etecoon_Func_12(uint16 k) { // 0xA7EC1B + Enemy_Etecoon *E = Get_Etecoon(k); + bool v2 = E->etecoon_var_E == 1; + bool v3 = (--E->etecoon_var_E & 0x8000u) != 0; + if (v2 || v3) { + E->etecoon_var_A = g_word_A7E900; + E->etecoon_var_B = g_word_A7E902; + funcs_A2A79[LOBYTE(E->etecoon_parameter_2)](k); + Get_Etecoon(k)->base.instruction_timer = 1; + } +} + +void Etecoon_Func_13(uint16 j) { // 0xA7EC47 + Enemy_Etecoon *E = Get_Etecoon(j); + E->etecoon_var_F = FUNC16(Etecoon_Func_16); + E->base.current_instruction = addr_stru_A7E828; + E->etecoon_var_C = g_word_A7E90C; + E->etecoon_var_D = g_word_A7E90E; +} + +void Etecoon_Func_14(uint16 j) { // 0xA7EC61 + Enemy_Etecoon *E = Get_Etecoon(j); + E->etecoon_var_F = FUNC16(Etecoon_Func_17); + E->base.current_instruction = addr_stru_A7E880; + E->etecoon_var_C = g_word_A7E908; + E->etecoon_var_D = g_word_A7E90A; +} + +void Etecoon_Func_15(uint16 j) { // 0xA7EC7B + Enemy_Etecoon *E = Get_Etecoon(j); + E->etecoon_var_F = FUNC16(Etecoon_Func_22); + E->base.current_instruction += 2; + E->etecoon_var_C = g_word_A7E908; + E->etecoon_var_D = g_word_A7E90A; +} + +void Etecoon_Func_16(uint16 k) { // 0xA7EC97 + Etecoon_Func_2(k); + Enemy_Etecoon *E = Get_Etecoon(k); + if (sign16(E->base.x_pos - 537)) { + E->etecoon_var_E = 11; + E->etecoon_var_F = FUNC16(Etecoon_Func_23); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kEtecoon_Ilist_E854; + } +} + +void Etecoon_Func_17(uint16 k) { // 0xA7ECBB + Etecoon_Func_2(k); + Enemy_Etecoon *E = Get_Etecoon(k); + if (!sign16(E->base.x_pos - 600)) { + E->etecoon_var_E = 11; + E->etecoon_var_F = FUNC16(Etecoon_Func_23); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kEtecoon_Ilist_E854; + } +} + +void Etecoon_Func_18(uint16 k) { // 0xA7ECDF + Etecoon_Func_2(k); + Enemy_Etecoon *E = Get_Etecoon(k); + if (!sign16(E->base.x_pos - 600)) { + E->etecoon_var_F = FUNC16(Etecoon_Func_19); + E->etecoon_var_A = g_word_A7E904; + E->etecoon_var_B = g_word_A7E906; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_stru_A7E898; + } +} + +void Etecoon_Func_19(uint16 k) { // 0xA7ED09 + Etecoon_Func_2(k); + Etecoon_Func_3(k); + Enemy_Etecoon *E = Get_Etecoon(k); + if (!sign16(E->base.x_pos - 680)) { + E->base.instruction_timer = 1; + E->base.current_instruction = addr_stru_A7E880; + E->etecoon_var_F = FUNC16(Etecoon_Func_20); + } +} + +void Etecoon_Func_20(uint16 k) { // 0xA7ED2A + Etecoon_Func_2(k); + Enemy_Etecoon *E = Get_Etecoon(k); + if (!sign16(E->base.x_pos - 840)) { + E->base.instruction_timer = 1; + E->base.current_instruction = addr_stru_A7E898; + E->etecoon_var_F = FUNC16(Etecoon_Func_21); + E->etecoon_var_A = -1; + E->etecoon_var_B = g_word_A7E906; + } +} + +void Etecoon_Func_21(uint16 k) { // 0xA7ED54 + Etecoon_Func_2(k); + if (Etecoon_Func_3(k) & 1) { + Enemy_Etecoon *E = Get_Etecoon(k); + E->etecoon_var_E = 11; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kEtecoon_Ilist_E854; + E->etecoon_var_F = FUNC16(Etecoon_Func_23); + } +} + +void Etecoon_Func_22(uint16 k) { // 0xA7ED75 + Etecoon_Func_1(k); + if (Etecoon_Func_3(k) & 1) { + Enemy_Etecoon *E = Get_Etecoon(k); + if ((E->etecoon_var_A & 0x8000u) == 0) { + E->etecoon_var_E = 11; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kEtecoon_Ilist_E854; + if ((E->etecoon_parameter_2 & 2) != 0 && (sign16(E->base.x_pos - 832))) + E->etecoon_var_F = FUNC16(Etecoon_Func_24); + else + E->etecoon_var_F = FUNC16(Etecoon_Func_23); + } else { + E->etecoon_var_A = 0; + E->etecoon_var_B = 0; + E->base.instruction_timer = 3; + E->base.current_instruction = addr_stru_A7E862; + } + } +} + +void Etecoon_Func_23(uint16 k) { // 0xA7EDC7 + Etecoon_Func_1(k); + Enemy_Etecoon *E = Get_Etecoon(k); + bool v2 = E->etecoon_var_E == 1; + bool v3 = (--E->etecoon_var_E & 0x8000u) != 0; + if (v2 || v3) { + uint16 v4 = E->etecoon_parameter_1 + 256; + E->etecoon_parameter_1 = v4; + if (sign16((v4 & 0xFF00) - 1024) + || (E->etecoon_parameter_1 = LOBYTE(E->etecoon_parameter_1), (E->etecoon_parameter_2 & 2) != 0)) { + E->etecoon_var_F = FUNC16(Etecoon_Func_22); + E->base.current_instruction += 2; + } else { + E->etecoon_var_F = FUNC16(Etecoon_Func_25); + E->base.current_instruction = addr_stru_A7E880; + E->etecoon_var_C = g_word_A7E908; + E->etecoon_var_D = g_word_A7E90A; + } + E->etecoon_var_A = g_word_A7E900; + E->etecoon_var_B = g_word_A7E902; + E->base.instruction_timer = 1; + if (!sign16(samus_x_pos - 256)) + QueueSfx2_Max6(0x33u); + } +} + +void Etecoon_Func_24(uint16 k) { // 0xA7EE3E + Etecoon_Func_1(k); + Enemy_Etecoon *E = Get_Etecoon(k); + bool v2 = E->etecoon_var_E == 1; + bool v3 = (--E->etecoon_var_E & 0x8000u) != 0; + if (v2 || v3) { + if (IsSamusWithinEnemy_Y(k, 0x40u) && IsSamusWithinEnemy_X(k, 0x30u)) { + E->base.current_instruction = addr_stru_A7E880; + E->etecoon_var_F = FUNC16(Etecoon_Func_18); + } else { + E->etecoon_var_A = g_word_A7E900; + E->etecoon_var_B = g_word_A7E902; + E->base.current_instruction += 2; + E->etecoon_var_F = FUNC16(Etecoon_Func_22); + if (!sign16(samus_x_pos - 256)) + QueueSfx2_Max6(0x33u); + } + E->base.instruction_timer = 1; + } +} + +void Etecoon_Func_25(uint16 k) { // 0xA7EE9A + Etecoon_Func_2(k); + Enemy_Etecoon *E = Get_Etecoon(k); + if (!sign16(E->base.x_pos - 600)) { + E->etecoon_var_F = FUNC16(Etecoon_Func_26); + E->base.instruction_timer = 1; + E->base.current_instruction = addr_stru_A7E898; + } +} + +void Etecoon_Func_26(uint16 k) { // 0xA7EEB8 + Etecoon_Func_2(k); + if (Etecoon_Func_3(k) & 1) { + Enemy_Etecoon *E = Get_Etecoon(k); + E->etecoon_var_C = g_word_A7E90C; + E->etecoon_var_D = g_word_A7E90E; + E->etecoon_var_F = FUNC16(Etecoon_Func_8); + E->etecoon_var_A = g_word_A7E900; + E->etecoon_var_B = g_word_A7E902; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_stru_A7E828; + } +} + +void Dachora_Init(void) { // 0xA7F4DD + int16 dachor_parameter_1; + + Enemy_Dachora *E = Get_Dachora(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A7; + E->base.instruction_timer = 1; + E->base.timer = 0; + dachor_parameter_1 = E->dachor_parameter_1; + if (dachor_parameter_1 < 0) { + if ((dachor_parameter_1 & 1) != 0) + E->base.current_instruction = addr_kDachora_Ilist_F4B9; + else + E->base.current_instruction = addr_kDachora_Ilist_F3F7; + E->dachor_var_F = FUNC16(Dachora_Func_12); + } else { + if (dachor_parameter_1) + E->base.current_instruction = addr_kDachora_Ilist_F45B; + else + E->base.current_instruction = addr_kDachora_Ilist_F399; + E->dachor_var_F = FUNC16(Dachora_Func_2); + } +} + +void Dachora_Main(void) { // 0xA7F52E + Enemy_Dachora *E = Get_Dachora(cur_enemy_index); + CallEnemyPreInstr(E->dachor_var_F | 0xA70000); +} +#define g_off_A7F55F ((uint16*)RomPtr(0xa7f55f)) +void Dachora_Func_1(uint16 j, uint16 k) { // 0xA7F535 + uint16 v3; + + *(VoidP *)((char *)&R0_.addr + 1) = 32256; + Enemy_Dachora *E = Get_Dachora(k); + LOBYTE(v3) = HIBYTE(E->base.palette_index); + HIBYTE(v3) = E->base.palette_index; + R0_.addr = g_off_A7F55F[v3 >> 1]; + uint16 v5 = 0; + do { + uint16 *v6 = (uint16 *)RomPtr_A7(j); + IndirWriteWord(&R0_, v5, *v6); + j += 2; + v5 += 2; + } while ((int16)(v5 - 32) < 0); +} + +void Dachora_Func_2(uint16 k) { // 0xA7F570 + R20_ = 1; + R18_ = 0; + Enemy_MoveDown(k); + if (IsSamusWithinEnemy_Y(k, 0x40u) && IsSamusWithinEnemy_X(k, g_word_A7F4C9)) { + Enemy_Dachora *E = Get_Dachora(k); + if (E->dachor_parameter_1) + E->base.current_instruction = addr_kDachora_Ilist_F48B; + else + E->base.current_instruction = addr_kDachora_Ilist_F3C9; + E->base.instruction_timer = 1; + E->dachor_var_F = FUNC16(Dachora_Func_3); + E->dachor_var_A = g_word_A7F4CD; + QueueSfx2_Max15(0x1Du); + } +} + +void Dachora_Func_3(uint16 k) { // 0xA7F5BC + Enemy_Dachora *E = Get_Dachora(k); + if (E->dachor_var_A-- == 1) { + if (E->dachor_parameter_1) { + E->base.current_instruction = addr_kDachora_Ilist_F407; + E->dachor_var_F = FUNC16(Dachora_Func_5); + } else { + E->base.current_instruction = addr_kDachora_Ilist_F345; + E->dachor_var_F = FUNC16(Dachora_Func_4); + } + E->base.instruction_timer = 1; + E->dachor_var_E = 1; + } +} + +void Dachora_Func_4(uint16 k) { // 0xA7F5ED + Dachora_Func_6(k); + R20_ = ~R20_; + bool v1 = R18_ == 0; + R18_ = -R18_; + if (v1) + ++R20_; + Enemy_Dachora *E = Get_Dachora(k); + if (Enemy_MoveRight_IgnoreSlopes(k) & 1 || (EnemyFunc_C8AD(k), sign16(E->base.x_pos - 96))) { + E->base.current_instruction = addr_kDachora_Ilist_F407; + E->dachor_var_F = FUNC16(Dachora_Func_5); + E->dachor_var_E = 1; + E->dachor_parameter_1 = 1; + E->base.instruction_timer = 1; + E->dachor_var_A = 0; + E->dachor_var_B = 0; + Dachora_Func_1(addr_kDachora_Palette, k); + } +} + +void Dachora_Func_5(uint16 k) { // 0xA7F65E + Dachora_Func_6(k); + Enemy_Dachora *E = Get_Dachora(k); + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + QueueSfx2_Max15(0x71u); + E->base.current_instruction = addr_kDachora_Ilist_F345; + E->dachor_var_F = FUNC16(Dachora_Func_4); + E->dachor_parameter_1 = 0; + E->dachor_var_A = 0; + Dachora_Func_1(addr_kDachora_Palette, k); +LABEL_4: + E->dachor_var_E = 0; + E->dachor_var_B = 0; + E->base.instruction_timer = 1; + return; + } + EnemyFunc_C8AD(k); + if (!sign16(E->base.x_pos - 1152)) { + E->base.current_instruction = addr_kDachora_Ilist_F4B3; + E->dachor_var_F = FUNC16(Dachora_Func_7); + E->dachor_var_A = g_word_A7F4CF; + E->base.y_pos += 8; + QueueSfx2_Max6(0x3Du); + goto LABEL_4; + } +} + +void Dachora_Func_6(uint16 k) { // 0xA7F6D5 + Enemy_Dachora *E = Get_Dachora(k); + if ((int16)(E->dachor_var_A - g_word_A7F4D5) >= 0) { + if (E->dachor_var_E == 1) + QueueSfx2_Max6(0x39u); + uint16 v2 = E->dachor_var_E - 1; + E->dachor_var_E = v2; + if (!(uint8)v2) { + Dachora_Func_1(g_off_A7F787[(uint16)(2 * HIBYTE(E->dachor_var_E)) >> 1], k); + uint16 v3 = E->dachor_var_E + 272; + E->dachor_var_E = v3; + if (!sign16(v3 - 1040)) + E->dachor_var_E = 784; + } + } + R20_ = 1; + R18_ = 0; + Enemy_MoveDown(k); + if ((int16)(E->dachor_var_A - g_word_A7F4D5) >= 0 && (int16)(E->dachor_var_B - g_word_A7F4D7) >= 0) { + uint16 v4 = g_word_A7F4D5; + E->dachor_var_A = g_word_A7F4D5; + R20_ = v4; + uint16 v5 = g_word_A7F4D7; + E->dachor_var_B = g_word_A7F4D7; + R18_ = v5; + return; + } + uint16 dachor_var_B = E->dachor_var_B; + bool v7 = __CFADD__uint16(g_word_A7F4DB, dachor_var_B); + uint16 v8 = g_word_A7F4DB + dachor_var_B; + E->dachor_var_B = v8; + R18_ = v8; + uint16 v9 = g_word_A7F4D9 + v7 + E->dachor_var_A; + E->dachor_var_A = v9; + R20_ = v9; + if (v9 == 4) { + if (R18_) + return; + goto LABEL_12; + } + if (v9 == 8 && !R18_) { +LABEL_12: + E->base.current_instruction += 28; + } +} + +void Dachora_Func_7(uint16 k) { // 0xA7F78F + Dachora_Func_10(k); + Enemy_Dachora *E = Get_Dachora(k); + if (E->dachor_var_A-- == 1) { + E->base.current_instruction += 2; + E->base.instruction_timer = 1; + E->dachor_var_F = FUNC16(Dachora_Func_8); + Enemy_Dachora *E1 = Get_Dachora(k + 64); + E1->dachor_var_A = 0; + E1->dachor_var_D = 0; + Get_Dachora(k + 128)->dachor_var_D = 0; + Get_Dachora(k + 192)->dachor_var_D = 0; + Get_Dachora(k + 256)->dachor_var_D = 0; + E->dachor_var_C = 0; + E->dachor_var_D = 0; + E->base.y_pos -= 8; + QueueSfx2_Max6(0x3Bu); + if (E->dachor_parameter_1) { + Get_Dachora(k + 64)->base.current_instruction = addr_kDachora_Ilist_F4B9; + Get_Dachora(k + 128)->base.current_instruction = addr_kDachora_Ilist_F4B9; + Get_Dachora(k + 192)->base.current_instruction = addr_kDachora_Ilist_F4B9; + Get_Dachora(k + 256)->base.current_instruction = addr_kDachora_Ilist_F4B9; + } else { + Get_Dachora(k + 64)->base.current_instruction = addr_kDachora_Ilist_F3F7; + Get_Dachora(k + 128)->base.current_instruction = addr_kDachora_Ilist_F3F7; + Get_Dachora(k + 192)->base.current_instruction = addr_kDachora_Ilist_F3F7; + Get_Dachora(k + 256)->base.current_instruction = addr_kDachora_Ilist_F3F7; + } + Get_Dachora(k + 64)->base.instruction_timer = 1; + Get_Dachora(k + 128)->base.instruction_timer = 1; + Get_Dachora(k + 192)->base.instruction_timer = 1; + Get_Dachora(k + 256)->base.instruction_timer = 1; + } +} + +void Dachora_Func_8(uint16 k) { // 0xA7F806 + Dachora_Func_10(k); + Dachora_Func_9(k); + Enemy_Dachora *E = Get_Dachora(k); + uint16 dachor_var_D = E->dachor_var_D; + bool v3 = __CFADD__uint16(samus_y_subaccel, dachor_var_D); + E->dachor_var_D = samus_y_subaccel + dachor_var_D; + E->dachor_var_C += samus_y_accel + v3; + uint16 dachor_var_B = E->dachor_var_B; + v3 = __CFADD__uint16(E->dachor_var_D, dachor_var_B); + uint16 v5 = E->dachor_var_D + dachor_var_B; + E->dachor_var_B = v5; + R18_ = v5; + uint16 v6 = E->dachor_var_C + v3 + E->dachor_var_A; + E->dachor_var_A = v6; + R20_ = v6; + if (!sign16(v6 - 15)) + R20_ = 15; + R20_ = ~R20_; + bool v7 = R18_ == 0; + R18_ = -R18_; + if (v7) + ++R20_; + if (Enemy_MoveDown(k) & 1) { + if (E->dachor_parameter_1) { + E->base.current_instruction = addr_kDachora_Ilist_F3FF; + E->dachor_parameter_1 = 0; + } else { + E->base.current_instruction = addr_kDachora_Ilist_F4C1; + E->dachor_parameter_1 = 1; + } + E->dachor_var_F = FUNC16(Dachora_Func_11); + E->base.instruction_timer = 1; + E->dachor_var_A = 0; + E->dachor_var_B = 0; + E->dachor_var_E = 0; + Dachora_Func_1(addr_kDachora_Palette, k); + QueueSfx2_Max6(0x3Cu); + } +} + +void Dachora_Func_9(uint16 k) { // 0xA7F89A + + Enemy_Dachora *EK = Get_Dachora(k); + Enemy_Dachora *E1 = Get_Dachora(k + 64); + uint16 dachor_var_A = E1->dachor_var_A; + if (dachor_var_A) { + E1->dachor_var_A = dachor_var_A - 1; + } else { + E1->dachor_var_A = g_word_A7F4D1; + if (E1->dachor_var_D) { + Enemy_Dachora *E2 = Get_Dachora(k + 128); + if (E2->dachor_var_D) { + Enemy_Dachora *E3 = Get_Dachora(k + 192); + if (E3->dachor_var_D) { + Enemy_Dachora *E4 = Get_Dachora(k + 256); + if (!E4->dachor_var_D) { + E4->base.x_pos = EK->base.x_pos; + E4->base.y_pos = EK->base.y_pos; + E4->dachor_var_D = g_word_A7F4D3; + } + } else { + E3->base.x_pos = EK->base.x_pos; + E3->base.y_pos = EK->base.y_pos; + E3->dachor_var_D = g_word_A7F4D3; + } + } else { + E2->base.x_pos = EK->base.x_pos; + E2->base.y_pos = EK->base.y_pos; + E2->dachor_var_D = g_word_A7F4D3; + } + } else { + E1->base.x_pos = EK->base.x_pos; + E1->base.y_pos = EK->base.y_pos; + E1->dachor_var_D = g_word_A7F4D3; + } + } +} + +void Dachora_Func_10(uint16 k) { // 0xA7F90A + Enemy_Dachora *E = Get_Dachora(k); + Dachora_Func_1(g_off_A7F92D[(uint16)(2 * HIBYTE(E->dachor_var_E)) >> 1], k); + uint16 v2 = E->dachor_var_E + 256; + E->dachor_var_E = v2; + if (!sign16(v2 - 1024)) + E->dachor_var_E = 0; +} + +void Dachora_Func_11(uint16 k) { // 0xA7F935 + Enemy_Dachora *E = Get_Dachora(k); + uint16 dachor_var_B = E->dachor_var_B; + bool v3 = __CFADD__uint16(samus_y_subaccel, dachor_var_B); + uint16 v4 = samus_y_subaccel + dachor_var_B; + E->dachor_var_B = v4; + R18_ = v4; + uint16 v5 = samus_y_accel + v3 + E->dachor_var_A; + E->dachor_var_A = v5; + R20_ = v5; + if (!sign16(v5 - 10)) { + R20_ = 10; + R18_ = 0; + } + if (Enemy_MoveDown(k) & 1) { + if (E->dachor_parameter_1) { + E->base.current_instruction = addr_kDachora_Ilist_F407; + E->dachor_var_F = FUNC16(Dachora_Func_5); + } else { + E->base.current_instruction = addr_kDachora_Ilist_F345; + E->dachor_var_F = FUNC16(Dachora_Func_4); + } + E->base.instruction_timer = 1; + E->dachor_var_A = 0; + E->dachor_var_B = 0; + } +} + +void Dachora_Func_12(uint16 k) { // 0xA7F98C + Enemy_Dachora *E = Get_Dachora(k); + uint16 dachor_var_D = E->dachor_var_D; + if (!dachor_var_D) + goto LABEL_6; + E->dachor_var_D = dachor_var_D - 1; + if ((k & 0x40) != 0) { + if ((nmi_frame_counter_word & 1) == 0) + goto LABEL_6; + } else if ((nmi_frame_counter_word & 1) != 0) { +LABEL_6: + E->base.properties |= kEnemyProps_Invisible; + return; + } + E->base.properties &= ~kEnemyProps_Invisible; +} diff --git a/src/sm_a8.c b/src/sm_a8.c new file mode 100644 index 0000000..7eee71a --- /dev/null +++ b/src/sm_a8.c @@ -0,0 +1,4565 @@ +// Enemy AI - inc. ki-hunter + +#include "ida_types.h" +#include "variables.h" +#include "sm_rtl.h" +#include "funcs.h" +#include "enemy_types.h" + +static const int16 g_word_A890CA[4] = { -8, 8, 0, 0 }; +static const int16 g_word_A890D2[4] = { 0, 0, -8, 8 }; +#define g_off_A890DA ((uint16*)RomPtr(0xa890da)) +static const uint16 g_word_A89050 = 0x80; +static const uint16 g_word_A89052 = 0xb0; +static const uint16 g_word_A89054 = 0x80; +static const uint16 g_word_A89056 = 0x80; + +static const uint16 g_word_A89A9C = 0x10; +static const uint16 g_word_A89A9E = 0x40; +static const uint16 g_word_A89AA0 = 0x1800; +static const uint16 g_word_A89AA2 = 1; +static const uint16 g_word_A89AA4 = 0x78; +static const uint16 g_word_A89AA6 = 0x78; +static const uint16 g_word_A89AA8[18] = { 0xffc0, 0xffc0, 0, 0xffc0, 0x40, 0, 0xffc0, 0, 0, 0, 0x40, 0, 0xffc0, 0x40, 0, 0x40, 0x40, 0x40 }; +static const uint16 g_word_A89ACC[17] = { 1, 8, 1, 8, 1, 7, 1, 7, 2, 6, 2, 6, 3, 5, 3, 5, 0xffff }; +static const uint16 kWreckedShipGhost_Palette[16] = { 0x3800, 0x57ff, 0x42f7, 0x929, 0xa5, 0x4f5a, 0x36b5, 0x2610, 0x1dce, 0x1df, 0x1f, 0x18, 0xa, 0x6b9, 0xea, 0x45 }; +static const uint16 g_word_A89D32 = 1; +static const uint16 g_word_A89D34 = 1; + +#define g_word_A8A0A7 (*(uint16*)RomPtr(0xa8a0a7)) +#define g_word_A8A0A9 (*(uint16*)RomPtr(0xa8a0a9)) +#define g_word_A8A0AB (*(uint16*)RomPtr(0xa8a0ab)) +#define g_word_A8A0AD (*(uint16*)RomPtr(0xa8a0ad)) +#define g_word_A8A0B3 (*(uint16*)RomPtr(0xa8a0b3)) +#define g_word_A8A0B5 (*(uint16*)RomPtr(0xa8a0b5)) +#define g_word_A8A0B7 (*(uint16*)RomPtr(0xa8a0b7)) +#define g_word_A8A0B9 (*(uint16*)RomPtr(0xa8a0b9)) +#define g_word_A8A0BB (*(uint16*)RomPtr(0xa8a0bb)) +#define g_word_A8A0BD (*(uint16*)RomPtr(0xa8a0bd)) +#define g_word_A8A0C3 (*(uint16*)RomPtr(0xa8a0c3)) +#define g_word_A8A0C5 (*(uint16*)RomPtr(0xa8a0c5)) + +#define g_off_A8A097 ((uint16*)RomPtr(0xa8a097)) +#define kNorfairLavaMan_Palette ((uint16*)RomPtr(0xa8ac1c)) +#define g_word_A8AF79 ((uint16*)RomPtr(0xa8af79)) +#define g_word_A8AF55 ((uint16*)RomPtr(0xa8af55)) +#define g_off_A8AF67 ((uint16*)RomPtr(0xa8af67)) + +#define kBeetom_Ilist_B74E ((uint16*)RomPtr(0xa8b74e)) +static const int16 g_word_A8C277[3] = { -12, -16, -20 }; +static const int16 g_word_A8C27D[3] = { -20, -16, -12 }; +static const uint16 g_word_A8C19F = 0x40; +static const uint16 g_word_A8C1A1[12] = { 0, 1, 2, 3, 2, 1, 0, 0xffff, 0xfffe, 0xfffd, 0xfffe, 0xffff }; +static const uint16 g_word_A8C1B9 = 0; +static const uint16 g_word_A8C1BB = 0; +static const uint16 g_word_A8C1BD = 0; +static const uint16 g_word_A8C1BF = 0; +static const uint16 g_word_A8C1C1 = 1; +static const uint16 g_word_A8C1C3 = 0; +static const uint16 g_word_A8C1C5 = 0xffff; +static const uint16 g_word_A8C1C7 = 0x8000; + +#define g_off_A8C599 ((uint16*)RomPtr(0xa8c599)) +#define g_off_A8CC30 ((uint16*)RomPtr(0xa8cc30)) +static const int16 g_word_A8CCC1[31] = { + 0x1f, 0x18, 0xf, 8, 0x40, + 0x18, 0xf, 8, 0x1f, 0x10, + 0xf, 8, 0x1f, 0x18, 0x10, + 8, 0x1f, 0x18, 0xf, 0x40, + 0xf, 8, 0x1f, 0x18, 0x10, + 0x18, 0xf, 8, 0x1f, 0x10, + -1, +}; +static const int16 g_word_A8D871[10] = { + 0xc0, 0xe0, 0, 0x20, 0x40, + 0x40, 0x60, 0x80, 0xa0, 0xc0, +}; +static const int16 g_word_A8D885[8] = { + 0x3ff, 0x4ff, 0x5ff, 0x6ff, 0x7ff, + 0x8ff, 0x9ff, 0xaff, +}; +static const int16 g_word_A8D895[26] = { + 3, 1, 4, 1, 5, + 2, 6, 2, 7, 2, + 8, 3, 9, 3, 0xa, + 4, 0xb, 4, 0xc, 5, + 0xd, 5, 0xe, 6, 0xf, + 6, +}; +static const uint16 g_word_A8DCC7 = 0x50; +static const uint16 g_word_A8DCCB = 0x70; +#define g_off_A8E380 ((uint16*)RomPtr(0xa8e380)) +#define g_off_A8E682 ((uint16*)RomPtr(0xa8e682)) +#define g_off_A8E688 ((uint16*)RomPtr(0xa8e688)) +#define g_word_A8E7CC ((uint16*)RomPtr(0xa8e7cc)) +#define g_off_A8F3B0 ((uint16*)RomPtr(0xa8f3b0)) +static const uint16 g_word_A8F180 = 0x60; +static const uint16 g_word_A8F182 = 0xe000; +static const uint16 g_word_A8F184 = 0; +static const uint8 g_byte_A8F186 = 0x30; + +uint16 EnemyInstr_DisableOffScreenProcessing_A8(uint16 k, uint16 j) { // 0xA8817D + EnemyData *v2 = gEnemyData(k); + v2->properties &= ~kEnemyProps_ProcessedOffscreen; + return j; +} +uint16 EnemyInstr_EnableOffScreenProcessing_A8(uint16 k, uint16 j) { // 0xA88173 + EnemyData *v2 = gEnemyData(k); + v2->properties |= kEnemyProps_ProcessedOffscreen; + return j; +} +uint16 EnemyInstr_SetTimer_A8(uint16 k, uint16 j) { // 0xA88123 + uint16 v2 = *(uint16 *)RomPtr_A8(j); + gEnemyData(k)->timer = v2; + return j + 2; +} +uint16 EnemyInstr_Sleep_A8(uint16 k, uint16 j) { // 0xA8812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + +uint16 EnemyInstr_Goto_A8(uint16 k, uint16 j) { // 0xA880ED + return *(uint16 *)RomPtr_A8(j); +} + +uint16 EnemyInstr_DecTimerAndGoto2_A8(uint16 k, uint16 j) { // 0xA88110 + EnemyData *v2 = gEnemyData(k); + if (v2->timer-- == 1) + return j + 2; + else + return EnemyInstr_Goto_A8(k, j); +} + +void Enemy_GrappleReact_NoInteract_A8(void) { // 0xA88000 + SwitchEnemyAiToMainAi(); +} + +void Enemy_GrappleReact_KillEnemy_A8(void) { // 0xA8800A + EnemyGrappleDeath(); +} + +void Enemy_GrappleReact_CancelBeam_A8(void) { // 0xA8800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_GrappleReact_SamusLatchesNoInvinc_A8(void) { // 0xA88014 + SamusLatchesOnWithGrappleNoInvinc(); +} + +void Enemy_GrappleReact_HurtSamus_A8(void) { // 0xA8801E + SamusHurtFromGrapple(); +} + +void Enemy_NormalTouchAI_A8(void) { // 0xA88023 + NormalEnemyTouchAi(); +} + +void Enemy_NormalShotAI_A8(void) { // 0xA8802D + NormalEnemyShotAi(); +} + +void Enemy_NormalPowerBombAI_A8(void) { // 0xA88037 + NormalEnemyPowerBombAi(); +} + +void Enemy_NormalFrozenAI_A8(void) { // 0xA88041 + NormalEnemyFrozenAI(); +} + +uint16 MiniDraygon_Instr_2(uint16 k, uint16 j) { // 0xA8878F + QueueSfx2_Max6(0x5Eu); + return j; +} + +uint16 MiniDraygon_Instr_1(uint16 k, uint16 j) { // 0xA8879B + if (gEnemySpawnData(cur_enemy_index)[30].cause_of_death == (uint16)addr_kMiniDraygon_Ilist_870B) + Get_MiniDraygon(cur_enemy_index)->mdn_var_F = -8; + else + Get_MiniDraygon(cur_enemy_index)->mdn_var_F = 8; + return j; +} + +uint16 MiniDraygon_Instr_3(uint16 k, uint16 j) { // 0xA887B6 + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + if (gEnemySpawnData(cur_enemy_index)[30].cause_of_death == (uint16)addr_kMiniDraygon_Ilist_870B) { + ++E->mdn_var_F; + } else { + --E->mdn_var_F; + } + return j; +} + +uint16 MiniDraygon_Instr_4(uint16 k, uint16 j) { // 0xA887CB + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + E->mdn_var_0C = 0; + E->mdn_var_0B = 0; + E->mdn_var_C = FUNC16(MiniDraygon_Func_8); + return j; +} + +void MiniDraygon_Init(void) { // 0xA887E0 + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + if (E->mdn_parameter_1) { + MiniDraygon_Func_2(); + E->base.layer = 4; + } else { + MiniDraygon_Func_1(); + uint16 v2 = 8 * LOBYTE(E->mdn_parameter_2); + int v3 = v2 >> 1; + E->mdn_var_04 = kCommonEnemySpeeds_Linear[v3]; + E->mdn_var_03 = kCommonEnemySpeeds_Linear[v3 + 1]; + E->mdn_var_06 = kCommonEnemySpeeds_Linear[v3 + 2]; + E->mdn_var_05 = kCommonEnemySpeeds_Linear[v3 + 3]; + E->mdn_var_E = HIBYTE(Get_MiniDraygon(v2)->mdn_parameter_2) >> 1; + } + E->mdn_var_00 = 0; + E->mdn_var_01 = 0; + E->mdn_var_C = FUNC16(MiniDraygon_Func_4); +} + +void MiniDraygon_Func_1(void) { // 0xA88838 + Get_MiniDraygon(cur_enemy_index)->mdn_var_B = (GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0; + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + E->mdn_var_02 = addr_kMiniDraygon_Ilist_86A7; + if (E->mdn_var_B) + E->mdn_var_02 = addr_kMiniDraygon_Ilist_870B; + MiniDraygon_Func_12(); +} + +void MiniDraygon_Func_2(void) { // 0xA88866 + int v0 = cur_enemy_index >> 1; + uint16 v1 = enemy_drawing_queue_sizes[v0 + 1]; + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + E->mdn_var_B = v1; + if (v1) { + E->base.x_pos = enemy_drawing_queue[v0 + 91] + 4; + E->base.y_pos = enemy_drawing_queue[v0 + 93] + 10; + E->mdn_var_02 = addr_kMiniDraygon_Ilist_8727; + } else { + E->base.x_pos = enemy_drawing_queue[v0 + 91] - 4; + E->base.y_pos = enemy_drawing_queue[v0 + 93] + 10; + E->mdn_var_02 = addr_kMiniDraygon_Ilist_86C3; + } + MiniDraygon_Func_12(); +} + +void EvirProjectile_Init(void) { // 0xA888B0 + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + E->mdn_var_02 = addr_kMiniDraygon_Ilist_876F; + MiniDraygon_Func_12(); + int v2 = cur_enemy_index >> 1; + E->base.palette_index = enemy_drawing_queue[v2 + 73]; + E->base.vram_tiles_index = enemy_drawing_queue[v2 + 74]; + MiniDraygon_Func_3(); + E->mdn_var_01 = 0; + E->mdn_var_0C = 0; + E->mdn_var_0B = 0; + E->mdn_var_F = 0; + E->mdn_var_C = FUNC16(MiniDraygon_Func_8); +} + +void MiniDraygon_Func_3(void) { // 0xA888E5 + int v0 = cur_enemy_index >> 1; + uint16 v1 = enemy_drawing_queue[v0 + 83]; + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + E->mdn_var_B = v1; + if (v1) + E->base.x_pos = enemy_drawing_queue[v0 + 59] + 4; + else + E->base.x_pos = enemy_drawing_queue[v0 + 59] - 4; + E->base.y_pos = enemy_drawing_queue[v0 + 61] + 18; +} + + +void CallMiniDraygonFunc(uint32 ea) { + switch (ea) { + case fnMiniDraygon_Func_4: MiniDraygon_Func_4(); return; + case fnMiniDraygon_Func_8: MiniDraygon_Func_8(); return; + case fnMiniDraygon_Func_9: MiniDraygon_Func_9(); return; + case fnMiniDraygon_Func_10: MiniDraygon_Func_10(); return; + default: Unreachable(); + } +} +void MiniDraygon_Main(void) { // 0xA8891B + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + CallMiniDraygonFunc(E->mdn_var_C | 0xA80000); +} + +void MiniDraygon_Func_4(void) { // 0xA88922 + if (Get_MiniDraygon(cur_enemy_index)->mdn_parameter_1) + MiniDraygon_Func_6(); + else + MiniDraygon_Func_5(); +} + +void MiniDraygon_Func_5(void) { // 0xA88933 + if (!Get_MiniDraygon(cur_enemy_index + 128)->mdn_var_0C) + MiniDraygon_Func_1(); + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + if (E->mdn_var_00) { + E->base.y_pos += E->mdn_var_04; + uint16 y_subpos = E->base.y_subpos; + bool v3 = __CFADD__uint16(E->mdn_var_03, y_subpos); + uint16 v6 = E->mdn_var_03 + y_subpos; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v6; + } else { + E->base.y_pos += E->mdn_var_06; + uint16 v2 = E->base.y_subpos; + bool v3 = __CFADD__uint16(E->mdn_var_05, v2); + uint16 v4 = E->mdn_var_05 + v2; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v4; + } + if ((--E->mdn_var_E & 0x8000u) != 0) { + E->mdn_var_E = HIBYTE(E->mdn_parameter_2); + E->mdn_var_00 ^= 1u; + } +} + +void MiniDraygon_Func_6(void) { // 0xA88997 + MiniDraygon_Func_2(); +} + + +void EvirProjectile_Main(void) { // 0xA8899E + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + if (!E->base.frozen_timer) { + if (E->mdn_var_0B) { + E->mdn_var_02 = addr_kMiniDraygon_Ilist_876F; + MiniDraygon_Func_12(); + } else if (E->mdn_var_0C) { + E->mdn_var_02 = addr_kMiniDraygon_Ilist_8775; + MiniDraygon_Func_12(); + } else { + MiniDraygon_Func_7(); + } + } + CallMiniDraygonFunc(E->mdn_var_C | 0xA80000); +} + +void MiniDraygon_Func_7(void) { // 0xA889D4 + if (IsSamusWithinEnemy_X(cur_enemy_index - 128, 0x80)) { + draw_enemy_layer = 4; + R22_ = -(uint8)(CalculateAngleOfSamusFromEnemy(cur_enemy_index) - 64); + uint16 v1 = CosineMult8bit(R22_); + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + E->mdn_var_07 = v1; + E->mdn_var_08 = loop_index; + E->mdn_var_09 = SineMult8bitNegative(R22_); + E->mdn_var_0A = loop_index; + E->mdn_var_02 = addr_kMiniDraygon_Ilist_876F; + MiniDraygon_Func_12(); + E->mdn_var_0B = 1; + E->mdn_var_C = FUNC16(MiniDraygon_Func_9); + } +} + +void MiniDraygon_Func_8(void) { // 0xA88A34 + MiniDraygon_Func_3(); +} + +void MiniDraygon_Func_9(void) { // 0xA88A3B + MiniDraygon_Func_11(); + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + E->base.x_pos += E->mdn_var_07; + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->mdn_var_08, x_subpos); + uint16 v4 = E->mdn_var_08 + x_subpos; + if (v3) + ++E->base.x_pos; + E->base.x_subpos = v4; + E->base.y_pos += E->mdn_var_09; + uint16 y_subpos = E->base.y_subpos; + v3 = __CFADD__uint16(E->mdn_var_0A, y_subpos); + uint16 v6 = E->mdn_var_0A + y_subpos; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v6; +} + +void MiniDraygon_Func_10(void) { // 0xA88A78 + if (!enemy_drawing_queue[(cur_enemy_index >> 1) + 77]) { + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + if (E->mdn_var_0C) { + MiniDraygon_Func_3(); + E->base.x_pos += E->mdn_var_F; + } else { + E->mdn_var_02 = addr_kMiniDraygon_Ilist_876F; + MiniDraygon_Func_12(); + E->mdn_var_0C = 0; + E->mdn_var_0B = 0; + E->mdn_var_C = FUNC16(MiniDraygon_Func_8); + } + } +} + +void MiniDraygon_Func_11(void) { // 0xA88AB1 + if (EnemyFunc_ADA3(0x100u)) { + if (!enemy_drawing_queue[(cur_enemy_index >> 1) + 77]) { + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + E->mdn_var_0B = 0; + E->mdn_var_0C = 1; + E->mdn_var_C = FUNC16(MiniDraygon_Func_10); + E->mdn_var_0C = 1; + E->mdn_var_02 = addr_kMiniDraygon_Ilist_8775; + MiniDraygon_Func_12(); + } + } +} + +void MiniDraygon_Func_12(void) { // 0xA88AE8 + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + uint16 mdn_var_02 = E->mdn_var_02; + if (mdn_var_02 != E->mdn_var_01) { + E->base.current_instruction = mdn_var_02; + E->mdn_var_01 = mdn_var_02; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void MiniDraygon_Touch(void) { // 0xA88B06 + Enemy_NormalTouchAI_A8(); + MiniDraygon_Func_13(); +} + +void MiniDraygon_Powerbomb(void) { // 0xA88B0C + Enemy_NormalPowerBombAI_A8(); + MiniDraygon_Func_13(); +} + +void MiniDraygon_Shot(void) { // 0xA88B12 + NormalEnemyShotAi(); + MiniDraygon_Func_13(); +} + +void MiniDraygon_Func_13(void) { // 0xA88B16 + Enemy_MiniDraygon *E = Get_MiniDraygon(cur_enemy_index); + Enemy_MiniDraygon *E1 = Get_MiniDraygon(cur_enemy_index + 64); + Enemy_MiniDraygon *E2 = Get_MiniDraygon(cur_enemy_index + 128); + if (!E->base.health) { + E1->base.properties |= 0x200u; + E2->base.properties |= 0x200u; + } + uint16 frozen_timer = E->base.frozen_timer; + if (frozen_timer) { + E1->base.frozen_timer = frozen_timer; + E1->base.ai_handler_bits |= 4u; + if (E2->mdn_var_C != (uint16)FUNC16(MiniDraygon_Func_9)) { + E2->base.ai_handler_bits |= 4u; + E2->base.frozen_timer = E->base.frozen_timer; + } + } +} + +void MorphBallEye_Init(void) { // 0xA89058 + Enemy_MorphBallEye *E = Get_MorphBallEye(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A8; + E->base.instruction_timer = 1; + E->base.timer = 0; + if ((E->mbee_parameter_2 & 0x8000u) != 0) { + int v1 = E->mbee_parameter_2 & 0xF; + E->base.x_pos += g_word_A890CA[v1]; + E->base.y_pos += g_word_A890D2[v1]; + E->mbee_var_F = FUNC16(nullsub_244); + E->base.current_instruction = g_off_A890DA[v1]; + for (int i = 510; i >= 0; i -= 2) + *(uint16 *)((char *)&g_word_7E9100 + (uint16)i) = 255; + } else { + E->mbee_var_F = FUNC16(MorphBallEye_Func_1); + if ((E->mbee_parameter_1 & 1) != 0) + E->base.current_instruction = addr_stru_A8900E; + else + E->base.current_instruction = addr_stru_A88FFC; + } +} + +void MorphBallEye_Main(void) { // 0xA890E2 + if ((collected_items & 4) != 0) { + Enemy_MorphBallEye *E = Get_MorphBallEye(cur_enemy_index); + CallEnemyPreInstr(E->mbee_var_F | 0xA80000); + } +} + +void MorphBallEye_Func_1(uint16 k) { // 0xA890F1 + if (IsSamusWithinEnemy_Y(k, g_word_A89054) && IsSamusWithinEnemy_X(k, g_word_A89050)) { + Enemy_MorphBallEye *E = Get_MorphBallEye(k); + E->mbee_var_E = 32; + E->base.instruction_timer = 1; + if ((E->mbee_parameter_1 & 1) != 0) + E->base.current_instruction = addr_kMorphBallEye_Ilist_9026; + else + E->base.current_instruction = addr_kMorphBallEye_Ilist_9014; + E->mbee_var_F = FUNC16(MorphBallEye_Func_2); + } +} + +void MorphBallEye_Func_2(uint16 k) { // 0xA8912E + Enemy_MorphBallEye *E = Get_MorphBallEye(k); + bool v2 = E->mbee_var_E == 1; + bool v3 = (--E->mbee_var_E & 0x8000u) != 0; + if (v2 || v3) { + QueueSfx2_Max6(0x17u); + SpawnMorphBallEyeBeamHdma(); + E->mbee_var_F = FUNC16(MorphBallEye_Func_3); + R18_ = samus_x_pos - E->base.x_pos; + R20_ = samus_y_pos - E->base.y_pos; + E->mbee_var_D = CalculateAngleFromXY(); + } +} + +void MorphBallEye_Func_3(uint16 k) { // 0xA89160 + Enemy_MorphBallEye *E = Get_MorphBallEye(k); + if (IsSamusWithinEnemy_Y(k, g_word_A89056) && IsSamusWithinEnemy_X(k, g_word_A89052)) { + R18_ = samus_x_pos - E->base.x_pos; + R20_ = samus_y_pos - E->base.y_pos; + uint16 v3 = CalculateAngleFromXY(); + E->mbee_var_D = v3; + E->base.current_instruction = ((uint8)(v3 & 0xF0) >> 2) - 28756; + } else { + QueueSfx2_Max6(0x71u); + E->mbee_var_C = 0; + E->mbee_var_E = 32; + if ((E->mbee_parameter_1 & 1) != 0) + E->base.current_instruction = addr_kMorphBallEye_Ilist_9002; + else + E->base.current_instruction = addr_kMorphBallEye_Ilist_8FF0; + E->mbee_var_F = FUNC16(MorphBallEye_Func_4); + } + E->base.instruction_timer = 1; +} + +void MorphBallEye_Func_4(uint16 k) { // 0xA891CE + Enemy_MorphBallEye *E = Get_MorphBallEye(k); + bool v2 = E->mbee_var_E == 1; + bool v3 = (--E->mbee_var_E & 0x8000u) != 0; + if (v2 || v3) + E->mbee_var_F = FUNC16(MorphBallEye_Func_1); +} + +uint16 Fune_Instr_2(uint16 k, uint16 j) { // 0xA89625 + QueueSfx2_Max9(0x1Fu); + return j; +} + +uint16 Fune_Instr_6(uint16 k, uint16 j) { // 0xA89631 + enemy_projectile_unk1995 = LOBYTE(Get_Fune(cur_enemy_index)->fune_parameter_2); + SpawnEnemyProjectileWithGfx(0, cur_enemy_index, addr_stru_86DFBC); + return j; +} + +uint16 Fune_Instr_7(uint16 k, uint16 j) { // 0xA8964A + enemy_projectile_unk1995 = LOBYTE(Get_Fune(cur_enemy_index)->fune_parameter_2); + SpawnEnemyProjectileWithGfx(1u, cur_enemy_index, addr_stru_86DFBC); + return j; +} + +uint16 Fune_Instr_1(uint16 k, uint16 j) { // 0xA89663 + enemy_projectile_unk1995 = LOBYTE(Get_Fune(cur_enemy_index)->fune_parameter_2); + SpawnEnemyProjectileWithGfx(0, cur_enemy_index, addr_stru_86DFCA); + return j; +} + +uint16 Fune_Instr_4(uint16 k, uint16 j) { // 0xA8967C + enemy_projectile_unk1995 = LOBYTE(Get_Fune(cur_enemy_index)->fune_parameter_2); + SpawnEnemyProjectileWithGfx(1u, cur_enemy_index, addr_stru_86DFCA); + return j; +} + +uint16 Fune_Instr_3(uint16 k, uint16 j) { // 0xA89695 + Enemy_Fune *E = Get_Fune(cur_enemy_index); + E->fune_var_A += 4; + E->fune_var_B = FUNC16(Fune_Func_1); + if (E->fune_var_D) + E->fune_var_B = FUNC16(Fune_Func_2); + return j; +} + +uint16 Fune_Instr_5(uint16 k, uint16 j) { // 0xA896B4 + Enemy_Fune *E = Get_Fune(cur_enemy_index); + E->fune_var_A += 4; + E->fune_var_B = FUNC16(Fune_Func_1); + if (E->fune_var_D) + E->fune_var_B = FUNC16(Fune_Func_2); + return j; +} + +void Fune_Init(void) { // 0xA896E3 + Enemy_Fune *E = Get_Fune(cur_enemy_index); + E->fune_var_A = addr_off_A896D7; + E->fune_var_B = FUNC16(Fune_Func_1); + uint16 v1 = E->fune_parameter_1 & 0xF; + E->fune_var_D = v1; + if (v1) { + E->fune_var_A = addr_off_A896DF; + E->fune_var_B = FUNC16(Fune_Func_2); + } + if ((E->fune_parameter_1 & 0xF0) != 0) { + ++E->fune_var_A; + ++E->fune_var_A; + } + Fune_Func_4(); + E->fune_var_C = HIBYTE(E->fune_parameter_2); + E->fune_var_F = HIBYTE(E->fune_parameter_1); + E->fune_var_E = 0; +} + +void CallFuneFunc(uint32 ea) { + switch (ea) { + case fnFune_Func_1: Fune_Func_1(); return; // 0xa89737 + case fnFune_Func_2: Fune_Func_2(); return; // 0xa8975c + case fnnullsub_247: return; // 0xa8978e + case fnnullsub_248: return; // 0xa8978f + default: Unreachable(); + } +} + +void Fune_Main(void) { // 0xA89730 + Enemy_Fune *E = Get_Fune(cur_enemy_index); + CallFuneFunc(E->fune_var_B | 0xA80000); +} + +void Fune_Func_1(void) { // 0xA89737 + Enemy_Fune *E = Get_Fune(cur_enemy_index); + if ((int16)(++E->fune_var_E - E->fune_var_F) >= 0) { + E->fune_var_A -= 4; + Fune_Func_4(); + E->fune_var_B = FUNC16(nullsub_247); + E->fune_var_E = 0; + } +} + +void Fune_Func_2(void) { // 0xA8975C + Enemy_Fune *E = Get_Fune(cur_enemy_index); + E->fune_var_00 = E->fune_var_A; + if (Fune_Func_3()) { + uint16 fune_var_00 = E->fune_var_00; + E->fune_var_A = fune_var_00; + fune_var_00 -= 4; + E->fune_var_00 = fune_var_00; + E->fune_var_A = fune_var_00; + Fune_Func_4(); + E->fune_var_B = FUNC16(nullsub_248); + } + E->fune_var_A = E->fune_var_00; +} + +uint16 Fune_Func_3(void) { // 0xA89790 + Enemy_Fune *E = Get_Fune(cur_enemy_index); + return IsSamusWithinEnemy_Y(cur_enemy_index, E->fune_var_C); +} + +void Fune_Func_4(void) { // 0xA8979B + Enemy_Fune *E = Get_Fune(cur_enemy_index); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = *(uint16 *)RomPtr_A8(E->fune_var_A); +} + +void WreckedShipGhost_Init(void) { // 0xA89AEE + int16 v2; + + Enemy_WreckedShipGhost *E = Get_WreckedShipGhost(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl | kEnemyProps_Tangible | kEnemyProps_Invisible; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kWreckedShipGhost_Ilist_9A8C; + E->wsgt_var_A = FUNC16(WreckedShipGhost_Func_6); + E->wsgt_var_B = g_word_A89AA4 + 160; + + LOBYTE(v2) = HIBYTE(E->base.palette_index); + HIBYTE(v2) = E->base.palette_index; + uint16 v3 = 16 * v2 + 256; + R18_ = 16; + do { + target_palettes[v3 >> 1] = 0; + v3 += 2; + --R18_; + } while ((R18_ & 0x8000u) == 0); +} + +void CallWreckedShipGhost(uint32 ea, uint16 k) { + switch (ea) { + case fnWreckedShipGhost_Func_1: WreckedShipGhost_Func_1(k); return; + case fnWreckedShipGhost_Func_2: WreckedShipGhost_Func_2(k); return; + case fnWreckedShipGhost_Func_4: WreckedShipGhost_Func_4(k); return; + case fnWreckedShipGhost_Func_5: WreckedShipGhost_Func_5(k); return; + case fnWreckedShipGhost_Func_6: WreckedShipGhost_Func_6(k); return; + case fnWreckedShipGhost_Func_7: WreckedShipGhost_Func_7(k); return; + default: Unreachable(); + } +} + +void WreckedShipGhost_Main(void) { // 0xA89B3C + Enemy_WreckedShipGhost *E = Get_WreckedShipGhost(cur_enemy_index); + CallWreckedShipGhost(E->wsgt_var_A | 0xA80000, cur_enemy_index); +} + +void WreckedShipGhost_Func_1(uint16 k) { // 0xA89B42 + int16 v1; + int16 v3; + int16 v7; + + WreckedShipGhost_Func_3(k); + v1 = 16; + Enemy_WreckedShipGhost *E = Get_WreckedShipGhost(cur_enemy_index); + LOBYTE(v3) = HIBYTE(E->base.palette_index); + HIBYTE(v3) = E->base.palette_index; + uint16 v4 = 16 * v3 + 256; + R18_ = 16; + do { + int v5 = v4 >> 1; + if (sign16((palette_buffer[v5] & 0x1F) - 31)) { + palette_buffer[v5] += 1057; + --v1; + } + v4 += 2; + --R18_; + } while (R18_); + if ((int16)(v1 - 16) >= 0) { + E->wsgt_var_A = FUNC16(WreckedShipGhost_Func_2); + LOBYTE(v7) = HIBYTE(E->base.palette_index); + HIBYTE(v7) = E->base.palette_index; + uint16 v8 = 16 * v7 + 256; + uint16 v9 = 0; + do { + target_palettes[v8 >> 1] = kWreckedShipGhost_Palette[v9 >> 1]; + v8 += 2; + v9 += 2; + } while ((int16)(v9 - 32) < 0); + } +} + +void WreckedShipGhost_Func_2(uint16 k) { // 0xA89BAD + uint16 v4 = WreckedShipGhost_Func_8(); + WreckedShipGhost_Func_3(cur_enemy_index); + Enemy_WreckedShipGhost *E = Get_WreckedShipGhost(cur_enemy_index); + if (!(E->wsgt_var_B | v4)) { + E->base.properties &= 0xFAFFu; + E->wsgt_var_A = FUNC16(WreckedShipGhost_Func_5); + E->wsgt_var_00 = E->base.y_pos; + E->wsgt_var_B = 1; + E->wsgt_var_C = 2; + E->wsgt_var_01 = 0; + E->wsgt_var_02 = g_word_A89AA2; + E->wsgt_var_B = g_word_A89AA6; + E->wsgt_var_05 = 4; + uint16 v2 = samus_x_pos; + E->wsgt_var_06 = samus_x_pos; + E->wsgt_var_07 = v2; + E->wsgt_var_08 = v2; + E->wsgt_var_09 = 12; + uint16 v3 = *(uint16 *)((char *)&samus_y_pos + cur_enemy_index); + E->wsgt_var_0A = v3; + E->wsgt_var_0B = v3; + E->wsgt_var_0C = v3; + E->wsgt_var_0D = g_word_A89A9E; + E->wsgt_var_0E = g_word_A89A9C; + } +} + +void WreckedShipGhost_Func_3(uint16 k) { // 0xA89C31 + int16 v5; + + Enemy_WreckedShipGhost *E = Get_WreckedShipGhost(k); + uint16 wsgt_var_B = E->wsgt_var_B; + if (!wsgt_var_B) + goto LABEL_6; + uint16 v3; + v3 = wsgt_var_B - 1; + E->wsgt_var_B = v3; + if (!v3) { + uint16 wsgt_var_C; + wsgt_var_C = E->wsgt_var_C; + v5 = g_word_A89ACC[wsgt_var_C >> 1]; + if (v5 < 0) { + E->wsgt_var_B = 0; + E->wsgt_var_C = 0; + return; + } + E->wsgt_var_B = v5; + E->wsgt_var_C = wsgt_var_C + 2; + if ((wsgt_var_C & 2) == 0) + LABEL_6: + E->base.properties &= ~kEnemyProps_Invisible; + } +} + +void WreckedShipGhost_Func_4(uint16 k) { // 0xA89C69 + if (!WreckedShipGhost_Func_8()) { + Enemy_WreckedShipGhost *E = Get_WreckedShipGhost(cur_enemy_index); + E->wsgt_var_A = FUNC16(WreckedShipGhost_Func_6); + E->base.properties |= kEnemyProps_Invisible; + E->wsgt_var_B = g_word_A89AA4; + } +} + +void WreckedShipGhost_Func_5(uint16 k) { // 0xA89C8A + int16 v8; + + Enemy_WreckedShipGhost *E = Get_WreckedShipGhost(k); + uint16 y_subpos = E->base.y_subpos; + bool v3 = __CFADD__uint16(E->wsgt_var_01, y_subpos); + E->base.y_subpos = E->wsgt_var_01 + y_subpos; + E->base.y_pos += E->wsgt_var_02 + v3; + uint16 wsgt_var_01 = E->wsgt_var_01; + uint16 v5; + if ((int16)(E->base.y_pos - E->wsgt_var_00) < 0) { + v3 = __CFADD__uint16(g_word_A89AA0, wsgt_var_01); + E->wsgt_var_01 = g_word_A89AA0 + wsgt_var_01; + v5 = v3 + E->wsgt_var_02; + } else { + v3 = wsgt_var_01 < g_word_A89AA0; + E->wsgt_var_01 = wsgt_var_01 - g_word_A89AA0; + v5 = E->wsgt_var_02 - v3; + } + E->wsgt_var_02 = v5; + uint16 v6 = E->wsgt_var_B - 1; + E->wsgt_var_B = v6; + if (!v6) { + E->wsgt_var_A = FUNC16(WreckedShipGhost_Func_4); + E->base.properties |= kEnemyProps_Tangible; + LOBYTE(v8) = HIBYTE(E->base.palette_index); + HIBYTE(v8) = E->base.palette_index; + uint16 v9 = 16 * v8 + 256; + R18_ = 16; + do { + target_palettes[v9 >> 1] = 0x7FFF; + v9 += 2; + --R18_; + } while ((R18_ & 0x8000u) == 0); + } +} + +void WreckedShipGhost_Func_6(uint16 k) { // 0xA89D13 + uint16 v3; + + Enemy_WreckedShipGhost *E = Get_WreckedShipGhost(k); + uint16 wsgt_var_B = E->wsgt_var_B; + if (!wsgt_var_B || (v3 = wsgt_var_B - 1, (E->wsgt_var_B = v3) == 0)) { + E->wsgt_var_B = 1; + E->wsgt_var_C = 2; + E->wsgt_var_A = FUNC16(WreckedShipGhost_Func_7); + } +} + +void WreckedShipGhost_Func_7(uint16 k) { // 0xA89D36 + int16 v2; + int16 v4; + int16 v7; + int16 v9; + + Enemy_WreckedShipGhost *E = Get_WreckedShipGhost(k); + if ((int16)(samus_x_pos - E->wsgt_var_07) < 0 + || (int16)(samus_x_pos - E->wsgt_var_08) >= 0 + || (v2 = *(uint16 *)((char *)&samus_y_pos + k), (int16)(v2 - E->wsgt_var_0B) < 0) + || (int16)(v2 - E->wsgt_var_0C) >= 0) { + E->wsgt_var_0D = g_word_A89A9E; + v4 = 0; + if ((int16)(samus_x_pos - E->wsgt_var_06) >= 0) { + if (samus_x_pos == E->wsgt_var_06) + v4 = 4; + else + v4 = 8; + } + if (v4 == E->wsgt_var_05) { + v7 = 0; + v9 = samus_y_pos - E->wsgt_var_0A; + if (v9 >= 0) { + if (v9) + v7 = 24; + else + v7 = 12; + } + if (v7 == E->wsgt_var_09) { + uint16 v10 = E->wsgt_var_0E - 1; + E->wsgt_var_0E = v10; + if (!v10) + goto LABEL_13; + } else { + E->wsgt_var_09 = v7; + E->wsgt_var_0E = g_word_A89A9C; + } + } else { + E->wsgt_var_05 = v4; + E->wsgt_var_0E = g_word_A89A9C; + } + } else { + uint16 v3; + v3 = E->wsgt_var_0D - 1; + E->wsgt_var_0D = v3; + if (!v3) { + E->wsgt_var_05 = 4; + E->wsgt_var_09 = 12; +LABEL_13: + E->wsgt_var_A = FUNC16(WreckedShipGhost_Func_1); + E->wsgt_var_0D = g_word_A89A9E; + E->wsgt_var_0E = g_word_A89A9C; + int v6 = (uint16)(E->wsgt_var_09 + E->wsgt_var_05) >> 1; + E->base.x_pos = g_word_A89AA8[v6] + *(uint16 *)((char *)&samus_x_pos + k); + E->base.y_pos = g_word_A89AA8[v6 + 1] + *(uint16 *)((char *)&samus_y_pos + k); + return; + } + } + uint16 v11 = samus_x_pos; + E->wsgt_var_06 = samus_x_pos; + E->wsgt_var_07 = v11 - g_word_A89D32; + E->wsgt_var_08 = g_word_A89D32 + samus_x_pos; + uint16 v13 = samus_y_pos; + E->wsgt_var_0A = samus_y_pos; + E->wsgt_var_0B = v13 - g_word_A89D34; + E->wsgt_var_0C = g_word_A89D34 + samus_y_pos; +} + +uint16 WreckedShipGhost_Func_8(void) { // 0xA89E88 + int16 v2; + int16 v5; + int16 v7; + int16 v9; + + uint16 v0 = 0; + if (!door_transition_flag_enemies) { + Enemy_WreckedShipGhost *E = Get_WreckedShipGhost(cur_enemy_index); + LOBYTE(v2) = HIBYTE(E->base.palette_index); + HIBYTE(v2) = E->base.palette_index; + uint16 v3 = 16 * v2 + 256; + R20_ = 16 * v2 + 288; + do { + int v4 = v3 >> 1; + if (target_palettes[v4] != palette_buffer[v4]) { + R18_ = target_palettes[v4] & 0x1F; + v5 = palette_buffer[v4] & 0x1F; + if (v5 != R18_) { + uint16 v6; + if ((int16)(v5 - R18_) >= 0) + v6 = v5 - 1; + else + v6 = v5 + 1; + R18_ = v6; + palette_buffer[v4] = v6 | palette_buffer[v4] & 0xFFE0; + ++v0; + } + R18_ = target_palettes[v4] & 0x3E0; + v7 = palette_buffer[v4] & 0x3E0; + if (v7 != R18_) { + uint16 v8; + if ((int16)(v7 - R18_) >= 0) + v8 = v7 - 32; + else + v8 = v7 + 32; + R18_ = v8; + palette_buffer[v4] = v8 | palette_buffer[v4] & 0xFC1F; + ++v0; + } + R18_ = target_palettes[v4] & 0x7C00; + v9 = palette_buffer[v4] & 0x7C00; + if (v9 != R18_) { + uint16 v10; + if ((int16)(v9 - R18_) >= 0) + v10 = v9 - 1024; + else + v10 = v9 + 1024; + R18_ = v10; + palette_buffer[v4] = v10 | palette_buffer[v4] & 0x83FF; + ++v0; + } + } + v3 += 2; + } while ((int16)(v3 - R20_) < 0); + } + return v0; +} + +uint16 YappingMaw_Instr_2(uint16 k, uint16 j) { // 0xA8A0C7 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + E->ymw_var_32 = g_word_A8A0AB; + E->ymw_var_33 = g_word_A8A0AD; + return j; +} + +uint16 YappingMaw_Instr_4(uint16 k, uint16 j) { // 0xA8A0D9 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + E->ymw_var_32 = g_word_A8A0C3; + E->ymw_var_33 = g_word_A8A0C5; + return j; +} + +uint16 YappingMaw_Instr_5(uint16 k, uint16 j) { // 0xA8A0EB + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + E->ymw_var_32 = g_word_A8A0B3; + E->ymw_var_33 = g_word_A8A0B5; + return j; +} + +uint16 YappingMaw_Instr_7(uint16 k, uint16 j) { // 0xA8A0FD + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + E->ymw_var_32 = g_word_A8A0BB; + E->ymw_var_33 = g_word_A8A0BD; + return j; +} + +uint16 YappingMaw_Instr_3(uint16 k, uint16 j) { // 0xA8A10F + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + E->ymw_var_32 = g_word_A8A0A7; + E->ymw_var_33 = g_word_A8A0A9; + return j; +} + +uint16 YappingMaw_Instr_6(uint16 k, uint16 j) { // 0xA8A121 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + E->ymw_var_32 = g_word_A8A0B7; + E->ymw_var_33 = g_word_A8A0B9; + return j; +} + +uint16 YappingMaw_Instr_1(uint16 k, uint16 j) { // 0xA8A133 + if (!Get_YappingMaw(cur_enemy_index)->ymw_var_36) + QueueSfx2_Max6(0x2Fu); + return j; +} + +void YappingMaw_Init(void) { // 0xA8A148 + int16 v1; + + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + E->ymw_var_0C = E->base.x_pos; + E->ymw_var_0D = E->base.y_pos; + E->ymw_var_00 = 0; + E->ymw_var_01 = 0; + E->ymw_var_02 = 0; + E->ymw_var_03 = 0; + E->ymw_var_04 = 0; + E->ymw_var_05 = 0; + E->ymw_var_06 = 0; + E->ymw_var_07 = 0; + E->ymw_var_30 = 0; + E->ymw_var_F = E->ymw_parameter_1; + E->ymw_var_E = 64; + E->base.current_instruction = addr_kYappingMaw_Ilist_9F6F; + R36 = 57; + R34 = 8; + if (!E->ymw_parameter_2) { + E->base.current_instruction = addr_kYappingMaw_Ilist_9FC7; + R36 = 56; + R34 = -8; + } + E->base.instruction_timer = 1; + E->base.timer = 0; + E->ymw_var_A = FUNC16(YappingMaw_Func_1); + E->ymw_var_45 = E->base.palette_index & 0xE00; + v1 = 3; + E->ymw_var_44 = 3; + do { + SpawnEnemyProjectileWithGfx(v1, cur_enemy_index, addr_kEproj_YappingMawsBody); + v1 = E->ymw_var_44 - 1; + E->ymw_var_44 = v1; + } while (v1 >= 0); + R18_ = E->base.x_pos; + R20_ = R34 + E->base.y_pos; + R22_ = R36; + uint16 v3 = E->base.vram_tiles_index | E->base.palette_index; + E->ymw_var_47 = v3; + R24_ = v3; + CreateSpriteAtPos(); + E->ymw_var_46 = R18_; +} + +void CallYappingMawFunc(uint32 ea) { + switch (ea) { + case fnYappingMaw_Func_1: YappingMaw_Func_1(); return; // 0xa8a235 + case fnYappingMaw_Func_2: YappingMaw_Func_2(); return; // 0xa8a28c + case fnYappingMaw_Func_8: YappingMaw_Func_8(); return; // 0xa8a445 + case fnYappingMaw_Func_11: YappingMaw_Func_11(); return; // 0xa8a68a + default: Unreachable(); + } +} + +void YappingMaw_Main(void) { // 0xA8A211 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + --E->ymw_var_35; + E->ymw_var_36 = CheckIfEnemyIsOnScreen(); + CallYappingMawFunc(E->ymw_var_A | 0xA80000); + YappingMaw_Func_15(); + YappingMaw_Func_14(); + YappingMaw_Func_13(); + YappingMaw_Func_12(); +} + +void YappingMaw_Func_1(void) { // 0xA8A235 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + draw_enemy_layer = E->base.x_pos; + enemy_drawing_queue_index = E->base.y_pos; + loop_index_end = samus_x_pos; + loop_index = samus_y_pos; + uint16 v1 = EnemyFunc_ACA8(); + uint16 v2 = Abs16(v1); + E->ymw_var_08 = v2; + if (sign16(v2 - 32)) { + E->ymw_var_35 = 48; + } else if ((int16)(v2 - E->ymw_var_F) < 0) { + if (!sign16(E->ymw_var_08 - 64)) + E->ymw_var_08 = 64; + E->ymw_var_0A = enemy_drawing_queue_base; + E->ymw_var_A = FUNC16(YappingMaw_Func_2); + } +} + +void YappingMaw_Func_2(void) { // 0xA8A28C + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + E->ymw_var_B = 0; + E->ymw_var_C = 0; + E->ymw_var_D = 0; + E->ymw_var_09 = E->ymw_var_08 >> 1; + uint16 v1 = (uint8)(64 - E->ymw_var_0A); + E->ymw_var_0B = v1; + if (sign16(v1 - 128)) + E->ymw_var_2F = 0; + else + E->ymw_var_2F = 1; + YappingMaw_Func_3(); + uint16 v2 = 2 * ((uint8)(E->ymw_var_0A + 16) >> 5); + E->ymw_var_34 = v2; + E->base.current_instruction = g_off_A8A097[v2 >> 1]; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->ymw_var_32 = *(uint16 *)((char *)&g_word_A8A0A7 + (uint16)(2 * v2)); + E->ymw_var_33 = *(uint16 *)((char *)&g_word_A8A0A9 + (uint16)(2 * v2)); + E->ymw_var_A = FUNC16(YappingMaw_Func_8); +} + +void YappingMaw_Func_3(void) { // 0xA8A310 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + draw_enemy_layer = E->ymw_var_09; + E->ymw_var_0E = YappingMaw_Func_16(0x80); + draw_enemy_layer = E->ymw_var_09 >> 1; + E->ymw_var_0F = YappingMaw_Func_17(0x80); +} + +void YappingMaw_Func_4(void) { // 0xA8A339 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + draw_enemy_layer = E->ymw_var_00; + E->ymw_var_10 = YappingMaw_Func_16(0); + E->ymw_var_11 = YappingMaw_Func_17(0); + E->ymw_var_27 = YappingMaw_Func_16(E->ymw_var_0B) - E->ymw_var_10; + E->ymw_var_28 = YappingMaw_Func_17(E->ymw_var_0B) - E->ymw_var_11; +} + +void YappingMaw_Func_5(void) { // 0xA8A37C + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + draw_enemy_layer = E->ymw_var_02; + E->ymw_var_10 = YappingMaw_Func_16(0); + E->ymw_var_11 = YappingMaw_Func_17(0); + E->ymw_var_29 = YappingMaw_Func_16(E->ymw_var_0B) - E->ymw_var_10; + E->ymw_var_2A = YappingMaw_Func_17(E->ymw_var_0B) - E->ymw_var_11; +} + +void YappingMaw_Func_6(void) { // 0xA8A3BF + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + draw_enemy_layer = E->ymw_var_04; + E->ymw_var_10 = YappingMaw_Func_16(0); + E->ymw_var_11 = YappingMaw_Func_17(0); + E->ymw_var_2B = YappingMaw_Func_16(E->ymw_var_0B) - E->ymw_var_10; + E->ymw_var_2C = YappingMaw_Func_17(E->ymw_var_0B) - E->ymw_var_11; +} + +void YappingMaw_Func_7(void) { // 0xA8A402 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + draw_enemy_layer = E->ymw_var_06; + E->ymw_var_10 = YappingMaw_Func_16(0); + E->ymw_var_11 = YappingMaw_Func_17(0); + E->ymw_var_2D = YappingMaw_Func_16(E->ymw_var_0B) - E->ymw_var_10; + E->ymw_var_2E = YappingMaw_Func_17(E->ymw_var_0B) - E->ymw_var_11; +} + +void YappingMaw_Func_8(void) { // 0xA8A445 + int16 v9; + int16 v11; // tt + int16 v13; // tt + int16 v16; + int16 v17; // tt + int16 v19; + int16 v20; // tt + int16 v22; + int16 v23; // tt + int16 v25; + int16 v26; // tt + int16 v28; + int16 v29; // tt + int16 v31; + int16 v32; // tt + uint16 v8; + + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + R20_ = E->ymw_var_B >> 2; + if (E->ymw_var_2F) { + bool v3 = __CFADD__uint16(R20_, 128); + v9 = R20_ + 128; + E->ymw_var_21 = R20_ + 128; + v11 = v3; + v3 = __CFADD__uint16(v3, v9); + uint16 v10 = v11 + v9; + v3 |= __CFADD__uint16(R20_, v10); + v10 += R20_; + E->ymw_var_22 = v10; + v13 = v3; + v3 = __CFADD__uint16(v3, v10); + uint16 v12 = v13 + v10; + v3 |= __CFADD__uint16(R20_, v12); + v12 += R20_; + E->ymw_var_23 = v12; + v8 = R20_ + v3 + v12; + } else { + uint16 v2 = 128 - R20_; + bool v3 = R20_ <= 0x80; + E->ymw_var_21 = 128 - R20_; + uint16 v5 = !v3 + R20_; + v3 = v2 < v5; + uint16 v4 = v2 - v5; + E->ymw_var_22 = v4; + uint16 v7 = v3 + R20_; + v3 = v4 < v7; + uint16 v6 = v4 - v7; + E->ymw_var_23 = v6; + v8 = v6 - (v3 + R20_); + } + E->ymw_var_24 = v8; + draw_enemy_layer = E->ymw_var_09; + E->ymw_var_00 = YappingMaw_Func_16(E->ymw_var_21) - E->ymw_var_0E; + E->ymw_var_02 = YappingMaw_Func_16(E->ymw_var_22) - E->ymw_var_0E; + E->ymw_var_04 = YappingMaw_Func_16(E->ymw_var_23) - E->ymw_var_0E; + E->ymw_var_06 = YappingMaw_Func_16(E->ymw_var_24) - E->ymw_var_0E; + draw_enemy_layer = E->ymw_var_09 >> 1; + E->ymw_var_01 = YappingMaw_Func_17(E->ymw_var_21) - E->ymw_var_0F; + E->ymw_var_03 = YappingMaw_Func_17(E->ymw_var_22) - E->ymw_var_0F; + E->ymw_var_05 = YappingMaw_Func_17(E->ymw_var_23) - E->ymw_var_0F; + E->ymw_var_07 = YappingMaw_Func_17(E->ymw_var_24) - E->ymw_var_0F; + YappingMaw_Func_4(); + YappingMaw_Func_5(); + YappingMaw_Func_6(); + YappingMaw_Func_7(); + uint16 ymw_var_00 = E->ymw_var_00; + bool v3 = __CFADD__uint16(E->ymw_var_27, ymw_var_00); + E->ymw_var_00 = E->ymw_var_27 + ymw_var_00; + uint16 ymw_var_01 = E->ymw_var_01; + v17 = v3; + v3 = __CFADD__uint16(v3, ymw_var_01); + v16 = v17 + ymw_var_01; + v3 |= __CFADD__uint16(E->ymw_var_28, v16); + E->ymw_var_01 = E->ymw_var_28 + v16; + uint16 ymw_var_02 = E->ymw_var_02; + v20 = v3; + v3 = __CFADD__uint16(v3, ymw_var_02); + v19 = v20 + ymw_var_02; + v3 |= __CFADD__uint16(E->ymw_var_29, v19); + E->ymw_var_02 = E->ymw_var_29 + v19; + uint16 ymw_var_03 = E->ymw_var_03; + v23 = v3; + v3 = __CFADD__uint16(v3, ymw_var_03); + v22 = v23 + ymw_var_03; + v3 |= __CFADD__uint16(E->ymw_var_2A, v22); + E->ymw_var_03 = E->ymw_var_2A + v22; + uint16 ymw_var_04 = E->ymw_var_04; + v26 = v3; + v3 = __CFADD__uint16(v3, ymw_var_04); + v25 = v26 + ymw_var_04; + v3 |= __CFADD__uint16(E->ymw_var_2B, v25); + E->ymw_var_04 = E->ymw_var_2B + v25; + uint16 ymw_var_05 = E->ymw_var_05; + v29 = v3; + v3 = __CFADD__uint16(v3, ymw_var_05); + v28 = v29 + ymw_var_05; + v3 |= __CFADD__uint16(E->ymw_var_2C, v28); + E->ymw_var_05 = E->ymw_var_2C + v28; + uint16 ymw_var_06 = E->ymw_var_06; + v32 = v3; + v3 = __CFADD__uint16(v3, ymw_var_06); + v31 = v32 + ymw_var_06; + v3 |= __CFADD__uint16(E->ymw_var_2D, v31); + E->ymw_var_06 = E->ymw_var_2D + v31; + E->ymw_var_07 += E->ymw_var_2E + v3; + E->base.x_pos = E->ymw_var_06 + E->ymw_var_0C; + E->base.y_pos = E->ymw_var_07 + E->ymw_var_0D; + YappingMaw_Func_9(cur_enemy_index); + if (!sign16(E->ymw_var_B)) { + if (!sign16(E->ymw_var_B - 128)) { + E->ymw_var_B = 128; + E->ymw_var_C = 0; + ++E->ymw_var_D; + ++E->ymw_var_D; + ++E->ymw_var_D; + ++E->ymw_var_D; + } +LABEL_19: + if (E->ymw_var_30) + YappingMaw_Func_10(); + return; + } + E->ymw_var_A = FUNC16(YappingMaw_Func_11); + E->ymw_var_35 = 48; + if (E->ymw_var_34 == 4) { + E->base.current_instruction = addr_kYappingMaw_Ilist_A01F; + } else if (E->ymw_var_34 == 12) { + E->base.current_instruction = addr_kYappingMaw_Ilist_A03D; + } else { + E->base.current_instruction = addr_off_A8A025; + } + if (!E->ymw_parameter_2) { + if (E->ymw_var_34 == 4) { + E->base.current_instruction = addr_kYappingMaw_Ilist_A05B; + } else { + if (E->ymw_var_34 != 12) { + E->base.current_instruction = addr_off_A8A061; + return; + } + E->base.current_instruction = addr_kYappingMaw_Ilist_A079; + } + goto LABEL_19; + } +} + +void YappingMaw_Func_9(uint16 k) { // 0xA8A63E + Enemy_YappingMaw *E = Get_YappingMaw(k); + int v2 = E->ymw_var_D >> 1; + E->ymw_var_B += kCommonEnemySpeeds_Quadratic[v2 + 1]; + uint16 ymw_var_C = E->ymw_var_C; + bool v4 = __CFADD__uint16(kCommonEnemySpeeds_Quadratic[v2], ymw_var_C); + uint16 v5 = kCommonEnemySpeeds_Quadratic[v2] + ymw_var_C; + if (v4) + ++E->ymw_var_B; + E->ymw_var_C = v5; + E->ymw_var_D += 8; +} + +void YappingMaw_Func_10(void) { // 0xA8A665 + CallSomeSamusCode(3u); + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + samus_x_pos = E->ymw_var_32 + E->base.x_pos; + samus_y_pos = E->ymw_var_33 + E->base.y_pos; + EnemyFunc_B7A1(); +} + +void YappingMaw_Func_11(void) { // 0xA8A68A + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + if (E->ymw_var_30) + YappingMaw_Func_10(); + if ((--E->ymw_var_E & 0x8000u) != 0 && samus_input_handler != (uint16)FUNC16(Samus_InputHandler_E91D)) { + samus_input_handler = FUNC16(Samus_InputHandler_E913); + E->ymw_var_30 = 0; + E->ymw_var_35 = 48; + E->ymw_var_E = 64; + E->ymw_var_A = FUNC16(YappingMaw_Func_1); + } +} + +void YappingMaw_Func_12(void) { // 0xA8A6C4 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + int v1 = E->ymw_var_40 >> 1; + enemy_projectile_x_pos[v1] = E->ymw_var_0C; + enemy_projectile_y_pos[v1] = E->ymw_var_0D; +} + +void YappingMaw_Func_13(void) { // 0xA8A6DB + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + int v1 = E->ymw_var_41 >> 1; + enemy_projectile_x_pos[v1] = E->ymw_var_00 + E->ymw_var_0C; + enemy_projectile_y_pos[v1] = E->ymw_var_01 + E->ymw_var_0D; +} + +void YappingMaw_Func_14(void) { // 0xA8A6FC + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + int v1 = E->ymw_var_42 >> 1; + enemy_projectile_x_pos[v1] = E->ymw_var_02 + E->ymw_var_0C; + enemy_projectile_y_pos[v1] = E->ymw_var_03 + E->ymw_var_0D; +} + +void YappingMaw_Func_15(void) { // 0xA8A71D + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + int v1 = E->ymw_var_43 >> 1; + enemy_projectile_x_pos[v1] = E->ymw_var_04 + E->ymw_var_0C; + enemy_projectile_y_pos[v1] = E->ymw_var_05 + E->ymw_var_0D; +} + +uint16 YappingMaw_Func_16(uint16 a) { // 0xA8A73E + return YappingMaw_Func_17(a - 64); +} + +uint16 YappingMaw_Func_17(uint16 a) { // 0xA8A742 + int16 v1; + + R18_ = a; + R20_ = 0; + R22_ = 0; + v1 = kSine16bit[(uint16)(2 * (uint8)-(int8)a) >> 1]; + if (v1 < 0) { + v1 = -v1; + ++R20_; + } + WriteReg(WRMPYA, HIBYTE(v1)); + if ((uint8)draw_enemy_layer) { + uint16 prod = Mult8x8(HIBYTE(v1), draw_enemy_layer); + R22_ = 2 * (uint8)((uint16)(prod & 0xFF00) >> 8); + if (R20_) + R22_ = (uint8)(2 * ((uint16)-prod >> 8)) | 0xFF00; + } + return R22_; +} + +void YappingMaw_Touch(void) { // 0xA8A799 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + if ((E->ymw_var_35 & 0x8000u) != 0 && !E->ymw_var_30) { + E->ymw_var_35 = 0; + E->ymw_var_30 = 1; + samus_input_handler = FUNC16(nullsub_152); + } +} + +void YappingMaw_Shot(void) { // 0xA8A7BD + NormalEnemyShotAi(); + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + if (E->base.health) { + if (E->base.frozen_timer) { + if (samus_input_handler != (uint16)FUNC16(Samus_InputHandler_E91D)) + samus_input_handler = FUNC16(Samus_InputHandler_E913); + E->ymw_var_30 = 0; + } + } else { + *(uint16 *)((char *)enemy_projectile_id + E->ymw_var_40) = 0; + *(uint16 *)((char *)enemy_projectile_id + E->ymw_var_41) = 0; + *(uint16 *)((char *)enemy_projectile_id + E->ymw_var_42) = 0; + *(uint16 *)((char *)enemy_projectile_id + E->ymw_var_43) = 0; + sprite_instr_list_ptrs[E->ymw_var_46 >> 1] = 0; + if (samus_input_handler != (uint16)FUNC16(Samus_InputHandler_E91D)) + samus_input_handler = FUNC16(Samus_InputHandler_E913); + Get_YappingMaw(cur_enemy_index)->ymw_var_30 = 0; + } +} + +void YappingMaw_Frozen(void) { // 0xA8A835 + Enemy_NormalFrozenAI_A8(); + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + YappingMaw_Func_18(E->ymw_var_40); + YappingMaw_Func_18(E->ymw_var_41); + YappingMaw_Func_18(E->ymw_var_42); + YappingMaw_Func_18(E->ymw_var_43); + YappingMaw_Func_19(); +} + +void YappingMaw_Func_18(uint16 j) { // 0xA8A85D + int v1 = j >> 1; + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + enemy_projectile_gfx_idx[v1] = E->ymw_var_45 | enemy_projectile_gfx_idx[v1] & 0xF1FF; + if (E->base.frozen_timer) { + enemy_projectile_gfx_idx[v1] = enemy_projectile_gfx_idx[v1] & 0xF1FF | 0xC00; + uint16 frozen_timer = E->base.frozen_timer; + if (sign16(frozen_timer - 90)) { + if ((frozen_timer & 2) == 0) + enemy_projectile_gfx_idx[v1] = E->ymw_var_45 | enemy_projectile_gfx_idx[v1] & 0xF1FF; + } + } +} + +void YappingMaw_Func_19(void) { // 0xA8A899 + Enemy_YappingMaw *E = Get_YappingMaw(cur_enemy_index); + R18_ = E->ymw_var_45; + R20_ = E->ymw_var_46; + sprite_palettes[R20_ >> 1] = R18_ | sprite_palettes[R20_ >> 1] & 0xF1FF; + if (Get_YappingMaw(cur_enemy_index)->base.frozen_timer) { + sprite_palettes[R20_ >> 1] = sprite_palettes[R20_ >> 1] & 0xF1FF | 0xC00; + uint16 frozen_timer = Get_YappingMaw(cur_enemy_index)->base.frozen_timer; + if (sign16(frozen_timer - 90)) { + if ((frozen_timer & 2) == 0) + sprite_palettes[R20_ >> 1] = R18_ | sprite_palettes[R20_ >> 1] & 0xF1FF; + } + } +} + +void Kago_Init(void) { // 0xA8AB46 + Enemy_Kago *E = Get_Kago(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->kago_var_E = 0; + E->base.current_instruction = addr_kKago_Ilist_AB1E; + E->kago_var_A = FUNC16(Kago_Func_1); + E->kago_var_F = 0; + E->kago_var_04 = E->kago_parameter_1; +} + +void CallKagoFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnKago_Func_1: Kago_Func_1(k); return; + case fnnullsub_306: return; + default: Unreachable(); + } +} + +void Kago_Main(void) { // 0xA8AB75 + Enemy_Kago *E = Get_Kago(cur_enemy_index); + CallKagoFunc(E->kago_var_A | 0xA80000, cur_enemy_index); +} + +void Kago_Func_1(uint16 k) { // 0xA8AB7B + Get_Kago(k)->kago_var_A = FUNC16(nullsub_306); +} + +void Kago_Shot(void) { // 0xA8AB83 + int16 v2; + + NormalEnemyShotAi(); + earthquake_type = 2; + earthquake_timer = 16; + Enemy_Kago *E = Get_Kago(cur_enemy_index); + if (!E->kago_var_B) { + E->kago_var_B = 1; + E->base.current_instruction = addr_kKago_Ilist_AB32; + E->base.instruction_timer = 1; + } + v2 = E->kago_var_04 - 1; + E->kago_var_04 = v2; + if (v2 < 0) { + EnemyDeathAnimation(cur_enemy_index, 4u); + E->kago_var_F = 1; + } + SpawnEnemyProjectileWithGfx(E->base.y_pos, cur_enemy_index, addr_loc_A8D02E); +} + +uint16 NorfairLavaMan_Instr_1(uint16 k, uint16 j) { // 0xA8AE12 + if (!CheckIfEnemyIsOnScreen()) { + uint16 *v2 = (uint16 *)RomPtr_A8(j); + QueueSfx2_Max6(*v2); + } + return j + 2; +} + +uint16 NorfairLavaMan_Instr_8(uint16 k, uint16 j) { // 0xA8AE26 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + ++E->base.y_pos; + ++E->base.y_pos; + return j; +} + +uint16 NorfairLavaMan_Instr_14(uint16 k, uint16 j) { // 0xA8AE30 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + --E->base.y_pos; + --E->base.y_pos; + return j; +} + +uint16 NorfairLavaMan_Instr_2(uint16 k, uint16 j) { // 0xA8AE3A + Get_NorfairLavaMan(cur_enemy_index)->nlmn_var_01 = 1; + return j; +} + +uint16 NorfairLavaMan_Instr_7(uint16 k, uint16 j) { // 0xA8AE45 + Get_NorfairLavaMan(cur_enemy_index)->nlmn_var_01 = 0; + return j; +} + +uint16 NorfairLavaMan_Instr_10(uint16 k, uint16 j) { // 0xA8AE50 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + --E->base.y_pos; + Enemy_NorfairLavaMan *E1 = Get_NorfairLavaMan(cur_enemy_index + 64); + --E1->base.y_pos; + return j; +} + +uint16 NorfairLavaMan_Instr_12(uint16 k, uint16 j) { // 0xA8AE5A + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + ++E->base.y_pos; + Enemy_NorfairLavaMan *E1 = Get_NorfairLavaMan(cur_enemy_index + 64); + ++E1->base.y_pos; + return j; +} + +uint16 NorfairLavaMan_Instr_9(uint16 k, uint16 j) { // 0xA8AE64 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + uint16 v4 = E->nlmn_var_03 + 24; + E->base.y_pos = v4; + Enemy_NorfairLavaMan *E1 = Get_NorfairLavaMan(cur_enemy_index + 64); + E1->base.y_pos = v4; + E1->base.properties &= ~0x100u; + Enemy_NorfairLavaMan *E2 = Get_NorfairLavaMan(cur_enemy_index + 128); + E2->base.properties &= ~0x100u; + return j; +} + +uint16 NorfairLavaMan_Instr_11(uint16 k, uint16 j) { // 0xA8AE88 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + uint16 nlmn_var_03 = E->nlmn_var_03; + E->base.y_pos = nlmn_var_03; + Get_NorfairLavaMan(cur_enemy_index + 64)->base.y_pos = nlmn_var_03; + return j; +} + +uint16 NorfairLavaMan_Instr_13(uint16 k, uint16 j) { // 0xA8AE96 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + uint16 v4 = E->nlmn_var_03 + 4; + E->base.y_pos = v4; + Enemy_NorfairLavaMan *E1 = Get_NorfairLavaMan(cur_enemy_index + 64); + E1->base.y_pos = v4; + E1->base.properties |= 0x100u; + Enemy_NorfairLavaMan *E2 = Get_NorfairLavaMan(cur_enemy_index + 128); + E2->base.properties |= 0x100u; + return j; +} + +uint16 NorfairLavaMan_Instr_5(uint16 k, uint16 j) { // 0xA8AEBA + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + SpawnEnemyProjectileWithGfx(E->nlmn_var_B, cur_enemy_index, addr_kEproj_LavaThrownByLavaman); + return j; +} + +uint16 NorfairLavaMan_Instr_15(uint16 k, uint16 j) { // 0xA8AECA + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + E->base.x_pos = E->nlmn_var_12 + 8; + E->base.y_pos = E->nlmn_var_13 - 4; + return j; +} + +uint16 NorfairLavaMan_Instr_4(uint16 k, uint16 j) { // 0xA8AEE4 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + E->base.x_pos = E->nlmn_var_12 - 8; + E->base.y_pos = E->nlmn_var_13 - 4; + return j; +} + +uint16 NorfairLavaMan_Instr_16(uint16 k, uint16 j) { // 0xA8AEFE + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + E->base.x_pos = E->nlmn_var_12 + 8; + E->base.y_pos = E->nlmn_var_13 - 8; + return j; +} + +uint16 NorfairLavaMan_Instr_6(uint16 k, uint16 j) { // 0xA8AF18 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + E->base.x_pos = E->nlmn_var_12 - 8; + E->base.y_pos = E->nlmn_var_13 - 4; + return j; +} + +void sub_A8AF32(void) { // 0xA8AF32 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + E->base.x_pos = E->nlmn_var_12; + E->base.y_pos = E->nlmn_var_13; +} + +uint16 NorfairLavaMan_Instr_3(uint16 k, uint16 j) { // 0xA8AF44 + Get_NorfairLavaMan(cur_enemy_index)->nlmn_var_04 = 256; + return j; +} +static Func_V *const g_off_A8AF4F[3] = { NorfairLavaMan_Func_1, NorfairLavaMan_Func_2, NorfairLavaMan_Func_3 }; +void NorfairLavaMan_Init(void) { // 0xA8AF8B + uint16 v0 = 2 * Get_NorfairLavaMan(cur_enemy_index)->nlmn_parameter_1; + g_off_A8AF4F[v0 >> 1](); + NorfairLavaMan_Func_4(); + NorfairLavaMan_Func_5(cur_enemy_index); +} + +void NorfairLavaMan_Func_1(void) { // 0xA8AF9D + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + E->nlmn_var_C = 0; + E->nlmn_var_00 = 0; + E->nlmn_var_02 = 0; + E->nlmn_var_03 = E->base.y_pos; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) != 0) + E->nlmn_var_00 = 1; + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AC9C; + if (!E->nlmn_var_00) + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AD3C; + NorfairLavaMan_Func_20(); + E->nlmn_var_F = FUNC16(NorfairLavaMan_Func_7); +} + +void NorfairLavaMan_Func_2(void) { // 0xA8AFE2 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + E->nlmn_var_03 = E->base.y_pos; + E->nlmn_var_C = 0; + E->nlmn_var_0C = 0; + E->nlmn_var_0D = 1; + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_ADDC; + NorfairLavaMan_Func_20(); + E->base.y_pos += 32; + E->nlmn_var_F = FUNC16(NorfairLavaMan_Func_10); + E->base.properties |= kEnemyProps_Invisible; +} + +void NorfairLavaMan_Func_3(void) { // 0xA8B020 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + E->nlmn_var_03 = E->base.y_pos; + E->nlmn_var_11 = E->base.x_pos; + E->nlmn_var_C = 0; + E->nlmn_var_04 = 0; + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AE0C; + NorfairLavaMan_Func_20(); + E->base.y_pos += 32; + E->nlmn_var_F = FUNC16(NorfairLavaMan_Func_15); + E->base.properties |= kEnemyProps_Invisible; +} + +void NorfairLavaMan_Func_4(void) { // 0xA8B05E + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + int v1 = (uint16)(8 * HIBYTE(E->nlmn_parameter_2)) >> 1; + E->nlmn_var_08 = kCommonEnemySpeeds_Linear[v1]; + E->nlmn_var_07 = kCommonEnemySpeeds_Linear[v1 + 1]; + E->nlmn_var_0A = kCommonEnemySpeeds_Linear[v1 + 2]; + E->nlmn_var_09 = kCommonEnemySpeeds_Linear[v1 + 3]; +} + +void NorfairLavaMan_Func_5(uint16 k) { // 0xA8B088 + enemy_gfx_drawn_hook.addr = FUNC16(NorfairLavaMan_Func_6); + *(uint16 *)&enemy_gfx_drawn_hook.bank = 168; + variables_for_enemy_graphics_drawn_hook[0] = ((uint16)(Get_NorfairLavaMan(k)->base.palette_index & 0xE00) >> 4) + + 256; + variables_for_enemy_graphics_drawn_hook[2] = 8; + variables_for_enemy_graphics_drawn_hook[1] = 0; +} + +void NorfairLavaMan_Func_6(void) { // 0xA8B0B2 + if (!door_transition_flag_enemies && !--variables_for_enemy_graphics_drawn_hook[2]) { + variables_for_enemy_graphics_drawn_hook[2] = 8; + ++variables_for_enemy_graphics_drawn_hook[1]; + int v0 = (uint16)(32 * (variables_for_enemy_graphics_drawn_hook[1] & 3)) >> 1; + R18_ = kNorfairLavaMan_Palette[v0 + 9]; + R20_ = kNorfairLavaMan_Palette[v0 + 10]; + R22_ = kNorfairLavaMan_Palette[v0 + 11]; + R24_ = kNorfairLavaMan_Palette[v0 + 12]; + int v1 = variables_for_enemy_graphics_drawn_hook[0] >> 1; + palette_buffer[v1 + 9] = R18_; + palette_buffer[v1 + 10] = R20_; + palette_buffer[v1 + 11] = R22_; + palette_buffer[v1 + 12] = R24_; + } +} + +void NorfairLavaMan_Main(void) { // 0xA8B10A + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + --E->nlmn_var_04; + CallEnemyPreInstr(E->nlmn_var_F | 0xA80000); +} + +void NorfairLavaMan_Func_7(uint16 k) { // 0xA8B11A + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + E->nlmn_var_00 = 0; + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AC9C; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) { + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AD3C; + E->nlmn_var_00 = 1; + } + NorfairLavaMan_Func_20(); + Enemy_NorfairLavaMan *E2 = Get_NorfairLavaMan(cur_enemy_index + 128); + if ((E2->nlmn_var_04 & 0x8000u) != 0) { + E2->nlmn_var_04 = 0; + if (IsSamusWithinEnemy_X(cur_enemy_index, LOBYTE(E->nlmn_parameter_2))) { + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_ACDE; + if (E->nlmn_var_00) + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AD7E; + NorfairLavaMan_Func_20(); + E->nlmn_var_F = FUNC16(NorfairLavaMan_Func_8); + } + } +} + +void NorfairLavaMan_Func_8(uint16 k) { // 0xA8B175 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + if (!E->nlmn_var_01) { + E->nlmn_var_02 = 1; + Get_NorfairLavaMan(cur_enemy_index + 64)->nlmn_var_0D = 0; + E->nlmn_var_F = FUNC16(sub_A8B193); + } +} + +void sub_A8B193(uint16 k) { // 0xA8B193 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + if (!E->nlmn_var_02) { + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AD0C; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_ADAC; + NorfairLavaMan_Func_20(); + E->nlmn_var_F = FUNC16(NorfairLavaMan_Func_9); + } +} + +void NorfairLavaMan_Func_9(uint16 k) { // 0xA8B1B8 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + if (!E->nlmn_var_01) { + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AC9C; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AD3C; + NorfairLavaMan_Func_20(); + E->nlmn_var_F = FUNC16(NorfairLavaMan_Func_7); + } +} + +void NorfairLavaMan_Func_10(uint16 k) { // 0xA8B1DD + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + if (!E->nlmn_var_0D) { + E->nlmn_var_F = FUNC16(NorfairLavaMan_Func_11); + E->nlmn_var_E = 0; + E->nlmn_var_0D = 0; + E->nlmn_var_B = 2; + E->base.y_pos = E->nlmn_var_03; + } +} + +void NorfairLavaMan_Func_11(uint16 k) { // 0xA8B204 + EnemySpawnData *v3; + + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + v3 = gEnemySpawnData(cur_enemy_index); + bool v4 = __CFADD__uint16(v3[31].ypos2, y_subpos); + E->base.y_subpos = v3[31].ypos2 + y_subpos; + if (v4) + ++E->nlmn_var_E; + E->base.y_pos += v3[31].field_14 + v4; + E->nlmn_var_E += v3[31].field_14; + NorfairLavaMan_Func_12(cur_enemy_index); +} + +void NorfairLavaMan_Func_12(uint16 k) { // 0xA8B230 + int v3; + + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(k); + if (!sign16(-E->nlmn_var_E - 108)) + printf("Y undefined %d!\n", -(int16)E->nlmn_var_E); + uint16 nlmn_var_B = E->nlmn_var_B; + + if (!sign16(-E->nlmn_var_E - 108) + || (v3 = nlmn_var_B >> 1, + (int16)(E->base.y_pos - g_word_A8AF79[v3] - samus_y_pos) < 0)) { + E->nlmn_var_F = FUNC16(sub_A8B291); + E->nlmn_var_0C = 1; + if ((int16)(-E->nlmn_var_E - g_word_A8AF55[nlmn_var_B >> 1]) < 0) + return; + goto LABEL_6; + } + if ((int16)(-E->nlmn_var_E - g_word_A8AF55[v3]) >= 0) { +LABEL_6: + ++E->nlmn_var_B; + ++E->nlmn_var_B; + E->base.y_pos += 8; + E->nlmn_var_D = g_off_A8AF67[E->nlmn_var_B >> 1]; + NorfairLavaMan_Func_20(); + } +} + +void sub_A8B291(uint16 k) { // 0xA8B291 + ; +} + +void NorfairLavaMan_Func_13(void) { // 0xA8B295 + EnemySpawnData *v2; + + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + v2 = gEnemySpawnData(cur_enemy_index); + E->base.y_pos += v2[31].xpos2; + E->nlmn_var_E += v2[31].xpos2; + uint16 y_subpos = E->base.y_subpos; + bool v4 = __CFADD__uint16(v2[31].field_E, y_subpos); + uint16 v5 = v2[31].field_E + y_subpos; + if (v4) { + ++E->base.y_pos; + ++E->nlmn_var_E; + } + E->base.y_subpos = v5; + NorfairLavaMan_Func_14(cur_enemy_index); +} + +void NorfairLavaMan_Func_14(uint16 k) { // 0xA8B2C5 + int16 nlmn_var_E; + + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(k); + nlmn_var_E = E->nlmn_var_E; + if (nlmn_var_E >= 0) { + E->nlmn_var_0D = 1; + gEnemySpawnData(k)[31].field_4 = 0; + E->nlmn_var_F = FUNC16(NorfairLavaMan_Func_10); + } else if ((int16)(-nlmn_var_E - g_word_A8AF55[(uint16)(E->nlmn_var_B - 2) >> 1]) < 0) { + --E->nlmn_var_B; + --E->nlmn_var_B; + E->base.y_pos -= 8; + E->nlmn_var_D = g_off_A8AF67[E->nlmn_var_B >> 1]; + NorfairLavaMan_Func_20(); + } +} + +void NorfairLavaMan_Func_15(uint16 k) { // 0xA8B30D + if (enemy_drawing_queue[(cur_enemy_index >> 1) + 87] == (uint16)FUNC16(NorfairLavaMan_Func_8)) + Get_NorfairLavaMan(cur_enemy_index)->nlmn_var_F = FUNC16(NorfairLavaMan_Func_17); +} + +void NorfairLavaMan_Func_16(uint16 k) { // 0xA8B31F + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + if (!E->nlmn_var_01) { + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AE0C; + NorfairLavaMan_Func_20(); + enemy_drawing_queue_sizes[(cur_enemy_index >> 1) + 5] = FUNC16(NorfairLavaMan_Func_13); + E->nlmn_var_F = FUNC16(NorfairLavaMan_Func_18); + gEnemySpawnData(cur_enemy_index)[31].field_18 = 0; + E->base.x_pos = E->nlmn_var_12; + E->base.y_pos = E->nlmn_var_13; + } + NorfairLavaMan_Func_19(cur_enemy_index); +} + +void NorfairLavaMan_Func_17(uint16 k) { // 0xA8B356 + if (gEnemySpawnData(cur_enemy_index)[31].field_18) { + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_ACB0; + E->nlmn_var_B = 0; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) { + E->nlmn_var_D = addr_kNorfairLavaMan_Ilist_AD50; + E->nlmn_var_B = 1; + } + NorfairLavaMan_Func_20(); + E->nlmn_var_F = FUNC16(NorfairLavaMan_Func_16); + E->nlmn_var_12 = E->base.x_pos; + E->nlmn_var_13 = E->base.y_pos; + } else { + Get_NorfairLavaMan(cur_enemy_index)->base.y_pos = enemy_drawing_queue[(cur_enemy_index >> 1) + 93] + - g_word_A8AF79[enemy_drawing_queue_sizes[(cur_enemy_index >> 1) + 1] >> 1]; + } + NorfairLavaMan_Func_19(cur_enemy_index); +} + +void NorfairLavaMan_Func_18(uint16 k) { // 0xA8B3A7 + int v1 = cur_enemy_index >> 1; + if (enemy_drawing_queue[v1 + 87] == (uint16)FUNC16(NorfairLavaMan_Func_7)) + Get_NorfairLavaMan(cur_enemy_index)->nlmn_var_F = FUNC16(NorfairLavaMan_Func_15); + else + Get_NorfairLavaMan(cur_enemy_index)->base.y_pos = enemy_drawing_queue[v1 + 93] + - g_word_A8AF79[enemy_drawing_queue_sizes[v1 + 1] >> 1]; + NorfairLavaMan_Func_19(cur_enemy_index); +} + +void NorfairLavaMan_Func_19(uint16 k) { // 0xA8B3CB + int v1 = k >> 1; + uint16 v2 = enemy_drawing_queue[v1 + 61] - Get_NorfairLavaMan(k)->base.y_pos + 2; + enemy_drawing_queue[v1 + 64] = v2; + if (sign16(v2 - 8)) + enemy_drawing_queue[v1 + 64] = 8; +} + +void NorfairLavaMan_Func_20(void) { // 0xA8B3E5 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + uint16 nlmn_var_D = E->nlmn_var_D; + if (nlmn_var_D != E->nlmn_var_C) { + E->base.current_instruction = nlmn_var_D; + E->nlmn_var_C = nlmn_var_D; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void NorfairLavaMan_Powerbomb(void) { // 0xA8B400 + Enemy_NormalPowerBombAI_A8(); + NorfairLavaMan_Common(); +} + +void NorfairLavaMan_Touch(void) { // 0xA8B406 + Enemy_NormalTouchAI_A8(); + NorfairLavaMan_Common(); +} + +void NorfairLavaMan_Shot(void) { // 0xA8B40C + NormalEnemyShotAi(); + NorfairLavaMan_Common(); +} + +void NorfairLavaMan_Common(void) { // 0xA8B410 + Enemy_NorfairLavaMan *E = Get_NorfairLavaMan(cur_enemy_index); + Enemy_NorfairLavaMan *E1 = Get_NorfairLavaMan(cur_enemy_index + 64); + Enemy_NorfairLavaMan *E2 = Get_NorfairLavaMan(cur_enemy_index + 128); + if (!E->base.health) { + E1->base.properties |= 0x200u; + E2->base.properties |= 0x200u; + } + uint16 frozen_timer = E->base.frozen_timer; + if (frozen_timer) { + E1->base.frozen_timer = frozen_timer; + E1->base.ai_handler_bits |= 4u; + E2->base.frozen_timer = frozen_timer; + E2->base.ai_handler_bits |= 4u; + } +} + +uint16 Beetom_Instr_1(uint16 k, uint16 j) { // 0xA8B75E + return j; +} + +void Beetom_Func_1(void) { // 0xA8B762 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->base.current_instruction = E->beetom_var_00; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void Beetom_Init(void) { // 0xA8B776 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_D = 0; + E->beetom_var_C = 0; + E->beetom_var_05 = 0; + E->beetom_var_08 = 0; + E->beetom_var_A = 0; + E->beetom_var_E = 64; + E->beetom_var_F = joypad1_lastkeys; + random_number = 23; + R22_ = 12288; + R24_ = 4; + E->beetom_var_02 = Beetom_Func_2(); + R22_ = 0x4000; + R24_ = 5; + E->beetom_var_03 = Beetom_Func_2(); + R22_ = 12288; + R24_ = 3; + E->beetom_var_04 = Beetom_Func_2(); + E->beetom_var_00 = addr_kBeetom_Ilist_B6F2; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) != 0) + E->beetom_var_00 = addr_kBeetom_Ilist_B696; + Beetom_Func_1(); + E->beetom_var_C = FUNC16(Beetom_Func_3); +} + +uint16 Beetom_Func_2(void) { // 0xA8B7EF + R18_ = 0; + R20_ = 0; + do { + R18_ += R24_; + R20_ += *(uint16 *)((char *)kCommonEnemySpeeds_Quadratic + (uint16)(8 * R18_) + 1); + } while (sign16(R20_ - R22_)); + return R18_; +} + +void CallBeetomFunc(uint32 ea) { + switch (ea) { + case fnBeetom_Func_3: Beetom_Func_3(); return; // 0xa8b814 + case fnBeetom_Func_4: Beetom_Func_4(); return; // 0xa8b82f + case fnBeetom_Func_5: Beetom_Func_5(); return; // 0xa8b84f + case fnBeetom_Func_6: Beetom_Func_6(); return; // 0xa8b85f + case fnBeetom_Func_7: Beetom_Func_7(); return; // 0xa8b873 + case fnBeetom_Func_8: Beetom_Func_8(); return; // 0xa8b887 + case fnBeetom_Func_9: Beetom_Func_9(); return; // 0xa8b8a9 + case fnBeetom_Func_10: Beetom_Func_10(); return; // 0xa8b8cb + case fnBeetom_Func_11: Beetom_Func_11(); return; // 0xa8b8ed + case fnBeetom_Func_12: Beetom_Func_12(); return; // 0xa8b90f + case fnBeetom_Func_13: Beetom_Func_13(); return; // 0xa8b952 + case fnBeetom_Func_14: Beetom_Func_14(); return; // 0xa8b966 + case fnBeetom_Func_15: Beetom_Func_15(); return; // 0xa8b97a + case fnBeetom_Func_16: Beetom_Func_16(); return; // 0xa8b9a2 + case fnBeetom_Func_17: Beetom_Func_17(); return; // 0xa8b9b2 + case fnBeetom_Func_18: Beetom_Func_18(); return; // 0xa8b9c1 + case fnBeetom_Func_19: Beetom_Func_19(); return; // 0xa8ba24 + case fnBeetom_Func_20: Beetom_Func_20(); return; // 0xa8ba84 + case fnBeetom_Func_21: Beetom_Func_21(); return; // 0xa8bab7 + case fnBeetom_Func_24: Beetom_Func_24(); return; // 0xa8bb55 + case fnBeetom_Func_25: Beetom_Func_25(); return; // 0xa8bb88 + case fnBeetom_Func_28: Beetom_Func_28(); return; // 0xa8bc26 + case fnBeetom_Func_29: Beetom_Func_29(); return; // 0xa8bc5a + case fnBeetom_Func_32: Beetom_Func_32(); return; // 0xa8bcf8 + case fnBeetom_Func_33: Beetom_Func_33(); return; // 0xa8bd42 + case fnBeetom_Func_35: Beetom_Func_35(); return; // 0xa8bd9d + case fnBeetom_Func_36: Beetom_Func_36(); return; // 0xa8bdc5 + default: Unreachable(); + } +} + +void Beetom_Main(void) { // 0xA8B80D + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + CallBeetomFunc(E->beetom_var_C | 0xA80000); +} + +void Beetom_Func_3(void) { // 0xA8B814 + if (IsSamusWithinEnemy_X(cur_enemy_index, 0x60u)) + Get_Beetom(cur_enemy_index)->beetom_var_C = FUNC16(Beetom_Func_12); + else + Get_Beetom(cur_enemy_index)->beetom_var_C = FUNC16(Beetom_Func_4); +} + +void Beetom_Func_4(void) { // 0xA8B82F + NextRandom(); + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_C = kBeetom_Ilist_B74E[random_number & 7]; + E->beetom_var_09 = random_number & 1; +} + +void Beetom_Func_5(void) { // 0xA8B84F + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_D = 32; + E->beetom_var_C = FUNC16(Beetom_Func_17); +} + +void Beetom_Func_6(void) { // 0xA8B85F + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_C = FUNC16(Beetom_Func_18); + E->beetom_var_00 = addr_kBeetom_Ilist_B696; + Beetom_Func_1(); +} + +void Beetom_Func_7(void) { // 0xA8B873 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_C = FUNC16(Beetom_Func_19); + E->beetom_var_00 = addr_kBeetom_Ilist_B6F2; + Beetom_Func_1(); +} + +void Beetom_Func_8(void) { // 0xA8B887 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_B = E->beetom_var_02; + E->beetom_var_C = FUNC16(Beetom_Func_20); + E->beetom_var_05 = 0; + E->beetom_var_00 = addr_kBeetom_Ilist_B6AC; + Beetom_Func_1(); +} + +void Beetom_Func_9(void) { // 0xA8B8A9 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_B = E->beetom_var_02; + E->beetom_var_C = FUNC16(Beetom_Func_21); + E->beetom_var_05 = 0; + E->beetom_var_00 = addr_kBeetom_Ilist_B708; + Beetom_Func_1(); +} + +void Beetom_Func_10(void) { // 0xA8B8CB + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_B = E->beetom_var_03; + E->beetom_var_C = FUNC16(Beetom_Func_24); + E->beetom_var_05 = 0; + E->beetom_var_00 = addr_kBeetom_Ilist_B6AC; + Beetom_Func_1(); +} + +void Beetom_Func_11(void) { // 0xA8B8ED + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_B = E->beetom_var_03; + E->beetom_var_C = FUNC16(Beetom_Func_25); + E->beetom_var_05 = 0; + E->beetom_var_00 = addr_kBeetom_Ilist_B708; + Beetom_Func_1(); +} + +void Beetom_Func_12(void) { // 0xA8B90F + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_B = E->beetom_var_04; + E->beetom_var_00 = addr_kBeetom_Ilist_B708; + E->beetom_var_C = FUNC16(Beetom_Func_29); + E->beetom_var_09 = 1; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) != 0) { + E->beetom_var_00 = addr_kBeetom_Ilist_B6AC; + E->beetom_var_C = FUNC16(Beetom_Func_28); + E->beetom_var_09 = 0; + } + Beetom_Func_1(); + E->beetom_var_05 = 0; +} + +void Beetom_Func_13(void) { // 0xA8B952 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_00 = addr_kBeetom_Ilist_B6CC; + Beetom_Func_1(); + E->beetom_var_C = FUNC16(Beetom_Func_32); +} + +void Beetom_Func_14(void) { // 0xA8B966 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_00 = addr_kBeetom_Ilist_B728; + Beetom_Func_1(); + E->beetom_var_C = FUNC16(Beetom_Func_33); +} + +void Beetom_Func_15(void) { // 0xA8B97A + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_00 = addr_kBeetom_Ilist_B696; + if (E->beetom_var_09) + E->beetom_var_00 = addr_kBeetom_Ilist_B6F2; + Beetom_Func_1(); + E->beetom_var_05 = 0; + E->beetom_var_C = FUNC16(Beetom_Func_35); +} + +void Beetom_Func_16(void) { // 0xA8B9A2 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + E->beetom_var_B = 0; + E->beetom_var_C = FUNC16(Beetom_Func_36); +} + +void Beetom_Func_17(void) { // 0xA8B9B2 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if ((--E->beetom_var_D & 0x8000u) != 0) + E->beetom_var_C = FUNC16(Beetom_Func_3); +} + +void Beetom_Func_18(void) { // 0xA8B9C1 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if ((--E->beetom_var_D & 0x8000u) != 0) { + E->beetom_var_D = 64; + E->beetom_var_C = FUNC16(Beetom_Func_3); + } else { + E->base.x_pos -= 8; + R20_ = 1; + R18_ = 0; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->base.x_pos += 8; + R18_ = -16384; + R20_ = -1; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) + E->beetom_var_C = FUNC16(Beetom_Func_7); + } else { + E->beetom_var_C = FUNC16(Beetom_Func_7); + --E->base.y_pos; + E->base.x_pos += 8; + } + } +} + +void Beetom_Func_19(void) { // 0xA8BA24 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if ((--E->beetom_var_D & 0x8000u) != 0) { + E->beetom_var_D = 64; + E->beetom_var_C = FUNC16(Beetom_Func_3); + } else { + E->base.x_pos += 8; + R20_ = 1; + R18_ = 0; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->base.x_pos -= 8; + R18_ = 0x4000; + R20_ = 0; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) + E->beetom_var_C = FUNC16(Beetom_Func_6); + } else { + E->beetom_var_C = FUNC16(Beetom_Func_6); + --E->base.y_pos; + E->base.x_pos -= 8; + } + } +} + +void Beetom_Func_20(void) { // 0xA8BA84 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (E->beetom_var_05) + Beetom_Func_23(cur_enemy_index); + else + Beetom_Func_22(cur_enemy_index); + R20_ = -1; + R18_ = -16384; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->beetom_var_09 ^= 1u; + E->beetom_var_C = FUNC16(Beetom_Func_15); + } +} + +void Beetom_Func_21(void) { // 0xA8BAB7 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (E->beetom_var_05) + Beetom_Func_23(cur_enemy_index); + else + Beetom_Func_22(cur_enemy_index); + R20_ = 0; + R18_ = 0x4000; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->beetom_var_09 ^= 1u; + E->beetom_var_C = FUNC16(Beetom_Func_15); + } +} + +void Beetom_Func_22(uint16 k) { // 0xA8BAE7 + int16 v3; + + Enemy_Beetom *E = Get_Beetom(k); + int v2 = (uint16)(8 * E->beetom_var_B) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 3]; + R18_ = kCommonEnemySpeeds_Quadratic[v2 + 2]; + if (Enemy_MoveDown(k) & 1) { + E->beetom_var_C = FUNC16(Beetom_Func_15); + } else { + v3 = E->beetom_var_B - 4; + E->beetom_var_B = v3; + if (v3 < 0) { + E->beetom_var_B = 0; + E->beetom_var_05 = 1; + } + } +} + +void Beetom_Func_23(uint16 k) { // 0xA8BB20 + Enemy_Beetom *E = Get_Beetom(k); + int v2 = (uint16)(8 * E->beetom_var_B) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 1]; + R18_ = kCommonEnemySpeeds_Quadratic[v2]; + if (Enemy_MoveDown(k) & 1) { + E->beetom_var_C = FUNC16(Beetom_Func_3); + } else { + uint16 v3 = E->beetom_var_B + 4; + E->beetom_var_B = v3; + if (!sign16(v3 - 64)) + E->beetom_var_B = 64; + } +} + +void Beetom_Func_24(void) { // 0xA8BB55 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (E->beetom_var_05) + Beetom_Func_27(cur_enemy_index); + else + Beetom_Func_26(cur_enemy_index); + R20_ = -1; + R18_ = -16384; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->beetom_var_09 ^= 1u; + E->beetom_var_C = FUNC16(Beetom_Func_15); + } +} + +void Beetom_Func_25(void) { // 0xA8BB88 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (E->beetom_var_05) + Beetom_Func_27(cur_enemy_index); + else + Beetom_Func_26(cur_enemy_index); + R20_ = 0; + R18_ = 0x4000; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->beetom_var_09 ^= 1u; + E->beetom_var_C = FUNC16(Beetom_Func_15); + } +} + +void Beetom_Func_26(uint16 k) { // 0xA8BBB8 + int16 v3; + + Enemy_Beetom *E = Get_Beetom(k); + int v2 = (uint16)(8 * E->beetom_var_B) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 3]; + R18_ = kCommonEnemySpeeds_Quadratic[v2 + 2]; + if (Enemy_MoveDown(k) & 1) { + E->beetom_var_C = FUNC16(Beetom_Func_15); + } else { + v3 = E->beetom_var_B - 5; + E->beetom_var_B = v3; + if (v3 < 0) { + E->beetom_var_B = 0; + E->beetom_var_05 = 1; + } + } +} + +void Beetom_Func_27(uint16 k) { // 0xA8BBF1 + Enemy_Beetom *E = Get_Beetom(k); + int v2 = (uint16)(8 * E->beetom_var_B) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 1]; + R18_ = kCommonEnemySpeeds_Quadratic[v2]; + if (Enemy_MoveDown(k) & 1) { + E->beetom_var_C = FUNC16(Beetom_Func_3); + } else { + uint16 v3 = E->beetom_var_B + 5; + E->beetom_var_B = v3; + if (!sign16(v3 - 64)) + E->beetom_var_B = 64; + } +} + +void Beetom_Func_28(void) { // 0xA8BC26 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (E->beetom_var_05) + Beetom_Func_31(cur_enemy_index); + else + Beetom_Func_30(cur_enemy_index); + R20_ = -3; + R18_ = 0; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->beetom_var_09 ^= 1u; + E->beetom_var_C = FUNC16(Beetom_Func_15); + } +} + +void Beetom_Func_29(void) { // 0xA8BC5A + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (E->beetom_var_05) + Beetom_Func_31(cur_enemy_index); + else + Beetom_Func_30(cur_enemy_index); + R20_ = 3; + R18_ = 0; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->beetom_var_09 ^= 1u; + E->beetom_var_C = FUNC16(Beetom_Func_15); + } +} + +void Beetom_Func_30(uint16 k) { // 0xA8BC8A + int16 v3; + + Enemy_Beetom *E = Get_Beetom(k); + int v2 = (uint16)(8 * E->beetom_var_B) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 3]; + R18_ = kCommonEnemySpeeds_Quadratic[v2 + 2]; + if (Enemy_MoveDown(k) & 1) { + E->beetom_var_C = FUNC16(Beetom_Func_15); + } else { + v3 = E->beetom_var_B - 5; + E->beetom_var_B = v3; + if (v3 < 0) { + E->beetom_var_B = 0; + E->beetom_var_05 = 1; + } + } +} + +void Beetom_Func_31(uint16 k) { // 0xA8BCC3 + Enemy_Beetom *E = Get_Beetom(k); + int v2 = (uint16)(8 * E->beetom_var_B) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 1]; + R18_ = kCommonEnemySpeeds_Quadratic[v2]; + if (Enemy_MoveDown(k) & 1) { + E->beetom_var_C = FUNC16(Beetom_Func_3); + } else { + uint16 v3 = E->beetom_var_B + 3; + E->beetom_var_B = v3; + if (!sign16(v3 - 64)) + E->beetom_var_B = 64; + } +} + +void Beetom_Func_32(void) { // 0xA8BCF8 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (E->beetom_var_E) { + E->base.x_pos = samus_x_pos; + E->base.y_pos = samus_y_pos - 4; + Beetom_Func_34(); + } else { + R18_ = 0; + R20_ = 16; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->beetom_var_09 = 1; + R18_ = 0; + R20_ = -32; + Enemy_MoveRight_IgnoreSlopes(cur_enemy_index); + } + E->beetom_var_08 = 0; + E->beetom_var_C = FUNC16(Beetom_Func_16); + } +} + +void Beetom_Func_33(void) { // 0xA8BD42 + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (E->beetom_var_E) { + E->base.x_pos = samus_x_pos; + E->base.y_pos = samus_y_pos - 4; + Beetom_Func_34(); + } else { + R18_ = 0; + R20_ = -16; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->beetom_var_09 = 0; + R18_ = 0; + R20_ = 32; + Enemy_MoveRight_IgnoreSlopes(cur_enemy_index); + } + E->beetom_var_08 = 0; + E->beetom_var_C = FUNC16(Beetom_Func_16); + } +} + +void Beetom_Func_34(void) { // 0xA8BD8C + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (joypad1_lastkeys != E->beetom_var_F) { + E->beetom_var_F = joypad1_lastkeys; + --E->beetom_var_E; + } +} + +void Beetom_Func_35(void) { // 0xA8BD9D + R20_ = 3; + R18_ = 0; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (E->beetom_var_09) + E->beetom_var_C = FUNC16(Beetom_Func_7); + else + E->beetom_var_C = FUNC16(Beetom_Func_6); + } +} + +void Beetom_Func_36(void) { // 0xA8BDC5 + Beetom_Func_37(cur_enemy_index); +} + +void Beetom_Func_37(uint16 k) { // 0xA8BDCC + Enemy_Beetom *E = Get_Beetom(k); + int v2 = (uint16)(8 * E->beetom_var_B) >> 1; + R20_ = kCommonEnemySpeeds_Quadratic[v2 + 1]; + R18_ = kCommonEnemySpeeds_Quadratic[v2]; + if (Enemy_MoveDown(k) & 1) { + E->beetom_var_C = FUNC16(Beetom_Func_3); + } else { + uint16 v3 = E->beetom_var_B + 1; + E->beetom_var_B = v3; + if (!sign16(v3 - 64)) + E->beetom_var_B = 64; + } + uint16 v4; + if (E->beetom_var_09) + v4 = -2; + else + v4 = 2; + R20_ = v4; + R18_ = 0; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->beetom_var_09 ^= 1u; + E->beetom_var_C = FUNC16(Beetom_Func_15); + } +} + +void Beetom_Touch(void) { // 0xA8BE2E + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (!E->beetom_var_08) { + if (E->beetom_var_09) + E->beetom_var_C = FUNC16(Beetom_Func_14); + else + E->beetom_var_C = FUNC16(Beetom_Func_13); + E->beetom_var_08 = 1; + E->beetom_var_E = 64; + E->base.layer = 2; + E->beetom_var_06 = samus_x_pos - E->base.x_pos; + E->beetom_var_07 = samus_y_pos - E->base.y_pos; + } + if (samus_contact_damage_index) + goto LABEL_11; + if ((enemy_damage_routine_exec_count & 7) == 7 && !sign16(samus_health - 30)) + QueueSfx3_Max6(0x2Du); + if ((E->base.frame_counter & 0x3F) == 63) { +LABEL_11: + Enemy_NormalTouchAI_A8(); + samus_invincibility_timer = 0; + samus_knockback_timer = 0; + } +} + +void Beetom_Shot(void) { // 0xA8BEAC + Enemy_NormalShotAI_A8(); + Enemy_Beetom *E = Get_Beetom(cur_enemy_index); + if (E->base.frozen_timer + && (E->beetom_var_C == (uint16)FUNC16(Beetom_Func_33) + || E->beetom_var_C == (uint16)FUNC16(Beetom_Func_32))) { + E->beetom_var_C = FUNC16(Beetom_Func_15); + } + E->beetom_var_08 = 0; +} + +void MaridiaFloater_Init(void) { // 0xA8C1C9 + Enemy_MaridiaFloater *E = Get_MaridiaFloater(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.spritemap_pointer = addr_kSpritemap_Nothing_A8; + E->base.instruction_timer = 1; + E->base.timer = 0; + if (E->mfr_parameter_1) { + E->mfr_var_A = E->base.x_pos; + E->mfr_var_B = E->base.y_pos; + E->mfr_var_F = FUNC16(nullsub_256); + E->base.current_instruction = addr_stru_A8C199; + E->mfr_var_D = E->mfr_parameter_2; + } else { + E->mfr_var_E = 60; + E->mfr_var_F = FUNC16(MaridiaFloater_Func_3); + E->base.current_instruction = addr_kMaridiaFloater_Ilist_C173; + } +} + +void MaridiaFloater_Main(void) { // 0xA8C21C + Enemy_MaridiaFloater *E = Get_MaridiaFloater(cur_enemy_index); + CallEnemyPreInstr(E->mfr_var_F | 0xA80000); +} + +void MaridiaFloater_Func_1(uint16 k) { // 0xA8C223 + for (int i = 7; i >= 0; --i) + SpawnEnemyProjectileWithGfx(i, k, addr_kEproj_MaridiaFloatersSpikes); +} + +void MaridiaFloater_Func_2(uint16 k) { // 0xA8C234 + int v1 = k >> 1; + uint16 v2 = enemy_drawing_queue[v1 + 103]; + if (sign16(v2 + 0x3E6F)) { + uint16 v3 = (uint16)(v2 - 4 + 15997) >> 1; + if (!sign16(v3 - 6)) + v3 = 0; + enemy_drawing_queue[v1 + 93] = g_word_A8C277[v3 >> 1] + Get_MaridiaFloater(k)->base.y_pos; + } else { + uint16 v4 = (uint16)(v2 - 4 + 15983) >> 1; + if (!sign16(v4 - 6)) + v4 = 0; + enemy_drawing_queue[v1 + 93] = g_word_A8C27D[v4 >> 1] + Get_MaridiaFloater(k)->base.y_pos; + } +} + +void MaridiaFloater_Func_3(uint16 k) { // 0xA8C283 + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + bool v2 = E->mfr_var_E == 1; + bool v3 = (--E->mfr_var_E & 0x8000u) != 0; + if (v2 || v3) { + int v4 = k >> 1; + enemy_drawing_queue[v4 + 104] = 1; + enemy_drawing_queue[v4 + 103] = addr_kMaridiaFloater_Ilist_C183; + E->mfr_var_F = FUNC16(MaridiaFloater_Func_4); + E->mfr_var_E = 10; + } + MaridiaFloater_Func_2(k); +} + +void MaridiaFloater_Func_4(uint16 k) { // 0xA8C2A6 + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + bool v2 = E->mfr_var_E == 1; + bool v3 = (--E->mfr_var_E & 0x8000u) != 0; + if (v2 || v3) { + E->mfr_var_F = FUNC16(MaridiaFloater_Func_5); + E->mfr_var_A = g_word_A8C1C5; + E->mfr_var_B = g_word_A8C1C7; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kMaridiaFloater_Ilist_C163; + } + MaridiaFloater_Func_2(k); +} + +void MaridiaFloater_Func_5(uint16 k) { // 0xA8C2CF + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + if ((E->base.ai_handler_bits & 1) != 0) { + E->mfr_var_F = FUNC16(MaridiaFloater_Func_7); + MaridiaFloater_Func_7(k); + } else { + bool v2 = E->mfr_var_D == 1; + bool v3 = (--E->mfr_var_D & 0x8000u) != 0; + if (v2 || v3) { + E->mfr_var_D = 5; + int v4 = k >> 1; + uint16 v5 = g_word_A8C1A1[E->mfr_var_C] + enemy_drawing_queue_sizes[v4]; + enemy_drawing_queue[v4 + 91] = v5; + E->base.x_pos = v5; + uint16 v6 = E->mfr_var_C + 1; + if (!sign16(E->mfr_var_C - 11)) + v6 = 0; + E->mfr_var_C = v6; + } + uint16 mfr_var_B = E->mfr_var_B; + bool v8 = __CFADD__uint16(g_word_A8C1BB, mfr_var_B); + E->mfr_var_B = g_word_A8C1BB + mfr_var_B; + E->mfr_var_A += g_word_A8C1B9 + v8; + R20_ = E->mfr_var_A; + R18_ = E->mfr_var_B; + if (Enemy_MoveDown(k) & 1 + || (int16)(enemy_drawing_queue_sizes[(k >> 1) + 1] - g_word_A8C19F - E->base.y_pos) >= 0) { + uint16 mfr_var_C = E->mfr_var_C; + if (!mfr_var_C || mfr_var_C == 6) { + E->mfr_var_F = FUNC16(MaridiaFloater_Func_10); + E->mfr_var_E = 10; + int v10 = k >> 1; + enemy_drawing_queue[v10 + 104] = 1; + enemy_drawing_queue[v10 + 103] = addr_kMaridiaFloater_Ilist_C191; + } else { + E->mfr_var_F = FUNC16(MaridiaFloater_Func_6); + } + } + MaridiaFloater_Func_2(k); + } +} + +void MaridiaFloater_Func_6(uint16 k) { // 0xA8C36B + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + bool v2 = E->mfr_var_D == 1; + bool v3 = (--E->mfr_var_D & 0x8000u) != 0; + if (!v2 && !v3) { +LABEL_9:; + uint16 mfr_var_B = E->mfr_var_B; + bool v9 = __CFADD__uint16(g_word_A8C1BB, mfr_var_B); + E->mfr_var_B = g_word_A8C1BB + mfr_var_B; + E->mfr_var_A += g_word_A8C1B9 + v9; + R20_ = E->mfr_var_A; + R18_ = E->mfr_var_B; + Enemy_MoveDown(k); + goto LABEL_10; + } + E->mfr_var_D = 5; + int v4; + v4 = k >> 1; + { + uint16 v5 = g_word_A8C1A1[E->mfr_var_C] + enemy_drawing_queue_sizes[v4]; + enemy_drawing_queue[v4 + 91] = v5; + E->base.x_pos = v5; + } + if (E->mfr_var_C && E->mfr_var_C != 6) { + uint16 v7 = E->mfr_var_C + 1; + if (!sign16(v7 - 12)) + v7 = 0; + E->mfr_var_C = v7; + goto LABEL_9; + } + E->mfr_var_F = FUNC16(MaridiaFloater_Func_10); + E->mfr_var_E = 10; + enemy_drawing_queue[v4 + 104] = 1; + enemy_drawing_queue[v4 + 103] = addr_kMaridiaFloater_Ilist_C191; +LABEL_10: + MaridiaFloater_Func_2(k); +} + +void MaridiaFloater_Func_7(uint16 k) { // 0xA8C3E1 + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + if ((E->base.ai_handler_bits & 1) != 0) { + bool v2 = E->mfr_var_D == 1; + bool v3 = (--E->mfr_var_D & 0x8000u) != 0; + if (v2 || v3) { + E->mfr_var_D = 5; + int v4 = k >> 1; + uint16 v5 = g_word_A8C1A1[E->mfr_var_C] + enemy_drawing_queue_sizes[v4]; + enemy_drawing_queue[v4 + 91] = v5; + E->base.x_pos = v5; + uint16 v6 = E->mfr_var_C + 1; + if (!sign16(E->mfr_var_C - 11)) + v6 = 0; + E->mfr_var_C = v6; + } + uint16 mfr_var_B = E->mfr_var_B; + bool v8 = __CFADD__uint16(g_word_A8C1BB, mfr_var_B); + E->mfr_var_B = g_word_A8C1BB + mfr_var_B; + E->mfr_var_A += g_word_A8C1B9 + v8; + R20_ = E->mfr_var_A; + R18_ = E->mfr_var_B; + if (Enemy_MoveDown(k) & 1 + || (int16)(enemy_drawing_queue_sizes[(k >> 1) + 1] + - enemy_drawing_queue_sizes[(k >> 1) + 3] + - E->base.y_pos) >= 0) { + uint16 mfr_var_C = E->mfr_var_C; + if (!mfr_var_C || mfr_var_C == 6) + E->mfr_var_F = FUNC16(MaridiaFloater_Func_9); + else + E->mfr_var_F = FUNC16(MaridiaFloater_Func_8); + } + MaridiaFloater_Func_2(k); + } else { + E->mfr_var_F = FUNC16(MaridiaFloater_Func_6); + } +} + +void MaridiaFloater_Func_8(uint16 k) { // 0xA8C469 + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + if ((E->base.ai_handler_bits & 1) == 0) { + E->mfr_var_F = FUNC16(MaridiaFloater_Func_6); + return; + } + bool v2 = E->mfr_var_D == 1; + bool v3 = (--E->mfr_var_D & 0x8000u) != 0; + if (!v2 && !v3) + goto LABEL_11; + E->mfr_var_D = 5; + int v4; + v4 = k >> 1; + uint16 v5; + v5 = g_word_A8C1A1[E->mfr_var_C] + enemy_drawing_queue_sizes[v4]; + enemy_drawing_queue[v4 + 91] = v5; + E->base.x_pos = v5; + if (E->mfr_var_C && E->mfr_var_C != 6) { + { + uint16 v7 = E->mfr_var_C + 1; + if (!sign16(v7 - 12)) + v7 = 0; + E->mfr_var_C = v7; + } +LABEL_11:; + uint16 mfr_var_B = E->mfr_var_B; + bool v9 = __CFADD__uint16(g_word_A8C1BB, mfr_var_B); + E->mfr_var_B = g_word_A8C1BB + mfr_var_B; + E->mfr_var_A += g_word_A8C1B9 + v9; + R20_ = E->mfr_var_A; + R18_ = E->mfr_var_B; + Enemy_MoveDown(k); + goto LABEL_12; + } + E->mfr_var_F = FUNC16(MaridiaFloater_Func_9); +LABEL_12: + MaridiaFloater_Func_2(k); +} + +void MaridiaFloater_Func_9(uint16 k) { // 0xA8C4DC + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + if ((E->base.ai_handler_bits & 1) == 0) { + E->mfr_var_F = FUNC16(MaridiaFloater_Func_10); + E->mfr_var_E = 10; + int v2 = k >> 1; + enemy_drawing_queue[v2 + 104] = 1; + enemy_drawing_queue[v2 + 103] = addr_kMaridiaFloater_Ilist_C191; + } + MaridiaFloater_Func_2(k); +} + +void MaridiaFloater_Func_10(uint16 k) { // 0xA8C500 + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + bool v2 = E->mfr_var_E == 1; + bool v3 = (--E->mfr_var_E & 0x8000u) != 0; + if (v2 || v3) { + E->mfr_var_F = FUNC16(MaridiaFloater_Func_11); + E->mfr_var_A = g_word_A8C1C1; + E->mfr_var_B = g_word_A8C1C3; + } + MaridiaFloater_Func_2(k); +} + +void MaridiaFloater_Func_11(uint16 k) { // 0xA8C51D + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + uint16 mfr_var_B = E->mfr_var_B; + bool v3 = __CFADD__uint16(g_word_A8C1BF, mfr_var_B); + E->mfr_var_B = g_word_A8C1BF + mfr_var_B; + E->mfr_var_A += g_word_A8C1BD + v3; + R20_ = E->mfr_var_A; + R18_ = E->mfr_var_B; + Enemy_MoveDown(k); + int v4 = k >> 1; + if ((int16)(E->base.y_pos - enemy_drawing_queue_sizes[v4 + 1]) >= 0) { + E->base.y_pos = enemy_drawing_queue_sizes[v4 + 1]; + E->mfr_var_F = FUNC16(MaridiaFloater_Func_3); + E->mfr_var_E = 60; + E->base.instruction_timer = 1; + E->base.current_instruction = addr_kMaridiaFloater_Ilist_C173; + } + MaridiaFloater_Func_2(k); +} + +void MaridiaFloater_Func_12(uint16 k) { // 0xA8C569 + int v1 = k >> 1; + if (!sign16(enemy_drawing_queue[v1 + 103] + 0x3E6F)) { + uint16 v2 = (uint16)(enemy_drawing_queue[v1 + 103] - 4 + 15983) >> 1; + if (v2) { + enemy_drawing_queue[v1 + 103] = g_off_A8C599[v2 >> 1]; + enemy_drawing_queue[v1 + 104] = 1; + } + } + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + E->mfr_var_F = FUNC16(MaridiaFloater_Func_13); + E->mfr_var_E = 32; + MaridiaFloater_Func_2(k); +} + +void MaridiaFloater_Func_13(uint16 k) { // 0xA8C59F + uint16 v5; + + Enemy_MaridiaFloater *E = Get_MaridiaFloater(k); + bool v2 = E->mfr_var_E == 1; + bool v3 = (--E->mfr_var_E & 0x8000u) != 0; + if (v2 || v3) { + int v4 = k >> 1; + enemy_drawing_queue[v4 + 100] = 0; + enemy_drawing_queue[v4 + 97] |= 0x200u; + MaridiaFloater_Func_1(k); + printf("A undefined!\n"); v5 = 0; + EnemyDeathAnimation(k, v5); + } else { + MaridiaFloater_Func_2(k); + } +} + +void MaridiaFloater_Touch(void) { // 0xA8C5BE + Enemy_MaridiaFloater *E = Get_MaridiaFloater(cur_enemy_index); + if (!E->mfr_parameter_2) { + uint16 palette_index = E->base.palette_index; + NormalEnemyTouchAi(); + if (!E->base.health) { + enemy_drawing_queue[(cur_enemy_index >> 1) + 97] |= 0x200u; + E->base.palette_index = palette_index; + MaridiaFloater_Func_1(cur_enemy_index); + E->base.palette_index = 2560; + } + } +} + +void MaridiaFloater_Shot(void) { // 0xA8C5EF + Enemy_MaridiaFloater *E = Get_MaridiaFloater(cur_enemy_index); + if (!E->mfr_parameter_2) { + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + if ((E->base.ai_handler_bits & 4) != 0) { + int v2 = cur_enemy_index >> 1; + enemy_drawing_queue[v2 + 109] = E->base.frozen_timer; + enemy_drawing_queue[v2 + 99] |= 4u; + } + if ((E->base.ai_handler_bits & 2) != 0) { + int v3 = cur_enemy_index >> 1; + enemy_drawing_queue[v3 + 108] = E->base.flash_timer; + enemy_drawing_queue[v3 + 99] |= 2u; + } + if (!E->base.health) { + E->mfr_var_F = FUNC16(MaridiaFloater_Func_12); + E->mfr_parameter_2 = 1; + } + } +} + +void MaridiaFloater_Powerbomb(void) { // 0xA8C63F + Enemy_NormalPowerBombAI_A8(); + Enemy_MaridiaFloater *E = Get_MaridiaFloater(cur_enemy_index); + if (E->base.health) { + int v1 = cur_enemy_index >> 1; + enemy_drawing_queue[v1 + 111] = E->base.shake_timer; + enemy_drawing_queue[v1 + 110] = E->base.invincibility_timer; + enemy_drawing_queue[v1 + 108] = E->base.flash_timer; + enemy_drawing_queue[v1 + 109] = E->base.frozen_timer; + enemy_drawing_queue[v1 + 99] = E->base.ai_handler_bits; + } else { + enemy_drawing_queue[(cur_enemy_index >> 1) + 97] |= 0x200u; + } +} + +void WreckedShipRobot_Init(void) { // 0xA8CB77 + if ((*(uint16 *)&boss_bits_for_area[area_index] & 1) != 0) { + enemy_gfx_drawn_hook.bank = -88; + enemy_gfx_drawn_hook.addr = FUNC16(WreckedShipRobot_Func_1); + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + E->base.properties |= 0xA000u; + E->base.instruction_timer = 4; + E->base.timer = 0; + E->base.current_instruction = addr_kWreckedShipRobot_Ilist_C6E5; + E->wsrt_var_A = -512; + wrecked_ship_robot_palanim_timer = 1; + *(uint16 *)&wrecked_ship_robot_palanim_table_index = 0; + E->wsrt_var_B = 0; + wrecked_ship_robot_palanim_palindex = E->base.palette_index; + } else { + WreckedShipRobotDeactivated_Init(); + } +} + +void WreckedShipRobotDeactivated_Init(void) { // 0xA8CBCC + EnemyData *v0 = gEnemyData(cur_enemy_index); + uint16 parameter_1 = v0->parameter_1; + if (sign16(parameter_1) || !sign16(parameter_1 - 4)) + parameter_1 = 0; + v0->parameter_1 = parameter_1; + v0->current_instruction = g_off_A8CC30[parameter_1]; + v0->properties |= 0x8000u; + v0->instruction_timer = 1; + v0->timer = 0; + wrecked_ship_robot_palanim_timer = 0; + v0->ai_var_E = 0; + v0->ai_preinstr = 1; + int v2 = (uint16)(16 * (uint8)((uint16)(wrecked_ship_robot_palanim_palindex & 0xFF00) >> 8)) >> 1; + palette_buffer[v2 + 137] = 10; + palette_buffer[v2 + 138] = 10; + palette_buffer[v2 + 139] = 10; + palette_buffer[v2 + 140] = 10; +} + +void WreckedShipRobot_Main(void) { // 0xA8CC36 + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + R18_ = E->wsrt_var_E; + R20_ = E->wsrt_var_F; + if (!(Enemy_MoveDown(cur_enemy_index) & 1)) { + ++E->base.instruction_timer; + uint16 wsrt_var_E = E->wsrt_var_E; + E->wsrt_var_E = wsrt_var_E + 0x8000; + E->wsrt_var_F += __CFADD__uint16(wsrt_var_E, 0x8000); + } +} + +void WreckedShipRobot_Func_1(void) { // 0xA8CC67 + uint16 i; + int16 v2; + + if (!door_transition_flag_enemies) { + if (wrecked_ship_robot_palanim_timer) { + if (!--wrecked_ship_robot_palanim_timer) { + int v1; + for (i = *(uint16 *)&wrecked_ship_robot_palanim_table_index; ; i = 0) { + v1 = i >> 1; + v2 = g_word_A8CCC1[v1]; + if (v2 >= 0) + break; + } + int v3 = (uint16)(16 * (uint8)((uint16)(wrecked_ship_robot_palanim_palindex & 0xFF00) >> 8)) >> 1; + palette_buffer[v3 + 137] = v2; + palette_buffer[v3 + 138] = g_word_A8CCC1[v1 + 1]; + palette_buffer[v3 + 139] = g_word_A8CCC1[v1 + 2]; + palette_buffer[v3 + 140] = g_word_A8CCC1[v1 + 3]; + wrecked_ship_robot_palanim_timer = g_word_A8CCC1[v1 + 4]; + *(uint16 *)&wrecked_ship_robot_palanim_table_index = i + 10; + } + } + } +} + +void WreckedShipRobot_Func_2(uint16 k) { // 0xA8CCFF + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(k); + uint16 wsrt_var_B = E->wsrt_var_B; + if (wsrt_var_B) + E->wsrt_var_B = wsrt_var_B - 1; +} + +uint16 WreckedShipRobot_Instr_4(uint16 k, uint16 j) { // 0xA8CD09 + WreckedShipRobot_Func_2(cur_enemy_index); + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + E->wsrt_var_A = -512; + R18_ = 0; + R20_ = -4; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->wsrt_var_B += 8; + return addr_kWreckedShipRobot_Ilist_C73F; + } else { + if (CheckIfEnemyTouchesSamus(cur_enemy_index)) { + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = -4; + } + E->wsrt_var_D = E->base.y_pos; + uint16 x_pos = E->base.x_pos; + E->wsrt_var_C = x_pos; + E->base.x_pos = x_pos - E->base.x_width - E->base.x_width; + R18_ = 0; + R20_ = 1; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->base.x_pos = E->wsrt_var_C; + E->base.y_pos = E->wsrt_var_D; + } else { + E->wsrt_var_B += 8; + E->base.x_pos = E->wsrt_var_C; + E->base.y_pos = E->wsrt_var_D; + E->wsrt_var_A = 512; + return addr_kWreckedShipRobot_Ilist_CB65; + } + } + return j; +} + +uint16 WreckedShipRobot_Instr_9(uint16 k, uint16 j) { // 0xA8CDA4 + WreckedShipRobot_Func_2(cur_enemy_index); + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + E->wsrt_var_A = -512; + R18_ = 0; + R20_ = -4; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->wsrt_var_B += 8; + return addr_kWreckedShipRobot_Ilist_C73F; + } else if (CheckIfEnemyTouchesSamus(cur_enemy_index)) { + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = -4; + } + return j; +} + +uint16 WreckedShipRobot_Instr_6(uint16 k, uint16 j) { // 0xA8CDEA + WreckedShipRobot_Func_2(cur_enemy_index); + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + E->wsrt_var_A = -512; + R18_ = 0; + R20_ = 4; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->wsrt_var_B += 8; + return addr_stru_A8C6E9; + } else { + if (CheckIfEnemyTouchesSamus(cur_enemy_index)) { + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = 4; + } + E->wsrt_var_D = E->base.y_pos; + uint16 x_pos = E->base.x_pos; + E->wsrt_var_C = x_pos; + E->base.x_pos = E->base.x_width + E->base.x_width + x_pos; + R18_ = 0; + R20_ = 1; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->base.x_pos = E->wsrt_var_C; + E->base.y_pos = E->wsrt_var_D; + } else { + E->wsrt_var_B += 8; + E->base.x_pos = E->wsrt_var_C; + E->base.y_pos = E->wsrt_var_D; + E->wsrt_var_A = -512; + return addr_kWreckedShipRobot_Ilist_C91B; + } + } + return j; +} + +uint16 WreckedShipRobot_Instr_8(uint16 k, uint16 j) { // 0xA8CE85 + WreckedShipRobot_Func_2(cur_enemy_index); + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + E->wsrt_var_A = -512; + R18_ = 0; + R20_ = 4; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->wsrt_var_B += 8; + return addr_stru_A8C6E9; + } else if (CheckIfEnemyTouchesSamus(cur_enemy_index)) { + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = 4; + } + return j; +} + +uint16 WreckedShipRobot_Instr_7(uint16 k, uint16 j) { // 0xA8CECB + return addr_kWreckedShipRobot_Ilist_C92D; +} + +uint16 WreckedShipRobot_Instr_15(uint16 k, uint16 j) { // 0xA8CECF + WreckedShipRobot_Func_2(cur_enemy_index); + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + E->wsrt_var_A = 512; + R18_ = 0; + R20_ = 4; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->wsrt_var_B += 8; + return addr_kWreckedShipRobot_Ilist_C985; + } else { + if (CheckIfEnemyTouchesSamus(cur_enemy_index)) { + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = 4; + } + E->wsrt_var_D = E->base.y_pos; + uint16 x_pos = E->base.x_pos; + E->wsrt_var_C = x_pos; + E->base.x_pos = E->base.x_width + E->base.x_width + x_pos; + R18_ = 0; + R20_ = 1; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->base.x_pos = E->wsrt_var_C; + E->base.y_pos = E->wsrt_var_D; + } else { + E->wsrt_var_B += 8; + E->base.x_pos = E->wsrt_var_C; + E->base.y_pos = E->wsrt_var_D; + E->wsrt_var_A = -512; + return addr_kWreckedShipRobot_Ilist_C91B; + } + } + return j; +} + +uint16 WreckedShipRobot_Instr_18(uint16 k, uint16 j) { // 0xA8CF6A + WreckedShipRobot_Func_2(cur_enemy_index); + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + E->wsrt_var_A = 512; + R18_ = 0; + R20_ = 4; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->wsrt_var_B += 8; + return addr_kWreckedShipRobot_Ilist_C985; + } else if (CheckIfEnemyTouchesSamus(cur_enemy_index)) { + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = 4; + } + return j; +} + +uint16 WreckedShipRobot_Instr_16(uint16 k, uint16 j) { // 0xA8CFB0 + WreckedShipRobot_Func_2(cur_enemy_index); + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + E->wsrt_var_A = 512; + R18_ = 0; + R20_ = -4; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->wsrt_var_B += 8; + return addr_stru_A8C6E9; + } else { + if (CheckIfEnemyTouchesSamus(cur_enemy_index)) { + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = -4; + } + E->wsrt_var_D = E->base.y_pos; + uint16 x_pos = E->base.x_pos; + E->wsrt_var_C = x_pos; + E->base.x_pos = x_pos - E->base.x_width - E->base.x_width; + R18_ = 0; + R20_ = 1; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->base.y_pos = E->wsrt_var_D; + E->base.x_pos = E->wsrt_var_C; + } else { + E->wsrt_var_B += 8; + E->base.y_pos = E->wsrt_var_D; + E->base.x_pos = E->wsrt_var_C; + E->wsrt_var_A = 512; + return addr_kWreckedShipRobot_Ilist_CB65; + } + } + return j; +} + +uint16 WreckedShipRobot_Instr_17(uint16 k, uint16 j) { // 0xA8D04B + WreckedShipRobot_Func_2(cur_enemy_index); + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + E->wsrt_var_A = 512; + R18_ = 0; + R20_ = -4; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + E->wsrt_var_B += 8; + return addr_stru_A8C6E9; + } else if (CheckIfEnemyTouchesSamus(cur_enemy_index)) { + extra_samus_x_subdisplacement = 0; + extra_samus_x_displacement = -4; + } + return j; +} + +uint16 WreckedShipRobot_Instr_3(uint16 k, uint16 j) { // 0xA8D091 + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + if ((int16)(layer1_x_pos - E->base.x_pos) < 0 + && (int16)(layer1_x_pos + 256 - E->base.x_pos) >= 0 + && (int16)(layer1_y_pos - E->base.y_pos) < 0 + && (int16)(layer1_y_pos + 224 - E->base.y_pos) >= 0) { + QueueSfx2_Max6(0x68u); + } + return j; +} + +uint16 WreckedShipRobot_Instr_10(uint16 k, uint16 j) { // 0xA8D0C2 + return addr_stru_A8C6E9; +} + +uint16 WreckedShipRobot_Instr_14(uint16 k, uint16 j) { // 0xA8D0C6 + R50 = addr_kWreckedShipRobot_Ilist_CB1D; + R48 = addr_kEproj_WreckedShipRobotLaserUpRight; + return WreckedShipRobot_CommonInstr(k, j); +} + +uint16 WreckedShipRobot_Instr_2(uint16 k, uint16 j) { // 0xA8D0D2 + R50 = addr_kWreckedShipRobot_Ilist_C8D1; + R48 = addr_kEproj_WreckedShipRobotLaserUpLeft; + return WreckedShipRobot_CommonInstr(k, j); +} + +uint16 WreckedShipRobot_CommonInstr(uint16 k, uint16 j) { // 0xA8D0DC + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(k); + if (E->wsrt_var_B) { + WreckedShipRobot_Func_2(k); + } else { + uint16 v3 = (random_number & 0x1F) + 16; + E->wsrt_var_B = v3; + SpawnEnemyProjectileWithGfx(v3, cur_enemy_index, R48); + return R50; + } + return j; +} + +uint16 WreckedShipRobot_Instr_13(uint16 k, uint16 j) { // 0xA8D100 + R50 = addr_kWreckedShipRobot_Ilist_CB09; + return WreckedShipRobot_D10C(k, j); +} + +uint16 WreckedShipRobot_Instr_1(uint16 k, uint16 j) { // 0xA8D107 + R50 = addr_kWreckedShipRobot_Ilist_C8BD; + return WreckedShipRobot_D10C(k, j); +} + +uint16 WreckedShipRobot_D10C(uint16 k, uint16 j) { // 0xA8D10C + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(k); + if (E->wsrt_var_B) { + WreckedShipRobot_Func_2(k); + } else { + uint16 v3 = (random_number & 0x1F) + 16; + E->wsrt_var_B = v3; + SpawnEnemyProjectileWithGfx(v3, cur_enemy_index, addr_kEproj_WreckedShipRobotLaserHorizontal); + return R50; + } + return j; +} + +uint16 WreckedShipRobot_Instr_12(uint16 k, uint16 j) { // 0xA8D131 + R48 = addr_kEproj_WreckedShipRobotLaserDownRight; + R50 = addr_kWreckedShipRobot_Ilist_CAFD; + return WreckedShipRobot_D147(k, j); +} + +uint16 WreckedShipRobot_Instr_5(uint16 k, uint16 j) { // 0xA8D13D + R48 = addr_kEproj_WreckedShipRobotLaserDownLeft; + R50 = addr_kWreckedShipRobot_Ilist_C8B1; + return WreckedShipRobot_D147(k, j); +} + +uint16 WreckedShipRobot_D147(uint16 k, uint16 j) { // 0xA8D147 + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(k); + if (E->wsrt_var_B) { + WreckedShipRobot_Func_2(k); + } else { + uint16 v3 = (random_number & 0x1F) + 16; + E->wsrt_var_B = v3; + SpawnEnemyProjectileWithGfx(v3, cur_enemy_index, R48); + return R50; + } + return j; +} + +uint16 WreckedShipRobot_Instr_11(uint16 k, uint16 j) { // 0xA8D16B + WreckedShipRobot_Func_2(cur_enemy_index); + return j; +} + +void WreckedShipRobotDeactivated_Touch(void) { // 0xA8D174 + if ((int16)(gEnemyData(cur_enemy_index)->x_pos - samus_x_pos) < 0) + extra_samus_x_displacement = 4; + else + extra_samus_x_displacement = -4; +} + +void WreckedShipRobotDeactivated_Shot(void) { // 0xA8D18D + NormalEnemyShotAi(); +} + +void WreckedShipRobot_Shot(void) { // 0xA8D192 + if ((*(uint16 *)&boss_bits_for_area[area_index] & 1) != 0) { + NormalEnemyShotAi(); + Enemy_WreckedShipRobot *E = Get_WreckedShipRobot(cur_enemy_index); + if (E->base.health) { + uint16 v1; + if ((E->wsrt_var_A & 0x8000u) != 0) { + if ((int16)(samus_x_pos - E->base.x_pos) >= 0) + v1 = addr_kWreckedShipRobot_Ilist_C833; + else + v1 = addr_kWreckedShipRobot_Ilist_C7BB; + } else if ((int16)(samus_x_pos - E->base.x_pos) < 0) { + v1 = addr_kWreckedShipRobot_Ilist_CA7D; + } else { + v1 = addr_kWreckedShipRobot_Ilist_CA01; + } + E->base.current_instruction = v1; + E->base.instruction_timer = 1; + E->wsrt_var_B += 64; + } + } +} + +void MaridiaPuffer_Init(void) { // 0xA8D8C9 + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(cur_enemy_index); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMaridiaPuffer_Ilist_D841; + int v1 = (uint16)(4 * E->mpr_parameter_1) >> 1; + uint16 v2 = g_word_A8D895[v1]; + E->mpr_var_05 = v2; + E->mpr_var_F = v2; + E->mpr_var_06 = g_word_A8D895[v1 + 1]; + E->mpr_var_E = 16; + E->mpr_var_A = FUNC16(MaridiaPuffer_Func_1); + E->mpr_var_00 = g_word_A8D885[E->mpr_parameter_2]; +} + +void CallMaridiaPuffer(uint32 ea) { + switch (ea) { + case fnMaridiaPuffer_Func_1: MaridiaPuffer_Func_1(); return; + case fnMaridiaPuffer_Func_2: MaridiaPuffer_Func_2(); return; + case fnMaridiaPuffer_Func_3: MaridiaPuffer_Func_3(); return; + case fnMaridiaPuffer_Func_4: MaridiaPuffer_Func_4(); return; + default: Unreachable(); + } +} + +void MaridiaPuffer_Main(void) { // 0xA8D90B + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(cur_enemy_index); + uint16 v1 = E->mpr_var_07 - 1; + E->mpr_var_07 = v1; + if (!v1) { + E->mpr_var_07 = 1; + E->mpr_var_03 = 0; + } + CallMaridiaPuffer(E->mpr_var_A | 0xA80000); +} + +void MaridiaPuffer_Func_1(void) { // 0xA8D92B + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(cur_enemy_index); + if (E->mpr_var_E-- == 1) { + E->mpr_var_E = 16; + E->mpr_var_A = FUNC16(MaridiaPuffer_Func_2); + } +} + +void MaridiaPuffer_Func_2(void) { // 0xA8D940 + uint8 v1 = CalculateAngleOfSamusFromEnemy(cur_enemy_index) - 64; + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(cur_enemy_index); + E->mpr_var_01 = v1; + E->mpr_var_02 = v1; + E->mpr_var_A = FUNC16(MaridiaPuffer_Func_3); + E->mpr_var_C = 24; +} + +void MaridiaPuffer_Func_3(void) { // 0xA8D963 + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(cur_enemy_index); + if ((int16)(E->mpr_var_D - E->mpr_var_00) < 0) + MaridiaPuffer_Func_8(cur_enemy_index); + MaridiaPuffer_Func_6(); + MaridiaPuffer_Func_7(); + MaridiaPuffer_Func_5(); +} + +void MaridiaPuffer_Func_4(void) { // 0xA8D97C + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(cur_enemy_index); + if ((int16)E->mpr_var_D > 0 && (int16)E->mpr_var_B > 0) { + MaridiaPuffer_Func_6(); + MaridiaPuffer_Func_7(); + MaridiaPuffer_Func_9(cur_enemy_index); + } else { + E->mpr_var_A = FUNC16(MaridiaPuffer_Func_1); + E->mpr_var_B = 0; + E->mpr_var_C = 0; + E->mpr_var_D = 0; + } +} + +void MaridiaPuffer_Func_5(void) { // 0xA8D9AA + uint8 v1 = CalculateAngleOfSamusFromEnemy(cur_enemy_index) - 64; + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(cur_enemy_index); + E->mpr_var_01 = v1; + uint16 v3 = SignExtend8(v1 - E->mpr_var_02); + uint16 v4 = Abs16(v3); + if (!sign16(v4 - 48)) { + E->mpr_var_A = FUNC16(MaridiaPuffer_Func_4); + E->mpr_var_C = 24; + } +} + +void MaridiaPuffer_Func_6(void) { // 0xA8D9DB + char v2; // t0 + + R26_ = 0; + R18_ = kSine16bit[(uint8)(Get_MaridiaPuffer(cur_enemy_index)->mpr_var_02 + 64)]; + if ((R18_ & 0x8000u) != 0) + ++R26_; + uint16 v1 = Abs16(R18_) & 0xFF00; + v2 = v1; + LOBYTE(v1) = HIBYTE(v1); + HIBYTE(v1) = v2; + R22_ = v1; + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(cur_enemy_index); + R24_ = E->mpr_var_D; + MaridiaPuffer_Func_10(); + if (R26_) + MaridiaPuffer_Func_11(); + uint16 x_subpos = E->base.x_subpos; + bool v5 = __CFADD__uint16(R28_, x_subpos); + E->base.x_subpos = R28_ + x_subpos; + E->base.x_pos += g_word_7E001E + v5; +} + +void MaridiaPuffer_Func_7(void) { // 0xA8DA28 + char v2; // t0 + + R26_ = 0; + R18_ = kSine16bit[(uint16)(2 * (uint8)Get_MaridiaPuffer(cur_enemy_index)->mpr_var_02) >> 1]; + if ((R18_ & 0x8000u) != 0) + ++R26_; + uint16 v1 = Abs16(R18_) & 0xFF00; + v2 = v1; + LOBYTE(v1) = HIBYTE(v1); + HIBYTE(v1) = v2; + R22_ = v1; + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(cur_enemy_index); + R24_ = E->mpr_var_D; + MaridiaPuffer_Func_10(); + if (R26_) + MaridiaPuffer_Func_11(); + uint16 y_subpos = E->base.y_subpos; + bool v5 = __CFADD__uint16(R28_, y_subpos); + E->base.y_subpos = R28_ + y_subpos; + E->base.y_pos += g_word_7E001E + v5; +} + +void MaridiaPuffer_Func_8(uint16 k) { // 0xA8DA71 + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(k); + if (E->mpr_var_F-- == 1) { + E->mpr_var_F = E->mpr_var_05; + E->mpr_var_B += E->mpr_var_C; + E->mpr_var_D += E->mpr_var_B; + } +} + +void MaridiaPuffer_Func_9(uint16 k) { // 0xA8DA92 + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(k); + if (E->mpr_var_F-- == 1) { + E->mpr_var_F = E->mpr_var_06; + E->mpr_var_B -= E->mpr_var_C; + E->mpr_var_D -= E->mpr_var_B; + } +} + +void MaridiaPuffer_Func_10(void) { // 0xA8DAB3 + int16 v1; + + uint16 prod1 = Mult8x8(R22_, R24_); + uint16 prod2 = Mult8x8(R22_, HIBYTE(R24_)); + R28_ = prod1; + g_word_7E001E = (uint8)((uint16)(prod2 & 0xFF00) >> 8); + uint16 RegWord = (uint8)prod2; + LOBYTE(v1) = HIBYTE(RegWord); + HIBYTE(v1) = RegWord; + bool v2 = __CFADD__uint16(R28_, v1); + R28_ += v1; + if (v2) + ++g_word_7E001E; +} + +void MaridiaPuffer_Func_11(void) { // 0xA8DAF6 + if (R28_) { + R28_ = -R28_; + } else { + if (!g_word_7E001E) + return; + --R28_; + } + g_word_7E001E = ~g_word_7E001E; +} + +void MaridiaPuffer_Shot(void) { // 0xA8DB14 + Enemy_MaridiaPuffer *E = Get_MaridiaPuffer(cur_enemy_index); + E->mpr_var_40 = E->base.health; + Enemy_NormalShotAI_A8(); + if (E->base.health == E->mpr_var_40 && !E->mpr_var_03) { + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kMaridiaPuffer_Ilist_D855; + E->mpr_var_02 = g_word_A8D871[(uint16)(2 + * (projectile_dir[(uint16)(2 + * collision_detection_index) >> 1] & 0xF)) >> 1]; + E->mpr_var_B = 256; + E->mpr_var_D = 1536; + E->mpr_var_A = FUNC16(MaridiaPuffer_Func_4); + E->mpr_var_07 = 48; + E->mpr_var_03 = 1; + } +} + +void WalkingLavaSeahorse_Init(void) { // 0xA8DCCD + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(cur_enemy_index); + E->wlse_var_04 = 0; + E->wlse_var_F = E->base.y_pos; + E->wlse_var_02 = E->base.x_pos; + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.current_instruction = addr_kWalkingLavaSeahorse_Ilist_DBE7; + E->wlse_var_A = FUNC16(WalkingLavaSeahorse_Func_3); + WalkingLavaSeahorse_Func_1(cur_enemy_index); + do { + uint16 wlse_var_C = E->wlse_var_C; + bool v4 = __CFADD__uint16(E->base.y_subpos, wlse_var_C); + E->base.y_subpos += wlse_var_C; + E->base.y_pos += v4 + E->wlse_var_B; + } while ((WalkingLavaSeahorse_Func_2(cur_enemy_index) & 0x8000u) != 0); + while (1) { + R18_ = E->wlse_var_C; + R20_ = E->wlse_var_B; + if (Enemy_MoveDown(cur_enemy_index) & 1) + break; + WalkingLavaSeahorse_Func_2(cur_enemy_index); + } + E->wlse_var_03 = E->base.y_pos; + E->base.y_pos = E->wlse_var_F; +} + +void WalkingLavaSeahorse_Func_1(uint16 k) { // 0xA8DD37 + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(k); + E->wlse_var_B = -12; + E->wlse_var_C = 0; + E->wlse_var_D = 0; + E->wlse_var_E = 0; + E->wlse_var_00 = 0; + E->wlse_var_01 = FUNC16(Enemy_GrappleReact_NoInteract_A8); +} + +uint16 WalkingLavaSeahorse_Func_2(uint16 k) { // 0xA8DD55 + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(k); + uint16 wlse_var_C = E->wlse_var_C; + bool v3 = __CFADD__uint16(E->wlse_var_01, wlse_var_C); + E->wlse_var_C = E->wlse_var_01 + wlse_var_C; + uint16 result = E->wlse_var_00 + v3 + E->wlse_var_B; + E->wlse_var_B = result; + return result; +} + +void CallWalkingLavaSeahorseFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnnullsub_257: return; + case fnWalkingLavaSeahorse_Func_3: WalkingLavaSeahorse_Func_3(k); return; + case fnWalkingLavaSeahorse_Func_4: WalkingLavaSeahorse_Func_4(k); return; + case fnWalkingLavaSeahorse_Func_6: WalkingLavaSeahorse_Func_6(k); return; + case fnWalkingLavaSeahorse_Func_7: WalkingLavaSeahorse_Func_7(k); return; + case fnWalkingLavaSeahorse_Func_8: WalkingLavaSeahorse_Func_8(k); return; + case fnWalkingLavaSeahorse_Func_9: WalkingLavaSeahorse_Func_9(k); return; + default: Unreachable(); + } +} + +void WalkingLavaSeahorse_Main(void) { // 0xA8DD6B + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(cur_enemy_index); + CallWalkingLavaSeahorseFunc(E->wlse_var_A | 0xA80000, cur_enemy_index); +} + +void WalkingLavaSeahorse_Func_3(uint16 k) { // 0xA8DD71 + uint16 v4; + int16 v5; + + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(k); + uint16 xxx; + uint16 v3 = abs16(E->wlse_var_03 - samus_y_pos); + if (sign16(v3 - 32) && (int16)(abs16((xxx = samus_x_pos - E->base.x_pos)) - g_word_A8DCC7) < 0) { + WalkingLavaSeahorse_Func_1(k); + v4 = addr_stru_A8DC4B; + v5 = -2; + if (!sign16(xxx)) { + v4 = addr_stru_A8DCBB; + v5 = 2; + } + E->wlse_var_D = v5; + E->base.current_instruction = v4; + E->base.instruction_timer = 1; + E->wlse_var_A = FUNC16(WalkingLavaSeahorse_Func_4); + QueueSfx2_Max6(0x5Eu); + } +} + +void WalkingLavaSeahorse_Func_4(uint16 k) { // 0xA8DDC6 + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(k); + uint16 wlse_var_C = E->wlse_var_C; + bool v3 = __CFADD__uint16(E->base.y_subpos, wlse_var_C); + E->base.y_subpos += wlse_var_C; + E->base.y_pos += v3 + E->wlse_var_B; + if ((WalkingLavaSeahorse_Func_2(k) & 0x8000u) == 0) + sub_A8DDDE(k); +} + +void sub_A8DDDE(uint16 k) { // 0xA8DDDE + EnemyData *v1 = gEnemyData(k); + v1->ai_var_A = FUNC16(WalkingLavaSeahorse_Func_6); + uint16 v2 = addr_kWalkingLavaSeahorse_Ilist_DC51; + if ((v1->ai_var_D & 0x8000u) == 0) + v2 = addr_kWalkingLavaSeahorse_Ilist_DCC1; + v1->current_instruction = v2; + v1->instruction_timer = 1; +} + +void WalkingLavaSeahorse_Func_5(uint16 k) { // 0xA8DDFA + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(k); + E->wlse_var_B = 0; + E->wlse_var_C = 0; + sub_A8DDDE(k); +} + +void WalkingLavaSeahorse_Func_6(uint16 k) { // 0xA8DE05 + int16 v3; + + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(k); + R18_ = E->wlse_var_C; + R20_ = E->wlse_var_B; + if (Enemy_MoveDown(k) & 1) { + int t = samus_x_pos - E->base.x_pos; + uint16 v2 = addr_kWalkingLavaSeahorse_Ilist_DBE7; + v3 = -2; + if (!sign16(t)) { + v3 = 2; + v2 = addr_kWalkingLavaSeahorse_Ilist_DC57; + } + E->wlse_var_D = v3; + E->base.current_instruction = v2; + E->base.instruction_timer = 1; + E->wlse_var_A = FUNC16(WalkingLavaSeahorse_Func_7); + E->wlse_var_04 = 1; + } else { + WalkingLavaSeahorse_Func_2(k); + } +} + +void WalkingLavaSeahorse_Func_7(uint16 k) { // 0xA8DE4B + R18_ = 0; + R20_ = 2; + Enemy_MoveDown(k); + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(k); + if ((int16)(abs16(E->wlse_var_02 - E->base.x_pos) - g_word_A8DCCB) >= 0) { + E->wlse_var_A = FUNC16(WalkingLavaSeahorse_Func_8); + E->wlse_var_B = -4; + E->wlse_var_C = 0; + uint16 v4 = addr_kWalkingLavaSeahorse_Ilist_DC51; + if ((E->wlse_var_D & 0x8000u) == 0) + v4 = addr_kWalkingLavaSeahorse_Ilist_DCC1; + E->base.current_instruction = v4; + E->base.instruction_timer = 1; + } else { + if (E->wlse_var_04) + return; + int t = samus_x_pos - E->base.x_pos; + uint16 v3; + if (!sign16(t)) { + v3 = addr_kWalkingLavaSeahorse_Ilist_DC73; + if ((E->wlse_var_D & 0x8000u) != 0) + return; + } else { + v3 = addr_kWalkingLavaSeahorse_Ilist_DC03; + if ((E->wlse_var_D & 0x8000u) == 0) + return; + } + E->base.current_instruction = v3; + E->base.instruction_timer = 1; + E->wlse_var_A = FUNC16(nullsub_257); + } +} + +void WalkingLavaSeahorse_Func_8(uint16 k) { // 0xA8DECD + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(k); + uint16 wlse_var_C = E->wlse_var_C; + bool v3 = __CFADD__uint16(E->base.y_subpos, wlse_var_C); + E->base.y_subpos += wlse_var_C; + E->base.y_pos += v3 + E->wlse_var_B; + if ((WalkingLavaSeahorse_Func_2(k) & 0x8000u) == 0) + E->wlse_var_A = FUNC16(WalkingLavaSeahorse_Func_9); +} + +void WalkingLavaSeahorse_Func_9(uint16 k) { // 0xA8DEEC + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(k); + uint16 wlse_var_C = E->wlse_var_C; + bool v3 = __CFADD__uint16(E->base.y_subpos, wlse_var_C); + E->base.y_subpos += wlse_var_C; + uint16 v4 = E->base.y_pos + v3 + E->wlse_var_B; + E->base.y_pos = v4; + if ((int16)(v4 - E->wlse_var_F) >= 0) { + E->base.y_pos = E->wlse_var_F; + E->base.x_pos = E->wlse_var_02; + E->wlse_var_A = FUNC16(WalkingLavaSeahorse_Func_3); + } else { + WalkingLavaSeahorse_Func_2(k); + } +} + +uint16 WalkingLavaSeahorse_Instr_4(uint16 k, uint16 j) { // 0xA8DF1C + WalkingLavaSeahorse_DF20(0); + return j; +} + +void WalkingLavaSeahorse_DF20(uint16 a) { // 0xA8DF20 + SpawnEnemyProjectileWithGfx(a, cur_enemy_index, addr_loc_A89E90); + QueueSfx2_Max6(0x3Fu); +} + +uint16 WalkingLavaSeahorse_Instr_3(uint16 k, uint16 j) { // 0xA8DF33 + WalkingLavaSeahorse_DF20(2u); + return j; +} + +uint16 WalkingLavaSeahorse_Instr_5(uint16 k, uint16 j) { // 0xA8DF39 + WalkingLavaSeahorse_DF20(4u); + return j; +} + +uint16 WalkingLavaSeahorse_Instr_6(uint16 k, uint16 j) { // 0xA8DF3F + int16 v3; + + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(cur_enemy_index); + E->wlse_var_A = FUNC16(WalkingLavaSeahorse_Func_7); + v3 = random_number & 3; + if ((random_number & 3) == 0) + v3 = 2; + E->wlse_var_04 = v3; + uint16 result = addr_kWalkingLavaSeahorse_Ilist_DBE7; + if ((E->wlse_var_D & 0x8000u) == 0) + return addr_kWalkingLavaSeahorse_Ilist_DC57; + return result; +} + +uint16 WalkingLavaSeahorse_Instr_2(uint16 k, uint16 j) { // 0xA8DF63 + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(cur_enemy_index); + uint16 wlse_var_04 = E->wlse_var_04; + if (wlse_var_04) + E->wlse_var_04 = wlse_var_04 - 1; + return WalkingLavaSeahorse_Instr_1(cur_enemy_index, j); +} + +uint16 WalkingLavaSeahorse_Instr_1(uint16 k, uint16 j) { // 0xA8DF71 + int16 wlse_var_D; + + R18_ = 0; + Enemy_WalkingLavaSeahorse *E = Get_WalkingLavaSeahorse(cur_enemy_index); + R20_ = E->wlse_var_D; + if (Enemy_MoveRight_IgnoreSlopes(cur_enemy_index) & 1) { + j = addr_stru_A8DBE9; + wlse_var_D = E->wlse_var_D; + if (wlse_var_D < 0) + j = addr_stru_A8DC59; + E->wlse_var_D = -wlse_var_D; + } else { + EnemyFunc_C8AD(cur_enemy_index); + } + return j; +} + +void WalkingLavaSeahorse_Func_10(void) { // 0xA8DF9D + NormalEnemyShotAi(); +} + +void WreckedShipOrbs_Init(void) { // 0xA8E388 + Enemy_WreckedShipOrbs *E = Get_WreckedShipOrbs(cur_enemy_index); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = g_off_A8E380[E->wsos_parameter_1]; + int v1 = (uint16)(8 * E->wsos_parameter_2) >> 1; + E->wsos_var_01 = kCommonEnemySpeeds_Linear[v1]; + E->wsos_var_00 = kCommonEnemySpeeds_Linear[v1 + 1]; + E->wsos_var_03 = kCommonEnemySpeeds_Linear[v1 + 2]; + E->wsos_var_02 = kCommonEnemySpeeds_Linear[v1 + 3]; +} + +void CallWreckedShipOrbsA(uint32 ea) { + switch (ea) { + case fnWreckedShipOrbs_Func_3: WreckedShipOrbs_Func_3(); return; + case fnWreckedShipOrbs_Func_4: WreckedShipOrbs_Func_4(); return; + default: Unreachable(); + } +} +void CallWreckedShipOrbsB(uint32 ea) { + switch (ea) { + case fnWreckedShipOrbs_Func_5: WreckedShipOrbs_Func_5(); return; + case fnWreckedShipOrbs_Func_6: WreckedShipOrbs_Func_6(); return; + default: Unreachable(); + } +} +void WreckedShipOrbs_Main(void) { // 0xA8E3C3 + WreckedShipOrbs_Func_1(); + WreckedShipOrbs_Func_2(); + Enemy_WreckedShipOrbs *E = Get_WreckedShipOrbs(cur_enemy_index); + CallWreckedShipOrbsA(E->wsos_var_A | 0xA80000); + CallWreckedShipOrbsB(E->wsos_var_B | 0xA80000); +} + +void WreckedShipOrbs_Func_1(void) { // 0xA8E3D9 + Enemy_WreckedShipOrbs *E = Get_WreckedShipOrbs(cur_enemy_index); + E->wsos_var_A = FUNC16(WreckedShipOrbs_Func_3); + if ((GetSamusEnemyDelta_Y(cur_enemy_index) & 0x8000u) == 0) + E->wsos_var_A = FUNC16(WreckedShipOrbs_Func_4); +} + +void WreckedShipOrbs_Func_2(void) { // 0xA8E3EF + Enemy_WreckedShipOrbs *E = Get_WreckedShipOrbs(cur_enemy_index); + E->wsos_var_B = FUNC16(WreckedShipOrbs_Func_5); + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) + E->wsos_var_B = FUNC16(WreckedShipOrbs_Func_6); +} + +void WreckedShipOrbs_Func_3(void) { // 0xA8E405 + Enemy_WreckedShipOrbs *E = Get_WreckedShipOrbs(cur_enemy_index); + E->base.y_pos += E->wsos_var_03; + uint16 y_subpos = E->base.y_subpos; + bool v2 = __CFADD__uint16(E->wsos_var_02, y_subpos); + uint16 v3 = E->wsos_var_02 + y_subpos; + if (v2) + ++E->base.y_pos; + E->base.y_subpos = v3; +} + +void WreckedShipOrbs_Func_4(void) { // 0xA8E424 + Enemy_WreckedShipOrbs *E = Get_WreckedShipOrbs(cur_enemy_index); + E->base.y_pos += E->wsos_var_01; + uint16 y_subpos = E->base.y_subpos; + bool v2 = __CFADD__uint16(E->wsos_var_00, y_subpos); + uint16 v3 = E->wsos_var_00 + y_subpos; + if (v2) + ++E->base.y_pos; + E->base.y_subpos = v3; +} + +void WreckedShipOrbs_Func_5(void) { // 0xA8E443 + Enemy_WreckedShipOrbs *E = Get_WreckedShipOrbs(cur_enemy_index); + E->base.x_pos += E->wsos_var_03; + uint16 x_subpos = E->base.x_subpos; + bool v2 = __CFADD__uint16(E->wsos_var_02, x_subpos); + uint16 v3 = E->wsos_var_02 + x_subpos; + if (v2) + ++E->base.x_pos; + E->base.x_subpos = v3; +} + +void WreckedShipOrbs_Func_6(void) { // 0xA8E462 + Enemy_WreckedShipOrbs *E = Get_WreckedShipOrbs(cur_enemy_index); + E->base.x_pos += E->wsos_var_01; + uint16 x_subpos = E->base.x_subpos; + bool v2 = __CFADD__uint16(E->wsos_var_00, x_subpos); + uint16 v3 = E->wsos_var_00 + x_subpos; + if (v2) + ++E->base.x_pos; + E->base.x_subpos = v3; +} + +uint16 WreckedShipSpark_Instr_2(uint16 k, uint16 j) { // 0xA8E61D + Enemy_WreckedShipSpark *E = Get_WreckedShipSpark(cur_enemy_index); + E->base.properties |= kEnemyProps_Tangible; + return j; +} + +uint16 WreckedShipSpark_Instr_1(uint16 k, uint16 j) { // 0xA8E62A + Enemy_WreckedShipSpark *E = Get_WreckedShipSpark(cur_enemy_index); + E->base.properties &= ~kEnemyProps_Tangible; + return j; +} + +void WreckedShipSpark_Init(void) { // 0xA8E637 + Enemy_WreckedShipSpark *v3; // r10 + + Enemy_WreckedShipSpark *E = Get_WreckedShipSpark(cur_enemy_index); + int v2 = E->wssk_parameter_1 & 3; + E->wssk_var_B = g_off_A8E688[v2]; + E->wssk_var_E = E->wssk_parameter_2; + R18_ = 0; + WreckedShipSpark_Func_4(cur_enemy_index); + E->base.instruction_timer = 1; + E->base.current_instruction = g_off_A8E682[v2]; + E->base.timer = 0; + E->base.instruction_timer = 1; + if ((boss_bits_for_area[area_index] & 1) == 0) { + v3 = Get_WreckedShipSpark(cur_enemy_index); + v3->base.properties |= *(uint16 *)((char *)&gVramWriteEntry(0)[6].vram_dst + 1); + } +} + +void CallWreckedShipSpark(uint32 ea, uint16 k) { + switch (ea) { + case fnWreckedShipSpark_Func_1: WreckedShipSpark_Func_1(k); return; + case fnWreckedShipSpark_Func_2: WreckedShipSpark_Func_2(k); return; + case fnWreckedShipSpark_Func_3: WreckedShipSpark_Func_3(k); return; + case fnnullsub_259: return; + default: Unreachable(); + } +} + +void WreckedShipSpark_Main(void) { // 0xA8E68E + Enemy_WreckedShipSpark *E = Get_WreckedShipSpark(cur_enemy_index); + CallWreckedShipSpark(E->wssk_var_B | 0xA80000, cur_enemy_index); +} + +void WreckedShipSpark_Func_1(uint16 k) { // 0xA8E695 + Enemy_WreckedShipSpark *E = Get_WreckedShipSpark(k); + if (E->wssk_var_F == 1) { + E->wssk_var_B = FUNC16(WreckedShipSpark_Func_2); + E->base.current_instruction = addr_kWreckedShipSpark_Ilist_E5A7; + E->base.instruction_timer = 1; + R18_ = 0; + WreckedShipSpark_Func_4(k); + } else { + --E->wssk_var_F; + } +} + +void WreckedShipSpark_Func_2(uint16 k) { // 0xA8E6B7 + Enemy_WreckedShipSpark *E = Get_WreckedShipSpark(k); + if (E->wssk_var_F == 1) { + E->wssk_var_B = FUNC16(WreckedShipSpark_Func_1); + E->base.current_instruction = addr_kWreckedShipSpark_Ilist_E5E5; + E->base.instruction_timer = 1; + R18_ = 8; + WreckedShipSpark_Func_4(k); + } else { + --E->wssk_var_F; + } +} + +void WreckedShipSpark_Func_3(uint16 k) { // 0xA8E6DC + Enemy_WreckedShipSpark *E = Get_WreckedShipSpark(k); + if (E->wssk_var_F == 1) { + uint16 v2 = cur_enemy_index; + SpawnEnemyProjectileWithGfx(0, cur_enemy_index, addr_kEproj_Sparks); + R18_ = 0; + WreckedShipSpark_Func_4(v2); + } else { + --E->wssk_var_F; + } +} + +void WreckedShipSpark_Func_4(uint16 k) { // 0xA8E6F6 + int16 wssk_var_E; + + Enemy_WreckedShipSpark *E = Get_WreckedShipSpark(k); + wssk_var_E = E->wssk_var_E; + if (wssk_var_E < 0) + wssk_var_E = (NextRandom() & 0x3F) + 4; + E->wssk_var_F = R18_ + wssk_var_E; +} + +void WreckedShipSpark_Shot(void) { // 0xA8E70E + projectile_dir[collision_detection_index] &= ~0x10u; +} + +void BlueBrinstarFaceBlock_Init(void) { // 0xA8E82E + VoidP v1; + + EnemyData *v0 = gEnemyData(cur_enemy_index); + v0->current_instruction = addr_kBlueBrinstarFaceBlock_Ilist_E828; + v1 = FUNC16(BlueBrinstarFaceBlock_Func_1); + if ((collected_items & 4) == 0) + v1 = FUNC16(nullsub_170_A8); + enemy_gfx_drawn_hook.addr = v1; + *(uint16 *)&enemy_gfx_drawn_hook.bank = 168; + variables_for_enemy_graphics_drawn_hook[0] = (uint8)((uint16)((16 * v0->palette_index) & 0xFF00) >> 8); + variables_for_enemy_graphics_drawn_hook[2] = 16; + v0->parameter_2 = ((uint8)(v0->parameter_2 & 1) >> 2) | ((v0->parameter_2 & 1) << 15); +} + +void BlueBrinstarFaceBlock_Func_1(void) { // 0xA8E86E + if (!door_transition_flag_enemies && !--variables_for_enemy_graphics_drawn_hook[2]) { + variables_for_enemy_graphics_drawn_hook[2] = 16; + uint16 v0 = variables_for_enemy_graphics_drawn_hook[0]; + uint16 v1 = 8 * variables_for_enemy_graphics_drawn_hook[1]; + remaining_enemy_spritemap_entries = 4; + do { + palette_buffer[(v0 >> 1) + 137] = g_word_A8E7CC[v1 >> 1]; + v1 += 2; + v0 += 2; + --remaining_enemy_spritemap_entries; + } while (remaining_enemy_spritemap_entries); + variables_for_enemy_graphics_drawn_hook[1] = (LOBYTE(variables_for_enemy_graphics_drawn_hook[1]) + 1) & 7; + } +} + +void BlueBrinstarFaceBlock_Main(void) { // 0xA8E8AE + if ((collected_items & 4) != 0) { + enemy_gfx_drawn_hook.addr = FUNC16(BlueBrinstarFaceBlock_Func_1); + EnemyData *v1 = gEnemyData(cur_enemy_index); + variables_for_enemy_graphics_drawn_hook[0] = (uint8)((uint16)((16 * v1->palette_index) & 0xFF00) >> 8); + if (!v1->ai_var_A) { + uint16 SamusEnemyDelta_Y = GetSamusEnemyDelta_Y(cur_enemy_index); + if ((int16)(Abs16(SamusEnemyDelta_Y) - v1->parameter_1) < 0) { + uint16 SamusEnemyDelta_X = GetSamusEnemyDelta_X(cur_enemy_index); + v1->ai_var_B = SamusEnemyDelta_X; + if ((int16)(Abs16(SamusEnemyDelta_X) - v1->parameter_1) < 0 && (v1->ai_var_B & 0x8000) != v1->parameter_2) { + uint16 v4 = addr_kBlueBrinstarFaceBlock_Ilist_E80C; + if ((v1->ai_var_B & 0x8000u) == 0) + v4 = addr_kBlueBrinstarFaceBlock_Ilist_E81A; + v1->current_instruction = v4; + v1->instruction_timer = 1; + v1->ai_var_A = 1; + variables_for_enemy_graphics_drawn_hook[2] = 16; + } + } + } + } +} + +void BlueBrinstarFaceBlock_Shot(void) { // 0xA8E91D + projectile_dir[collision_detection_index] &= ~0x10u; +} + +void KiHunter_Init(void) { // 0xA8F188 + Enemy_KiHunter *E = Get_KiHunter(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl; + E->khr_var_14 = 0; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kKiHunter_Ilist_E9FA; + E->khr_var_F = 0; + E->khr_var_A = FUNC16(KiHunter_Func_1); + E->khr_var_08 = 0; + E->khr_var_09 = 1; + E->khr_var_06 = 0; + E->khr_var_07 = -1; + uint16 v1 = E->base.y_pos - 16; + E->khr_var_0A = v1; + E->khr_var_0B = v1 + 32; + E->khr_var_0C = E->base.x_pos; + E->khr_var_0D = E->base.y_pos; + if ((E->khr_parameter_1 & 0x8000u) != 0) { + E->khr_var_14 = 1; + E->khr_var_A = FUNC16(KiHunter_Func_4); + E->khr_var_08 = 0; + E->khr_var_09 = 1; + } +} + +void KiHunterWings_Init(void) { // 0xA8F214 + Enemy_KiHunter *E = Get_KiHunter(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kKiHunter_Ilist_EA4E; + int v2 = cur_enemy_index >> 1; + E->base.y_pos = enemy_drawing_queue[v2 + 93]; + E->base.x_pos = enemy_drawing_queue[v2 + 91]; + E->khr_var_A = FUNC16(KiHunter_Func_9); + E->base.palette_index = enemy_drawing_queue[v2 + 105]; + E->base.vram_tiles_index = enemy_drawing_queue[v2 + 106]; + if ((enemy_drawing_queue_sizes[v2 + 6] & 0x8000u) != 0) + E->base.properties |= kEnemyProps_Deleted; +} + +void CallKiHunterFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnKiHunter_Func_1: KiHunter_Func_1(k); return; // 0xa8f268 + case fnKiHunter_Func_2: KiHunter_Func_2(k); return; // 0xa8f3b8 + case fnKiHunter_Func_3: KiHunter_Func_3(k); return; // 0xa8f4ed + case fnKiHunter_Func_4: KiHunter_Func_4(k); return; // 0xa8f55a + case fnKiHunter_Func_5: KiHunter_Func_5(k); return; // 0xa8f58b + case fnKiHunter_Func_6: KiHunter_Func_6(k); return; // 0xa8f5f0 + case fnKiHunter_Func_7: KiHunter_Func_7(k); return; // 0xa8f68b + case fnKiHunter_Func_8: KiHunter_Func_8(k); return; + case fnKiHunter_Func_9: KiHunter_Func_9(k); return; // 0xa8f6f3 + case fnKiHunter_Func_10: KiHunter_Func_10(k); return; // 0xa8f7cf + case fnnullsub_346: return; + default: Unreachable(); + } +} + +void KiHunter_Main(void) { // 0xA8F25C + Enemy_KiHunter *E = Get_KiHunter(cur_enemy_index); + CallKiHunterFunc(E->khr_var_A | 0xA80000, cur_enemy_index); +} + +void KiHunterWings_Main(void) { // 0xA8F262 + Enemy_KiHunter *E = Get_KiHunter(cur_enemy_index); + CallKiHunterFunc(E->khr_var_A | 0xA80000, cur_enemy_index); +} + +void KiHunter_Func_1(uint16 k) { // 0xA8F268 + int16 v4; + + Enemy_KiHunter *E = Get_KiHunter(k); + R18_ = E->khr_var_08; + R20_ = E->khr_var_09; + if (Enemy_MoveDown(k) & 1) { + v4 = -E->khr_var_09; + } else { + uint16 y_pos = E->base.y_pos; + if ((int16)(y_pos - E->khr_var_0A) < 0) { + v4 = 1; + } else { + if ((int16)(y_pos - E->khr_var_0B) < 0) + goto LABEL_8; + v4 = -1; + } + } + E->khr_var_09 = v4; +LABEL_8: + R18_ = E->khr_var_06; + R20_ = E->khr_var_07; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + uint16 v5 = 0; + bool v6 = (-E->khr_var_07 & 0x8000u) != 0; + E->khr_var_07 = -E->khr_var_07; + if (!v6) + v5 = 4; + int v7 = v5 >> 1; + E->base.current_instruction = g_off_A8F3B0[v7]; + Enemy_KiHunter *E1 = Get_KiHunter(k + 64); + E1->base.current_instruction = g_off_A8F3B0[v7 + 1]; + E->base.instruction_timer = 1; + E1->base.instruction_timer = 1; + } + EnemyFunc_C8AD(k); + R18_ = samus_x_pos - E->base.x_pos; + R20_ = abs16(R18_); + if ((int16)(R20_ - g_word_A8F180) < 0 && !sign16(samus_y_pos - E->base.y_pos - 32)) { + R24_ = samus_y_pos - E->base.y_pos; + uint16 v9; + if ((R18_ & 0x8000u) != 0) { + E->khr_var_00 = -2; + E->khr_var_02 = 0; + E->khr_var_03 = 0; + E->khr_var_04 = -1; + E->khr_var_07 = -1; + E->khr_var_05 = -8192; + E->khr_var_F = 255; + E->khr_var_0E = 240; + v9 = 0; + } else { + E->khr_var_00 = 2; + E->khr_var_02 = 0; + E->khr_var_03 = 0; + E->khr_var_04 = 0; + E->khr_var_05 = 0x2000; + E->khr_var_F = 128; + E->khr_var_07 = 1; + E->khr_var_0E = 144; + v9 = 4; + } + int v10 = v9 >> 1; + E->base.current_instruction = g_off_A8F3B0[v10]; + Enemy_KiHunter *E1 = Get_KiHunter(k + 64); + E1->base.current_instruction = g_off_A8F3B0[v10 + 1]; + E->base.instruction_timer = 1; + E1->base.instruction_timer = 1; + E->khr_var_B = R18_ + E->base.x_pos; + E->khr_var_C = E->base.y_pos; + E->khr_var_A = FUNC16(KiHunter_Func_2); + E->khr_var_12 = R24_; + E->khr_var_11 = R20_; + E->khr_var_10 = 0; + } +} + +void KiHunter_Func_2(uint16 k) { // 0xA8F3B8 + Enemy_KiHunter *E = Get_KiHunter(k); + if ((E->khr_var_04 & 0x8000u) == 0) { + if ((int16)(E->khr_var_F - E->khr_var_0E) < 0) + goto LABEL_9; + } else if ((int16)(E->khr_var_F - E->khr_var_0E) >= 0) { + goto LABEL_9; + } + if (!E->khr_var_10) { + E->khr_var_10 = 1; + uint16 v2 = addr_kKiHunter_Ilist_EA32; + if ((E->khr_var_04 & 0x8000u) != 0) + v2 = addr_kKiHunter_Ilist_EA08; + E->base.current_instruction = v2; + E->base.instruction_timer = 1; + } +LABEL_9: + if ((E->khr_var_04 & 0x8000u) == 0) { + uint16 khr_var_03 = E->khr_var_03; + bool v4 = __CFADD__uint16(E->khr_var_05, khr_var_03); + E->khr_var_03 = E->khr_var_05 + khr_var_03; + uint16 khr_var_00 = E->khr_var_04 + v4 + E->khr_var_02; + if ((int16)(khr_var_00 - E->khr_var_00) >= 0) + khr_var_00 = E->khr_var_00; + E->khr_var_02 = khr_var_00; + uint16 v9 = E->khr_var_02 + E->khr_var_F; + E->khr_var_F = v9; + if (!sign16(v9 - 256)) { + E->khr_var_A = FUNC16(KiHunter_Func_1); + return; + } + } else { + uint16 v3 = E->khr_var_03; + bool v4 = __CFADD__uint16(E->khr_var_05, v3); + E->khr_var_03 = E->khr_var_05 + v3; + uint16 v5 = E->khr_var_04 + v4 + E->khr_var_02; + if ((int16)(v5 - E->khr_var_00) < 0) + v5 = E->khr_var_00; + E->khr_var_02 = v5; + uint16 v6 = E->khr_var_02 + E->khr_var_F; + E->khr_var_F = v6; + if (sign16(v6 - 128)) { + E->khr_var_A = FUNC16(KiHunter_Func_1); + return; + } + } + draw_enemy_layer = E->khr_var_11; + R20_ = E->khr_var_B + CosineMult8bit(E->khr_var_F) - E->base.x_pos; + R18_ = 0; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + if ((E->khr_var_04 & 0x8000u) == 0) { + E->khr_var_06 = 0; + E->khr_var_07 = -1; + } else { + E->khr_var_06 = 0; + E->khr_var_07 = 1; + } + goto LABEL_24; + } + EnemyFunc_C8AD(k); + draw_enemy_layer = E->khr_var_12; + R20_ = E->khr_var_C + SineMult8bitNegative(E->khr_var_F) - E->base.y_pos; + R18_ = 0; + if (Enemy_MoveDown(k) & 1) { +LABEL_24: + E->khr_var_A = FUNC16(KiHunter_Func_3); + E->khr_var_08 = 0; + E->khr_var_09 = -1; + } +} + +void KiHunter_Func_3(uint16 k) { // 0xA8F4ED + Enemy_KiHunter *E = Get_KiHunter(k); + R18_ = E->khr_var_06; + R20_ = E->khr_var_07; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1 + || (EnemyFunc_C8AD(k), R18_ = E->khr_var_08, R20_ = E->khr_var_09, Enemy_MoveDown(k) & 1) + || (int16)(E->base.y_pos - E->khr_var_0D) < 0) { + E->khr_var_A = FUNC16(KiHunter_Func_1); + } +} + +uint16 KiHunter_Instr_1(uint16 k, uint16 j) { // 0xA8F526 + uint16 result = addr_kKiHunter_Ilist_E9FA; + R18_ = addr_kKiHunter_Ilist_EA4E; + Enemy_KiHunter *E = Get_KiHunter(k); + if ((E->khr_var_07 & 0x8000u) == 0) { + result = addr_kKiHunter_Ilist_EA24; + R18_ = addr_kKiHunter_Ilist_EA5E; + } + E->base.current_instruction = result; + E->base.instruction_timer = 1; + Enemy_KiHunter *E1 = Get_KiHunter(k + 64); + if (E1->khr_var_A == (uint16)FUNC16(KiHunter_Func_9)) { + E1->base.current_instruction = R18_; + E1->base.instruction_timer = 1; + } + return result; +} + +void KiHunter_Func_4(uint16 k) { // 0xA8F55A + Enemy_KiHunter *E = Get_KiHunter(k); + R18_ = E->khr_var_08; + R20_ = E->khr_var_09; + if (Enemy_MoveDown(k) & 1) { + E->khr_var_A = FUNC16(KiHunter_Func_5); + } else { + uint16 khr_var_08 = E->khr_var_08; + bool v3 = __CFADD__uint16(g_word_A8F182, khr_var_08); + E->khr_var_08 = g_word_A8F182 + khr_var_08; + E->khr_var_09 += g_word_A8F184 + v3; + } +} + +void KiHunter_Func_5(uint16 k) { // 0xA8F58B + Enemy_KiHunter *E = Get_KiHunter(k); + E->khr_var_A = addr_locret_A8F5E3; + E->khr_var_08 = 0; + E->khr_var_09 = (random_number & 1) - 8; + if ((int16)(E->base.x_pos - samus_x_pos) >= 0) { + E->khr_var_06 = 0; + E->khr_var_07 = -2; + E->base.current_instruction = addr_kKiHunter_Ilist_EA8A; + } else { + E->khr_var_06 = 0; + E->khr_var_07 = 2; + E->base.current_instruction = addr_kKiHunter_Ilist_EAA6; + } + E->base.instruction_timer = 1; +} + +uint16 KiHunter_Instr_2(uint16 k, uint16 j) { // 0xA8F5E4 + Get_KiHunter(cur_enemy_index)->khr_var_A = FUNC16(KiHunter_Func_6); + return j; +} + +void KiHunter_Func_6(uint16 k) { // 0xA8F5F0 + Enemy_KiHunter *E = Get_KiHunter(k); + R18_ = E->khr_var_08; + R20_ = E->khr_var_09; + if (Enemy_MoveDown(k) & 1) { + if ((E->khr_var_09 & 0x8000u) != 0) { + E->khr_var_09 = 1; + } else { + E->khr_var_08 = 0; + E->khr_var_09 = -4; + E->khr_var_A = addr_locret_A8F5E3; + E->khr_var_0F = 12; + uint16 v4 = addr_kKiHunter_Ilist_EAC2; + if (!sign16(E->base.current_instruction + 0x155A)) + v4 = addr_kKiHunter_Ilist_EADA; + E->base.current_instruction = v4; + E->base.instruction_timer = 1; + } + } else { + R18_ = E->khr_var_06; + R20_ = E->khr_var_07; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->khr_var_07 = -E->khr_var_07; + } else { + EnemyFunc_C8AD(k); + uint16 khr_var_08 = E->khr_var_08; + bool v3 = __CFADD__uint16(g_word_A8F182, khr_var_08); + E->khr_var_08 = g_word_A8F182 + khr_var_08; + E->khr_var_09 += g_word_A8F184 + v3; + } + } +} + +uint16 KiHunter_Instr_3(uint16 k, uint16 j) { // 0xA8F67F + Get_KiHunter(cur_enemy_index)->khr_var_A = FUNC16(KiHunter_Func_7); + return j; +} + +void KiHunter_Func_7(uint16 k) { // 0xA8F68B + Enemy_KiHunter *E = Get_KiHunter(k); + uint16 v2 = E->khr_var_0F - 1; + E->khr_var_0F = v2; + if (!v2) { + uint16 v3 = FUNC16(KiHunter_Func_5); + uint16 v4 = abs16(E->base.x_pos - samus_x_pos); + if (sign16(v4 - 96)) + v3 = FUNC16(KiHunter_Func_8); + E->khr_var_A = v3; + } +} + +void KiHunter_Func_8(uint16 k) { // 0xA8F6B3 + uint16 v1 = addr_kKiHunter_Ilist_EAF2; + Enemy_KiHunter *E = Get_KiHunter(k); + if ((int16)(E->base.x_pos - samus_x_pos) < 0) + v1 = addr_kKiHunter_Ilist_EB10; + E->base.current_instruction = v1; + E->base.instruction_timer = 1; + E->khr_var_A = addr_locret_A8F5E3; +} + +uint16 KiHunter_Instr_4(uint16 k, uint16 j) { // 0xA8F6D2 + sub_A8F6DC(k, addr_loc_A8CF18); + return j; +} + +uint16 KiHunter_Instr_5(uint16 k, uint16 j) { // 0xA8F6D8 + sub_A8F6DC(k, addr_loc_A8CF26); + return j; +} + +void sub_A8F6DC(uint16 k, uint16 j) { // 0xA8F6DC + QueueSfx2_Max6(0x4Cu); + SpawnEnemyProjectileWithGfx(0, cur_enemy_index, j); + Get_KiHunter(cur_enemy_index)->khr_var_0F = 24; +} + +void KiHunter_Func_9(uint16 k) { // 0xA8F6F3 + int v1 = k >> 1; + Enemy_KiHunter *E = Get_KiHunter(k); + E->base.x_pos = enemy_drawing_queue[v1 + 91]; + E->base.y_pos = enemy_drawing_queue[v1 + 93]; +} + +void KiHunter_Shot(void) { // 0xA8F701 + NormalEnemyShotAi(); + uint16 old_cur_enemy_index = cur_enemy_index; + Enemy_KiHunter *EK = Get_KiHunter(cur_enemy_index); + Enemy_KiHunter *E1 = Get_KiHunter(cur_enemy_index + 64); + uint16 health = EK->base.health; + if (health) { + if (health == E1->khr_parameter_1 || (int16)(health - E1->khr_parameter_1) < 0) { + if (!EK->khr_var_14) { + EK->khr_var_14 = 1; + EK->khr_var_A = FUNC16(KiHunter_Func_4); + EK->khr_var_08 = 0; + EK->khr_var_09 = 1; + cur_enemy_index = old_cur_enemy_index + 64; + if (E1->khr_var_A != (uint16)FUNC16(KiHunter_Func_10)) { + E1->khr_var_07 = E1->base.y_pos; + E1->khr_var_08 = E1->base.x_pos; + KiHunter_Func_17(); + KiHunter_Func_12(); + KiHunter_Func_13(); + E1->khr_var_F = -8192; + E1->khr_var_A = FUNC16(KiHunter_Func_10); + E1->khr_var_00 = FUNC16(KiHunter_Func_11); + E1->khr_var_06 = E1->khr_var_07 - E1->khr_var_0B; + E1->khr_var_05 = E1->base.x_pos; + E1->khr_var_B = E1->khr_var_0A; + E1->base.current_instruction = addr_kKiHunter_Ilist_EA7E; + E1->base.spritemap_pointer = addr_kSpritemap_Nothing_A8; + E1->base.instruction_timer = 1; + E1->base.timer = 0; + E1->base.properties |= kEnemyProps_ProcessedOffscreen; + } + cur_enemy_index = old_cur_enemy_index; + } + } else { + E1->base.ai_handler_bits = EK->base.ai_handler_bits; + E1->base.frozen_timer = EK->base.frozen_timer; + E1->base.invincibility_timer = EK->base.invincibility_timer; + E1->base.flash_timer = EK->base.flash_timer; + } + } else { + E1->base.properties = 512; + } +} + +void CallKiHunterBFunc(uint32 ea) { + switch (ea) { + case fnKiHunter_Func_11: KiHunter_Func_11(); return; + case fnKiHunter_Func_14: KiHunter_Func_14(); return; + default: Unreachable(); + } +} +void KiHunter_Func_10(uint16 k) { // 0xA8F7CF + R18_ = Get_KiHunter(cur_enemy_index)->khr_var_00; + CallKiHunterBFunc(R18_ | 0xA80000); +} + +void KiHunter_Func_11(void) { // 0xA8F7DB + int16 v2; + + Enemy_KiHunter *E = Get_KiHunter(cur_enemy_index); + E->khr_var_F += *(uint16 *)((char *)&kCommonEnemySpeeds_Quadratic[2] + + (uint16)(8 * HIBYTE(E->khr_var_B)) + + 1); + draw_enemy_layer = g_byte_A8F186; + E->base.y_pos = E->khr_var_06 + SineMult8bitNegative(HIBYTE(E->khr_var_F)) - E->khr_var_04; + draw_enemy_layer = g_byte_A8F186; + E->base.x_pos = E->khr_var_05 + CosineMult8bit(HIBYTE(E->khr_var_F)) - E->khr_var_03; + if (sign16(E->khr_var_F + 0x4000)) { + KiHunter_Func_16(cur_enemy_index); + } else { + v2 = E->khr_var_B - 384; + if (v2 < 0) + v2 = 256; + E->khr_var_B = v2; + } +} + +void KiHunter_Func_12(void) { // 0xA8F851 + draw_enemy_layer = g_byte_A8F186; + uint16 v1 = CosineMult8bit(0xE0u); + Enemy_KiHunter *E = Get_KiHunter(cur_enemy_index); + E->khr_var_03 = v1; + draw_enemy_layer = g_byte_A8F186; + E->khr_var_04 = SineMult8bitNegative(0xE0u); +} + +void KiHunter_Func_13(void) { // 0xA8F87F + draw_enemy_layer = g_byte_A8F186; + uint16 v1 = CosineMult8bit(0xA0u); + Enemy_KiHunter *E = Get_KiHunter(cur_enemy_index); + E->khr_var_01 = v1; + draw_enemy_layer = g_byte_A8F186; + E->khr_var_02 = SineMult8bitNegative(0xA0u); +} + +void KiHunter_Func_14(void) { // 0xA8F8AD + int16 khr_var_07; + + Enemy_KiHunter *E = Get_KiHunter(cur_enemy_index); + E->khr_var_F += *(uint16 *)((char *)kCommonEnemySpeeds_Quadratic + + (uint16)(8 * HIBYTE(E->khr_var_B)) + + 1); + draw_enemy_layer = g_byte_A8F186; + R20_ = E->khr_var_06 + + SineMult8bitNegative(HIBYTE(E->khr_var_F)) + - E->khr_var_02 + - E->base.y_pos; + R18_ = 0; + if (Enemy_MoveDown(cur_enemy_index) & 1) { + E->base.properties |= kEnemyProps_Deleted; + E->base.x_pos = E->khr_var_08; + khr_var_07 = E->khr_var_07; + E->base.y_pos = khr_var_07; + } else { + draw_enemy_layer = g_byte_A8F186; + E->base.x_pos = E->khr_var_05 + CosineMult8bit(HIBYTE(E->khr_var_F)) - E->khr_var_01; + if (!sign16(E->khr_var_F + 0x4000)) { + KiHunter_Func_15(cur_enemy_index); + return; + } + khr_var_07 = E->khr_var_B - 384; + if (khr_var_07 < 0) + khr_var_07 = 256; + } + Get_KiHunter(cur_enemy_index)->khr_var_B = khr_var_07; +} + +void KiHunter_Func_15(uint16 k) { // 0xA8F947 + Enemy_KiHunter *E = Get_KiHunter(k); + E->khr_var_00 = FUNC16(KiHunter_Func_11); + E->khr_var_B = E->khr_var_0A; + E->khr_var_F = -8192; + E->khr_var_05 = E->base.x_pos; + E->khr_var_06 = E->base.y_pos; +} + +void KiHunter_Func_16(uint16 k) { // 0xA8F96A + Enemy_KiHunter *E = Get_KiHunter(k); + E->khr_var_00 = FUNC16(KiHunter_Func_14); + E->khr_var_B = E->khr_var_0A; + E->khr_var_F = -24576; + E->khr_var_05 = E->base.x_pos; + E->khr_var_06 = E->base.y_pos; +} + +void KiHunter_Func_17(void) { // 0xA8F98D + char v4; // t0 + uint16 v5; + + Enemy_KiHunter *E = Get_KiHunter(cur_enemy_index); + E->khr_var_0A = 0; + E->khr_var_B = 0; + do { + uint16 v3 = E->khr_var_0A + 384; + E->khr_var_0A = v3; + v3 &= 0xFF00u; + v4 = v3; + LOBYTE(v3) = HIBYTE(v3); + HIBYTE(v3) = v4; + v5 = *(uint16 *)((char *)kCommonEnemySpeeds_Quadratic + (uint16)(8 * v3) + 1) + E->khr_var_D; + E->khr_var_D = v5; + } while (sign16(v5 - 0x2000)); +} diff --git a/src/sm_a9.c b/src/sm_a9.c new file mode 100644 index 0000000..81bf688 --- /dev/null +++ b/src/sm_a9.c @@ -0,0 +1,6997 @@ +// Enemy AI - Mother Brain(complete), Shitroid &dead monsters + +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" +#include "sm_rtl.h" + +#define g_word_A98929 ((uint16*)RomPtr(0xa98929)) +static const uint16 g_word_A98B5D[5] = { 0x10, 0x10, 8, 8, 0x10 }; +static const uint16 g_word_A98B67[5] = { 0x20, 0x20, 0x18, 0x18, 0x20 }; +static const uint16 g_word_A98B71[5] = { 0xf8, 0xf8, 0xf0, 0xf0, 0xf6 }; +#define g_off_A98B7B ((uint16*)RomPtr(0xa98b7b)) +static const uint16 g_word_A98C61[4] = { 0xfff8, 2, 0xfffc, 6 }; +static const uint8 g_byte_A98F7D[2] = { 9, 0x12 }; +static const uint16 g_word_A98F7F[8] = { 0x3d, 0x54, 0x20, 0x35, 0x5a, 0x43, 0x67, 0x29 }; + +static const int16 g_word_A993BB[4] = { 0, -1, 0, 1 }; +static const int16 g_word_A993C3[4] = { 0, 1, -1, 1 }; + +static const uint16 g_word_A99E0F[13] = { 0x6f, 0x6f, 0x6f, 0x7e, 0x6f, 0x6f, 0x7e, 0x6f, 0x6f, 0x7e, 0x7e, 0x6f, 0x6f }; +#define g_word_A9B099 ((uint16*)RomPtr(0xa9b099)) +#define g_word_A9B109 ((uint16*)RomPtr(0xa9b109)) +#define g_word_A9B10F ((uint16*)RomPtr(0xa9b10f)) +static const uint16 g_word_A9B393[8] = { 8, 0x6c, 0x18, 0x80, 9, 0x90, 0x18, 0x74 }; +static const uint8 g_byte_A9B546[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; +static const uint8 g_byte_A9B5A1[8] = { 2, 1, 1, 0, 0, 0, 0, 0 }; +#define g_off_A9B6D4 ((uint16*)RomPtr(0xa9b6d4)) +static const uint8 g_byte_A9B6DC[3] = { 0x40, 0x80, 0xc0 }; +static const uint8 g_byte_A9B6DF[3] = { 0x10, 0x20, 0xd0 }; +static const int16 g_word_A9B72C[28] = { + -1, -17, 0, 0, -1, -1, 0, -1, 0, 0, -1, 0, 0, 0, -17, -1, + -1, -1, 0, 0, 0, -17, -1, -1, -1, -1, -1, -1, +}; +static const int16 g_word_A9BCA6[8] = { -8, 6, -4, 2, 3, -6, 8, 0 }; +static const int16 g_word_A9BCB6[8] = { -7, 2, 5, -4, 6, -2, -6, 7 }; +#define MotherBrain_RainbowBeamPalettes ((uint16*)RomPtr(0xade434)) +static const uint8 g_byte_A9BEEE[16] = { 2, 0, 2, 0, 6, 0, 6, 0, 8, 0, 8, 0, 10, 0, 10, 0 }; +static const uint16 g_word_A9BEFE[8] = { 0x500, 0x500, 0x200, 0x200, 0xc0, 0xc0, 0x40, 0x40 }; +static const int16 g_word_A9C049[8] = { 0x10, 0x10, 0x20, 0x20, 0x30, 0x30, 0x40, 0x40 }; +static const uint16 g_word_A9C544 = 1; +#define g_off_A9C61E ((uint16*)RomPtr(0xa9c61e)) +#define g_off_A9C664 ((uint16*)RomPtr(0xa9c664)) +#define kShitroid_FadingToBlack ((uint16*)RomPtr(0xade8e2)) +#define g_word_A9CDFC ((uint16*)RomPtr(0xa9cdfc)) + +#define kShitroid_HealthBasedPalettes_Shell ((uint16*)RomPtr(0xade7e2)) +#define kShitroid_HealthBasedPalettes_Innards ((uint16*)RomPtr(0xade882)) +#define g_off_A9D260 ((uint16*)RomPtr(0xa9d260)) +#define g_word_A9D583 ((uint16*)RomPtr(0xa9d583)) +#define g_word_A9D549 ((uint16*)RomPtr(0xa9d549)) +#define g_word_A9D67C ((uint16*)RomPtr(0xa9d67c)) +#define g_word_A9D69C ((uint16*)RomPtr(0xa9d69c)) +#define kDeadTorizo_TileData ((uint16*)RomPtr(0xb7a800)) + +#define g_off_A9D86A ((uint16*)RomPtr(0xa9d86a)) +#define g_off_A9D870 ((uint16*)RomPtr(0xa9d870)) +#define g_off_A9D897 ((uint16*)RomPtr(0xa9d897)) +#define g_off_A9D89B ((uint16*)RomPtr(0xa9d89b)) +#define g_off_A9D8C0 ((uint16*)RomPtr(0xa9d8c0)) +#define g_off_A9D8C6 ((uint16*)RomPtr(0xa9d8c6)) +#define g_word_A9D951 ((uint16*)RomPtr(0xa9d951)) +#define g_word_A9D959 ((uint16*)RomPtr(0xa9d959)) +static const int8 g_byte_A9F56A[16] = { 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + +void CallCorpseRottingMove(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnTorizo_CorpseRottingCopyFunc: Torizo_CorpseRottingCopyFunc(k, j); return; + case fnSidehopper_CorpseRottingCopyFunc_0: Sidehopper_CorpseRottingCopyFunc_0(k, j); return; + case fnSidehopper_CorpseRottingCopyFunc_2: Sidehopper_CorpseRottingCopyFunc_2(k, j); return; + case fnZoomer_CorpseRottingCopyFunc_0: Zoomer_CorpseRottingCopyFunc_0(k, j); return; + case fnZoomer_CorpseRottingCopyFunc_2: Zoomer_CorpseRottingCopyFunc_2(k, j); return; + case fnZoomer_CorpseRottingCopyFunc_4: Zoomer_CorpseRottingCopyFunc_4(k, j); return; + case fnRipper_CorpseRottingCopyFunc_0: Ripper_CorpseRottingCopyFunc_0(k, j); return; + case fnRipper_CorpseRottingCopyFunc_2: Ripper_CorpseRottingCopyFunc_2(k, j); return; + case fnSkree_CorpseRottingCopyFunc_0: Skree_CorpseRottingCopyFunc_0(k, j); return; + case fnSkree_CorpseRottingCopyFunc_2: Skree_CorpseRottingCopyFunc_2(k, j); return; + case fnSkree_CorpseRottingCopyFunc_4: Skree_CorpseRottingCopyFunc_4(k, j); return; + case fnMotherBrain_CorpseRottingCopyFunc: MotherBrain_CorpseRottingCopyFunc(k, j); return; + + case fnTorizo_CorpseRottingMoveFunc: Torizo_CorpseRottingMoveFunc(k, j); return; + case fnSidehopper_CorpseRottingMoveFunc_0: Sidehopper_CorpseRottingMoveFunc_0(k, j); return; + case fnSidehopper_CorpseRottingMoveFunc_2: Sidehopper_CorpseRottingMoveFunc_2(k, j); return; + case fnZoomer_CorpseRottingMoveFunc_0: Zoomer_CorpseRottingMoveFunc_0(k, j); return; + case fnZoomer_CorpseRottingMoveFunc_2: Zoomer_CorpseRottingMoveFunc_2(k, j); return; + case fnZoomer_CorpseRottingMoveFunc_4: Zoomer_CorpseRottingMoveFunc_4(k, j); return; + case fnRipper_CorpseRottingMoveFunc_0: Ripper_CorpseRottingMoveFunc_0(k, j); return; + case fnRipper_CorpseRottingMoveFunc_2: Ripper_CorpseRottingMoveFunc_2(k, j); return; + case fnSkree_CorpseRottingMoveFunc_0: Skree_CorpseRottingMoveFunc_0(k, j); return; + case fnSkree_CorpseRottingMoveFunc_2: Skree_CorpseRottingMoveFunc_2(k, j); return; + case fnSkree_CorpseRottingMoveFunc_4: Skree_CorpseRottingMoveFunc_4(k, j); return; + case fnMotherBrain_CorpseRottingMoveFunc: MotherBrain_CorpseRottingMoveFunc(k, j); return; + default: Unreachable(); + } +} +void CallCorpseRottingInit(uint32 ea) { + switch (ea) { + case fnTorizo_CorpseRottingInitFunc: Torizo_CorpseRottingInitFunc(); return; + case fnSidehopper_CorpseRottingInitFunc_0: Sidehopper_CorpseRottingInitFunc_0(); return; + case fnSidehopper_CorpseRottingInitFunc_2: Sidehopper_CorpseRottingInitFunc_2(); return; + case fnZoomer_CorpseRottingInitFunc_0: Zoomer_CorpseRottingInitFunc_0(); return; + case fnZoomer_CorpseRottingInitFunc_2: Zoomer_CorpseRottingInitFunc_2(); return; + case fnZoomer_CorpseRottingInitFunc_4: Zoomer_CorpseRottingInitFunc_4(); return; + case fnRipper_CorpseRottingInitFunc_0: Ripper_CorpseRottingInitFunc_0(); return; + case fnRipper_CorpseRottingInitFunc_2: Ripper_CorpseRottingInitFunc_2(); return; + case fnSkree_CorpseRottingInitFunc_0: Skree_CorpseRottingInitFunc_0(); return; + case fnSkree_CorpseRottingInitFunc_2: Skree_CorpseRottingInitFunc_2(); return; + case fnSkree_CorpseRottingInitFunc_4: Skree_CorpseRottingInitFunc_4(); return; + case fnMotherBrain_CorpseRottingInitFunc: MotherBrain_CorpseRottingInitFunc(); return; + default: Unreachable(); + } +} +void CallCorpseRottingFinish(uint32 ea) { + switch (ea) { + case fnMotherBrain_CorpseRottingFinished: MotherBrain_CorpseRottingFinished(); return; + case fnDeadTorizo_CorpseRottingFinished: DeadTorizo_CorpseRottingFinished(); return; + case fnCorpseRottingRotEntryFinishedHook: CorpseRottingRotEntryFinishedHook(); return; + default: Unreachable(); + } +} + +void CallMotherBrainFunc(uint32 ea) { + switch (ea) { + case fnMotherBrainsBrain_SetupBrainToDraw: MotherBrainsBrain_SetupBrainToDraw(); return; + case fnMotherBrainsBody_FirstPhase_DoubleRet: Unreachable(); return; + case fnMotherBrainBody_0_Wait: MotherBrainBody_0_Wait(); return; + case fnMotherBrainBody_1_ClearBottomLeftTube: MotherBrainBody_1_ClearBottomLeftTube(); return; + case fnMotherBrainBody_2_SpawnTopRightTubeFalling: MotherBrainBody_2_SpawnTopRightTubeFalling(); return; + case fnMotherBrainBody_3_ClearCeilingBlock9: MotherBrainBody_3_ClearCeilingBlock9(); return; + case fnMotherBrainBody_4_SpawnTopLeftTubeFalling: MotherBrainBody_4_SpawnTopLeftTubeFalling(); return; + case fnMotherBrainBody_4_ClearCeilingBlock6: MotherBrainBody_4_ClearCeilingBlock6(); return; + case fnMotherBrainBody_5_SpawnTubeFallingEnemy1: MotherBrainBody_5_SpawnTubeFallingEnemy1(); return; + case fnMotherBrainBody_6_ClearBottomRightTube: MotherBrainBody_6_ClearBottomRightTube(); return; + case fnMotherBrainBody_7_SpawnTubeFallingEnemy2: MotherBrainBody_7_SpawnTubeFallingEnemy2(); return; + case fnMotherBrainBody_8_ClearBottomMiddleLeftTube: MotherBrainBody_8_ClearBottomMiddleLeftTube(); return; + case fnMotherBrainBody_9_SpawnTopMiddleLeftFalling: MotherBrainBody_9_SpawnTopMiddleLeftFalling(); return; + case fnMotherBrainBody_10_ClearCeilingTubeColumn7: MotherBrainBody_10_ClearCeilingTubeColumn7(); return; + case fnMotherBrainBody_11_SpawnTopMiddleRightFalling: MotherBrainBody_11_SpawnTopMiddleRightFalling(); return; + case fnMotherBrainBody_12_ClearCeilingTubeColumn8: MotherBrainBody_12_ClearCeilingTubeColumn8(); return; + case fnMotherBrainBody_13_SpawnTubeFallingEnemy3: MotherBrainBody_13_SpawnTubeFallingEnemy3(); return; + case fnMotherBrainBody_14_ClearBottomMiddleRightTube: MotherBrainBody_14_ClearBottomMiddleRightTube(); return; + case fnMotherBrainBody_15_SpawnTubeFallingEnemy4: MotherBrainBody_15_SpawnTubeFallingEnemy4(); return; + case fnMotherBrainBody_16_ClearBottomMiddleTubes: MotherBrainBody_16_ClearBottomMiddleTubes(); return; + case fnMotherBrainBody_FakeDeath_Descent_0_Pause: MotherBrainBody_FakeDeath_Descent_0_Pause(); return; + case fnMotherBrainBody_FakeDeath_Descent_1: MotherBrainBody_FakeDeath_Descent_1(); return; + case fnMotherBrainBody_FakeDeath_Descent_2: MotherBrainBody_FakeDeath_Descent_2(); return; + case fnMotherBrainBody_FakeDeath_Descent_3: MotherBrainBody_FakeDeath_Descent_3(); return; + case fnMotherBrainBody_FakeDeath_Descent_4: MotherBrainBody_FakeDeath_Descent_4(); return; + case fnMotherBrainBody_FakeDeath_Descent_5: MotherBrainBody_FakeDeath_Descent_5(); return; + case fnMotherBrainBody_FakeDeath_Descent_6: MotherBrainBody_FakeDeath_Descent_6(); return; + case fnMotherBrainBody_FakeDeath_Ascent_0_DrawBG1Row23: MotherBrainBody_FakeDeath_Ascent_0_DrawBG1Row23(); return; + case fnMotherBrainBody_FakeDeath_Ascent_1_DrawBG1Row45: MotherBrainBody_FakeDeath_Ascent_1_DrawBG1Row45(); return; + case fnMotherBrainBody_FakeDeath_Ascent_2_DrawBG1Row67: MotherBrainBody_FakeDeath_Ascent_2_DrawBG1Row67(); return; + case fnMotherBrainBody_FakeDeath_Ascent_3_DrawBG1Row89: MotherBrainBody_FakeDeath_Ascent_3_DrawBG1Row89(); return; + case fnMotherBrainBody_FakeDeath_Ascent_4_DrawBG1RowAB: MotherBrainBody_FakeDeath_Ascent_4_DrawBG1RowAB(); return; + case fnMotherBrainBody_FakeDeath_Ascent_5_DrawBG1RowCD: MotherBrainBody_FakeDeath_Ascent_5_DrawBG1RowCD(); return; + case fnMotherBrainBody_FakeDeath_Ascent_6_SetupPhase2Gfx: MotherBrainBody_FakeDeath_Ascent_6_SetupPhase2Gfx(); return; + case fnMotherBrainBody_FakeDeath_Ascent_7_SetupPhase2Brain: MotherBrainBody_FakeDeath_Ascent_7_SetupPhase2Brain(); return; + case fnMotherBrainBody_FakeDeath_Ascent_8_Pause: MotherBrainBody_FakeDeath_Ascent_8_Pause(); return; + case fnMotherBrainBody_FakeDeath_Ascent_9_PrepareRise: MotherBrainBody_FakeDeath_Ascent_9_PrepareRise(); return; + case fnMotherBrainBody_FakeDeath_Ascent_10_LoadLegTiles: MotherBrainBody_FakeDeath_Ascent_10_LoadLegTiles(); return; + case fnMotherBrainBody_FakeDeath_Ascent_11_ContinuePause: MotherBrainBody_FakeDeath_Ascent_11_ContinuePause(); return; + case fnMotherBrainBody_FakeDeath_Ascent_12_StartMusic: MotherBrainBody_FakeDeath_Ascent_12_StartMusic(); return; + case fnMotherBrainBody_FakeDeath_Ascent_13_Raise: MotherBrainBody_FakeDeath_Ascent_13_Raise(); return; + case fnMotherBrainBody_FakeDeath_Ascent_14_WaitForUncouching: MotherBrainBody_FakeDeath_Ascent_14_WaitForUncouching(); return; + case fnMotherBrainBody_FakeDeath_Ascent_15_TransitionFromGrey: MotherBrainBody_FakeDeath_Ascent_15_TransitionFromGrey(); return; + case fnMotherBrainBody_2ndphase_16_ShakeHeadMenacingly: MotherBrainBody_2ndphase_16_ShakeHeadMenacingly(); return; + case fnMotherBrainBody_2ndphase_17_BringHeadBackUp: MotherBrainBody_2ndphase_17_BringHeadBackUp(); return; + case fnMotherBrainBody_2ndphase_18_FinishStretching: MotherBrainBody_2ndphase_18_FinishStretching(); return; + case fnMotherBrain_Phase3_Death_0: MotherBrain_Phase3_Death_0(); return; + case fnMotherBrain_Phase3_Death_1: MotherBrain_Phase3_Death_1(); return; + case fnMotherBrain_Phase3_Death_2: MotherBrain_Phase3_Death_2(); return; + case fnMotherBrain_Phase3_Death_3: MotherBrain_Phase3_Death_3(); return; + case fnMotherBrain_Phase3_Death_4: MotherBrain_Phase3_Death_4(); return; + case fnMotherBrain_Phase3_Death_5: MotherBrain_Phase3_Death_5(); return; + case fnMotherBrain_Phase3_Death_6: MotherBrain_Phase3_Death_6(); return; + case fnMotherBrain_Phase3_Death_7: MotherBrain_Phase3_Death_7(); return; + case fnMotherBrain_Phase3_Death_8: MotherBrain_Phase3_Death_8(); return; + case fnMotherBrain_Phase3_Death_9: MotherBrain_Phase3_Death_9(); return; + case fnMotherBrain_Phase3_Death_10: MotherBrain_Phase3_Death_10(); return; + case fnMotherBrain_Phase3_Death_11: MotherBrain_Phase3_Death_11(); return; + case fnMotherBrain_Phase3_Death_12: MotherBrain_Phase3_Death_12(); return; + case fnMotherBrain_Phase3_Death_13: MotherBrain_Phase3_Death_13(); return; + case fnMotherBrain_Phase3_Death_14_20framedelay: MotherBrain_Phase3_Death_14_20framedelay(); return; + case fnMotherBrain_Phase3_Death_15_LoadEscapeTimerTiles: MotherBrain_Phase3_Death_15_LoadEscapeTimerTiles(); return; + case fnMotherBrain_Phase3_Death_16_StartEscape: MotherBrain_Phase3_Death_16_StartEscape(); return; + case fnMotherBrain_Phase3_Death_17_SpawnTimeBomb: MotherBrain_Phase3_Death_17_SpawnTimeBomb(); return; + case fnMotherBrain_Phase3_Death_18_TypesZebesText: MotherBrain_Phase3_Death_18_TypesZebesText(); return; + case fnMotherBrain_Phase3_Death_19_EscapeDoorExploding: MotherBrain_Phase3_Death_19_EscapeDoorExploding(); return; + case fnMotherBrain_Phase3_Death_20_BlowUpEscapeDoor: MotherBrain_Phase3_Death_20_BlowUpEscapeDoor(); return; + case fnMotherBrain_Phase3_Death_21_KeepEarthquakeGoing: MotherBrain_Phase3_Death_21_KeepEarthquakeGoing(); return; + case fnMotherBrain_Body_Phase2_Thinking: MotherBrain_Body_Phase2_Thinking(); return; + case fnMotherBrain_Body_Phase2_TryAttack: MotherBrain_Body_Phase2_TryAttack(); return; + case fnMotherBrain_FiringBomb_DecideOnWalking: MotherBrain_FiringBomb_DecideOnWalking(); return; + case fnMotherBrain_FiringBomb_WalkingBackwards: MotherBrain_FiringBomb_WalkingBackwards(); return; + case fnMotherBrain_FiringBomb_Crouch: MotherBrain_FiringBomb_Crouch(); return; + case fnMotherBrain_FiringBomb_Fired: MotherBrain_FiringBomb_Fired(); return; + case fnMotherBrain_FiringBomb_Standup: MotherBrain_FiringBomb_Standup(); return; + case fnMotherBomb_FiringLaser_PositionHead: MotherBomb_FiringLaser_PositionHead(); return; + case fnMotherBomb_FiringLaser_PositionHeadSlowlyFire: MotherBomb_FiringLaser_PositionHeadSlowlyFire(); return; + case fnMotherBomb_FiringLaser_FinishAttack: MotherBomb_FiringLaser_FinishAttack(); return; + case fnMotherBomb_FiringDeathBeam: MotherBomb_FiringDeathBeam(); return; + case fnMotherBomb_FiringRainbowBeam_0: MotherBomb_FiringRainbowBeam_0(); return; + case fnMotherBomb_FiringRainbowBeam_1_StartCharge: MotherBomb_FiringRainbowBeam_1_StartCharge(); return; + case fnMotherBomb_FiringRainbowBeam_2_RetractNeck: MotherBomb_FiringRainbowBeam_2_RetractNeck(); return; + case fnMotherBomb_FiringRainbowBeam_3_Wait: MotherBomb_FiringRainbowBeam_3_Wait(); return; + case fnMotherBomb_FiringRainbowBeam_4_ExtendNeckDown: MotherBomb_FiringRainbowBeam_4_ExtendNeckDown(); return; + case fnMotherBomb_FiringRainbowBeam_5_StartFiring: MotherBomb_FiringRainbowBeam_5_StartFiring(); return; + case fnMotherBomb_FiringRainbowBeam_6_MoveSamusToWall: MotherBomb_FiringRainbowBeam_6_MoveSamusToWall(); return; + case fnMotherBomb_FiringRainbowBeam_7_DelayFrame: MotherBomb_FiringRainbowBeam_7_DelayFrame(); return; + case fnMotherBomb_FiringRainbowBeam_8_StartDrainSamus: MotherBomb_FiringRainbowBeam_8_StartDrainSamus(); return; + case fnMotherBomb_FiringRainbowBeam_9_DrainingSamus: MotherBomb_FiringRainbowBeam_9_DrainingSamus(); return; + case fnMotherBomb_FiringRainbowBeam_10_FinishFiringRainbow: MotherBomb_FiringRainbowBeam_10_FinishFiringRainbow(); return; + case fnMotherBomb_FiringRainbowBeam_11_LetSamusFall: MotherBomb_FiringRainbowBeam_11_LetSamusFall(); return; + case fnMotherBomb_FiringRainbowBeam_12_WaitForSamusHitGround: MotherBomb_FiringRainbowBeam_12_WaitForSamusHitGround(); return; + case fnMotherBomb_FiringRainbowBeam_13_LowerHead: MotherBomb_FiringRainbowBeam_13_LowerHead(); return; + case fnMotherBomb_FiringRainbowBeam_14_DecideNextAction: MotherBomb_FiringRainbowBeam_14_DecideNextAction(); return; + case fnMotherBrain_Phase2Cut_0: MotherBrain_Phase2Cut_0(); return; + case fnMotherBrain_Phase2Cut_1: MotherBrain_Phase2Cut_1(); return; + case fnMotherBrain_Phase2Cut_2: MotherBrain_Phase2Cut_2(); return; + case fnMotherBrain_Phase2Cut_3: MotherBrain_Phase2Cut_3(); return; + case fnMotherBrain_Phase2Cut_4: MotherBrain_Phase2Cut_4(); return; + case fnMotherBrain_Phase2Cut_5: MotherBrain_Phase2Cut_5(); return; + case fnnullsub_364: return; + case fnMotherBrain_DrainedByShitroid_0: MotherBrain_DrainedByShitroid_0(); return; + case fnMotherBrain_DrainedByShitroid_1: MotherBrain_DrainedByShitroid_1(); return; + case fnMotherBrain_DrainedByShitroid_2: MotherBrain_DrainedByShitroid_2(); return; + case fnMotherBrain_DrainedByShitroid_3: MotherBrain_DrainedByShitroid_3(); return; + case fnMotherBrain_DrainedByShitroid_4: MotherBrain_DrainedByShitroid_4(); return; + case fnMotherBrain_DrainedByShitroid_5: MotherBrain_DrainedByShitroid_5(); return; + case fnMotherBrain_DrainedByShitroid_6: MotherBrain_DrainedByShitroid_6(); return; + case fnMotherBrain_DrainedByShitroid_7: MotherBrain_DrainedByShitroid_7(); return; + case fnMotherBrain_Phase2_Revive_0: MotherBrain_Phase2_Revive_0(); return; + case fnMotherBrain_Phase2_Revive_1: MotherBrain_Phase2_Revive_1(); return; + case fnMotherBrain_Phase2_Revive_2: MotherBrain_Phase2_Revive_2(); return; + case fnMotherBrain_Phase2_Revive_3: MotherBrain_Phase2_Revive_3(); return; + case fnMotherBrain_Phase2_Revive_4: MotherBrain_Phase2_Revive_4(); return; + case fnMotherBrain_Phase2_Revive_5: MotherBrain_Phase2_Revive_5(); return; + case fnMotherBrain_Phase2_Revive_6: MotherBrain_Phase2_Revive_6(); return; + case fnMotherBrain_Phase2_Revive_7: MotherBrain_Phase2_Revive_7(); return; + case fnMotherBrain_Phase2_Revive_8: MotherBrain_Phase2_Revive_8(); return; + case fnMotherBrain_Phase2_MurderShitroid_1: MotherBrain_Phase2_MurderShitroid_1(); return; + case fnMotherBrain_Phase2_MurderShitroid_2: MotherBrain_Phase2_MurderShitroid_2(); return; + case fnMotherBrain_Phase2_PrepareForFinalShitroid: MotherBrain_Phase2_PrepareForFinalShitroid(); return; + case fnMotherBrain_Phase2_ExecuteFinalkShitroid: MotherBrain_Phase2_ExecuteFinalkShitroid(); return; + case fnnullsub_363: return; + case fnMotherBrain_Phase3_Recover_MakeDistance: MotherBrain_Phase3_Recover_MakeDistance(); return; + case fnMotherBrain_Phase3_Recover_SetupForFight: MotherBrain_Phase3_Recover_SetupForFight(); return; + case fnMotherBrain_Phase3_Fighting_Main: MotherBrain_Phase3_Fighting_Main(); return; + case fnMotherBrain_Phase3_Fighting_Cooldown: MotherBrain_Phase3_Fighting_Cooldown(); return; + case fnnullsub_365: return; + case fnnullsub_367: return; + case fnMotherBrainsBrain_SetupBrainAndNeckToDraw: MotherBrainsBrain_SetupBrainAndNeckToDraw(); return; + default: Unreachable(); + } +} +void Enemy_GrappleReact_CancelBeam_A9(void) { // 0xA9800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_NormalFrozenAI_A9(void) { // 0xA98041 + NormalEnemyFrozenAI(); +} + +uint16 EnemyInstr_Sleep_A9(uint16 k, uint16 j) { // 0xA9812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + +void MotherBrainsBody_Init(void) { // 0xA98687 + for (int i = 4094; i >= 0; i -= 2) + tilemap_stuff[i >> 1] = 824; + MotherBrain_SetBodyInstrs(addr_kMotherBrain_Ilist_9C13); + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.vram_tiles_index = 0; + E->base.properties |= kEnemyProps_BlockPlasmaBeam | kEnemyProps_Tangible | kEnemyProps_Invisible; + E->base.palette_index = 0; + WriteColorsToTargetPalette(0xa9, 0x162u, addr_kMotherBrainPalette_4__plus__2, 0xFu); + WriteColorsToTargetPalette(0xa9, 0x1E2u, addr_kMotherBrainPalette_3__plus__2, 0xFu); + E->mbn_var_00 = 0; + + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_02 = 0; + E->mbn_var_04 = 2; + E1->mbn_var_A = FUNC16(MotherBrainsBrain_SetupBrainToDraw); + E->mbn_var_A = FUNC16(MotherBrainsBody_FirstPhase_DoubleRet); + LoadFxEntry(1u); + uint16 v3 = 0, v4; + do { + v4 = v3; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainRoomTurrets, v3); + v3 = v4 + 1; + } while ((uint16)(v4 + 1) < 0xCu); +} + +void MotherBrainsBrain_Init(void) { // 0xA98705 + InitializeEnemyCorpseRotting(0x40u, addr_stru_A9DE08); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->base.health = 3000; + MotherBrain_SetBrainUnusedInstrs(addr_kMotherBrain_Ilist_9C13); + E1->base.vram_tiles_index = 0; + E1->base.properties |= 0x1100u; + E1->base.palette_index = 512; + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_0C = 512; + E->mbn_var_0D = 512; + MotherBrain_SetBrainInstrs(addr_stru_A99C21); + MotherBrain_SetupBrainNormalPal(); +} + +void MotherBrainsBody_Hurt(void) { // 0xA9873E + MotherBrain_Pal_HandleRoomPal(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + + if (E->mbn_var_A == (uint16)fnMotherBrainsBody_FirstPhase_DoubleRet) { + MotherBrainsBody_FirstPhase_DoubleRet(); + return; + } + + CallMotherBrainFunc(E->mbn_var_A | 0xA90000); + MotherBrain_HandlePalette(); + MotherBrain_SamusCollDetect(); + MotherBrain_Pal_ProcessInvincibility(); + if (Get_MotherBrain(0x40u)->mbn_var_02) + mov24(&unpause_hook, fnMotherBrainsBody_UnpauseHook); +} + +void MotherBrainsBody_UnpauseHook(void) { // 0xA98763 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (E->mbn_var_16) + QueueSfx1_Max6(0x40u); + if ((E->base.extra_properties & 4) != 0) { + enemy_bg2_tilemap_size = 2048; + nmi_flag_bg2_enemy_vram_transfer = 1; + } +} + +void MotherBrainsBody_Powerbomb(void) { // 0xA98787 + NormalEnemyPowerBombAiSkipDeathAnim_CurEnemy(); + MotherBrainsBrain_Hurt(); +} + +void MotherBrainsBrain_Hurt(void) { // 0xA9878B + mov24(&enemy_gfx_drawn_hook, 0xA98786u); + EnemyData *v0 = gEnemyData(0); + if ((v0[1].properties & 0x100) != 0) + CallMotherBrainFunc(v0[1].ai_var_A | 0xA90000); +} + +void MotherBrainsBrain_SetupBrainAndNeckToDraw(void) { // 0xA987A2 + if (!time_is_frozen_flag) + MotherBrain_HandleNeck(); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->base.x_pos = E1->mbn_var_2E; + E1->base.y_pos = E1->mbn_var_2F - 21; + mov24(&enemy_gfx_drawn_hook, 0xA987C9u); +} + +void MotherBrain_DrawBrainNeck_EnemyGfxDrawHook(void) { // 0xA987C9 + MotherBrain_DrawBrain(); + MotherBrain_DrawNeck(); +} + +void MotherBrainsBrain_SetupBrainToDraw(void) { // 0xA987D0 + mov24(&enemy_gfx_drawn_hook, 0xA987DDu); +} + +void MotherBrainsBrain_GfxDrawHook(void) { // 0xA987DD + MotherBrain_DrawBrain(); +} + +void MotherBrainsBody_FirstPhase_DoubleRet(void) { // 0xA987E1 + if (CheckEventHappened(2u)) { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_00 = earthquake_timer; + if (sign16(samus_x_pos - 236)) { + if (!E1->base.health) { + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_1D = 1; + E->mbn_var_00 = 1; + DisableMinimapAndMarkBossRoomAsExplored(); + QueueMusic_Delayed8(6u); + MotherBrain_SealWall(); + } + } + } + MotherBrain_SamusCollDetect(); +} + +void MotherBrainBody_FakeDeath_Descent_0_Pause(void) { // 0xA9881D + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0); + E->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Descent_1); + E->mbby_var_F = 64; + MotherBrainBody_FakeDeath_Descent_1(); +} + +void MotherBrainBody_FakeDeath_Descent_1(void) { // 0xA98829 + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0); + if ((--E->mbby_var_F & 0x8000u) != 0) { + CallSomeSamusCode(0); + *(uint16 *)scrolls = scrolls[0]; + E->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Descent_2); + E->mbby_var_F = 32; + MotherBrainBody_FakeDeath_Descent_2(); + } +} + +void MotherBrainBody_FakeDeath_Descent_2(void) { // 0xA9884D + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0); + if ((--E->mbby_var_F & 0x8000u) != 0) { + QueueMusic_Delayed8(0); + QueueMusic_Delayed8(0xFF21u); + E->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Descent_3); + E->mbby_var_F = 12; + MotherBrainBody_FakeDeath_Descent_3(); + } +} + +void MotherBrainBody_FakeDeath_Descent_3(void) { // 0xA9886C + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0); + if ((--E->mbby_var_F & 0x8000u) != 0) { + CallSomeSamusCode(1u); + E->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Descent_4); + E->mbby_var_F = 8; + MotherBrainBody_FakeDeath_Descent_4(); + } +} + +void MotherBrainBody_FakeDeath_Descent_4(void) { // 0xA98884 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + MotherBrain_Pal_BeginScreenFlash(); + LoadFxEntry(2u); + Get_MotherBrain(0x40u)->mbn_var_E = FUNC16(MotherBrainBody_0_Wait); + E->mbn_var_A = FUNC16(MotherBrainBody_FakeDeath_Descent_5); + E->mbn_var_F = 0; + E->mbn_var_37 = 0; + static const SpawnHardcodedPlmArgs unk_A988AD = { 0x0e, 0x02, 0xb6b3 }; + SpawnHardcodedPlm(&unk_A988AD); + } +} + +void MotherBrainBody_FakeDeath_Descent_5(void) { // 0xA988B2 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->mbn_var_F = 8; + uint16 v2 = E->mbn_var_37 + 1; + E->mbn_var_37 = v2; + if (MotherBrain_FadeToGray_FakeDeath(v2 - 1) & 1) + E->mbn_var_A = FUNC16(MotherBrainBody_FakeDeath_Descent_6); + } + MotherBrainBody_FakeDeath_Descent_6(); +} + +void MotherBrainBody_FakeDeath_Descent_6(void) { // 0xA988D3 + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + CallMotherBrainFunc(E->mbby_var_E | 0xA90000); + MotherBrain_HandleFakeDeathExplosions(); +} + +void MotherBrain_HandleFakeDeathExplosions(void) { // 0xA988DD + int16 v1; + int16 v2; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + v1 = E->mbn_var_38 - 1; + if (v1 < 0) { + E->mbn_var_38 = 8; + v2 = E->mbn_var_39 - 1; + if (v2 < 0) + v2 = 7; + E->mbn_var_39 = v2; + int v3 = (uint16)(4 * v2) >> 1; + R18_ = g_word_A98929[v3]; + R20_ = g_word_A98929[v3 + 1]; + uint16 v4 = 3; + if (random_number < 0x4000u) + v4 = 12; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, v4); + QueueSfx2_Max3(0x24u); + } else { + E->mbn_var_38 = v1; + } +} + +void MotherBrainBody_0_Wait(void) { // 0xA98949 + int16 v1; + + uint16 v0 = 0; + v1 = 0; + do { + if (!*(uint16 *)((char *)enemy_projectile_id + v0)) + ++v1; + v0 += 2; + } while ((int16)(v0 - 36) < 0); + if ((int16)(v1 - 4) >= 0) { + SpawnEnemy(0xA9u, addr_stru_A98AE5); + Get_MotherBrainBody(0x40u)->mbby_var_E = FUNC16(MotherBrainBody_1_ClearBottomLeftTube); + } +} + +static const SpawnHardcodedPlmArgs unk_A98972 = { 0x05, 0x09, 0xb6c3 }; +static const SpawnHardcodedPlmArgs unk_A989D6 = { 0x06, 0x02, 0xb6b3 }; +static const SpawnHardcodedPlmArgs unk_A989FE = { 0x0a, 0x09, 0xb6c7 }; +static const SpawnHardcodedPlmArgs unk_A98A26 = { 0x06, 0x0a, 0xb6bb }; +static const SpawnHardcodedPlmArgs unk_A98A58 = { 0x07, 0x02, 0xb6b7 }; +static const SpawnHardcodedPlmArgs unk_A98A8A = { 0x08, 0x02, 0xb6b7 }; +static const SpawnHardcodedPlmArgs unk_A989A4 = { 0x09, 0x02, 0xb6b3 }; +static const SpawnHardcodedPlmArgs unk_A98AB2 = { 0x09, 0x0a, 0xb6bb }; +static const SpawnHardcodedPlmArgs unk_A98ADA = { 0x07, 0x07, 0xb6bf }; + +void MotherBrainBody_1_ClearBottomLeftTube(void) { // 0xA9896E + SpawnHardcodedPlm(&unk_A98972); + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + E->mbby_var_E = FUNC16(MotherBrainBody_2_SpawnTopRightTubeFalling); + E->mbby_var_F = 32; +} + +void MotherBrainBody_2_SpawnTopRightTubeFalling(void) { // 0xA98983 + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + if ((--E->mbby_var_F & 0x8000u) != 0) { + R18_ = 152; + R20_ = 47; + SpawnEnemyProjectileWithRoomGfx(0xCC5Bu, 0x2Fu); + E->mbby_var_E = -30304; + } +} + +void MotherBrainBody_3_ClearCeilingBlock9(void) { // 0xA989A0 + SpawnHardcodedPlm(&unk_A989A4); + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + E->mbby_var_E = FUNC16(MotherBrainBody_4_SpawnTopLeftTubeFalling); + E->mbby_var_F = 32; +} + +void MotherBrainBody_4_SpawnTopLeftTubeFalling(void) { // 0xA989B5 + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + if ((--E->mbby_var_F & 0x8000u) != 0) { + R18_ = 104; + R20_ = 47; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainTubeFalling_TopLeft, 0x2Fu); + E->mbby_var_E = FUNC16(MotherBrainBody_4_ClearCeilingBlock6); + } +} + +void MotherBrainBody_4_ClearCeilingBlock6(void) { // 0xA989D2 + SpawnHardcodedPlm(&unk_A989D6); + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + E->mbby_var_E = FUNC16(MotherBrainBody_5_SpawnTubeFallingEnemy1); + E->mbby_var_F = 32; +} + +void MotherBrainBody_5_SpawnTubeFallingEnemy1(void) { // 0xA989E7 + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + if ((--E->mbby_var_F & 0x8000u) != 0) { + SpawnEnemy(0xA9u, addr_stru_A98AF5); + E->mbby_var_E = FUNC16(MotherBrainBody_6_ClearBottomRightTube); + } +} + +void MotherBrainBody_6_ClearBottomRightTube(void) { // 0xA989FA + SpawnHardcodedPlm(&unk_A989FE); + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + E->mbby_var_E = FUNC16(MotherBrainBody_7_SpawnTubeFallingEnemy2); + E->mbby_var_F = 32; +} + +void MotherBrainBody_7_SpawnTubeFallingEnemy2(void) { // 0xA98A0F + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + if ((--E->mbby_var_F & 0x8000u) != 0) { + SpawnEnemy(0xA9u, addr_stru_A98B05); + E->mbby_var_E = FUNC16(MotherBrainBody_8_ClearBottomMiddleLeftTube); + } +} + +void MotherBrainBody_8_ClearBottomMiddleLeftTube(void) { // 0xA98A22 + SpawnHardcodedPlm(&unk_A98A26); + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + E->mbby_var_E = FUNC16(MotherBrainBody_9_SpawnTopMiddleLeftFalling); + E->mbby_var_F = 32; +} + +void MotherBrainBody_9_SpawnTopMiddleLeftFalling(void) { // 0xA98A37 + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + if ((--E->mbby_var_F & 0x8000u) != 0) { + R18_ = 120; + R20_ = 59; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainTubeFalling_TopMiddleLeft, 0x3Bu); + E->mbby_var_E = FUNC16(MotherBrainBody_10_ClearCeilingTubeColumn7); + } +} + +void MotherBrainBody_10_ClearCeilingTubeColumn7(void) { // 0xA98A54 + SpawnHardcodedPlm(&unk_A98A58); + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + E->mbby_var_E = FUNC16(MotherBrainBody_11_SpawnTopMiddleRightFalling); + E->mbby_var_F = 32; +} + +void MotherBrainBody_11_SpawnTopMiddleRightFalling(void) { // 0xA98A69 + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + if ((--E->mbby_var_F & 0x8000u) != 0) { + R18_ = 136; + R20_ = 59; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainTubeFalling_TopMiddleRight, 0x3Bu); + E->mbby_var_E = FUNC16(MotherBrainBody_12_ClearCeilingTubeColumn8); + } +} + +void MotherBrainBody_12_ClearCeilingTubeColumn8(void) { // 0xA98A86 + SpawnHardcodedPlm(&unk_A98A8A); + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + E->mbby_var_E = FUNC16(MotherBrainBody_13_SpawnTubeFallingEnemy3); + E->mbby_var_F = 32; +} + +void MotherBrainBody_13_SpawnTubeFallingEnemy3(void) { // 0xA98A9B + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + if ((--E->mbby_var_F & 0x8000u) != 0) { + SpawnEnemy(0xA9u, FUNC16(EnemyProj_Init_0x8bde_SkreeDownLeft)); + E->mbby_var_E = FUNC16(MotherBrainBody_14_ClearBottomMiddleRightTube); + } +} + +void MotherBrainBody_14_ClearBottomMiddleRightTube(void) { // 0xA98AAE + SpawnHardcodedPlm(&unk_A98AB2); + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + E->mbby_var_E = FUNC16(MotherBrainBody_15_SpawnTubeFallingEnemy4); + E->mbby_var_F = 2; +} + +void MotherBrainBody_15_SpawnTubeFallingEnemy4(void) { // 0xA98AC3 + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + if ((--E->mbby_var_F & 0x8000u) != 0) { + SpawnEnemy(0xA9u, addr_stru_A98B25); + E->mbby_var_E = FUNC16(MotherBrainBody_16_ClearBottomMiddleTubes); + } +} + +void MotherBrainBody_16_ClearBottomMiddleTubes(void) { // 0xA98AD6 + SpawnHardcodedPlm(&unk_A98ADA); + Get_MotherBrainBody(0x40u)->mbby_var_E = addr_locret_A98AE4; +} + +void MotherBrainsTubesFalling_Init(void) { // 0xA98B35 + Enemy_MotherBrainsTubesFalling *E = Get_MotherBrainsTubesFalling(cur_enemy_index); + int v1 = E->mbtfg_parameter_1 >> 1; + E->base.x_width = g_word_A98B5D[v1]; + E->base.y_height = g_word_A98B67[v1]; + E->mbtfg_var_B = g_word_A98B71[v1]; + E->mbtfg_var_D = 0; + E->mbtfg_var_E = 0; + E->mbtfg_var_C = 0; + E->mbtfg_var_A = g_off_A98B7B[v1]; +} + +void CallMotherBrainsTubesFalling(uint32 ea, uint16 k) { + switch (ea) { + case fnMotherBrainsTubesFalling_Main_NonMain: MotherBrainsTubesFalling_Main_NonMain(k); return; + case fnMotherBrainsTubesFalling_WaitToFall: MotherBrainsTubesFalling_WaitToFall(k); return; + case fnMotherBrainsTubesFalling_Falling: MotherBrainsTubesFalling_Falling(k); return; + default: Unreachable(); + } +} + +void MotherBrainsTubesFalling_Main(uint16 k) { // 0xA98B85 + Enemy_MotherBrainsTubesFalling *E = Get_MotherBrainsTubesFalling(k); + CallMotherBrainsTubesFalling(E->mbtfg_var_A | 0xA90000, k); +} + +void MotherBrainsTubesFalling_Main_NonMain(uint16 k) { // 0xA98B88 + Enemy_MotherBrainsTubesFalling *E = Get_MotherBrainsTubesFalling(k); + uint16 v2 = E->mbtfg_var_C + 6; + E->mbtfg_var_C = v2; + Enemy_IncreaseYpos(k, v2); + if ((int16)(E->base.y_pos - E->mbtfg_var_B) < 0) + MotherBrainsTubesFalling_HandleSmoke(k); + else + MotherBrainsTubesFalling_Explode(k); +} + +void MotherBrainsTubesFalling_HandleSmoke(uint16 k) { // 0xA98B9D + Enemy_MotherBrainsTubesFalling *E = Get_MotherBrainsTubesFalling(k); + if ((--E->mbtfg_var_D & 0x8000u) != 0) + MotherBrainsTubesFalling_SpawnSmoke(k); +} + +void MotherBrainsTubesFalling_Explode(uint16 k) { // 0xA98BA6 + Enemy_MotherBrainsTubesFalling *E = Get_MotherBrainsTubesFalling(k); + E->base.properties |= kEnemyProps_Deleted; + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 3u); + QueueSfx2_Max3(0x24u); +} + +void MotherBrainsTubesFalling_WaitToFall(uint16 k) { // 0xA98BCB + Enemy_MotherBrainsTubesFalling *E = Get_MotherBrainsTubesFalling(k); + if ((--E->mbtfg_parameter_2 & 0x8000u) != 0) { + E->mbtfg_var_A = FUNC16(MotherBrainsTubesFalling_Falling); + MotherBrainsTubesFalling_Falling(k); + } +} + +void MotherBrainsTubesFalling_Falling(uint16 k) { // 0xA98BD6 + Enemy_MotherBrainsTubesFalling *E = Get_MotherBrainsTubesFalling(k); + uint16 v2 = E->mbtfg_var_C + 6; + E->mbtfg_var_C = v2; + Enemy_IncreaseYpos(k, v2); + uint16 ypos = E->base.y_pos; + if (!sign16(ypos - 244)) + E->base.properties |= kEnemyProps_Invisible; + Enemy_MotherBrainsTubesFalling *E1 = Get_MotherBrainsTubesFalling(0x40u); + E1->base.y_pos = ypos - 56; + if (sign16(E1->base.y_pos - 0xc4)) { + MotherBrainsTubesFalling_HandleSmoke(k); + } else { + MotherBrain_Pal_EndScreenFlash(); + EnableEarthquakeAframes(0x19u); + hdma_object_channels_bitmask[0] = 0; + hdma_object_channels_bitmask[1] = 0; + // BUG! + //E->mbtfg_var_C = 0; + E1->base.y_pos = 196; + Enemy_MotherBrainsTubesFalling *E0 = Get_MotherBrainsTubesFalling(0); + E0->base.x_pos = 59; + E0->base.y_pos = 279; + MotherBrain_SetupNeckForFakeAscent(); + E0->mbtfg_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_0_DrawBG1Row23); + MotherBrainsTubesFalling_Explode(cur_enemy_index); + } +} + +void MotherBrainsTubesFalling_SpawnSmoke(uint16 k) { // 0xA98C36 + Enemy_MotherBrainsTubesFalling *E = Get_MotherBrainsTubesFalling(k); + E->mbtfg_var_D = 8; + uint16 v2 = ((uint8)E->mbtfg_var_E + 1) & 3; + E->mbtfg_var_E = v2; + R18_ = E->base.x_pos + g_word_A98C61[v2]; + R20_ = 208; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 9u); +} + +static const SpawnHardcodedPlmArgs unk_A98C8B = { 0x02, 0x02, 0xb67b }; +static const SpawnHardcodedPlmArgs unk_A98C93 = { 0x02, 0x03, 0xb67f }; +static const SpawnHardcodedPlmArgs unk_A98CA2 = { 0x02, 0x04, 0xb683 }; +static const SpawnHardcodedPlmArgs unk_A98CAA = { 0x02, 0x05, 0xb687 }; +static const SpawnHardcodedPlmArgs unk_A98CB9 = { 0x02, 0x06, 0xb68b }; +static const SpawnHardcodedPlmArgs unk_A98CC1 = { 0x02, 0x07, 0xb68f }; +static const SpawnHardcodedPlmArgs unk_A98CD0 = { 0x02, 0x08, 0xb693 }; +static const SpawnHardcodedPlmArgs unk_A98CD8 = { 0x02, 0x09, 0xb697 }; +static const SpawnHardcodedPlmArgs unk_A98CE7 = { 0x02, 0x0a, 0xb69b }; +static const SpawnHardcodedPlmArgs unk_A98CEF = { 0x02, 0x0b, 0xb69f }; +static const SpawnHardcodedPlmArgs unk_A98CFE = { 0x02, 0x0c, 0xb6a3 }; +static const SpawnHardcodedPlmArgs unk_A98D06 = { 0x02, 0x0d, 0xb6a7 }; + +void MotherBrainBody_FakeDeath_Ascent_0_DrawBG1Row23(void) { // 0xA98C87 + SpawnHardcodedPlm(&unk_A98C8B); + SpawnHardcodedPlm(&unk_A98C93); + Get_MotherBrainBody(0)->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_1_DrawBG1Row45); +} + +void MotherBrainBody_FakeDeath_Ascent_1_DrawBG1Row45(void) { // 0xA98C9E + SpawnHardcodedPlm(&unk_A98CA2); + SpawnHardcodedPlm(&unk_A98CAA); + Get_MotherBrainBody(0)->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_2_DrawBG1Row67); +} + +void MotherBrainBody_FakeDeath_Ascent_2_DrawBG1Row67(void) { // 0xA98CB5 + SpawnHardcodedPlm(&unk_A98CB9); + SpawnHardcodedPlm(&unk_A98CC1); + Get_MotherBrainBody(0)->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_3_DrawBG1Row89); +} + +void MotherBrainBody_FakeDeath_Ascent_3_DrawBG1Row89(void) { // 0xA98CCC + SpawnHardcodedPlm(&unk_A98CD0); + SpawnHardcodedPlm(&unk_A98CD8); + Get_MotherBrainBody(0)->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_4_DrawBG1RowAB); +} + +void MotherBrainBody_FakeDeath_Ascent_4_DrawBG1RowAB(void) { // 0xA98CE3 + SpawnHardcodedPlm(&unk_A98CE7); + SpawnHardcodedPlm(&unk_A98CEF); + Get_MotherBrainBody(0)->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_5_DrawBG1RowCD); +} + +void MotherBrainBody_FakeDeath_Ascent_5_DrawBG1RowCD(void) { // 0xA98CFA + SpawnHardcodedPlm(&unk_A98CFE); + SpawnHardcodedPlm(&unk_A98D06); + Get_MotherBrainBody(0)->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_6_SetupPhase2Gfx); +} + +void MotherBrainBody_FakeDeath_Ascent_6_SetupPhase2Gfx(void) { // 0xA98D11 + *(uint16 *)&layer2_scroll_x = 257; + *(uint16 *)®_BG2SC &= 0xFFFCu; + WriteColorsToPalette(0x142u, 0xa9, addr_kMotherBrainPalette_1__plus__2, 0xFu); + WriteColorsToPalette(0x162u, 0xa9, addr_kMotherBrainPalette_0__plus__2, 0xFu); + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_7_SetupPhase2Brain); + nmi_flag_bg2_enemy_vram_transfer = 1; + Get_MotherBrain(0x40u)->mbn_var_02 = 1; +} + +void MotherBrainBody_FakeDeath_Ascent_7_SetupPhase2Brain(void) { // 0xA98D49 + fx_layer_blending_config_a = 52; + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0x40u); + E->mbby_var_A = FUNC16(MotherBrainsBrain_SetupBrainAndNeckToDraw); + Enemy_MotherBrainBody *E0 = Get_MotherBrainBody(0); + E0->base.properties &= ~kEnemyProps_Tangible; + E->base.properties &= ~0x400u; + E->base.health = 18000; + E0->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_8_Pause); + E0->mbby_var_F = 128; + MotherBrainBody_FakeDeath_Ascent_8_Pause(); +} + +void MotherBrainBody_FakeDeath_Ascent_8_Pause(void) { // 0xA98D79 + Enemy_MotherBrainBody *E = Get_MotherBrainBody(0); + if ((--E->mbby_var_F & 0x8000u) != 0) { + E->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_9_PrepareRise); + E->mbby_var_F = 32; + MotherBrainBody_FakeDeath_Ascent_9_PrepareRise(); + } +} + +void MotherBrainBody_FakeDeath_Ascent_9_PrepareRise(void) { // 0xA98D8B + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->mbn_var_09 = MotherBrainRisingHdmaObject(); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->base.properties |= 0x100u; + MotherBrain_SetBrainInstrs(addr_stru_A99C21); + E->mbn_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_10_LoadLegTiles); + E->mbn_var_F = 256; + MotherBrainBody_FakeDeath_Ascent_10_LoadLegTiles(); + } +} + +void MotherBrainBody_FakeDeath_Ascent_10_LoadLegTiles(void) { // 0xA98DB4 + if (ProcessSpriteTilesTransfers(0xa9, addr_stru_A98F8F)) { + Get_MotherBrainBody(0)->mbby_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_11_ContinuePause); + MotherBrainBody_FakeDeath_Ascent_11_ContinuePause(); + } +} + +void MotherBrainBody_FakeDeath_Ascent_11_ContinuePause(void) { // 0xA98DC3 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->base.x_pos = 59; + E->base.y_pos = 279; + reg_BG2HOFS = -27; + reg_BG2VOFS = -217; + E->mbn_var_04 = 7; + E->mbn_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_12_StartMusic); + } +} + +void MotherBrainBody_FakeDeath_Ascent_12_StartMusic(void) { // 0xA98DEC + MotherBrain_SetBodyInstrs(addr_kMotherBrain_Ilist_9A02); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->base.instruction_timer = 1; + Enemy_MotherBrain *E0 = Get_MotherBrain(0); + E0->base.properties &= ~kEnemyProps_Invisible; + E0->base.x_pos = 59; + E0->base.y_pos = 279; + reg_BG2HOFS = -27; + reg_BG2VOFS = -217; + QueueMusic_Delayed8(5u); + earthquake_type = 2; + earthquake_timer = 256; + E1->mbn_var_34 = 80; + E1->mbn_var_31 = 1; + E1->mbn_var_32 = 8; + E1->mbn_var_33 = 6; + E0->mbn_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_13_Raise); +} + +void MotherBrainBody_FakeDeath_Ascent_13_Raise(void) { // 0xA98E4D + Enemy_MotherBrain *E = Get_MotherBrain(0); + uint16 v1; + if ((nmi_frame_counter_word & 3) != 0 + || (MotherBrain_SpawnDustCloudsForAscent(), + R18_ = 2, + reg_BG2VOFS += 2, + v1 = E->base.y_pos - 2, + E->base.y_pos = v1, + v1 >= 0xBDu)) { + } else { + enemy_bg2_tilemap_size = 320; + E->base.y_pos = 188; + earthquake_timer = 0; + hdma_object_channels_bitmask[E->mbn_var_09 >> 1] = 0; + MotherBrain_SetBodyInstrs(addr_kMotherBrain_Ilist_99AA); + E->mbn_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_14_WaitForUncouching); + MotherBrainBody_FakeDeath_Ascent_14_WaitForUncouching(); + } +} + +void MotherBrainBody_FakeDeath_Ascent_14_WaitForUncouching(void) { // 0xA98E95 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (!E->mbn_var_02) { + E->mbn_var_37 = 0; + E->mbn_var_A = FUNC16(MotherBrainBody_FakeDeath_Ascent_15_TransitionFromGrey); + E->mbn_var_F = 0; + } +} + +void MotherBrainBody_FakeDeath_Ascent_15_TransitionFromGrey(void) { // 0xA98EAA + Enemy_MotherBrain *E0 = Get_MotherBrain(0); + if ((--E0->mbn_var_F & 0x8000u) != 0) { + E0->mbn_var_F = 4; + uint16 v3 = E0->mbn_var_37 + 1; + E0->mbn_var_37 = v3; + if (MotherBrain_FadeFromGray_FakeDeath(v3 - 1) & 1) { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_10 = 1; + E0->mbn_var_00 = 2; + E1->mbn_var_12 = 1; + E1->mbn_var_32 = 6; + E1->mbn_var_33 = 6; + E1->mbn_var_34 = 1280; + E0->mbn_var_A = FUNC16(MotherBrainBody_2ndphase_16_ShakeHeadMenacingly); + E0->mbn_var_F = 23; + } + } +} + +void MotherBrainBody_2ndphase_16_ShakeHeadMenacingly(void) { // 0xA98EF5 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9B7F); + E->mbn_var_A = FUNC16(MotherBrainBody_2ndphase_17_BringHeadBackUp); + Get_MotherBrain(0x40u)->mbn_var_34 = 64; + E->mbn_var_F = 256; + MotherBrainBody_2ndphase_17_BringHeadBackUp(); + } +} + +void MotherBrainBody_2ndphase_17_BringHeadBackUp(void) { // 0xA98F14 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_32 = 2; + E1->mbn_var_33 = 4; + E->mbn_var_A = FUNC16(MotherBrainBody_2ndphase_18_FinishStretching); + E->mbn_var_F = 64; + MotherBrainBody_2ndphase_18_FinishStretching(); + } +} + +void MotherBrainBody_2ndphase_18_FinishStretching(void) { // 0xA98F33 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + Get_MotherBrain(0x40u)->mbn_var_14 = 1; + E->mbn_var_A = FUNC16(MotherBrain_Body_Phase2_Thinking); + } +} + +void MotherBrain_SpawnDustCloudsForAscent(void) { // 0xA98F46 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + if ((--E->mbn_var_F & 0x8000u) != 0) + E->mbn_var_F = 7; + R18_ = g_word_A98F7F[E->mbn_var_F]; + R20_ = 212; + SpawnEnemyProjectileWithRoomGfx( + addr_kEproj_DustCloudExplosion, + g_byte_A98F7D[(uint16)(random_number & 0x100) >> 8]); + QueueSfx2_Max3(0x29u); +} + +void MotherBrain_SetupNeckForFakeAscent(void) { // 0xA9903F + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + E->mbn_var_24 = 2; + E->mbn_var_27 = 10; + E->mbn_var_2D = 10; + E->mbn_var_2A = 20; + E->mbn_var_30 = 20; + E->mbn_var_20 = 18432; + E->mbn_var_21 = 20480; + E->mbn_var_34 = 256; +} + +void MotherBrain_HandleNeckLower(void) { // 0xA99072 + uint16 mbn_var_32 = Get_MotherBrain(0x40u)->mbn_var_32; + if (mbn_var_32) { + switch (mbn_var_32) { + case 2u: + MotherBrain_HandleNeckLower_2_BobDown(); + break; + case 4u: + MotherBrain_HandleNeckLower_4_BobUp(); + break; + case 6u: + MotherBrain_HandleNeckLower_6_Lower(); + break; + case 8u: + MotherBrain_HandleNeckLower_8_Raise(); + break; + default: + Unreachable(); + while (1) + ; + } + } else { + MotherBrain_HandleNeckLower_0(); + } +} + +void MotherBrain_HandleNeckLower_0(void) { // 0xA99084 + ; +} + +void MotherBrain_HandleNeckLower_2_BobDown(void) { // 0xA99085 + int16 v1; + + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + v1 = E->mbn_var_20 - E->mbn_var_34; + if ((uint16)v1 < 0x2800u) { + E->mbn_var_32 = 4; + v1 = 10240; + } + E->mbn_var_20 = v1; +} + +void MotherBrain_HandleNeckLower_4_BobUp(void) { // 0xA990A2 + int16 v1; + + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + if (sign16(E->base.y_pos - 60)) { + E->mbn_var_32 = 2; + } else { + v1 = E->mbn_var_34 + E->mbn_var_20; + if ((uint16)v1 >= 0x9000u) { + E->mbn_var_32 = 2; + v1 = -28672; + } + E->mbn_var_20 = v1; + } +} + +void MotherBrain_HandleNeckLower_6_Lower(void) { // 0xA990CF + int16 v1; + + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + v1 = E->mbn_var_20 - E->mbn_var_34; + if ((uint16)v1 < 0x3000u) { + E->mbn_var_32 = 0; + v1 = 12288; + } + E->mbn_var_20 = v1; +} + +void MotherBrain_HandleNeckLower_8_Raise(void) { // 0xA990EC + int16 v1; + + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + v1 = E->mbn_var_34 + E->mbn_var_20; + if ((uint16)v1 >= 0x9000u) { + E->mbn_var_32 = 0; + v1 = -28672; + } + E->mbn_var_20 = v1; +} + +void MotherBrain_HandleNeckUpper(void) { // 0xA99109 + int16 v2; + int16 v6; + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + uint16 mbn_var_33 = E->mbn_var_33; + if (mbn_var_33) { + switch (mbn_var_33) { + case 2u: + if ((int16)(E->base.y_pos + 4 - samus_y_pos) < 0) { + v2 = E->mbn_var_21 - E->mbn_var_34; + if ((uint16)v2 < 0x2000u) { + E->mbn_var_33 = 4; + v2 = 0x2000; + } + E->mbn_var_21 = v2; + } else { + E->mbn_var_32 = 4; + E->mbn_var_33 = 4; + } + break; + case 4u: { + R18_ = E->mbn_var_20 + 2048; + uint16 v4 = E->mbn_var_34 + E->mbn_var_21; + if (v4 >= R18_) { + E->mbn_var_33 = 2; + v4 = R18_; + } + E->mbn_var_21 = v4; + break; + } + case 6u: { + v6 = E->mbn_var_21 - E->mbn_var_34; + if ((uint16)v6 < 0x2000u) { + E->mbn_var_33 = 0; + v6 = 0x2000; + } + E->mbn_var_21 = v6; + break; + } + case 8u: { + R18_ = E->mbn_var_20 + 2048; + uint16 v8 = E->mbn_var_34 + E->mbn_var_21; + if (v8 >= R18_) { + E->mbn_var_33 = 0; + v8 = R18_; + } + E->mbn_var_21 = v8; + break; + } + default: + Unreachable(); + while (1) + ; + } + } +} + +void MotherBrain_HandleNeck(void) { // 0xA991B8 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_0A = E->base.x_pos - 80; + E->mbn_var_0B = E->base.y_pos + 46; + + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + if (E1->mbn_var_31) { + MotherBrain_HandleNeckLower(); + MotherBrain_HandleNeckUpper(); + } + R18_ = HIBYTE(E1->mbn_var_20); + E1->mbn_var_22 = E->mbn_var_0A + ComputeSinMult(E1->mbn_var_24) + 112; + E1->mbn_var_23 = E->mbn_var_0B + ComputeCosMult(E1->mbn_var_24) - 96; + E1->mbn_var_25 = E->mbn_var_0A + ComputeSinMult(E1->mbn_var_27) + 112; + E1->mbn_var_26 = E->mbn_var_0B + ComputeCosMult(E1->mbn_var_27) - 96; + E1->mbn_var_28 = E->mbn_var_0A + ComputeSinMult(E1->mbn_var_2A) + 112; + E1->mbn_var_29 = E->mbn_var_0B + ComputeCosMult(E1->mbn_var_2A) - 96; + R18_ = HIBYTE(E1->mbn_var_21); + E1->mbn_var_2B = E1->mbn_var_28 + ComputeSinMult(E1->mbn_var_2D); + E1->mbn_var_2C = E1->mbn_var_29 + ComputeCosMult(E1->mbn_var_2D); + E1->mbn_var_2E = E1->mbn_var_28 + ComputeSinMult(E1->mbn_var_30); + E1->mbn_var_2F = E1->mbn_var_29 + ComputeCosMult(E1->mbn_var_30); +} + + +uint16 CallMotherBrainInstr(uint32 ea, uint16 k) { + switch (ea) { + case fnMotherBrain_Instr_Goto: return MotherBrain_Instr_Goto(k); + case fnMotherBrain_Instr_EnableNeckMovementGoto: return MotherBrain_Instr_EnableNeckMovementGoto(k); + case fnMotherBrain_Instr_DisableNeckMovement: return MotherBrain_Instr_DisableNeckMovement(k); + case fnMotherBrain_Instr_QueueSfx2: return MotherBrain_Instr_QueueSfx2(k); + case fnMotherBrain_Instr_QueueSfx3: return MotherBrain_Instr_QueueSfx3(k); + case fnMotherBrain_Instr_SpawnDroolEproj: return MotherBrain_Instr_SpawnDroolEproj(k); + case fnMotherBrain_Instr_SpawnPurpleBreath: return MotherBrain_Instr_SpawnPurpleBreath(k); + case fnMotherBrain_Instr_SetMainShakeTimer50: return MotherBrain_Instr_SetMainShakeTimer50(k); + case fnMotherBrain_Instr_GotoEitherOr: return MotherBrain_Instr_GotoEitherOr(k); + case fnMotherBrain_Instr_MaybeGoto: return MotherBrain_Instr_MaybeGoto(k); + case fnMotherBrain_Instr_MaybeGoto2: return MotherBrain_Instr_MaybeGoto2(k); + case fnMotherBrain_Instr_Goto2: return MotherBrain_Instr_Goto2(k); + case fnMotherBrain_Instr_QueueShitroidAttackSfx: return MotherBrain_Instr_QueueShitroidAttackSfx(k); + case fnMotherBrain_Instr_SpawnBlueRingEproj: return MotherBrain_Instr_SpawnBlueRingEproj(k); + case fnMotherBrain_Instr_AimRingsAtShitroid: return MotherBrain_Instr_AimRingsAtShitroid(k); + case fnMotherBrain_Instr_AimRingsAtSamus: return MotherBrain_Instr_AimRingsAtSamus(k); + case fnMotherBrain_Instr_IncrShitroidAttackCtr: return MotherBrain_Instr_IncrShitroidAttackCtr(k); + case fnMotherBrain_Instr_SetShitroidAttackCtr0: return MotherBrain_Instr_SetShitroidAttackCtr0(k); + case fnMotherBrain_Instr_SpawnBombEproj: return MotherBrain_Instr_SpawnBombEproj(k); + case fnMotherBrain_Instr_SpawnLaserEproj: return MotherBrain_Instr_SpawnLaserEproj(k); + case fnMotherBrain_Instr_SpawnRainbowEproj: return MotherBrain_Instr_SpawnRainbowEproj(k); + case fnMotherBrain_Instr_SetupFxForRainbowBeam: return MotherBrain_Instr_SetupFxForRainbowBeam(k); + default: return Unreachable(); + } +} + +int MotherBrain_Func_1_DoubleRet(void) { + int16 v1; + int16 mbn_var_21; + int16 v5; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + + if (time_is_frozen_flag) { + mbn_var_21 = E->mbn_var_21; + if (mbn_var_21 >= 0) + return -1; + return *((uint16 *)RomPtr_A9(mbn_var_21) + 1); + } else { + v1 = E->mbn_var_21; + if (v1 >= 0) + return -1; + uint16 v4 = E->mbn_var_21; + v5 = *(uint16 *)RomPtr_A9(v1); + if (v5 < 0) + goto LABEL_10; + if ((int16)(v5 - E->mbn_var_20) >= 0) { + ++E->mbn_var_20; + return *((uint16 *)RomPtr_A9(v4) + 1); + } else { + for (v4 += 4; ; ) { + v5 = *(uint16 *)RomPtr_A9(v4); + if (v5 >= 0) + break; +LABEL_10: + R0_.addr = v5; + v4 = CallMotherBrainInstr((uint16)v5 | 0xA90000, v4 + 2); + } + E->mbn_var_20 = 1; + E->mbn_var_21 = v4; + return *((uint16 *)RomPtr_A9(v4) + 1); + } + } +} + +void MotherBrain_DrawNeck(void) { // 0xA99303 + if ((Get_MotherBrain(0)->base.properties & kEnemyProps_Invisible) == 0) { + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + R18_ = E->mbn_var_2E; + R20_ = E->mbn_var_2F; + MotherBrain_DrawNeckSegment(); + R18_ = E->mbn_var_2B; + R20_ = E->mbn_var_2C; + MotherBrain_DrawNeckSegment(); + R18_ = E->mbn_var_28; + R20_ = E->mbn_var_29; + MotherBrain_DrawNeckSegment(); + R18_ = E->mbn_var_25; + R20_ = E->mbn_var_26; + MotherBrain_DrawNeckSegment(); + R18_ = E->mbn_var_22; + R20_ = E->mbn_var_23; + MotherBrain_DrawNeckSegment(); + } +} + +void MotherBrain_DrawBrain(void) { // 0xA99357 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + if (E->mbn_var_14 && !E->mbn_var_15 && (random_number & 0x8000u) == 0) + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainPurpleBreathSmall, random_number); + int tt = MotherBrain_Func_1_DoubleRet(); + if (tt < 0) + return; + uint16 v2 = tt; + uint16 mbn_var_0D = Get_MotherBrain(0)->mbn_var_0D; + if (E->base.flash_timer & 1) + mbn_var_0D = 0; + R22_ = mbn_var_0D; + uint16 mbn_var_00 = E->mbn_var_00; + uint16 flash_timer; + if (mbn_var_00) { + flash_timer = mbn_var_00 - 1; + E->mbn_var_00 = flash_timer; + } else { + flash_timer = E->base.flash_timer; + if (!flash_timer) + flash_timer = E->base.shake_timer; + } + int v6 = (uint8)(flash_timer & 6) >> 1; + R18_ = E->base.x_pos + g_word_A993BB[v6]; + if ((int16)(R18_ + 32 - layer1_x_pos) >= 0) { + R20_ = E->base.y_pos + g_word_A993C3[v6]; + MotherBrain_AddSpritemapToOam(v2); + } +} + +void MotherBrain_DrawNeckSegment(void) { // 0xA993CB + int v0 = (uint8)(Get_MotherBrain(0x40u)->base.flash_timer & 6) >> 1; + R18_ += g_word_A993BB[v0]; + R20_ += g_word_A993C3[v0]; + R22_ = Get_MotherBrain(0)->mbn_var_0C; + MotherBrain_AddSpritemapToOam(addr_kMotherBrain_Sprmap_A694); +} + +void MotherBrain_AddSpritemapToOam(uint16 j) { // 0xA993EE + int16 *v5; + int16 v6; + int16 v7; + char v8; // t0 + int16 v10; + int16 v12; + OamEnt *v13; + int16 v15; + int16 v17; + + uint16 *v1 = (uint16 *)RomPtr_A9(j); + uint16 v2 = j + 2; + R24_ = *v1; + uint16 v3 = oam_next_ptr; + do { + uint8 *v4 = RomPtr_A9(v2); + v5 = (int16 *)v4; + v6 = v4[2] << 8; + if ((v4[2] & 0x80) != 0) + v6 |= 0xFFu; + v8 = v6; + LOBYTE(v7) = HIBYTE(v6); + HIBYTE(v7) = v8; + uint16 v9 = R20_ + v7; + bool v11 = v9 < layer1_y_pos; + v10 = v9 - layer1_y_pos; + v11 = !v11; + if (v10 >= 0) { + R26_ = v10; + v12 = R18_ + v11 + *(uint16 *)v4 - layer1_x_pos; + v13 = gOamEnt(v3); + *(uint16 *)&v13->xcoord = v12; + if ((v12 & 0x100) != 0) { + int v14 = v3 >> 1; + R28_ = kOamExtra_Address_And_X8Large[v14]; + v15 = kOamExtra_X8Small_And_Large[v14] | *(uint16 *)RomPtr_RAM(R28_); + *(uint16 *)RomPtr_RAM(R28_) = v15; + } + if (*v5 < 0) { + int v16 = v3 >> 1; + R28_ = kOamExtra_Address_And_X8Large[v16]; + v17 = kOamExtra_X8Small_And_Large[v16 + 1] | *(uint16 *)RomPtr_RAM(R28_); + *(uint16 *)RomPtr_RAM(R28_) = v17; + } + *(uint16 *)&v13->ycoord = R26_; + *(uint16 *)&v13->charnum = R22_ | *(int16 *)((char *)v5 + 3); + v3 = (v3 + 4) & 0x1FF; + } + v2 += 5; + --R24_; + } while (R24_); + oam_next_ptr = v3; +} + +void MotherBrain_CalculateRainbowBeamHdma(void) { // 0xA99466 + MotherBrain_CalcHdma(); +} + +void MotherBrain_MoveBodyDownScrollLeft(uint16 k, uint16 a) { // 0xA99552 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.y_pos += a; + reg_BG2VOFS -= a; + R20_ = k + 34; + reg_BG2HOFS = k + 34 - E->base.x_pos; +} + +void MotherBrain_MoveBodyDown(uint16 a) { // 0xA99579 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.y_pos += a; + reg_BG2VOFS -= a; + reg_BG2HOFS = 34 - E->base.x_pos; +} + +void MotherBrain_FootstepEffect(void) { // 0xA99599 + earthquake_type = 1; + earthquake_timer = 4; + if (Get_MotherBrain(0)->mbn_var_00 == 3) + printf("Write to rom!\n"); + // word_80914D = 22; +} + +uint16 MotherBrain_Instr_MoveBodyUp10Left4(uint16 k, uint16 j) { // 0xA995B6 + MotherBrain_MoveBodyDownScrollLeft(4u, 0xFFF6u); + return j; +} + +uint16 MotherBrain_Instr_MoveBodyUp16Left4(uint16 k, uint16 j) { // 0xA995C0 + MotherBrain_MoveBodyDownScrollLeft(4u, 0xFFF0u); + return j; +} + +uint16 MotherBrain_Instr_MoveBodyUp12Right2(uint16 k, uint16 j) { // 0xA995CA + MotherBrain_MoveBodyDownScrollLeft(0xFFFEu, 0xFFF4u); + return j; +} + +uint16 MotherBrain_Instr_MoveDown12Left4(uint16 k, uint16 j) { // 0xA995DE + MotherBrain_MoveBodyDownScrollLeft(4u, 0xCu); + return j; +} + +uint16 MotherBrain_Instr_MoveDown16Right2(uint16 k, uint16 j) { // 0xA995E8 + MotherBrain_MoveBodyDownScrollLeft(0xFFFEu, 0x10u); + return j; +} + +uint16 MotherBrain_Instr_MoveDown10Right2(uint16 k, uint16 j) { // 0xA995F2 + MotherBrain_MoveBodyDownScrollLeft(0xFFFEu, 0xAu); + return j; +} + +uint16 MotherBrain_Instr_MoveUp2Right1(uint16 k, uint16 j) { // 0xA995FC + Enemy_MotherBrain *E = Get_MotherBrain(0); + ++E->base.x_pos; + MotherBrain_MoveBodyDown(0xFFFEu); + return j; +} + +uint16 MotherBrain_Instr_MoveRight2(uint16 k, uint16 j) { // 0xA9960C + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.x_pos += 2; + MotherBrain_MoveBodyDown(0); + return j; +} + +uint16 MotherBrain_Instr_MoveUp1(uint16 k, uint16 j) { // 0xA9961C + MotherBrain_MoveBodyDown(1u); + return j; +} + +uint16 MotherBrain_Instr_MoveUp1Right3_Sfx(uint16 k, uint16 j) { // 0xA99622 + MotherBrain_FootstepEffect(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.x_pos += 3; + MotherBrain_MoveBodyDown(1u); + return j; +} + +uint16 MotherBrain_Instr_Down2Right15(uint16 k, uint16 j) { // 0xA99638 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.x_pos += 15; + MotherBrain_MoveBodyDown(0xFFFEu); + return j; +} + +uint16 MotherBrain_Instr_Down4Right6(uint16 k, uint16 j) { // 0xA99648 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.x_pos += 6; + MotherBrain_MoveBodyDown(0xFFFCu); + return j; +} + +uint16 MotherBrain_Instr_Up4Left2(uint16 k, uint16 j) { // 0xA99658 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.x_pos -= 2; + MotherBrain_MoveBodyDown(4u); + return j; +} + +uint16 MotherBrain_Instr_Up2Left1_Sfx(uint16 k, uint16 j) { // 0xA99668 + MotherBrain_FootstepEffect(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + --E->base.x_pos; + MotherBrain_MoveBodyDown(2u); + return j; +} + +uint16 MotherBrain_Instr_Up2Left1_Sfx2(uint16 k, uint16 j) { // 0xA9967E + MotherBrain_FootstepEffect(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + --E->base.x_pos; + MotherBrain_MoveBodyDown(2u); + return j; +} + +uint16 MotherBrain_Instr_MoveLeft2(uint16 k, uint16 j) { // 0xA99694 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.x_pos -= 2; + MotherBrain_MoveBodyDown(0); + return j; +} + +uint16 MotherBrain_Instr_MoveDown1(uint16 k, uint16 j) { // 0xA996A4 + MotherBrain_MoveBodyDown(0xFFFFu); + return j; +} + +uint16 MotherBrain_Instr_MoveDown1Left3(uint16 k, uint16 j) { // 0xA996AA + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.x_pos -= 3; + MotherBrain_MoveBodyDown(0xFFFFu); + return j; +} + +uint16 MotherBrain_Instr_MoveUp2Left15_Sfx(uint16 k, uint16 j) { // 0xA996BA + MotherBrain_FootstepEffect(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.x_pos -= 15; + MotherBrain_MoveBodyDown(2u); + return j; +} + +uint16 MotherBrain_Instr_MoveUp4Left6(uint16 k, uint16 j) { // 0xA996D0 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.x_pos -= 6; + MotherBrain_MoveBodyDown(4u); + return j; +} + +uint16 MotherBrain_Instr_MoveDown4Right2(uint16 k, uint16 j) { // 0xA996E0 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.x_pos += 2; + MotherBrain_MoveBodyDown(0xFFFCu); + return j; +} + +uint16 MotherBrain_Instr_MoveDown2Right1(uint16 k, uint16 j) { // 0xA996F0 + Enemy_MotherBrain *E = Get_MotherBrain(0); + ++E->base.x_pos; + MotherBrain_MoveBodyDown(0xFFFEu); + return j; +} + +uint16 MotherBrain_Instr_SetPose_Standing(uint16 k, uint16 j) { // 0xA99700 + Get_MotherBrain(0)->mbn_var_02 = 0; + return j; +} + +uint16 MotherBrain_Instr_SetPose_Walking(uint16 k, uint16 j) { // 0xA99708 + Get_MotherBrain(0)->mbn_var_02 = 1; + return j; +} + +uint16 MotherBrain_Instr_SetPose_Crouched(uint16 k, uint16 j) { // 0xA99710 + Get_MotherBrain(0)->mbn_var_02 = 3; + return j; +} + +uint16 MotherBrain_Instr_SetPose_CrouchedTrans(uint16 k, uint16 j) { // 0xA99718 + Get_MotherBrain(0)->mbn_var_02 = 2; + return j; +} + +uint16 MotherBrain_Instr_SetPose_DeathBeamMode(uint16 k, uint16 j) { // 0xA99720 + Get_MotherBrain(0)->mbn_var_02 = 4; + return j; +} + +uint16 MotherBrain_Instr_SetPose_LeaningDown(uint16 k, uint16 j) { // 0xA99728 + Get_MotherBrain(0)->mbn_var_02 = 6; + return j; +} + +uint16 MotherBrain_Instr_SpawnEprojToOffset(uint16 k, uint16 j) { // 0xA99AC8 + uint8 *v2 = RomPtr_A9(j); + Enemy_MotherBrain *E = Get_MotherBrain(0); + R18_ = E->base.x_pos + *(uint16 *)v2; + R20_ = E->base.y_pos + *((uint16 *)v2 + 1); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, *((uint16 *)v2 + 2)); + return j + 6; +} + +uint16 MotherBrain_Instr_SpawnDeathBeamEproj(uint16 k, uint16 j) { // 0xA99AEF + uint16 v2; + printf("A undefined\n"); v2 = 0; + QueueSfx2_Max6(0x63u); + SpawnEnemyProjectileWithGfx(v2, 0x40u, addr_kEproj_MotherBrainDeathBeamCharging); + return j; +} + +uint16 MotherBrain_Instr_IncrBeamAttackPhase(uint16 k, uint16 j) { // 0xA99B05 + Enemy_MotherBrain *E = Get_MotherBrain(0); + ++E->mbn_var_17; + return j; +} + +uint16 MotherBrain_Instr_Goto(uint16 k) { // 0xA99B0F + return *(uint16 *)RomPtr_A9(k); +} + +uint16 MotherBrain_Instr_EnableNeckMovementGoto(uint16 k) { // 0xA99B14 + Get_MotherBrain(0x40u)->mbn_var_31 = 1; + return *(uint16 *)RomPtr_A9(k); +} + +uint16 MotherBrain_Instr_DisableNeckMovement(uint16 k) { // 0xA99B20 + Get_MotherBrain(0x40u)->mbn_var_31 = 0; + return k; +} + +uint16 MotherBrain_Instr_QueueSfx2(uint16 k) { // 0xA99B28 + uint16 *v2 = (uint16 *)RomPtr_A9(k); + QueueSfx2_Max6(*v2); + return k + 2; +} + +uint16 MotherBrain_Instr_QueueSfx3(uint16 k) { // 0xA99B32 + uint16 *v2 = (uint16 *)RomPtr_A9(k); + QueueSfx3_Max6(*v2); + return k + 2; +} + +uint16 MotherBrain_Instr_SpawnDroolEproj(uint16 k) { // 0xA99B3C + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + if (E->mbn_var_12) { + uint16 v2 = E->mbn_var_13 + 1; + if (!sign16(E->mbn_var_13 - 5)) + v2 = 0; + E->mbn_var_13 = v2; + uint16 v3 = addr_kEproj_MotherBrainDrool; + if (!sign16(E->mbn_var_34 - 128)) + v3 = addr_kEproj_MotherBrainDyingDrool; + SpawnEnemyProjectileWithRoomGfx(v3, E->mbn_var_13); + } + return k; +} + +uint16 MotherBrain_Instr_SpawnPurpleBreath(uint16 k) { // 0xA99B6D + uint16 v2; + printf("A undefined\n"); v2 = 0; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainPurpleBreathBig, v2); + return k; +} + +uint16 MotherBrain_Instr_SetMainShakeTimer50(uint16 k) { // 0xA99B77 + Get_MotherBrain(0x40u)->mbn_var_00 = 50; + return k; +} + +uint16 MotherBrain_Instr_GotoEitherOr(uint16 k) { // 0xA99C65 + uint16 result = addr_stru_A99C5F; + if ((random_number & 0xFFFu) >= 0xFE0) + return addr_stru_A99C47; + return result; +} + +uint16 MotherBrain_Instr_MaybeGoto(uint16 k) { // 0xA99CAD + if (random_number < 0xF000u) + return addr_stru_A99C9F; + return k; +} + +uint16 MotherBrain_Instr_MaybeGoto2(uint16 k) { // 0xA99D0D + if ((random_number & 0xFFFu) < 0xEC0) + return MotherBrain_Instr_Goto2(k); + return k; +} + +uint16 MotherBrain_Instr_QueueShitroidAttackSfx(uint16 k) { // 0xA99DF7 + if (Get_MotherBrain(0)->mbn_var_13 != 11) + QueueSfx2_Max6(g_word_A99E0F[0]); + return k; +} + +uint16 MotherBrain_Instr_Goto2(uint16 k) { // 0xA99D21 + return addr_stru_A99CD1; +} + +uint16 MotherBrain_Instr_SpawnBlueRingEproj(uint16 k) { // 0xA99E29 + Enemy_MotherBrain *E = Get_MotherBrain(0); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainBlueRingLasers, E->mbn_var_1A); + return k; +} + +uint16 MotherBrain_Instr_AimRingsAtShitroid(uint16 k) { // 0xA99E37 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + Enemy_MotherBrain *E1 = Get_MotherBrain(E->mbn_var_0A); + R18_ = E1->base.x_pos - E->base.x_pos - 10; + R20_ = E1->base.y_pos - E->base.y_pos - 16; + MotherBrain_Instr_AimRings(); + return k; +} + +uint16 MotherBrain_Instr_AimRingsAtSamus(uint16 k) { // 0xA99E5B + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + R18_ = samus_x_pos - E->base.x_pos - 10; + R20_ = samus_y_pos - E->base.y_pos - 16; + MotherBrain_Instr_AimRings(); + return k; +} + +void MotherBrain_Instr_AimRings(void) { // 0xA99E77 + uint16 v0 = (uint8)-(int8)(CalculateAngleFromXY() + 0x80); + if (!sign8(v0 - 16)) { + if ((uint8)v0 < 0x48u) + goto LABEL_6; +LABEL_5: + LOBYTE(v0) = 72; + goto LABEL_6; + } + if (sign8(v0 + 64)) + goto LABEL_5; + LOBYTE(v0) = 16; +LABEL_6: + Get_MotherBrain(0)->mbn_var_1A = v0; +} + +uint16 MotherBrain_Instr_IncrShitroidAttackCtr(uint16 k) { // 0xA99EA3 + int16 v3; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + v3 = E->mbn_var_13 + 1; + if ((uint16)v3 >= 0xCu) + v3 = 12; + E->mbn_var_13 = v3; + return k; +} + +uint16 MotherBrain_Instr_SetShitroidAttackCtr0(uint16 k) { // 0xA99EB5 + Get_MotherBrain(0)->mbn_var_13 = 0; + return k; +} + +uint16 MotherBrain_Instr_SpawnBombEproj(uint16 k) { // 0xA99EBD + uint16 *v2 = (uint16 *)RomPtr_A9(k); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainBomb, *v2); + return k + 2; +} + +uint16 MotherBrain_Instr_SpawnLaserEproj(uint16 k) { // 0xA99F46 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + E->mbn_var_31 = 0; + R18_ = E->base.x_pos + 16; + R20_ = E->base.y_pos + 4; + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A17B, 1u); + return k; +} + +uint16 MotherBrain_Instr_SpawnRainbowEproj(uint16 k) { // 0xA99F84 + uint16 v2; + printf("A undefined\n"); v2 = 0; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainRainbowBeamCharging, v2); + return k; +} + +uint16 MotherBrain_Instr_SetupFxForRainbowBeam(uint16 k) { // 0xA99F8E + Get_MotherBrain(0x40u)->mbn_var_14 = 0; + MotherBrain_SetupBrainPalForLaser(); + QueueSfx2_Max6(0x7Fu); + return k; +} + +void MotherBrain_Phase3_Death_0(void) { // 0xA9AEE1 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.properties |= kEnemyProps_Tangible; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->base.properties |= 0x400u; + E->mbn_var_04 = 0; + if (MotherBrain_MakeWalkBackwards(0x28u, 6u) & 1) { + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_1); + E->mbn_var_F = 128; + MotherBrain_Phase3_Death_1(); + } +} + +void MotherBrain_Phase3_Death_1(void) { // 0xA9AF12 + MotherBrain_GenerateSmokyExplosions(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_2); +} + +void MotherBrain_Phase3_Death_2(void) { // 0xA9AF21 + MotherBrain_GenerateSmokyExplosions(); + if (MotherBrain_MakeWalkForwards(2u, 0x60u) & 1) { + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9C39); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_32 = 6; + E1->mbn_var_33 = 6; + E1->mbn_var_34 = 1280; + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_3); + E->mbn_var_F = 32; + } +} + +void MotherBrain_Phase3_Death_3(void) { // 0xA9AF54 + MotherBrain_GenerateSmokyExplosions(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_32 = 0; + E1->mbn_var_33 = 0; + E1->mbn_var_12 = 0; + E1->mbn_var_14 = 0; + E1->mbn_var_10 = 0; + E1->mbn_var_11 = 0; + for (int i = 28; i >= 0; i -= 2) + palette_buffer[(i >> 1) + 241] = palette_buffer[(i >> 1) + 145]; + MotherBrain_HealthBasedPaletteHandling(); + E->mbn_var_0D = 3584; + E1->mbn_var_E = 0; + E1->mbn_var_F = 0; + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_4); + MotherBrain_Phase3_Death_4(); + } +} + +void MotherBrain_Phase3_Death_4(void) { // 0xA9AF9D + MotherBrain_GenerateMixedExplosions(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->mbn_var_37 = 0; + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_5); + E->mbn_var_F = 0; + MotherBrain_Phase3_Death_5(); + } +} + +void MotherBrain_Phase3_Death_5(void) { // 0xA9AFB6 + HandleMotherBrainBodyFlickering(); + MotherBrain_GenerateMixedExplosions(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->mbn_var_F = 16; + uint16 v2 = E->mbn_var_37 + 1; + E->mbn_var_37 = v2; + if (MotherBrain_FadePalToBlack(v2 - 1) & 1) { + enemy_bg2_tilemap_size = 710; + for (int i = 710; i >= 0; i -= 2) + tilemap_stuff[i >> 1] = 824; + nmi_flag_bg2_enemy_vram_transfer = 1; + E->base.properties = E->base.properties & 0xDEFF | 0x100; + E->base.extra_properties = 0; + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_6); + E->mbn_var_F = 16; + } + } +} + +void MotherBrain_Phase3_Death_6(void) { // 0xA9B013 + MotherBrain_GenerateMixedExplosions(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_7); +} + +void MotherBrain_GenerateSmokyExplosions(void) { // 0xA9B022 + R22_ = addr_word_A9B10F; + R24_ = 2; + MotherBrain_GenerateExplosions(0x10u); +} + +void MotherBrain_GenerateMixedExplosions(void) { // 0xA9B031 + R22_ = addr_word_A9B109; + R24_ = 4; + MotherBrain_GenerateExplosions(8u); +} + +void MotherBrain_GenerateExplosions(uint16 a) { // 0xA9B03E + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + bool v2 = (--E->mbn_var_E & 0x8000u) != 0; + if (v2) { + E->mbn_var_E = a; + v2 = (--E->mbn_var_F & 0x8000u) != 0; + if (v2) + E->mbn_var_F = 6; + uint16 v3 = 16 * E->mbn_var_F; + uint16 v4 = R24_; + uint16 v9; + do { + v9 = v4; + int v5 = v3 >> 1; + R18_ = g_word_A9B099[v5]; + R20_ = g_word_A9B099[v5 + 1]; + uint16 *v6 = (uint16 *)RomPtr_A9(R22_); + uint16 v7 = *v6; + uint16 Random = NextRandom(); + if (Random >= 0x4000u) { + v7 = v6[1]; + if (Random >= 0xE000u) + v7 = v6[2]; + } + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainDeathExplosion, v7); + v3 += 4; + v4 = v9 - 1; + } while (v9 != 1); + QueueSfx3_Max3(0x13u); + } +} + +void MotherBrain_Phase3_Death_7(void) { // 0xA9B115 + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9C29); + Get_MotherBrain(0x40u)->mbn_var_A = FUNC16(MotherBrainsBrain_SetupBrainToDraw); + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_F = 0; + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_8); + MotherBrain_Phase3_Death_8(); +} + +void MotherBrain_Phase3_Death_8(void) { // 0xA9B12D + int16 v3; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + uint16 v1 = E->mbn_var_F + 32; + E->mbn_var_F = v1; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + v3 = E1->base.y_pos + HIBYTE(v1); + if ((uint16)v3 >= 0xC4u) { + EnableEarthquakeAframes(2u); + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_9); + E->mbn_var_F = 256; + v3 = 196; + } + E1->base.y_pos = v3; +} + +void MotherBrain_Phase3_Death_9(void) { // 0xA9B15E + if (ProcessSpriteTilesTransfers(0xa9, addr_stru_A99003)) { + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_10); + E->mbn_var_F = 32; + } +} + +void MotherBrain_Phase3_Death_10(void) { // 0xA9B173 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->mbn_var_37 = 0; + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_11); + E->mbn_var_F = 0; + } +} + +void MotherBrain_Phase3_Death_11(void) { // 0xA9B189 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + uint16 v2 = E->mbn_var_37 + 1; + E->mbn_var_37 = v2; + if (MotherBrain_FadeToGray_RealDeath(v2 - 1) & 1) { + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9D25); + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_12); + E->mbn_var_F = 256; + } else { + E->mbn_var_F = 16; + } + } +} + +void MotherBrain_Phase3_Death_12(void) { // 0xA9B1B8 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_13); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->base.properties |= 0x400u; + E->mbn_var_04 = 0; + } +} + +void MotherBrain_Phase3_Death_13(void) { // 0xA9B1D5 + if (ProcessCorpseRotting(0x40u) & 1) { + uint16 dms_var_53 = Get_DeadMonsters(0x40u)->dms_var_53; + ProcessCorpseRottingVramTransfers(dms_var_53); + } else { + Enemy_DeadMonsters *E1 = Get_DeadMonsters(0x40u); + E1->base.properties = E1->base.properties & 0xDEFF | 0x100; + E1->base.extra_properties = 0; + QueueMusic_Delayed8(0); + QueueMusic_Delayed8(0xFF24u); + E1 = Get_DeadMonsters(0); + E1->dms_var_A = FUNC16(MotherBrain_Phase3_Death_14_20framedelay); + E1->dms_var_F = 20; + MotherBrain_Phase3_Death_14_20framedelay(); + } +} + +void MotherBrain_Phase3_Death_14_20framedelay(void) { // 0xA9B211 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->base.x_pos = 0; + E1->base.y_pos = 0; + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_15_LoadEscapeTimerTiles); + } +} + +void MotherBrain_CorpseRottingFinished(void) { // 0xA9B223 + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + R18_ = E1->base.x_pos + (random_number & 0x1F) - 16; + R20_ = E1->base.y_pos + 16; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0xAu); + if ((enemy_damage_routine_exec_count & 7) == 0) + QueueSfx2_Max3(0x10u); +} + +void MotherBrain_Phase3_Death_15_LoadEscapeTimerTiles(void) { // 0xA9B258 + if (ProcessSpriteTilesTransfers(0xa6, addr_stru_A6C4CB)) { + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_16_StartEscape); + MotherBrain_Phase3_Death_16_StartEscape(); + } +} + +void MotherBrain_Phase3_Death_16_StartEscape(void) { // 0xA9B26D + if (ProcessSpriteTilesTransfers(0xa9, addr_stru_A9902F)) { + WriteColorsToPalette(0x122u, 0xa9, addr_kMotherBrainPalette_5__plus__2, 0xEu); + QueueMusic_Delayed8(7u); + earthquake_type = 5; + earthquake_timer = -1; + SpawnPalfxObject(addr_kPalfx_FFC9); + SpawnPalfxObject(addr_kPalfx_FFCD); + SpawnPalfxObject(addr_kPalfx_FFD1); + SpawnPalfxObject(addr_kPalfx_FFD5); + Get_MotherBrain(0x40u)->mbn_var_02 = 0; + SetupZebesEscapeTypewriter(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_F = 32; + uint16 v1 = FUNC16(MotherBrain_Phase3_Death_17_SpawnTimeBomb); + if (!japanese_text_flag) + v1 = FUNC16(MotherBrain_Phase3_Death_18_TypesZebesText); + E->mbn_var_A = v1; + } +} + +void MotherBrain_Phase3_Death_17_SpawnTimeBomb(void) { // 0xA9B2D1 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_18_TypesZebesText); + SpawnEnemyProjectileWithRoomGfx( + addr_kEproj_TimeBombSetJapaneseText, + FUNC16(MotherBrain_Phase3_Death_18_TypesZebesText)); + } + MotherBrain_Phase3_Death_18_TypesZebesText(); +} + +void MotherBrain_Phase3_Death_18_TypesZebesText(void) { // 0xA9B2E3 + if (HandleTypewriterText_Ext(0x2610u) & 1) { + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_19_EscapeDoorExploding); + E->mbn_var_F = 32; + } +} + +void MotherBrain_Phase3_Death_19_EscapeDoorExploding(void) { // 0xA9B2F9 + MotherBrain_GenerateEscapeDoorExploding(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + CallSomeSamusCode(0xFu); + timer_status = 2; + SetBossBitForCurArea(2u); + SetEventHappened(0xEu); + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_20_BlowUpEscapeDoor); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_E = 0; + E1->mbn_var_F = 0; + } +} + +void MotherBrain_Phase3_Death_20_BlowUpEscapeDoor(void) { // 0xA9B32A + static const SpawnHardcodedPlmArgs unk_A9B337 = { 0x00, 0x06, 0xb677 }; + MotherBrain_ExplodeEscapeDoor(); + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_21_KeepEarthquakeGoing); + SpawnHardcodedPlm(&unk_A9B337); +} + +void MotherBrain_Phase3_Death_21_KeepEarthquakeGoing(void) { // 0xA9B33C + if (!earthquake_timer) + --earthquake_timer; +} + +void MotherBrain_GenerateEscapeDoorExploding(void) { // 0xA9B346 + int16 v1; + int16 v2; + + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + v1 = E->mbn_var_E - 1; + E->mbn_var_E = v1; + if (v1 < 0) { + E->mbn_var_E = 4; + v2 = E->mbn_var_F - 1; + E->mbn_var_F = v2; + if (v2 < 0) + E->mbn_var_F = 3; + int v3 = (uint16)(4 * E->mbn_var_F) >> 1; + R18_ = g_word_A9B393[v3]; + R20_ = g_word_A9B393[v3 + 1]; + uint16 v4 = 3; + if (NextRandom() < 0x4000u) + v4 = 12; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, v4); + QueueSfx2_Max3(0x24u); + } +} + +void MotherBrain_ExplodeEscapeDoor(void) { // 0xA9B3A3 + uint16 v0 = 0, v1; + do { + v1 = v0; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainExplodedEscapeDoor, v0); + v0 = v1 + 1; + } while ((uint16)(v1 + 1) < 8u); +} + +void MotherBrain_SamusCollDetect(void) { // 0xA9B3B6 + char v1; // cf + + Enemy_MotherBrain *E0 = Get_MotherBrain(0); + R26_ = E0->mbn_var_04; + v1 = R26_ & 1; + R26_ >>= 1; + if (!v1 + || (R18_ = E0->base.x_pos, + R20_ = E0->base.y_pos, + !(MotherBrain_SamusCollDetectPart(addr_word_A9B427) & 1))) { + + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + v1 = R26_ & 1; + R26_ >>= 1; + if (!v1 + || (R18_ = E->base.x_pos, + R20_ = E->base.y_pos, + !(MotherBrain_SamusCollDetectPart(0xB439u) & 1))) { + v1 = R26_ & 1; + R26_ >>= 1; + if (v1) { + R18_ = E->mbn_var_25; + R20_ = E->mbn_var_26; + if (!(MotherBrain_SamusCollDetectPart(0xB44Bu) & 1)) { + R18_ = E->mbn_var_28; + R20_ = E->mbn_var_29; + if (!(MotherBrain_SamusCollDetectPart(0xB44Bu) & 1)) { + R18_ = E->mbn_var_2B; + R20_ = E->mbn_var_2C; + MotherBrain_SamusCollDetectPart(0xB44Bu); + } + } + } + } + } +} + +uint8 MotherBrain_SamusCollDetectPart(uint16 k) { // 0xA9B455 + int16 v5; + + uint16 *v1 = (uint16 *)RomPtr_A9(k); + if (!*v1) + return 0; + R22_ = *v1; + for (int i = k + 2; ; i += 8) { + uint16 v3, v4; + if ((int16)(samus_y_pos - R20_) >= 0) { + R24_ = samus_y_pos - R20_; + v3 = *((uint16 *)RomPtr_A9(i) + 3); + } else { + R24_ = R20_ - samus_y_pos; + v3 = *((uint16 *)RomPtr_A9(i) + 1); + } + if ((int16)(samus_y_radius + abs16(v3) - R24_) >= 0) { + if ((int16)(samus_x_pos - R18_) >= 0) { + R24_ = samus_x_pos - R18_; + v4 = *((uint16 *)RomPtr_A9(i) + 2); + } else { + R24_ = R18_ - samus_x_pos; + v4 = *(uint16 *)RomPtr_A9(i); + } + v5 = samus_x_radius + abs16(v4) - R24_; + if (v5 >= 0) + break; + } + if (!--R22_) + return 0; + } + if (sign16(v5 - 4)) + v5 = 4; + extra_samus_x_displacement = v5; + extra_samus_y_displacement = 4; + extra_samus_x_subdisplacement = 0; + extra_samus_y_subdisplacement = 0; + samus_invincibility_timer = 96; + samus_knockback_timer = 5; + knockback_x_dir = 1; + if (sign16(samus_y_pos - 192)) + samus_y_dir = 2; + if ((int16)(Get_MotherBrain(0)->base.x_pos + 24 - samus_x_pos) < 0) + MotherBrain_HurtSamus(); + return 1; +} + +void MotherBrainsBody_Shot(void) { // 0xA9B503 + CreateDudShot(); +} + +void MotherBrainsBrain_Shot(void) { // 0xA9B507 + int16 v2; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (E->mbn_var_00) { + MotherBrain_Phase23_ShotReaction(); + if (E->mbn_var_00 == 1) + CreateDudShot(); + else + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + } else { + uint16 v1 = HIBYTE(projectile_type[collision_detection_index]) & 7; + if (g_byte_A9B546[v1]) { + plm_room_arguments[39] += g_byte_A9B546[v1]; + QueueSfx2_Max6(0x6Eu); + v2 = 13; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + uint16 flash_timer = E1->base.flash_timer; + if (flash_timer) { + if (flash_timer & 1) + v2 = 14; + } + E1->base.flash_timer = v2; + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + } + } +} + +void MotherBrain_Phase23_ShotReaction(void) { // 0xA9B562 + int16 v1; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (E->mbn_var_00 == 4 && MotherBrain_DetermineShotReactionType() == 2) { + MotherBrain_Phase3_BeamShotReaction(); + } else { + if (MotherBrain_DetermineShotReactionType() == 1 || (v1 = E->mbn_var_07 - 256, v1 < 0)) + v1 = 0; + E->mbn_var_07 = v1; + } +} + +uint16 MotherBrain_DetermineShotReactionType(void) { // 0xA9B58E + return g_byte_A9B5A1[HIBYTE(projectile_type[collision_detection_index]) & 7]; +} + +void MotherBrain_Phase3_BeamShotReaction(void) { // 0xA9B5A9 + int16 v1; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + v1 = E->mbn_var_07 - 266; + if (v1 < 0) { + Get_MotherBrain(0x40u)->mbn_var_18 = FUNC16(MotherBrain_Phase3_Neck_SetupHyperBeamRecoil); + v1 = 0; + E->mbn_var_F = 0; + } + E->mbn_var_07 = v1; +} + +void MotherBrainsBrain_Touch(void) { // 0xA9B5C6 + int16 v0; + + if (samus_movement_type == 3) { + v0 = 13; + EnemyData *v1 = gEnemyData(0); + uint16 flash_timer = v1[1].flash_timer; + if (flash_timer) { + if (flash_timer & 1) + v0 = 14; + } + v1[1].flash_timer = v0; + } +} + +void MotherBrain_HurtSamus(void) { // 0xA9B5E1 + Ridley_Func_98(); + samus_invincibility_timer = 96; + samus_knockback_timer = 5; + knockback_x_dir = (int16)(samus_x_pos - Get_MotherBrain(cur_enemy_index)->base.x_pos) >= 0; +} + +void MotherBrain_Body_Phase2_Thinking(void) { // 0xA9B605 + Enemy_MotherBrain *E = Get_MotherBrain(0); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + if (!E1->base.health) { + E->mbn_var_A = FUNC16(MotherBomb_FiringRainbowBeam_0); + MotherBomb_FiringRainbowBeam_0(); + return; + } + if (!E->mbn_var_02) { + if (!sign16(E1->base.health - 4500)) { + if (random_number >= 0x1000u) { +LABEL_6: + MotherBrain_HandleWalking(); + return; + } +LABEL_7: + E->mbn_var_A = FUNC16(MotherBrain_Body_Phase2_TryAttack); + return; + } + if (random_number < 0x2000u) + goto LABEL_6; + if (random_number >= 0xA000u) + goto LABEL_7; + E->mbn_var_A = FUNC16(MotherBomb_FiringDeathBeam); + } +} + +void MotherBrain_Body_Phase2_TryAttack(void) { // 0xA9B64B + int16 v0; + Enemy_MotherBrain *E = Get_MotherBrain(0); + + v0 = 2 * E->mbn_var_18; + if (v0) { + if (v0 == 2) { + MotherBrain_Phase2_Attack_Cooldown(); + } else { + if (v0 != 4) { + Unreachable(); + while (1) + ; + } + MotherBrain_Phase2_Attack_End(); + } + } else { + E->mbn_parameter_1 = 64; + ++E->mbn_var_18; + if (MotherBrain_Phase2_DecideAttackStrategy_DoubleRet()) + return; + uint16 v2 = addr_byte_A9B6DC; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + if (abs16(E1->base.y_pos + 4 - samus_y_pos) < 0x20u) + v2 = addr_byte_A9B6DF; + uint16 v4 = 0; + uint8 *v5 = RomPtr_A9(v2); + if ((uint8)random_number >= *v5) { + v4 = 2; + if ((uint8)random_number >= v5[1]) { + v4 = 4; + if ((uint8)random_number >= v5[2]) + v4 = 6; + } + } + uint16 v6 = g_off_A9B6D4[v4 >> 1]; + if (v6 == (uint16)addr_kMotherBrain_Ilist_9ECC) { + if (sign16(E1->mbn_var_05 - 1)) { + E->mbn_var_A = FUNC16(MotherBrain_FiringBomb_DecideOnWalking); + MotherBrain_FiringBomb_DecideOnWalking(); + } + } else if (v6 == (uint16)addr_kMotherBrain_Ilist_9F34) { + E->mbn_var_A = FUNC16(MotherBomb_FiringLaser_PositionHead); + MotherBomb_FiringLaser_PositionHead(); + } else { + MotherBrain_SetBrainInstrs(v6); + } + } +} + +uint8 MotherBrain_Phase2_DecideAttackStrategy_DoubleRet(void) { // 0xA9B6E2 + if (g_word_A9B72C[samus_movement_type]) { + if (sign16((uint8)random_number - 128)) { + return 0; + } else { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + if (sign16(E1->mbn_var_05 - 1)) { + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrain_FiringBomb_DecideOnWalking); + MotherBrain_FiringBomb_DecideOnWalking(); + return 1; + } + return 0; + } + } else { + if (sign16((uint8)random_number - 128)) { + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBomb_FiringLaser_PositionHead); + MotherBomb_FiringLaser_PositionHead(); + } else { + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9D3D); + } + return 1; + } +} + +void MotherBrain_Phase2_Attack_Cooldown(void) { // 0xA9B764 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (E->mbn_parameter_1-- == 1) + ++E->mbn_var_18; +} + +void MotherBrain_Phase2_Attack_End(void) { // 0xA9B773 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_18 = 0; + E->mbn_var_A = FUNC16(MotherBrain_Body_Phase2_Thinking); +} + +void MotherBrain_FiringBomb_DecideOnWalking(void) { // 0xA9B781 + if (random_number >= 0xFF80u) { + MotherBrain_FiringBomb_DecideOnCrouching(); + return; + } + uint16 v0 = 64; + if (random_number < 0x6000u) + v0 = 96; + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((int16)(v0 - E->base.x_pos) >= 0 + || (E->mbn_var_F = v0, MotherBrain_MakeWalkBackwards(v0, 6u) & 1)) { + MotherBrain_FiringBomb_DecideOnCrouching(); + } else { + E->mbn_var_A = FUNC16(MotherBrain_FiringBomb_WalkingBackwards); + } +} + +void MotherBrain_FiringBomb_WalkingBackwards(void) { // 0xA9B7AC + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (MotherBrain_MakeWalkBackwards(E->mbn_var_F, 6u) & 1) + MotherBrain_FiringBomb_DecideOnCrouching(); +} + +void MotherBrain_FiringBomb_DecideOnCrouching(void) { // 0xA9B7B7 + if (NextRandom() >= 0x8000u) { + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrain_FiringBomb_Crouch); + MotherBrain_FiringBomb_Crouch(); + } else { + MotherBrain_B7CB(); + } +} + +void MotherBrain_FiringBomb_Crouch(void) { // 0xA9B7C6 + if (MotherBrain_MakeHerCrouch() & 1) + MotherBrain_B7CB(); +} + +void MotherBrain_B7CB(void) { // 0xA9B7CB + uint16 v0 = addr_kMotherBrain_Ilist_9ECC; + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (E->mbn_var_1F) + v0 = addr_kMotherBrain_Ilist_9F00; + MotherBrain_SetBrainInstrs(v0); + E->mbn_var_A = FUNC16(MotherBrain_FiringBomb_Fired); + E->mbn_var_F = 44; +} + +void MotherBrain_FiringBomb_Fired(void) { // 0xA9B7E8 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + if (MotherBrain_MakeHerStandUp() & 1) { + MotherBrain_FiringBomb_Finish(); + } else { + E->mbn_var_A = FUNC16(MotherBrain_FiringBomb_Standup); + MotherBrain_FiringBomb_Standup(); + } + } +} + +void MotherBrain_FiringBomb_Standup(void) { // 0xA9B7F8 + if (MotherBrain_MakeHerStandUp() & 1) + MotherBrain_FiringBomb_Finish(); +} + +void MotherBrain_FiringBomb_Finish(void) { // 0xA9B7FD + uint16 v0 = FUNC16(MotherBrain_Body_Phase2_Thinking); + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (E->mbn_var_1F) + v0 = FUNC16(MotherBrain_Phase2_MurderShitroid_1); + E->mbn_var_A = v0; +} + +void MotherBomb_FiringLaser_PositionHead(void) { // 0xA9B80E + int16 v0; + + v0 = 8; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + if ((int16)(E1->base.y_pos - samus_y_pos) < 0) + v0 = 6; + E1->mbn_var_32 = v0; + E1->mbn_var_33 = v0; + E1->mbn_var_34 = 512; + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBomb_FiringLaser_PositionHeadSlowlyFire); + E->mbn_var_F = 4; +} + +void MotherBomb_FiringLaser_PositionHeadSlowlyFire(void) { // 0xA9B839 + int16 v2; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + v2 = 256; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + if ((E1->mbn_var_34 & 0x8000u) != 0) + v2 = -256; + E1->mbn_var_34 = v2; + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9F34); + E->mbn_var_A = FUNC16(MotherBomb_FiringLaser_FinishAttack); + E->mbn_var_F = 16; + } +} + +void MotherBomb_FiringLaser_FinishAttack(void) { // 0xA9B863 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_32 = 4; + E1->mbn_var_33 = 4; + E->mbn_var_A = FUNC16(MotherBrain_Body_Phase2_Thinking); + MotherBrain_Body_Phase2_Thinking(); + } +} + +static Func_V *const off_A9B887[4] = { // 0xA9B87D + MotherBomb_FiringDeathBeam_0, + MotherBomb_FiringDeathBeam_1, + MotherBomb_FiringDeathBeam_2, + MotherBomb_FiringDeathBeam_3, +}; +void MotherBomb_FiringDeathBeam(void) { + + int v0 = (uint16)(2 * Get_MotherBrain(0)->mbn_var_17) >> 1; + off_A9B887[v0](); +} + +void MotherBomb_FiringDeathBeam_0(void) { // 0xA9B88F + if (MotherBrain_MakeWalkBackwards(0x28u, 8u) & 1) { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_32 = 8; + E1->mbn_var_33 = 6; + Enemy_MotherBrain *E = Get_MotherBrain(0); + ++E->mbn_var_17; + } +} + +void MotherBomb_FiringDeathBeam_1(void) { // 0xA9B8B2 + if (!Get_MotherBrain(0x40u)->mbn_var_05) { + MotherBrain_SetBodyInstrs(addr_kMotherBrain_Ilist_9A42); + Enemy_MotherBrain *E = Get_MotherBrain(0); + ++E->mbn_var_17; + } +} + +void MotherBomb_FiringDeathBeam_2(void) { // 0xA9B8C8 + ; +} + +void MotherBomb_FiringDeathBeam_3(void) { // 0xA9B8C9 + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9C87); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_32 = 2; + E1->mbn_var_33 = 4; + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_17 = 0; + E->mbn_var_A = FUNC16(MotherBrain_Body_Phase2_Thinking); +} + +void MotherBomb_FiringRainbowBeam_0(void) { // 0xA9B8EB + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9C87); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_34 = 64; + E1->mbn_var_31 = 1; + E1->mbn_var_32 = 2; + E1->mbn_var_33 = 4; + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBomb_FiringRainbowBeam_1_StartCharge); + E->mbn_var_F = 256; + +} + +void MotherBomb_FiringRainbowBeam_1_StartCharge(void) { // 0xA9B91A + Enemy_MotherBomb *E = Get_MotherBomb(0); + if ((--E->mbb_var_F & 0x8000u) != 0) { + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9F6C); + E->mbb_var_A = FUNC16(MotherBomb_FiringRainbowBeam_2_RetractNeck); + MotherBomb_FiringRainbowBeam_2_RetractNeck(); + } +} + +void MotherBomb_FiringRainbowBeam_2_RetractNeck(void) { // 0xA9B92B + if (MotherBrain_WalkBackwardsSlowlyAndRetractHead(0x28u) & 1) { + Enemy_MotherBomb *E = Get_MotherBomb(0); + E->mbb_var_A = FUNC16(MotherBomb_FiringRainbowBeam_3_Wait); + E->mbb_var_F = 256; + MotherBomb_FiringRainbowBeam_3_Wait(); + } +} + +void MotherBomb_FiringRainbowBeam_3_Wait(void) { // 0xA9B93F + Enemy_MotherBomb *E = Get_MotherBomb(0); + if ((--E->mbb_var_F & 0x8000u) != 0) { + QueueSfx2_Max6(0x71u); + E->mbb_var_A = FUNC16(MotherBomb_FiringRainbowBeam_4_ExtendNeckDown); + MotherBomb_FiringRainbowBeam_4_ExtendNeckDown(); + } +} + +void MotherBomb_FiringRainbowBeam_4_ExtendNeckDown(void) { // 0xA9B951 + cooldown_timer = 8; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_32 = 6; + E1->mbn_var_33 = 6; + E1->mbn_var_34 = 1280; + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBomb_FiringRainbowBeam_5_StartFiring); + E->mbn_var_F = 16; + MotherBomb_FiringRainbowBeam_5_StartFiring(); +} + +void MotherBomb_FiringRainbowBeam_5_StartFiring(void) { // 0xA9B975 + MotherBrain_AimBeamAndIncrWidth(); + if (!power_bomb_flag) { + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0 && !power_bomb_flag) { + cooldown_timer = 0; + MotherBrain_BodyRainbowBeamPalAnimIndex0(); + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9C77); + E->mbn_var_33 = 512; + E->mbn_var_09 = SpawnMotherBrainRainbowBeamHdma(); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_34 = 64; + E1->mbn_var_31 = 1; + E1->mbn_var_32 = 2; + E1->mbn_var_33 = 4; + E->mbn_parameter_1 = 0; + E->mbn_parameter_2 = 0; + uint16 v4 = 5; + if ((int16)(samus_health - 700) < 0) + v4 = 24; + CallSomeSamusCode(v4); + E->mbn_var_15 = 6; + E->mbn_var_A = FUNC16(MotherBomb_FiringRainbowBeam_6_MoveSamusToWall); + } + } +} + +void MotherBomb_FiringRainbowBeam_6_MoveSamusToWall(void) { // 0xA9B9E5 + MotherBrain_PlayRainbowBeamSfx(); + MotherBrain_HandleRainbowBeamPalette(); + MotherBrain_AimBeamAndIncrWidth(); + MotherBrain_HandleRainbowBeamExplosions(); + if (MotherBrain_MoveSamusTowardsWallDueToBeam() & 1) { + Enemy_MotherBomb *E = Get_MotherBomb(0); + E->mbb_var_A = FUNC16(MotherBomb_FiringRainbowBeam_7_DelayFrame); + E->mbb_var_F = 0; + } +} + +void MotherBomb_FiringRainbowBeam_7_DelayFrame(void) { // 0xA9BA00 + MotherBrain_PlayRainbowBeamSfx(); + MotherBrain_HandleRainbowBeamPalette(); + MotherBrain_AimBeamAndIncrWidth(); + MotherBrain_HandleRainbowBeamExplosions(); + MotherBrain_MoveSamusTowardsWallDueToBeam(); + Enemy_MotherBomb *E = Get_MotherBomb(0); + if ((--E->mbb_var_F & 0x8000u) != 0) { + earthquake_type = 8; + earthquake_timer = 8; + E->mbb_var_A = FUNC16(MotherBomb_FiringRainbowBeam_8_StartDrainSamus); + } +} + +void MotherBomb_FiringRainbowBeam_8_StartDrainSamus(void) { // 0xA9BA27 + Enemy_MotherBomb *E = Get_MotherBomb(0); + E->mbb_var_A = FUNC16(MotherBomb_FiringRainbowBeam_9_DrainingSamus); + E->mbb_var_F = 299; + earthquake_timer = 299; + earthquake_type = 8; + MotherBomb_FiringRainbowBeam_9_DrainingSamus(); +} + +void MotherBomb_FiringRainbowBeam_9_DrainingSamus(void) { // 0xA9BA3C + MotherBrain_PlayRainbowBeamSfx(); + MotherBrain_HandleRainbowBeamPalette(); + MotherBrain_AimBeamAndIncrWidth(); + MotherBrain_HandleRainbowBeamExplosions(); + Samus_DamageDueToRainbowBeam(); + Samus_DecrementAmmoDueToRainbowBeam(); + MotherBrain_MoveSamusTowardsMiddleOfWall(); + Enemy_MotherBomb *E = Get_MotherBomb(0); + if ((--E->mbb_var_F & 0x8000u) != 0) + E->mbb_var_A = FUNC16(MotherBomb_FiringRainbowBeam_10_FinishFiringRainbow); +} + +void MotherBomb_FiringRainbowBeam_10_FinishFiringRainbow(void) { // 0xA9BA5E + MotherBrain_PlayRainbowBeamSfx(); + MotherBrain_HandleRainbowBeamPalette(); + MotherBrain_AimBeam(); + MotherBrain_HandleRainbowBeamExplosions(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + uint16 v1 = E->mbn_var_33 - 384; + E->mbn_var_33 = v1; + if (sign16(v1 - 512)) { + E->mbn_var_33 = 512; + E->mbn_parameter_1 = -256; + E->mbn_parameter_2 = 0; + hdma_object_channels_bitmask[E->mbn_var_09 >> 1] = 0; + earthquake_timer = 0; + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9C87); + MotherBrain_SetupBrainNormalPal(); + MotherBrain_WriteDefaultPalette(); + QueueSfx1_Max6(2u); + E->mbn_var_16 = 0; + CallSomeSamusCode(1u); + cooldown_timer = 8; + E->mbn_var_A = FUNC16(MotherBomb_FiringRainbowBeam_11_LetSamusFall); + } +} + +void MotherBomb_FiringRainbowBeam_11_LetSamusFall(void) { // 0xA9BAC4 + SomeMotherBrainScripts(0); + Get_MotherBomb(0)->mbb_var_A = FUNC16(MotherBomb_FiringRainbowBeam_12_WaitForSamusHitGround); + MotherBomb_FiringRainbowBeam_12_WaitForSamusHitGround(); +} + +void MotherBomb_FiringRainbowBeam_12_WaitForSamusHitGround(void) { // 0xA9BAD1 + if (MotherBrain_MoveSamusForFallingAfterBeam() & 1) + Get_MotherBomb(0)->mbb_var_A = FUNC16(MotherBomb_FiringRainbowBeam_13_LowerHead); +} + +void MotherBomb_FiringRainbowBeam_13_LowerHead(void) { // 0xA9BADD + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_34 = 64; + E1->mbn_var_31 = 1; + E1->mbn_var_32 = 2; + E1->mbn_var_33 = 4; + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBomb_FiringRainbowBeam_14_DecideNextAction); + E->mbn_var_F = 128; +} + +void MotherBomb_FiringRainbowBeam_14_DecideNextAction(void) { // 0xA9BB06 + Enemy_MotherBomb *E = Get_MotherBomb(0); + if ((--E->mbb_var_F & 0x8000u) != 0) { + if (sign16(samus_health - 400)) { + MotherBrain_MakeWalkForwards(0xAu, E->base.x_pos + 16); + E->mbb_var_A = FUNC16(MotherBrain_Phase2Cut_0); + } else { + E->mbb_var_A = FUNC16(MotherBomb_FiringRainbowBeam_0); + } + } +} + +void MotherBrain_PlayRainbowBeamSfx(void) { // 0xA9BB2E + int16 mbn_var_15; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + mbn_var_15 = E->mbn_var_15; + if (mbn_var_15 >= 0) { + E->mbn_var_15 = mbn_var_15 - 1; + QueueSfx1_Max6(0x40u); + E->mbn_var_16 = 1; + } +} + +uint8 MotherBrain_WalkBackwardsSlowlyAndRetractHead(uint16 a) { // 0xA9BB48 + uint8 rv = MotherBrain_MakeWalkBackwards(a, 0xAu); + if (rv) + MotherBrain_RetractHead(); + return rv; +} + +void MotherBrain_RetractHead(void) { // 0xA9BB51 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + E->mbn_var_34 = 80; + E->mbn_var_31 = 1; + E->mbn_var_32 = 8; + E->mbn_var_33 = 6; +} + +void MotherBrain_AimBeamAndIncrWidth(void) { // 0xA9BB6E + int16 v1; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + v1 = E->mbn_var_33 + 384; + if (!sign16(E->mbn_var_33 - 2688)) + v1 = 3072; + E->mbn_var_33 = v1; + MotherBrain_AimBeam(); +} + +void MotherBrain_AimBeam(void) { // 0xA9BB82 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + R18_ = samus_x_pos - E->base.x_pos - 16; + R20_ = samus_y_pos - E->base.y_pos - 4; + uint16 v1 = (uint8)-(int8)(CalculateAngleFromXY() + 0x80); + Get_MotherBrain(0)->mbn_var_31 = v1; +} + +void MotherBrain_CalculateRainbowBeamHdma_(void) { // 0xA9BBB0 + MotherBrain_CalculateRainbowBeamHdma(); +} + +uint8 MotherBrain_MoveSamusTowardsWallDueToBeam(void) { // 0xA9BBB5 + uint8 v0 = MotherBrain_MoveSamusHorizTowardsWall(0x1000u); + if (!v0) { + R18_ = Get_MotherBrain(0)->mbn_var_31; + uint16 v1 = Math_MultByCos(0x1000u); + MotherBrain_MoveSamusVerticallyTowardsCeilingFloor(v1); + } + return v0; +} + +void MotherBrain_MoveSamusTowardsMiddleOfWall(void) { // 0xA9BBCF + uint16 v0 = 64; + if ((int16)(124 - samus_y_pos) < 0) + v0 = -64; + MotherBrain_MoveSamusVerticallyTowardsCeilingFloor(v0); +} + +uint8 MotherBrain_MoveSamusForFallingAfterBeam(void) { // 0xA9BBE1 + int16 v1; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + v1 = E->mbn_parameter_1 + 2; + if (v1 >= 0) + v1 = 0; + E->mbn_parameter_1 = v1; + MotherBrain_MoveSamusHorizTowardsWall(v1); + uint16 v2 = E->mbn_parameter_2 + 24; + E->mbn_parameter_2 = v2; + return MotherBrain_MoveSamusVerticallyTowardsCeilingFloor(v2) & 1; +} + +uint8 MotherBrain_MoveSamusVerticallyTowardsCeilingFloor(uint16 a) { // 0xA9BBFD + int16 v1; + int16 v2; + char v3; // t0 + + int carry = HIBYTE(samus_y_subpos) + LOBYTE(a); + LOBYTE(a) = carry; + HIBYTE(samus_y_subpos) = a; + HIBYTE(samus_prev_y_subpos) = a; + v1 = a & 0xFF00; + v3 = v1; + LOBYTE(v2) = HIBYTE(v1); + HIBYTE(v2) = v3; + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + uint16 v4 = samus_y_pos + v2 + (carry >> 8), v6; + if (sign16(v4 - 48)) { + v6 = 48; + } else { + if (sign16(v4 - 192)) { + samus_y_pos = v4; + samus_prev_y_pos = v4; + return 0; + } + v6 = 192; + } + samus_y_pos = v6; + samus_prev_y_pos = v6; + samus_y_subpos = 0; + samus_prev_y_subpos = 0; + return 1; +} + +uint8 MotherBrain_MoveSamusHorizTowardsWall(uint16 a) { // 0xA9BC3F + int16 v1; + int16 v2; + char v3; // t0 + + int carry = HIBYTE(samus_x_subpos) + LOBYTE(a); + LOBYTE(a) = carry; + HIBYTE(samus_x_subpos) = a; + HIBYTE(samus_prev_x_subpos) = a; + v1 = a & 0xFF00; + v3 = v1; + LOBYTE(v2) = HIBYTE(v1); + HIBYTE(v2) = v3; + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + uint16 v4 = samus_x_pos + v2 + (carry >> 8); + if (sign16(v4 - 235)) { + samus_x_pos = v4; + samus_prev_x_pos = v4; + return 0; + } else { + samus_x_pos = 235; + samus_prev_x_pos = 235; + samus_x_subpos = 0; + samus_prev_x_subpos = 0; + return 1; + } +} + +void MotherBrain_HandleRainbowBeamExplosions(void) { // 0xA9BC76 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_parameter_2 & 0x8000u) != 0) { + E->mbn_parameter_2 = 8; + ++E->mbn_parameter_1; + int v2 = E->mbn_parameter_1 & 7; + R18_ = g_word_A9BCA6[v2]; + R20_ = g_word_A9BCB6[v2]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_MotherBrainRainbowBeamExplosion, R20_); + QueueSfx2_Max6(0x24u); + } +} + +void MotherBrain_BodyRainbowBeamPalAnimIndex0(void) { // 0xA9BCC6 + Get_MotherBrain(0x40u)->mbn_var_01 = 0; +} + +void MotherBrain_WriteDefaultPalette(void) { // 0xA9BCCE + WriteColorsToPalette(0x82u, 0xa9, addr_kMotherBrainsBrain_Palette__plus__2, 0xFu); + WriteColorsToPalette(0x122u, 0xa9, addr_kMotherBrainsBrain_Palette__plus__2, 0xFu); + WriteColorsToPalette(0x162u, 0xa9, addr_kMotherBrainPalette_0__plus__2, 0xFu); +} + +void MotherBrain_WritePhase2DeathPalette(void) { // 0xA9BCF6 + MotherBrain_WritePalette(MotherBrain_RainbowBeamPalettes[6]); +} + +void MotherBrain_HandleRainbowBeamPalette(void) { // 0xA9BCFD + if ((Get_MotherBrain(0)->base.frame_counter & 2) != 0) { + uint16 mbn_var_01 = Get_MotherBrain(0x40u)->mbn_var_01; + uint16 v1; + do { + v1 = mbn_var_01; + mbn_var_01 = MotherBrain_RainbowBeamPalettes[mbn_var_01 >> 1]; + } while (!mbn_var_01); + uint16 v2 = v1 + 2; + Get_MotherBrain(0x40u)->mbn_var_01 = v2; + MotherBrain_WritePalette(*(uint16 *)((char *)MotherBrain_RainbowBeamPalettes + v2 - 2)); + } +} + +void MotherBrain_WritePalette(uint16 j) { // 0xA9BD1D + WriteColorsToPalette(0x82u, 0xad, j, 15); + WriteColorsToPalette(0x122u, 0xad, j, 15); + WriteColorsToPalette(0x162u, 0xad, j + 30, 15); +} + +void MotherBrain_Phase2Cut_0(void) { // 0xA9BD45 + uint16 v0 = SuitDamageDivision(0x50u); + if ((int16)(4 * v0 + 20 - samus_health) >= 0) { + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrain_Phase2Cut_1); + } else if ((random_number & 0xFFFu) < 0xFA0) { + if ((Get_MotherBrain(0)->base.frame_counter & 0x1F) == 0) + MotherBrain_MaybeStandupOrLeanDown(); + } else { + uint16 v1; + if ((int16)(SuitDamageDivision(0xA0u) + 20 - samus_health) >= 0 + || (v1 = addr_kMotherBrain_Ilist_9ECC, (random_number & 0xFFFu) < 0xFF0)) { + v1 = addr_kMotherBrain_Ilist_9D7F; + } + MotherBrain_SetBrainInstrs(v1); + } +} + +void MotherBrain_Phase2Cut_1(void) { // 0xA9BD98 + if (MotherBrain_MakeHerStandUp() & 1) { + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBrain_Phase2Cut_2); + E->mbn_var_F = 16; + MotherBrain_Phase2Cut_2(); + } +} + +void MotherBrain_Phase2Cut_2(void) { // 0xA9BDA9 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9B7F); + E->mbn_var_A = FUNC16(MotherBrain_Phase2Cut_3); + E->mbn_var_F = 256; + } +} + +void MotherBrain_Phase2Cut_3(void) { // 0xA9BDC1 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9F6C); + E->mbn_var_A = FUNC16(MotherBrain_Phase2Cut_4); + MotherBrain_Phase2Cut_4(); + } +} + +void MotherBrain_Phase2Cut_4(void) { // 0xA9BDD2 + if (ProcessSpriteTilesTransfers(0xa9, addr_stru_A98FE5)) { + MotherBrain_RetractHead(); + MotherBrain_SpawnShitroidInCutscene(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBrain_Phase2Cut_5); + E->mbn_var_F = 256; + } +} + +void MotherBrain_Phase2Cut_5(void) { // 0xA9BDED + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + MotherBrain_BodyRainbowBeamPalAnimIndex0(); + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9C77); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_32 = 6; + E1->mbn_var_33 = 6; + E1->mbn_var_34 = 1280; + QueueSfx2_Max6(0x71u); + E->mbn_var_A = FUNC16(nullsub_364); + } +} + +void MotherBrain_SpawnShitroidInCutscene(void) { // 0xA9BE1B + Get_MotherBrain(0x40u)->mbn_var_0A = SpawnEnemy(0xA9u, addr_stru_A9BE28); +} + +void MotherBrain_DrainedByShitroid_0(void) { // 0xA9BE38 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_00 = 3; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_32 = 8; + E1->mbn_var_33 = 8; + E1->mbn_var_34 = 1792; + E->mbn_var_A = FUNC16(MotherBrain_DrainedByShitroid_1); + E->mbn_var_F = 48; + MotherBrain_DrainedByShitroid_1(); +} + +void MotherBrain_DrainedByShitroid_1(void) { // 0xA9BE5D + MotherBrain_HandleRainbowBeamPalette(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->mbn_var_A = FUNC16(MotherBrain_DrainedByShitroid_2); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_08 = FUNC16(MotherBrain_PainfulWalkForwards); + E1->mbn_var_06 = 0; + E1->mbn_var_07 = 2; + E1->mbn_var_32 = 2; + E1->mbn_var_33 = 4; + } +} + +void CallMotherBrainPainfulWalk(uint32 ea) { + switch (ea) { + case fnMotherBrain_PainfulWalkForwards: MotherBrain_PainfulWalkForwards(); return; + case fnMotherBrain_PainfulWalkingForwards: MotherBrain_PainfulWalkingForwards(); return; + case fnMotherBrain_PainfulWalkBackwards: MotherBrain_PainfulWalkBackwards(); return; + case fnMotherBrain_PainfulWalkingBackwards: MotherBrain_PainfulWalkingBackwards(); return; + default: Unreachable(); + } +} + +void MotherBrain_DrainedByShitroid_2(void) { // 0xA9BE96 + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + if (!E1->mbn_var_00) + E1->mbn_var_00 = 50; + MotherBrain_HandleRainbowBeamPalette(); + R18_ = E1->mbn_var_08; + CallMotherBrainPainfulWalk(R18_ | 0xA90000); + uint16 v2 = 2 * E1->mbn_var_06; + E1->mbn_var_07 = g_byte_A9BEEE[v2]; + E1->mbn_var_34 = g_word_A9BEFE[v2 >> 1]; + if (E1->mbn_var_06 == 6) { + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_16 = 0; + E1->mbn_var_10 = 0; + MotherBrain_WritePhase2DeathPalette(); + QueueSfx1_Max6(2u); + E->mbn_var_A = FUNC16(MotherBrain_DrainedByShitroid_3); + } +} + +void MotherBrain_DrainedByShitroid_3(void) { // 0xA9BF0E + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + R18_ = E1->mbn_var_08; + CallMotherBrainPainfulWalk(R18_ | 0xA90000); + if (sign16(E1->mbn_var_06 - 8)) { + } else { + E1->mbn_var_34 = 64; + E1->mbn_var_32 = 8; + E1->mbn_var_33 = 8; + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9C39); + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrain_DrainedByShitroid_4); + MotherBrain_DrainedByShitroid_4(); + } +} + +void MotherBrain_DrainedByShitroid_4(void) { // 0xA9BF41 + if (MotherBrain_MakeWalkBackwards(0x28u, 0) & 1) { + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrain_DrainedByShitroid_5); + Get_MotherBrain(0x40u)->mbn_var_33 = 0; + MotherBrain_DrainedByShitroid_5(); + } +} + +void MotherBrain_DrainedByShitroid_5(void) { // 0xA9BF56 + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + if (!*(uint32 *)&E1->mbn_var_32) { + E1->mbn_var_12 = E1->mbn_var_33 | E1->mbn_var_32; + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (!E->mbn_var_02) { + MotherBrain_SetBodyInstrs(addr_kMotherBrain_Ilist_9A26); + E->mbn_var_A = FUNC16(MotherBrain_DrainedByShitroid_6); + E->mbn_var_F = 64; + } + } +} + +void MotherBrain_DrainedByShitroid_6(void) { // 0xA9BF7D + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->mbn_var_37 = 0; + E->mbn_var_A = FUNC16(MotherBrain_DrainedByShitroid_7); + E->mbn_var_F = 16; + MotherBrain_DrainedByShitroid_7(); + } +} + +void MotherBrain_DrainedByShitroid_7(void) { // 0xA9BF95 + Enemy_MotherBrain *E = Get_MotherBrain(0); + bool v2 = (--E->mbn_var_F & 0x8000u) != 0; + uint16 v3; + if (v2 + && (E->mbn_var_F = 16, + v3 = E->mbn_var_37 + 1, + E->mbn_var_37 = v3, + MotherBrain_FadeToGray_Drained(v3 - 1) & 1)) { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->base.health = -29536; + E->mbn_var_1F = 1; + E1->mbn_var_14 = 0; + E->mbn_var_00 = 2; + E->mbn_var_A = FUNC16(MotherBrain_Phase2_Revive_0); + } +} + +void MotherBrain_PainfulWalkForwards(void) { // 0xA9BFD0 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + if (MotherBrain_MakeWalkForwards(E->mbn_var_07, 0x48u) & 1) { + E->mbn_var_08 = FUNC16(MotherBrain_PainfulWalkingForwards); + MotherBrain_SetPainfulWalkingTimer(); + } +} + +void MotherBrain_PainfulWalkingForwards(void) { // 0xA9BFE8 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + uint16 v1 = E->mbn_var_09 - 1; + E->mbn_var_09 = v1; + if (!v1) { + ++E->mbn_var_06; + E->mbn_var_08 = FUNC16(MotherBrain_PainfulWalkBackwards); + } +} + +void MotherBrain_PainfulWalkBackwards(void) { // 0xA9C004 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + if (MotherBrain_MakeWalkBackwards(0x28u, E->mbn_var_07) & 1) { + E->mbn_var_08 = FUNC16(MotherBrain_PainfulWalkingBackwards); + MotherBrain_SetPainfulWalkingTimer(); + } +} + +void MotherBrain_PainfulWalkingBackwards(void) { // 0xA9C01C + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + uint16 v1 = E->mbn_var_09 - 1; + E->mbn_var_09 = v1; + if (!v1) { + ++E->mbn_var_06; + E->mbn_var_08 = FUNC16(MotherBrain_PainfulWalkForwards); + } +} + +void MotherBrain_SetPainfulWalkingTimer(void) { // 0xA9C038 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + E->mbn_var_09 = LOBYTE(g_word_A9C049[E->mbn_var_06]); +} + +void MotherBrain_Phase2_Revive_0(void) { // 0xA9C059 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBrain_Phase2_Revive_1); + E->mbn_var_F = 768; +} + +void MotherBrain_Phase2_Revive_1(void) { // 0xA9C066 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_14 = 1; + E1->mbn_var_12 = 1; + E->mbn_var_A = FUNC16(MotherBrain_Phase2_Revive_2); + E->mbn_var_F = 224; + MotherBrain_Phase2_Revive_2(); + } +} + +void MotherBrain_Phase2_Revive_2(void) { // 0xA9C082 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBrain_Phase2_Revive_3); + E->mbn_var_37 = 0; + MotherBrain_Phase2_Revive_3(); +} + +void MotherBrain_Phase2_Revive_3(void) { // 0xA9C08F + Enemy_MotherBrain *E = Get_MotherBrain(0); + bool v1 = (--E->mbn_var_F & 0x8000u) != 0; + uint16 v2; + if (v1 + && (E->mbn_var_F = 16, + v2 = E->mbn_var_37 + 1, + E->mbn_var_37 = v2, + MotherBrain_FadeFromGray_Drained(v2 - 1) & 1)) { + E->mbn_var_A = FUNC16(MotherBrain_Phase2_Revive_4); + Get_MotherBrain(0x40u)->mbn_var_10 = 1; + MotherBrain_SetupBrainNormalPal(); + MotherBrain_Phase2_Revive_4(); + } +} + +void MotherBrain_Phase2_Revive_4(void) { // 0xA9C0BA + if (MotherBrain_MakeHerStandUp() & 1) { + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_32 = 6; + E1->mbn_var_33 = 6; + E1->mbn_var_34 = 1280; + E1->mbn_var_31 = 1; + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBrain_Phase2_Revive_5); + E->mbn_var_F = 16; + MotherBrain_Phase2_Revive_5(); + } +} + +void MotherBrain_Phase2_Revive_5(void) { // 0xA9C0E4 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9BB3); + E->mbn_var_A = FUNC16(MotherBrain_Phase2_Revive_6); + E->mbn_var_F = 128; + MotherBrain_Phase2_Revive_6(); + } +} + +void MotherBrain_Phase2_Revive_6(void) { // 0xA9C0FB + Enemy_MotherBrain *E = Get_MotherBrain(0); + bool v1 = (--E->mbn_var_F & 0x8000u) != 0; + if (v1 && MotherBrain_MakeWalkForwards(4u, 0x50u) & 1) { + E->mbn_var_A = FUNC16(MotherBrain_Phase2_Revive_7); + E->mbn_var_1F = 2; + Get_MotherBrain(0x40u)->mbn_var_11 = 1; + } +} + +void MotherBrain_Phase2_Revive_7(void) { // 0xA9C11E + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_13 = 0; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_31 = 1; + E1->mbn_var_32 = 2; + E1->mbn_var_33 = 4; + E1->mbn_var_34 = 64; + E->mbn_var_A = FUNC16(MotherBrain_Phase2_Revive_8); + MotherBrain_Phase2_Revive_8(); +} + +void MotherBrain_Phase2_Revive_8(void) { // 0xA9C147 + if (MotherBrain_MakeHerStandUp() & 1) { + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrain_Phase2_MurderShitroid_1); + MotherBrain_MakeWalkForwards(0xAu, 0x50u); + MotherBrain_Phase2_MurderShitroid_1(); + } +} + +void MotherBrain_Phase2_MurderShitroid_1(void) { // 0xA9C15C + MotherBrain_MaybeStandupOrLeanDown(); + if ((random_number & 0x8000u) != 0) { + uint16 v0 = addr_kMotherBrain_Ilist_9DBB; + if (Get_MotherBrain(0x40u)->mbn_var_0A) + v0 = addr_kMotherBrain_Ilist_9DB1; + MotherBrain_SetBrainInstrs(v0); + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_A = FUNC16(MotherBrain_Phase2_MurderShitroid_2); + E->mbn_var_F = 64; + } +} + +void MotherBrain_Phase2_MurderShitroid_2(void) { // 0xA9C182 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) + E->mbn_var_A = FUNC16(MotherBrain_Phase2_MurderShitroid_1); +} + +void MotherBrain_Phase2_PrepareForFinalShitroid(void) { // 0xA9C18E + MotherBrain_MakeHerStandUp(); + MotherBrain_MakeWalkBackwards(0x40u, 4u); +} + +void MotherBrain_Phase2_ExecuteFinalkShitroid(void) { // 0xA9C19A + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9DB1); + Get_MotherBrain(0)->mbn_var_A = FUNC16(nullsub_363); +} + +void MotherBrain_MaybeStandupOrLeanDown(void) { // 0xA9C1A7 + uint16 mbn_var_02 = Get_MotherBrain(0)->mbn_var_02; + if (mbn_var_02) { + if (mbn_var_02 == 6 && (uint8)random_number >= 0xC0u) + MotherBrain_MakeHerStandUp(); + } else if ((uint8)random_number >= 0xC0u) { + MotherBrain_MakeHerLeanDown(); + } +} + +void MotherBrain_Phase3_Recover_MakeDistance(void) { // 0xA9C1CF + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_00 = 4; + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Recover_SetupForFight); + E->mbn_var_F = 32; + MotherBrain_MakeWalkBackwards(E->base.x_pos - 14, 2u); +} + +void MotherBrain_Phase3_Recover_SetupForFight(void) { // 0xA9C1F0 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) { + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Fighting_Main); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_18 = FUNC16(MotherBrain_Phase3_Neck_Normal); + E1->mbn_var_1A = FUNC16(MotherBrain_Phase3_Walk_TryToInchForward); + MotherBrain_Phase3_Fighting_Main(); + } +} + +void MotherBrain_Phase3_Fighting_Main(void) { // 0xA9C209 + if (Get_MotherBrain(0x40u)->base.health) { + MotherBrain_Phase3_NeckHandler(); + MotherBrain_Phase3_WalkHandler(); + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (!E->mbn_var_02 && !E->mbn_var_06 && (random_number & 0x8000u) != 0) { + uint16 v1 = addr_kMotherBrain_Ilist_9F00; + if ((uint8)random_number >= 0x80) + v1 = addr_kMotherBrain_Ilist_9DBB; + MotherBrain_SetBrainInstrs(v1); + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Fighting_Cooldown); + E->mbn_var_F = 64; + } + } else { + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrain_Phase3_Death_0); + } +} + +void MotherBrain_Phase3_Fighting_Cooldown(void) { // 0xA9C24E + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((--E->mbn_var_F & 0x8000u) != 0) + E->mbn_var_A = FUNC16(MotherBrain_Phase3_Fighting_Main); +} + +void CallMotherBrainWallkFunc1A(uint32 ea) { + switch (ea) { + case fnMotherBrain_Phase3_Walk_TryToInchForward: MotherBrain_Phase3_Walk_TryToInchForward(); return; + case fnMotherBrain_Phase3_Walk_RetreatQuickly: MotherBrain_Phase3_Walk_RetreatQuickly(); return; + case fnMotherBrain_Phase3_Walk_RetreatSlowly: MotherBrain_Phase3_Walk_RetreatSlowly(); return; + default: Unreachable(); + } +} + +void MotherBrain_Phase3_WalkHandler(void) { // 0xA9C25A + if (!Get_MotherBrain(0)->mbn_var_02) { + R18_ = Get_MotherBrain(0x40u)->mbn_var_1A; + CallMotherBrainWallkFunc1A(R18_ | 0xA90000); + } +} + +void MotherBrain_Phase3_Walk_TryToInchForward(void) { // 0xA9C26A + Enemy_MotherBrain *E = Get_MotherBrain(0); + uint16 mbn_var_07 = E->mbn_var_07; + if (mbn_var_07) { + uint16 v3 = mbn_var_07 + 32; + E->mbn_var_07 = v3; + if (v3 >= 0x100u) { + uint16 v4 = E->base.x_pos + 1; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_1B = v4; + if (MotherBrain_MakeWalkForwards((random_number & 2) + 4, E1->mbn_var_1B) & 1) + E->mbn_var_07 = 128; + } + } else { + uint16 v6 = E->base.x_pos - 14; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_1B = v6; + E1->mbn_var_1A = FUNC16(MotherBrain_Phase3_Walk_RetreatQuickly); + MotherBrain_Phase3_Walk_RetreatQuickly(); + } +} + +void MotherBrain_Phase3_Walk_RetreatQuickly(void) { // 0xA9C2B3 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + if (MotherBrain_MakeWalkBackwards(E->mbn_var_1B, 2u) & 1) { + E->mbn_var_1B = Get_MotherBrain(0)->base.x_pos - 14; + E->mbn_var_1A = FUNC16(MotherBrain_Phase3_Walk_RetreatSlowly); + } +} + +void MotherBrain_Phase3_Walk_RetreatSlowly(void) { // 0xA9C2D2 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + if (MotherBrain_MakeWalkBackwards(E->mbn_var_1B, 4u) & 1) + MotherBrain_SetToTryToInchForward(0x40u); +} + +void MotherBrain_SetToTryToInchForward(uint16 a) { // 0xA9C313 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_07 = a; + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40u); + E1->mbn_var_1A = FUNC16(MotherBrain_Phase3_Walk_TryToInchForward); + E1->mbn_var_1B = E->base.x_pos + 1; +} + +void CallMotherBrainNeckFunc(uint32 ea) { + switch (ea) { + case fnnullsub_369: return; + case fnMotherBrain_Phase3_Neck_Normal: MotherBrain_Phase3_Neck_Normal(); return; + case fnMotherBrain_Phase3_Neck_SetupRecoilRecovery: MotherBrain_Phase3_Neck_SetupRecoilRecovery(); return; + case fnMotherBrain_Phase3_Neck_RecoilRecovery: MotherBrain_Phase3_Neck_RecoilRecovery(); return; + case fnMotherBrain_Phase3_Neck_SetupHyperBeamRecoil: MotherBrain_Phase3_Neck_SetupHyperBeamRecoil(); return; + case fnMotherBrain_Phase3_Neck_HyperBeamRecoil: MotherBrain_Phase3_Neck_HyperBeamRecoil(); return; + default: Unreachable(); + } +} + +void MotherBrain_Phase3_NeckHandler(void) { // 0xA9C327 + R18_ = Get_MotherBrain(0x40u)->mbn_var_18; + CallMotherBrainNeckFunc(R18_ | 0xA90000); +} + +void MotherBrain_Phase3_Neck_Normal(void) { // 0xA9C330 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + E->mbn_var_32 = 1; + E->mbn_var_34 = 128; + E->mbn_var_32 = 2; + E->mbn_var_33 = 4; + E->mbn_var_18 = addr_locret_A9C353; +} + +void MotherBrain_Phase3_Neck_SetupRecoilRecovery(void) { // 0xA9C354 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + E->mbn_var_31 = 1; + E->mbn_var_34 = 1280; + E->mbn_var_32 = 6; + E->mbn_var_33 = 6; + E->mbn_var_18 = FUNC16(MotherBrain_Phase3_Neck_RecoilRecovery); + E->mbn_var_19 = 16; + MotherBrain_Phase3_Neck_RecoilRecovery(); +} + +void MotherBrain_Phase3_Neck_RecoilRecovery(void) { // 0xA9C37B + int16 v1; + + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + v1 = E->mbn_var_19 - 1; + if (v1 < 0) { + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9DBB); + E->mbn_var_18 = FUNC16(MotherBrain_Phase3_Neck_Normal); + } else { + E->mbn_var_19 = v1; + } +} + +void MotherBrain_Phase3_Neck_SetupHyperBeamRecoil(void) { // 0xA9C395 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + E->mbn_var_31 = 1; + Get_MotherBrain(0)->mbn_var_06 = 1; + MotherBrain_SetBrainInstrs(addr_kMotherBrain_Ilist_9BE7); + E->mbn_var_00 = 50; + E->mbn_var_34 = 2304; + E->mbn_var_32 = 8; + E->mbn_var_33 = 8; + E->mbn_var_18 = FUNC16(MotherBrain_Phase3_Neck_HyperBeamRecoil); + E->mbn_var_19 = 11; + MotherBrain_Phase3_Neck_HyperBeamRecoil(); +} + +void MotherBrain_Phase3_Neck_HyperBeamRecoil(void) { // 0xA9C3CD + int16 v2; + + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + v2 = E->mbn_var_19 - 1; + if (v2 < 0) { + E->mbn_var_34 = 128; + Get_MotherBrain(0)->mbn_var_06 = 0; + E->mbn_var_18 = FUNC16(MotherBrain_Phase3_Neck_SetupRecoilRecovery); + } else { + E->mbn_var_19 = v2; + } +} + +void MoveEnemyWithVelocity(void) { // 0xA9C3EF + int16 v2; + char v3; // t0 + int16 v5; + char v6; // t1 + + EnemyData *v0 = gEnemyData(cur_enemy_index); + uint16 ai_var_B = v0->ai_var_B; + int carry = HIBYTE(v0->x_subpos) + LOBYTE(ai_var_B); + LOBYTE(ai_var_B) = carry; + HIBYTE(v0->x_subpos) = ai_var_B; + ai_var_B &= 0xFF00u; + v3 = ai_var_B; + LOBYTE(v2) = HIBYTE(ai_var_B); + HIBYTE(v2) = v3; + if ((v2 & 0x80) != 0) + v2 |= 0xFF00u; + v0->x_pos += v2 + (carry >> 8); + uint16 ai_var_C = v0->ai_var_C; + carry = HIBYTE(v0->y_subpos) + LOBYTE(ai_var_C); + LOBYTE(ai_var_C) = carry; + HIBYTE(v0->y_subpos) = ai_var_C; + ai_var_C &= 0xFF00u; + v6 = ai_var_C; + LOBYTE(v5) = HIBYTE(ai_var_C); + HIBYTE(v5) = v6; + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + v0->y_pos += v5 + (carry >> 8); +} + +void MotherBrain_SetBodyInstrs(uint16 a) { // 0xA9C42D + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->base.current_instruction = a; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void MotherBrain_SetBrainUnusedInstrs(uint16 a) { // 0xA9C43A + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + E->base.current_instruction = a; + E->base.instruction_timer = 1; + E->base.timer = 0; +} + +void MotherBrain_SetBrainInstrs(uint16 a) { // 0xA9C447 + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_21 = a; + E->mbn_var_20 = 1; +} + +void Enemy_SetInstrList(uint16 k, uint16 a) { // 0xA9C453 + EnemyData *v2 = gEnemyData(k); + v2->current_instruction = a; + v2->instruction_timer = 1; + v2->timer = 0; +} + +uint16 ComputeSinMult(uint16 a) { // 0xA9C460 + return sub_A9C46C(R18_, a); +} + +uint16 ComputeCosMult(uint16 a) { // 0xA9C465 + return sub_A9C46C(R18_ + 64, a); +} + +uint16 sub_A9C46C(uint16 a, uint16 j) { // 0xA9C46C + uint16 v2 = kSinCosTable8bit_Sext[((uint16)((2 * a) & 0x1FE) >> 1) + 64]; + WriteReg(M7A, v2); + WriteReg(M7A, HIBYTE(v2)); + WriteReg(M7B, j); + return ReadRegWord(MPYM); +} + +void Enemy_IncreaseYpos(uint16 k, uint16 a) { // 0xA9C4A9 + int16 v3; + int16 v4; + char v5; // t0 + + EnemyData *v2 = gEnemyData(k); + int carry = HIBYTE(v2->y_subpos) + LOBYTE(a); + LOBYTE(a) = carry; + HIBYTE(v2->y_subpos) = a; + v3 = a & 0xFF00; + v5 = v3; + LOBYTE(v4) = HIBYTE(v3); + HIBYTE(v4) = v5; + if ((v4 & 0x80) != 0) + v4 |= 0xFF00u; + v2->y_pos += v4 + (carry >> 8); +} + +void Samus_DecrementAmmoDueToRainbowBeam(void) { // 0xA9C4C4 + if ((enemy_damage_routine_exec_count & 3) == 0 && samus_missiles) { + uint16 v0 = samus_missiles - g_word_A9C544; + if (sign16(samus_missiles - g_word_A9C544 - 1)) { + if (hud_item_index == 1) + hud_item_index = 0; + v0 = 0; + samus_auto_cancel_hud_item_index = 0; + } + samus_missiles = v0; + } + if ((enemy_damage_routine_exec_count & 3) == 0 && samus_super_missiles) { + uint16 v1 = samus_super_missiles - g_word_A9C544; + if (sign16(samus_super_missiles - g_word_A9C544 - 1)) { + if (hud_item_index == 2) + hud_item_index = 0; + v1 = 0; + samus_auto_cancel_hud_item_index = 0; + } + samus_super_missiles = v1; + } + if (samus_power_bombs) { + uint16 v2 = samus_power_bombs - g_word_A9C544; + if (sign16(samus_power_bombs - g_word_A9C544 - 1)) { + if (hud_item_index == 3) + hud_item_index = 0; + v2 = 0; + samus_auto_cancel_hud_item_index = 0; + } + samus_power_bombs = v2; + } +} + +void Samus_PlayGainingLosingHealthSfx(void) { // 0xA9C546 + if (!sign16(samus_health - 81) && (enemy_damage_routine_exec_count & 7) == 0) + QueueSfx3_Max3(0x2Du); +} + +void Samus_DamageDueToShitroid(void) { // 0xA9C560 + int16 v0; + + v0 = -4; + if (equipped_items & 1) + v0 = -3; + uint16 v1 = samus_health + (equipped_items & 1) + v0; + if (sign16(v1 - 2)) + v1 = 1; + samus_health = v1; +} + +void Samus_DamageDueToRainbowBeam(void) { // 0xA9C57D + uint16 v0 = samus_health + (equipped_items & 1) - 2; + if (sign16(v0 - 1)) + v0 = 0; + samus_health = v0; + Samus_PlayGainingLosingHealthSfx(); +} + +uint8 Samus_HealDueToShitroid(void) { // 0xA9C59F + if ((int16)(samus_health + 1 - samus_max_health) < 0) { + ++samus_health; + Samus_PlayGainingLosingHealthSfx(); + return 1; + } else { + samus_health = samus_max_health; + Samus_PlayGainingLosingHealthSfx(); + return 0; + } +} + +uint8 ProcessSpriteTilesTransfers(uint8 db, uint16 k) { // 0xA9C5BE + VramWriteEntry *v7; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + uint16 mbn_var_22 = E->mbn_var_22; + if (!mbn_var_22) + mbn_var_22 = k; + uint16 v3 = mbn_var_22; + uint16 v4 = vram_write_queue_tail; + uint8 *v5 = RomPtrWithBank(db, mbn_var_22); + uint16 v6 = *(uint16 *)v5; + if (*(uint16 *)v5) { + v7 = gVramWriteEntry(vram_write_queue_tail); + v7->size = v6; + *(VoidP *)((char *)&v7->src.addr + 1) = *(uint16 *)(v5 + 3); + v7->src.addr = *((uint16 *)v5 + 1); + v7->vram_dst = *(uint16 *)(v5 + 5); + vram_write_queue_tail = v4 + 7; + E->mbn_var_22 = v3 + 7; + v6 = *(uint16 *)RomPtrWithBank(db, E->mbn_var_22); + if (v6) + return 0; + } + E->mbn_var_22 = v6; + return 1; +} + +uint8 MotherBrain_MakeWalkForwards(uint16 j, uint16 a) { // 0xA9C601 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((int16)(a - E->base.x_pos) >= 0) { + if (E->mbn_var_02) + return 0; + if (sign16(E->base.x_pos - 128)) { + MotherBrain_SetBodyInstrs(g_off_A9C61E[j >> 1]); + return 0; + } + } + return 1; +} + +uint8 MotherBrain_MakeWalkBackwards(uint16 a, uint16 j) { // 0xA9C647 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if ((int16)(a - E->base.x_pos) < 0) { + if (E->mbn_var_02) + return 0; + if (!sign16(E->base.x_pos - 48)) { + MotherBrain_SetBodyInstrs(g_off_A9C664[j >> 1]); + return 0; + } + } + return 1; +} + +uint8 MotherBrain_MakeHerStandUp(void) { // 0xA9C670 + uint16 mbn_var_02 = Get_MotherBrain(0)->mbn_var_02; + if (mbn_var_02) { + uint16 v1 = addr_kMotherBrain_Ilist_99C6; + if (mbn_var_02 != 3) { + if (mbn_var_02 != 6) + return 0; + v1 = addr_kMotherBrain_Ilist_99E2; + } + MotherBrain_SetBodyInstrs(v1); + return 0; + } + return 1; +} + +uint8 MotherBrain_MakeHerCrouch(void) { // 0xA9C68E + uint16 mbn_var_02 = Get_MotherBrain(0)->mbn_var_02; + if (mbn_var_02) { + if (mbn_var_02 == 3) + return 1; + } else { + MotherBrain_SetBodyInstrs(addr_kMotherBrain_Ilist_9A0A); + } + return 0; +} + +uint8 MotherBrain_MakeHerLeanDown(void) { // 0xA9C6A3 + uint16 mbn_var_02 = Get_MotherBrain(0)->mbn_var_02; + if (mbn_var_02) { + if (mbn_var_02 == 6) + return 1; + } else { + MotherBrain_SetBodyInstrs(addr_kMotherBrain_Ilist_99F2); + } + return 0; +} + +void MotherBrain_HandleWalking(void) { // 0xA9C6B8 + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (!E->mbn_var_02) { + uint16 mbn_var_07 = E->mbn_var_07; + if (mbn_var_07) { + uint16 v2; + v2 = mbn_var_07 + 6; + E->mbn_var_07 = v2; + if (v2 >= 0x100u) { +LABEL_4: + E->mbn_var_07 = 128; + if (sign16(E->base.x_pos - 128)) + MotherBrain_SetBodyInstrs(addr_kMotherBrain_Ilist_97A4); + return; + } + if (!sign16(E->base.x_pos - 48)) + return; + } else { + E->mbn_var_07 = 1; + if (!sign16(E->base.x_pos - 48)) { + MotherBrain_SetBodyInstrs(addr_kMotherBrain_Ilist_98C6); + return; + } + } + if (sign16((random_number & 0xFFF) - 4032)) + return; + goto LABEL_4; + } +} + +void ShitroidInCutscene_Init(void) { // 0xA9C710 + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl | kEnemyProps_BlockPlasmaBeam; + E->base.palette_index = 3584; + E->base.current_instruction = addr_kShitroid_Ilist_CFA2; + E->base.instruction_timer = 1; + E->sice_var_04 = 1; + E->base.timer = 0; + E->sice_var_E = 10; + E->base.vram_tiles_index = 160; + E->base.x_pos = 320; + E->base.y_pos = 96; + E->sice_var_B = 0; + E->sice_var_C = 0; + E->sice_var_09 = 0; + E->sice_var_A = FUNC16(ShitroidInCutscene_DashOntoScreen); + E->sice_var_F = 248; + E->sice_var_0F = FUNC16(Shitroid_HandleCutscenePalette); + WriteColorsToPalette(0x1E2u, 0xa9, addr_kMotherBrainPalette_2__plus__2, 0xFu); +} + +void CallShitroidCutsceneFuncA(uint32 ea, uint16 k) { + switch (ea) { + case fnnullsub_367: return; + case fnShitroidInCutscene_DashOntoScreen: ShitroidInCutscene_DashOntoScreen(k); return; + case fnShitroidInCutscene_CurveTowardsBrain: ShitroidInCutscene_CurveTowardsBrain(k); return; + case fnShitroidInCutscene_GetIntoFace: ShitroidInCutscene_GetIntoFace(k); return; + case fnShitroidInCutscene_LatchOntoBrain: ShitroidInCutscene_LatchOntoBrain(k); return; + case fnShitroidInCutscene_SetMotherBrainToStumbleBack: ShitroidInCutscene_SetMotherBrainToStumbleBack(k); return; + case fnShitroidInCutscene_ActivateRainbowBeam: ShitroidInCutscene_ActivateRainbowBeam(k); return; + case fnShitroidInCutscene_BrainTurnsToCorpse: ShitroidInCutscene_BrainTurnsToCorpse(k); return; + case fnShitroidInCutscene_StopDraining: ShitroidInCutscene_StopDraining(k); return; + case fnShitroidInCutscene_LetGoAndSpawnDust: ShitroidInCutscene_LetGoAndSpawnDust(k); return; + case fnShitroidInCutscene_MoveUpToCeiling: ShitroidInCutscene_MoveUpToCeiling(k); return; + case fnShitroidInCutscene_MoveToSamus: ShitroidInCutscene_MoveToSamus(k); return; + case fnShitroidInCutscene_LatchOntoSamus: ShitroidInCutscene_LatchOntoSamus(k); return; + case fnShitroidInCutscene_HealSamusToFullHealth: ShitroidInCutscene_HealSamusToFullHealth(k); return; + case fnShitroidInCutscene_IdleUntilToNoHealth: ShitroidInCutscene_IdleUntilToNoHealth(k); return; + case fnShitroidInCutscene_ReleaseSamus: ShitroidInCutscene_ReleaseSamus(k); return; + case fnShitroidInCutscene_StareDownMotherBrain: ShitroidInCutscene_StareDownMotherBrain(k); return; + case fnShitroidInCutscene_FlyOffScreen: ShitroidInCutscene_FlyOffScreen(k); return; + case fnShitroidInCutscene_MoveToFinalChargeStart: ShitroidInCutscene_MoveToFinalChargeStart(k); return; + case fnShitroidInCutscene_InitiateFinalCharge: ShitroidInCutscene_InitiateFinalCharge(k); return; + case fnShitroidInCutscene_FinalCharge: ShitroidInCutscene_FinalCharge(k); return; + case fnShitroidInCutscene_ShitroidFinalBelow: ShitroidInCutscene_ShitroidFinalBelow(k); return; + case fnShitroidInCutscene_PlaySamusTheme: ShitroidInCutscene_PlaySamusTheme(k); return; + case fnShitroidInCutscene_PrepareSamusHyperbeam: ShitroidInCutscene_PrepareSamusHyperbeam(k); return; + case fnShitroidInCutscene_DeathSequence: ShitroidInCutscene_DeathSequence(k); return; + case fnShitroidInCutscene_UnloadShitroid: ShitroidInCutscene_UnloadShitroid(k); return; + case fnShitroidInCutscene_LetSamusRainbowMore: ShitroidInCutscene_LetSamusRainbowMore(k); return; + case fnShitroidInCutscene_FinishCutscene: ShitroidInCutscene_FinishCutscene(k); return; + default: Unreachable(); + } +} + +void CallShitroidCutsceneFunc0F(uint32 ea) { + switch (ea) { + case fnnullsub_368: return; + case fnnullsub_338: return; + case fnShitroid_HandleCutscenePalette: Shitroid_HandleCutscenePalette(); return; + case fnShitroid_HandleCutscenePalette_LowHealth: Shitroid_HandleCutscenePalette_LowHealth(); return; + default: Unreachable(); + } +} + +void ShitroidInCutscene_Main(void) { // 0xA9C779 + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(cur_enemy_index); + E->base.shake_timer = 0; + CallShitroidCutsceneFuncA(E->sice_var_A | 0xA90000, cur_enemy_index); + MoveEnemyWithVelocity(); + ShitroidInCutscene_Flashing(cur_enemy_index); + ShitroidInCutscene_HandleHealthBasedPalette(cur_enemy_index); + R18_ = Get_ShitdroidInCutscene(cur_enemy_index)->sice_var_0F; + CallShitroidCutsceneFunc0F(R18_ | 0xA90000); +} + +void ShitroidInCutscene_Flashing(uint16 k) { // 0xA9C79C + int16 v1; + + v1 = 3584; + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + uint16 sice_var_06 = E->sice_var_06; + if (sice_var_06) { + uint16 v4 = sice_var_06 - 1; + E->sice_var_06 = v4; + if ((v4 & 2) != 0) + v1 = 0; + } + E->base.palette_index = v1; +} + +void ShitroidInCutscene_HandleCry(void) { // 0xA9C7B7 + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(0); + if (E->sice_var_14) { + E->sice_var_14 = 0; + QueueSfx2_Max6(0x72u); + } +} + +void ShitroidInCutscene_DashOntoScreen(uint16 k) { // 0xA9C7CC + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + if ((--E->sice_var_F & 0x8000u) != 0) { + E->sice_var_0A = -10240; + E->sice_var_0B = 2560; + E->sice_var_A = FUNC16(ShitroidInCutscene_CurveTowardsBrain); + E->sice_var_F = 10; + ShitroidInCutscene_CurveTowardsBrain(k); + } +} + +void ShitroidInCutscene_CurveTowardsBrain(uint16 k) { // 0xA9C7EC + R18_ = -384; + R20_ = -20480; + R22_ = 2560; + ShitroidInCutscene_UpdateSpeedAndAngle(k); + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(k); + if ((--E->sice_var_F & 0x8000u) != 0) { + E->sice_var_A = FUNC16(ShitroidInCutscene_GetIntoFace); + E->sice_var_F = 9; + } +} + +void ShitroidInCutscene_GetIntoFace(uint16 k) { // 0xA9C811 + bool v3; // sf + + R18_ = -1536; + R20_ = -32256; + R22_ = 3584; + ShitroidInCutscene_UpdateSpeedAndAngle(k); + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(0x40u); + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + R22_ = 4; + R24_ = 4; + if (!(Shitroid_Func_2(k) & 1) + || (E = Get_ShitroidInCutscene(k), v3 = (int16)(E->sice_var_F - 1) < 0, --E->sice_var_F, v3)) { + Get_ShitroidInCutscene(k)->sice_var_A = FUNC16(ShitroidInCutscene_LatchOntoBrain); + SomeMotherBrainScripts(1u); + } +} + +void ShitroidInCutscene_LatchOntoBrain(uint16 k) { // 0xA9C851 + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(0x40u); + R18_ = E->base.x_pos; + R20_ = E->base.y_pos - 24; + Shitroid_Func_GraduallyAccelerateTowards0x400(k, 0); + R22_ = 8; + R24_ = 8; + if (!(Shitroid_Func_2(k) & 1)) + Get_ShitroidInCutscene(k)->sice_var_A = FUNC16(ShitroidInCutscene_SetMotherBrainToStumbleBack); +} + +void ShitroidInCutscene_SetMotherBrainToStumbleBack(uint16 k) { // 0xA9C879 + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(0); + MotherBrain_MakeWalkBackwards(E->base.x_pos - 1, 2u); + Get_ShitroidInCutscene(k)->sice_var_A = FUNC16(ShitroidInCutscene_ActivateRainbowBeam); + ShitroidInCutscene_ActivateRainbowBeam(k); +} + +void ShitroidInCutscene_ActivateRainbowBeam(uint16 k) { // 0xA9C889 + Enemy_ShitroidInCutscene *E1 = Get_ShitdroidInCutscene(0x40u); + R18_ = E1->base.x_pos; + R20_ = E1->base.y_pos - 24; + if (Shitroid_AccelerateTowardsPoint(k, 0x200u) & 1) { + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + E->sice_var_B = 0; + E->sice_var_C = 0; + E->base.x_pos = E1->base.x_pos; + E->base.y_pos = E1->base.y_pos - 24; + Enemy_SetInstrList(k, addr_kShitroid_Ilist_CFB8); + E->sice_var_A = FUNC16(ShitroidInCutscene_BrainTurnsToCorpse); + E->sice_var_E = 1; + Enemy_ShitroidInCutscene *E0 = Get_ShitdroidInCutscene(0); + E0->sice_var_A = FUNC16(MotherBrain_DrainedByShitroid_0); + QueueSfx1_Max6(0x40u); + E0->sice_var_16 = 1; + } +} + +void ShitroidInCutscene_BrainTurnsToCorpse(uint16 k) { // 0xA9C8E2 + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + Enemy_ShitroidInCutscene *E1 = Get_ShitdroidInCutscene(0x40u); + + int v2 = (uint8)(E->base.frame_counter & 6) >> 1; + E->base.x_pos = E1->base.x_pos + g_word_A993BB[v2]; + E->base.y_pos = E1->base.y_pos + g_word_A993C3[v2] - 24; + if (Get_ShitdroidInCutscene(0)->sice_var_1F) { + E->sice_var_A = FUNC16(ShitroidInCutscene_StopDraining); + E->sice_var_F = 64; + } +} + +void ShitroidInCutscene_StopDraining(uint16 k) { // 0xA9C915 + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(k); + Enemy_ShitroidInCutscene *E1 = Get_ShitroidInCutscene(0x40u); + E->base.x_pos = E1->base.x_pos; + E->base.y_pos = E1->base.y_pos - 24; + if ((--E->sice_var_F & 0x8000u) != 0) { + Enemy_SetInstrList(k, addr_kShitroid_Ilist_CFA2); + E->sice_var_E = 10; + E->sice_var_A = FUNC16(ShitroidInCutscene_LetGoAndSpawnDust); + E->sice_var_F = 32; + E->sice_var_B = 0; + E->sice_var_C = 0; + } +} + +void ShitroidInCutscene_LetGoAndSpawnDust(uint16 k) { // 0xA9C94B + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + if ((--E->sice_var_F & 0x8000u) != 0) { + ShitroidInCutscene_SpawnThreeDustClouds(); + E->sice_var_A = addr_loc_A9C959; + } + ShitroidInCutscene_MoveUpToCeiling(k); +} + +void ShitroidInCutscene_MoveUpToCeiling(uint16 k) { // 0xA9C959 + R18_ = Get_ShitdroidInCutscene(0x40u)->base.x_pos; + R20_ = 0; + Shitroid_Func_GraduallyAccelerateTowards0x400(k, 0); + R22_ = 4; + R24_ = 4; + if (!(Shitroid_Func_2(k) & 1)) { + SomeMotherBrainScripts(4u); + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + E->sice_var_A = FUNC16(ShitroidInCutscene_MoveToSamus); + E->sice_var_0E = addr_stru_A9CA24; + } +} + +void ShitroidInCutscene_SpawnThreeDustClouds(void) { // 0xA9C98C + R20_ = -8; + ShitroidInCutscene_SpawnOneDustCloudAt(0xFFF0u); + R20_ = -16; + ShitroidInCutscene_SpawnOneDustCloudAt(0); + R20_ = -8; + ShitroidInCutscene_SpawnOneDustCloudAt(0x10u); +} + +void ShitroidInCutscene_SpawnOneDustCloudAt(uint16 a) { // 0xA9C9AA + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(0x40u); + R18_ = E->base.x_pos + a; + R20_ += E->base.y_pos; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 9u); +} + +void CallShitroidMoveFunc(uint32 ea, uint16 k, uint16 j) { + switch (ea) { + case fnShitroid_GraduallyAccelerateTowards0x8: Shitroid_GraduallyAccelerateTowards0x8(k, j); return; + case fnShitroid_GraduallyAccelerateTowards0x10: Shitroid_GraduallyAccelerateTowards0x10(k, j); return; + default: Unreachable(); + } +} + +void ShitroidInCutscene_MoveToSamus(uint16 k) { // 0xA9C9C3 + int16 v4; + + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + E->sice_var_04 = 0; + E->sice_var_09 = 1; + if ((random_number & 0xFFFu) >= 0xFA0) + QueueSfx2_Max6(0x52u); + uint16 sice_var_0E = E->sice_var_0E; + uint16 *v3 = (uint16 *)RomPtr_A9(sice_var_0E); + R18_ = *v3; + R20_ = v3[1]; + R22_ = v3[3]; + CallShitroidMoveFunc(R22_ | 0xA90000, k, v3[2]); + R22_ = 4; + R24_ = 4; + if (!(Shitroid_Func_2(k) & 1)) { + v4 = *((uint16 *)RomPtr_A9(sice_var_0E) + 4); + if (v4 < 0) { + E->sice_var_A = v4; + } else { + E->sice_var_0E += 8; + } + } +} + +void ShitroidInCutscene_LatchOntoSamus(uint16 k) { // 0xA9CA66 + R18_ = samus_x_pos; + R20_ = samus_y_pos - 20; + Shitroid_Func_GraduallyAccelerateTowards0x400(k, 0); +} + +void ShitroidInCutscene_HealSamusToFullHealth(uint16 k) { // 0xA9CA7A + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + E->sice_var_04 = 0; + ShitroidInCutscene_HandleCry(); + int v2 = (uint8)(E->base.frame_counter & 6) >> 1; + E->base.x_pos = samus_x_pos + g_word_A993BB[v2]; + E->base.y_pos = samus_y_pos + g_word_A993C3[v2] - 20; + if (!(Samus_HealDueToShitroid() & 1)) { + samus_reserve_health = samus_max_reserve_health; + E->sice_var_A = FUNC16(ShitroidInCutscene_IdleUntilToNoHealth); + E->sice_var_0F = FUNC16(nullsub_368); + } +} + +void ShitroidInCutscene_IdleUntilToNoHealth(uint16 k) { // 0xA9CABD + ShitroidInCutscene_HandleCry(); + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + uint16 sice_var_06 = E->sice_var_06; + if (sice_var_06) { + int v3 = (uint8)(sice_var_06 & 6) >> 1; + E->base.x_pos = samus_x_pos + 2 * g_word_A993BB[v3]; + E->base.y_pos = samus_y_pos + 2 * g_word_A993C3[v3] - 20; + } + if (!E->base.health) { + E->base.health = 320; + E->sice_var_A = FUNC16(ShitroidInCutscene_ReleaseSamus); + E->sice_var_E = 10; + E->sice_var_D = 0; + E->sice_var_0F = FUNC16(Shitroid_HandleCutscenePalette_LowHealth); + E->sice_var_04 = 1; + E->sice_var_09 = 0; + } +} + +void ShitroidInCutscene_ReleaseSamus(uint16 k) { // 0xA9CB13 + QueueSfx2_Max6(0x72u); + Get_ShitdroidInCutscene(0x40u)->sice_var_0B = 1; + Get_ShitdroidInCutscene(k)->sice_var_A = FUNC16(ShitroidInCutscene_StareDownMotherBrain); + Get_ShitdroidInCutscene(0)->sice_var_A = FUNC16(MotherBrain_Phase2_PrepareForFinalShitroid); + ShitroidInCutscene_StareDownMotherBrain(k); +} + +void ShitroidInCutscene_StareDownMotherBrain(uint16 k) { // 0xA9CB2D + R18_ = samus_x_pos - 4; + R20_ = 96; + Shitroid_GraduallyAccelerateTowards0x10(k, 0); + R22_ = 4; + R24_ = 4; + if (!(Shitroid_Func_2(k) & 1)) + Get_ShitroidInCutscene(k)->sice_var_A = FUNC16(ShitroidInCutscene_FlyOffScreen); +} + +void ShitroidInCutscene_FlyOffScreen(uint16 k) { // 0xA9CB56 + R18_ = 272; + R20_ = 64; + Shitroid_GraduallyAccelerateTowards0x10(k, 0); + R22_ = 4; + R24_ = 4; + if (!(Shitroid_Func_2(k) & 1)) + Get_ShitroidInCutscene(k)->sice_var_A = FUNC16(ShitroidInCutscene_MoveToFinalChargeStart); +} + +void ShitroidInCutscene_MoveToFinalChargeStart(uint16 k) { // 0xA9CB7B + R18_ = 305; + R20_ = 160; + Shitroid_GraduallyAccelerateTowards0x10(k, 0); + R22_ = 4; + R24_ = 4; + if (!(Shitroid_Func_2(k) & 1)) { + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + E->base.health = 79; + Get_ShitdroidInCutscene(0x40u)->sice_var_0B = 0; + Get_ShitdroidInCutscene(0)->sice_var_A = FUNC16(MotherBrain_Phase2_ExecuteFinalkShitroid); + E->sice_var_A = FUNC16(ShitroidInCutscene_InitiateFinalCharge); + } +} + +void ShitroidInCutscene_InitiateFinalCharge(uint16 k) { // 0xA9CBB3 + R18_ = 290; + R20_ = 128; + Shitroid_Func_GraduallyAccelerateTowards0x400(k, 0xAu); + R22_ = 4; + R24_ = 4; + if (!(Shitroid_Func_2(k) & 1)) + Get_ShitroidInCutscene(k)->sice_var_A = FUNC16(ShitroidInCutscene_FinalCharge); +} + +void ShitroidInCutscene_FinalCharge(uint16 k) { // 0xA9CBD8 + Enemy_ShitroidInCutscene *E1 = Get_ShitdroidInCutscene(0x40u); + R18_ = E1->base.x_pos; + R20_ = E1->base.y_pos - 32; + Shitroid_Func_GraduallyAccelerateTowards0x400(k, 0xCu); + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + if (!E->base.health) { + E->sice_var_0F = FUNC16(nullsub_338); + E->base.vram_tiles_index = 4256; + QueueSfx3_Max6(0x19u); + TurnOffLightsForShitroidDeath(); + Enemy_SetInstrList(k, addr_kShitroid_Ilist_CFCE); + E->sice_var_B = 0; + E->sice_var_C = 0; + Get_ShitdroidInCutscene(0)->sice_var_A = addr_locret_A9C18D; + QueueMusic_Delayed8(0); + E->sice_var_A = FUNC16(ShitroidInCutscene_ShitroidFinalBelow); + E->sice_var_F = 16; + E->sice_var_10 = E->base.x_pos; + E->sice_var_11 = E->base.y_pos; + ShitroidInCutscene_ShitroidFinalBelow(k); + } +} + +void ShitroidInCutscene_ShitroidFinalBelow(uint16 k) { // 0xA9CC3E + ShitroidInCutscene_Shake(k); + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + if ((--E->sice_var_F & 0x8000u) != 0) { + E->base.x_pos = E->sice_var_10; + E->base.y_pos = E->sice_var_11; + E->sice_var_A = FUNC16(ShitroidInCutscene_PlaySamusTheme); + E->sice_var_F = 56; + ShitroidInCutscene_PlaySamusTheme(k); + } +} + +void ShitroidInCutscene_PlaySamusTheme(uint16 k) { // 0xA9CC60 + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(k); + if ((--E->sice_var_F & 0x8000u) != 0) { + QueueMusic_Delayed8(0xFF48u); + QueueMusic_Delayed8(5u); + E->sice_var_A = FUNC16(ShitroidInCutscene_PrepareSamusHyperbeam); + E->sice_var_F = 12; + ShitroidInCutscene_PrepareSamusHyperbeam(k); + } +} + +void ShitroidInCutscene_PrepareSamusHyperbeam(uint16 k) { // 0xA9CC7F + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + if ((--E->sice_var_F & 0x8000u) != 0) { + CallSomeSamusCode(0x19u); + Get_ShitdroidInCutscene(0x40u)->sice_var_16 = FUNC16(SamusRainbowPaletteFunc_ActivateWhenEnemyLow); + E->sice_var_A = FUNC16(ShitroidInCutscene_DeathSequence); + } +} + +void ShitroidInCutscene_DeathSequence(uint16 k) { // 0xA9CC99 + HandleSamusRainbowPaletteAnimation(k); + ShitroidInCutscene_AccelerateDownwards(k); + if (ShitroidInCutscene_FadeShitroidToBlack(k) & 1) { + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(k); + E->base.properties |= kEnemyProps_Invisible; + E->sice_var_A = FUNC16(ShitroidInCutscene_UnloadShitroid); + E->sice_var_F = 128; + } else { + ShitroidInCutscene_HandleShitroidDeathExplosions(k); + ShitroidInCutscene_HandleEnemyBlinking(k); + } +} + +void ShitroidInCutscene_UnloadShitroid(uint16 k) { // 0xA9CCC0 + HandleSamusRainbowPaletteAnimation(k); + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(k); + bool v2 = (--E->sice_var_F & 0x8000u) != 0; + if (v2 && ProcessSpriteTilesTransfers(0xa9, addr_stru_A98FC7)) { + E->sice_var_A = FUNC16(ShitroidInCutscene_LetSamusRainbowMore); + E->sice_var_F = 176; + ShitroidInCutscene_LetSamusRainbowMore(k); + } +} + +void ShitroidInCutscene_LetSamusRainbowMore(uint16 k) { // 0xA9CCDE + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + if ((--E->sice_var_F & 0x8000u) != 0) { + E->sice_var_A = FUNC16(ShitroidInCutscene_FinishCutscene); + Get_ShitdroidInCutscene(0)->sice_var_37 = 0; + ShitroidInCutscene_FinishCutscene(k); + } +} + +void ShitroidInCutscene_FinishCutscene(uint16 k) { // 0xA9CCF0 + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(0); + uint16 v2 = E->sice_var_37 + 1; + E->sice_var_37 = v2; + if (MotherBrain_Phase3_TurnLightsBackOn(v2 - 1) & 1) { + E->sice_var_A = FUNC16(MotherBrain_Phase3_Recover_MakeDistance); + CallSomeSamusCode(0x17u); + SomeMotherBrainScripts(3u); + Get_ShitdroidInCutscene(k)->base.properties |= kEnemyProps_Deleted; + Get_ShitdroidInCutscene(0x40u)->sice_var_0A = 0; + } +} + +void CallSamusRainbowPaletteFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnSamusRainbowPaletteFunc_ActivateWhenEnemyLow: SamusRainbowPaletteFunc_ActivateWhenEnemyLow(k); return; + case fnSamusRainbowPaletteFunc_GraduallySlowDown: SamusRainbowPaletteFunc_GraduallySlowDown(); return; + default: Unreachable(); + } +} + +void HandleSamusRainbowPaletteAnimation(uint16 k) { // 0xA9CD27 + R18_ = Get_ShitdroidInCutscene(0x40u)->sice_var_16; + CallSamusRainbowPaletteFunc(R18_ | 0xA90000, k); +} + +void SamusRainbowPaletteFunc_ActivateWhenEnemyLow(uint16 k) { // 0xA9CD30 + if ((int16)(Get_ShitdroidInCutscene(k)->base.y_pos + 16 - samus_y_pos) >= 0) { + CallSomeSamusCode(0x16u); + Get_ShitdroidInCutscene(0x40u)->sice_var_16 = FUNC16(SamusRainbowPaletteFunc_GraduallySlowDown); + } +} + +void SamusRainbowPaletteFunc_GraduallySlowDown(void) { // 0xA9CD4B + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(0x40u); + uint16 sice_var_1D = E->sice_var_1D; + E->sice_var_1D = sice_var_1D + 768; + if (sice_var_1D >= 0xFD00u) { + uint16 v2 = special_samus_palette_frame + 1; + if (!sign16(special_samus_palette_frame - 9)) + v2 = 10; + special_samus_palette_frame = v2; + } +} + +uint8 ShitroidInCutscene_FadeShitroidToBlack(uint16 k) { // 0xA9CD69 + int16 v2; + + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + if (sign16(E->base.y_pos - 128)) + return 0; + v2 = E->sice_var_0C - 1; + if (v2 >= 0) { + E->sice_var_0C = v2; + return 0; + } + E->sice_var_0C = 8; + uint16 v4 = E->sice_var_0D + 1; + if (!sign16(E->sice_var_0D - 6)) + return 1; + E->sice_var_0D = v4; + WriteColorsToPalette(0x1E2u, 0xad, kShitroid_FadingToBlack[v4], 0xEu); + return 0; +} + +void ShitroidInCutscene_HandleShitroidDeathExplosions(uint16 k) { // 0xA9CDB1 + int16 v2; + + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + v2 = E->sice_var_08 - 1; + if (v2 < 0) { + E->sice_var_08 = 4; + uint16 v3 = E->sice_var_07 + 1; + if (!sign16(E->sice_var_07 - 9)) + v3 = 0; + E->sice_var_07 = v3; + int v4 = (uint16)(4 * v3) >> 1; + R18_ = E->base.x_pos + g_word_A9CDFC[v4]; + R20_ = E->base.y_pos + g_word_A9CDFC[v4 + 1]; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 3u); + QueueSfx3_Max3(0x13u); + } else { + E->sice_var_08 = v2; + } +} + +void ShitroidInCutscene_HandleEnemyBlinking(uint16 k) { // 0xA9CE24 + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(k); + if ((E->base.frame_counter & 1) != 0) + E->base.properties &= ~kEnemyProps_Invisible; + else + E->base.properties |= kEnemyProps_Invisible; +} + +void ShitroidInCutscene_AccelerateDownwards(uint16 k) { // 0xA9CE40 + int16 v2; + + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(k); + v2 = abs16(E->sice_var_B) - 32; + if (v2 < 0) + v2 = 0; + E->sice_var_B = sign16(E->sice_var_B) ? -v2 : v2; + E->sice_var_C += 2; +} + +void ShitroidInCutscene_HandleHealthBasedPalette(uint16 k) { // 0xA9CE69 + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + if (E->sice_var_09) { + uint16 health = E->base.health; + if (sign16(health - 2560)) { + uint16 v3 = 2; + if (sign16(health - 2240)) { + v3 = 4; + if (sign16(health - 1920)) { + v3 = 6; + if (sign16(health - 1600)) { + v3 = 8; + if (sign16(health - 1280)) { + v3 = 10; + if (sign16(health - 960)) { + v3 = 12; + if (sign16(health - 640)) + v3 = 14; + } + } + } + } + } + uint16 v5 = v3; + uint16 v4 = kShitroid_HealthBasedPalettes_Shell[v3 >> 1]; + WriteColorsToPalette(0x1E2u, 0xad, v4, 4); + WriteColorsToPalette(0x1F4u, 0xad, v4 + 8, 5); + WriteColorsToPalette(0x1EAu, 0xad, kShitroid_HealthBasedPalettes_Innards[v5 >> 1], 5u); + } + } +} + +void ShitroidInCutscene_Shake(uint16 k) { // 0xA9CEDB + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + --E->sice_var_C; + int v2 = (uint8)(E->base.frame_counter & 6) >> 1; + E->base.x_pos = E->sice_var_10 + g_word_A993BB[v2]; + E->base.y_pos = E->sice_var_11 + g_word_A993C3[v2]; +} + +void ShitroidInCutscene_Touch(void) { // 0xA9CF03 + Enemy_ShitroidInCutscene *E = Get_ShitroidInCutscene(cur_enemy_index); + if (E->sice_var_A == (uint16)FUNC16(ShitroidInCutscene_LatchOntoSamus)) { + R18_ = samus_x_pos; + R20_ = samus_y_pos - 20; + if (Shitroid_AccelerateTowardsPoint(cur_enemy_index, 0x10u) & 1) { + E->sice_var_B = 0; + E->sice_var_C = 0; + E->sice_var_A = FUNC16(ShitroidInCutscene_HealSamusToFullHealth); + } + } +} + +void ShitroidInCutscene_UpdateSpeedAndAngle(uint16 k) { // 0xA9CF31 + Enemy_ShitroidInCutscene *E = Get_ShitdroidInCutscene(k); + if (R22_ != E->sice_var_0B) { + if ((int16)(R22_ - E->sice_var_0B) >= 0) { + uint16 v3 = E->sice_var_0B + 32; + if (!sign16(v3 - R22_)) + v3 = R22_; + E->sice_var_0B = v3; + } else { + uint16 v2 = E->sice_var_0B - 32; + if (sign16(v2 - R22_)) + v2 = R22_; + E->sice_var_0B = v2; + } + } + uint16 v4; + if ((R18_ & 0x8000u) != 0) { + v4 = E->sice_var_0A + R18_; + if (sign16(v4 - R20_)) + LABEL_13: + v4 = R20_; + } else { + v4 = E->sice_var_0A + R18_; + if (!sign16(v4 - R20_)) + goto LABEL_13; + } + E->sice_var_0A = v4; + R18_ = HIBYTE(v4); + E->sice_var_B = Math_MultBySin(E->sice_var_0B); + E->sice_var_C = Math_MultByCos(E->sice_var_0B); +} + +uint16 Shitroid_Instr_1(uint16 k, uint16 j) { // 0xA9CFB4 + return addr_kShitroid_Ilist_CFA2; +} + +uint16 Shitroid_Instr_2(uint16 k, uint16 j) { // 0xA9CFCA + return addr_kShitroid_Ilist_CFB8; +} + +void MotherBrain_Pal_ProcessInvincibility(void) { // 0xA9CFD4 + if (Get_MotherBrain(0)->mbn_var_00 == 4) { + uint16 flash_timer = Get_MotherBrain(0x40u)->base.flash_timer; + if (flash_timer >> 1) { + if (!(flash_timer & 1)) { + for (int i = 28; i >= 0; i -= 2) { + int v2 = i >> 1; + uint16 v3 = palette_buffer[v2 + 129]; + palette_buffer[v2 + 145] = v3; + palette_buffer[v2 + 177] = v3; + palette_buffer[v2 + 65] = v3; + } + } + } + } +} + +void MotherBrain_Pal_BeginScreenFlash(void) { // 0xA9CFFD + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_0E = addr_stru_A9D046; + E->mbn_var_0F = 1; +} + +void MotherBrain_Pal_EndScreenFlash(void) { // 0xA9D00C + Enemy_MotherBrain *E = Get_MotherBrain(0); + E->mbn_var_0E = 0; + E->mbn_var_0F = 0; + MotherBrain_Pal_WriteRoomPal(addr_word_A9D082); +} + +void MotherBrain_Pal_HandleRoomPal(void) { // 0xA9D01C + uint16 j = HandleRoomPaletteInstructionList(ADDR16_OF_RAM(*enemy_ram7800) + 28); + if (j) + MotherBrain_Pal_WriteRoomPal(j); +} + +void MotherBrain_Pal_WriteRoomPal(uint16 j) { // 0xA9D025 + WriteColorsToPalette(0x68u, 0xa9, j, 12); + WriteColorsToPalette(0xA6u, 0xa9, j + 24, 12); + WriteColorsToPalette(0xE6u, 0xa9, j + 24, 12); +} + +uint16 HandleRoomPaletteInstructionList(uint16 a) { // 0xA9D192 + int16 v4; + + R0_.addr = a; + R3_.addr = a + 2; + R0_.bank = 126; + R3_.bank = 126; + uint16 *v1 = (uint16 *)IndirPtr(&R0_, 0); + if ((*v1 & 0x8000u) == 0) + return 0; + uint16 v3 = *v1; + v4 = *(uint16 *)RomPtr_A9(*v1); + if (v4 < 0) + goto LABEL_8; + if (v4 == *(uint16 *)IndirPtr(&R3_, 0)) { + for (v3 += 4; ; ) { + v4 = *(uint16 *)RomPtr_A9(v3); + if (!v4) + break; + if (v4 >= 0) { + IndirWriteWord(&R3_, 0, 1u); + IndirWriteWord(&R0_, 0, v3); + return *((uint16 *)RomPtr_A9(v3) + 1); + } +LABEL_8: + R6_ = v4; + v3 = CallMotherBrainInstr((uint16)v4 | 0xA90000, v3 + 2); + } + IndirWriteWord(&R0_, 0, 0); + IndirWriteWord(&R3_, 0, 0); + return 0; + } else { + uint8 *v5 = IndirPtr(&R3_, 0); + IndirWriteWord(&R3_, 0, *(uint16 *)v5 + 1); + return *((uint16 *)RomPtr_A9(v3) + 1); + } +} + +void MotherBrain_HandlePalette(void) { // 0xA9D1E4 + Enemy_MotherBrain *E = Get_MotherBrain(0x40u); + if (E->mbn_var_10) + MotherBrain_HandleBrainPal(); + if (E->mbn_var_11) + MotherBrain_HealthBasedPaletteHandling(); +} + +void MotherBrain_SetupBrainNormalPal(void) { // 0xA9D1F8 + Get_MotherBrain(0)->mbn_var_E = 10; +} + +void MotherBrain_SetupBrainPalForLaser(void) { // 0xA9D1FF + Get_MotherBrain(0)->mbn_var_E = 514; +} + +void MotherBrain_HandleBrainPal(void) { // 0xA9D206 + char mbn_var_D_high; + char mbn_var_D; + + Enemy_MotherBrain *E = Get_MotherBrain(0); + if (E->mbn_var_00 != 1) { + mbn_var_D_high = HIBYTE(E->mbn_var_D); + if (mbn_var_D_high) { + HIBYTE(E->mbn_var_D) = mbn_var_D_high - 1; + } else { + R18_ = g_off_A9D260[HIBYTE(E->mbn_var_E) >> 1]; + HIBYTE(E->mbn_var_D) = E->mbn_var_E; + mbn_var_D = E->mbn_var_D; + if (mbn_var_D + || Get_MotherBrain(0x40u)->mbn_var_A == (uint16)FUNC16(MotherBrainsBrain_SetupBrainAndNeckToDraw)) { + uint8 v4 = (mbn_var_D + 1) & 7; + LOBYTE(E->mbn_var_D) = v4; + uint16 v5 = 290; + if (E->mbn_var_0D != 512) + v5 = 482; + WriteColorsToPalette(v5, 0xa9, R18_ + 8 * v4, 3u); + } + } + } +} + +void WriteColorsToPalette(uint16 k, uint8 db, uint16 j, uint16 a) { // 0xA9D2E4 + R18_ = a; + do { + palette_buffer[k >> 1] = *(uint16 *)RomPtrWithBank(db, j); + k += 2; + j += 2; + --R18_; + } while (R18_); +} + +void WriteColorsToTargetPalette(uint8 db, uint16 k, uint16 j, uint16 a) { // 0xA9D2F6 + R18_ = a; + do { + target_palettes[k >> 1] = *(uint16 *)RomPtrWithBank(db, j); + k += 2; + j += 2; + --R18_; + } while (R18_); +} + +void DeadTorizo_Init(void) { // 0xA9D308 + for (int i = 4094; i >= 0; i -= 2) + tilemap_stuff[i >> 1] = 0; + Enemy_DeadTorizo *E = Get_DeadTorizo(0); + E->dto_var_A = FUNC16(DeadTorizo_WaitForSamusColl); + E->base.properties |= 0xA000u; + E->base.current_instruction = addr_kDeadTorizo_Ilist_D6DC; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.palette_index = 512; + E->dto_var_B = 0; + E->dto_var_C = 8; + E->dto_var_04 = 0; + E->dto_var_02 = 15; + E->dto_var_03 = 0; + InitializeEnemyCorpseRotting(0, addr_stru_A9DD58); +} + +void CallDeadTorizoFuncA(uint32 ea) { + switch (ea) { + case fnDeadTorizo_WaitForSamusColl: DeadTorizo_WaitForSamusColl(cur_enemy_index); return; + case fnDeadTorizo_Rotting: DeadTorizo_Rotting(); return; + case fnDeadTorizo_PreRotDelay: DeadTorizo_PreRotDelay(); return; + case fnnullsub_361: return; + default: Unreachable(); + } +} + +void DeadTorizo_Main(void) { // 0xA9D368 + Enemy_DeadTorizo *E = Get_DeadTorizo(0); + if ((E->base.properties & kEnemyProps_Tangible) == 0 && DeadTorizo_Func_0() & 1) { + E->base.properties |= kEnemyProps_Tangible; + E->dto_var_A = FUNC16(DeadTorizo_Rotting); + } + mov24(&enemy_gfx_drawn_hook, 0xA9D39Au); + CallDeadTorizoFuncA(E->dto_var_A | 0xA90000); + DeadTorizo_Func_1(); +} + +void DeadTorizo_MainGfxHook(void) { // 0xA9D39A + R22_ = 0; + R18_ = 296; + R20_ = 187; + MotherBrain_AddSpritemapToOam(addr_kDeadTorizo_Sprmap_D761); +} + +void DeadTorizo_WaitForSamusColl(uint16 k) { // 0xA9D3AD + if (k == enemy_index_colliding_dirs[0] + || k == enemy_index_colliding_dirs[1] + || k == enemy_index_colliding_dirs[2] + || k == enemy_index_colliding_dirs[3]) { + Get_DeadTorizo(0)->dto_var_A = FUNC16(DeadTorizo_PreRotDelay); + } +} + +void DeadTorizo_PreRotDelay(void) { // 0xA9D3C8 + Enemy_DeadTorizo *E = Get_DeadTorizo(0); + uint16 v1 = E->dto_var_04 + 1; + E->dto_var_04 = v1; + if (v1 >= 0x10u) { + E->base.properties |= kEnemyProps_Tangible; + E->dto_var_A = FUNC16(DeadTorizo_Rotting); + DeadTorizo_Rotting(); + } +} + +void DeadTorizo_Rotting(void) { // 0xA9D3E6 + Enemy_DeadTorizo *E = Get_DeadTorizo(0); + uint16 v1 = E->dto_var_03 + 1; + E->dto_var_03 = v1; + if (v1 >= 0xFu) { + E->dto_var_03 = 0; + uint16 dto_var_02 = E->dto_var_02; + if (dto_var_02) { + DeadTorizo_CopyLineOfSandHeapTileData(dto_var_02); + --E->dto_var_02; + } + } + ++E->dto_var_C; + MoveEnemyWithVelocity(); + if (!(ProcessCorpseRotting(0) & 1)) + E->dto_var_A = FUNC16(nullsub_361); +} + +void DeadTorizo_Powerbomb(void) { // 0xA9D42A + if ((Get_DeadTorizo(0)->base.properties & kEnemyProps_Tangible) == 0) + DeadTorizo_Shot(); +} + +void DeadTorizo_Shot(void) { // 0xA9D433 + Enemy_DeadTorizo *E = Get_DeadTorizo(0); + E->base.properties |= kEnemyProps_Tangible; + E->dto_var_A = FUNC16(DeadTorizo_Rotting); +} + +uint8 DeadTorizo_Func_0(void) { // 0xA9D443 + int16 v5; + uint16 v3, v4; + + Enemy_DeadTorizo *E = Get_DeadTorizo(0); + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + uint16 *v1 = (uint16 *)RomPtr_A9(addr_kDeadTorizo_Hitbox_D77C); + if (!*v1) + return 0; + R22_ = *v1; + for (int i = 0xd77c + 2; ; i += 8) { + if ((int16)(samus_y_pos - R20_) >= 0) { + R24_ = samus_y_pos - R20_; + v3 = *((uint16 *)RomPtr_A9(i) + 3); + } else { + R24_ = R20_ - samus_y_pos; + v3 = *((uint16 *)RomPtr_A9(i) + 1); + } + if ((int16)(samus_y_radius + abs16(v3) - R24_) >= 0) { + if ((int16)(samus_x_pos - R18_) >= 0) { + R24_ = samus_x_pos - R18_; + v4 = *((uint16 *)RomPtr_A9(i) + 2); + } else { + R24_ = R18_ - samus_x_pos; + v4 = *(uint16 *)RomPtr_A9(i); + } + v5 = samus_x_radius + abs16(v4) - R24_; + if (v5 >= 0) + break; + } + if (!--R22_) + return 0; + } + if (sign16(v5 - 4)) + v5 = 4; + extra_samus_x_displacement = v5; + extra_samus_y_displacement = 4; + extra_samus_x_subdisplacement = 0; + extra_samus_y_subdisplacement = 0; + return 1; +} + +void DeadTorizo_Func_1(void) { // 0xA9D4CF + VramWriteEntry *v5; + VramWriteEntry *v10; + Enemy_DeadTorizo *E = Get_DeadTorizo(0); + uint16 v1 = E->dto_var_00 + 1; + E->dto_var_00 = v1; + uint16 v3 = vram_write_queue_tail; + if (v1 & 1) { + uint16 v8 = 0; + uint16 v9 = g_word_A9D583[0]; + do { + v10 = gVramWriteEntry(v3); + v10->size = v9; + int v11 = v8 >> 1; + *(VoidP *)((char *)&v10->src.addr + 1) = g_word_A9D583[v11 + 1]; + v10->src.addr = g_word_A9D583[v11 + 2]; + v10->vram_dst = g_word_A9D583[v11 + 3]; + v3 += 7; + v8 += 8; + v9 = g_word_A9D583[v8 >> 1]; + } while (v9); + } else { + uint16 v2 = 0; + uint16 v4 = g_word_A9D549[0]; + do { + v5 = gVramWriteEntry(v3); + v5->size = v4; + int v6 = v2 >> 1; + *(VoidP *)((char *)&v5->src.addr + 1) = g_word_A9D549[v6 + 1]; + v5->src.addr = g_word_A9D549[v6 + 2]; + v5->vram_dst = g_word_A9D549[v6 + 3]; + v3 += 7; + v2 += 8; + v4 = g_word_A9D549[v2 >> 1]; + } while (v4); + } + Get_DeadEnemy(0)->dey_var_22 = 0; + vram_write_queue_tail = v3; +} + +void DeadTorizo_CorpseRottingFinished(void) { // 0xA9D5BD + R18_ = (random_number & 0x1F) + 272; + R20_ = 188; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0xAu); + if ((enemy_damage_routine_exec_count & 7) == 0) + QueueSfx2_Max6(0x10u); +} + +void DeadTorizo_CopyLineOfSandHeapTileData(uint16 a) { // 0xA9D5EA + uint16 v1 = g_word_A9D67C[a]; + int v2 = g_word_A9D69C[a] >> 1; + *(uint16 *)(&g_byte_7E9500 + v1) = kDeadTorizo_TileData[v2]; + *(uint16 *)(&g_byte_7E9510 + v1) = kDeadTorizo_TileData[v2 + 8]; + *(uint16 *)(&g_byte_7E9520 + v1) = kDeadTorizo_TileData[v2 + 16]; + *(uint16 *)(&g_byte_7E9530 + v1) = kDeadTorizo_TileData[v2 + 24]; + *(uint16 *)(&g_byte_7E9540 + v1) = kDeadTorizo_TileData[v2 + 32]; + *(uint16 *)(&g_byte_7E9550 + v1) = kDeadTorizo_TileData[v2 + 40]; + *(uint16 *)(&g_byte_7E9560 + v1) = kDeadTorizo_TileData[v2 + 48]; + *(uint16 *)(&g_byte_7E9570 + v1) = kDeadTorizo_TileData[v2 + 56]; + *(uint16 *)(&g_byte_7E9580 + v1) = kDeadTorizo_TileData[v2 + 64]; + *(uint16 *)(&g_byte_7E9590 + v1) = kDeadTorizo_TileData[v2 + 72]; + *(uint16 *)(&g_byte_7E95A0 + v1) = kDeadTorizo_TileData[v2 + 80]; + *(uint16 *)(&g_byte_7E95B0 + v1) = kDeadTorizo_TileData[v2 + 88]; + *(uint16 *)(&g_byte_7E95C0 + v1) = kDeadTorizo_TileData[v2 + 96]; + *(uint16 *)(&g_byte_7E95D0 + v1) = kDeadTorizo_TileData[v2 + 104]; + *(uint16 *)(&g_byte_7E95E0 + v1) = kDeadTorizo_TileData[v2 + 112]; + *(uint16 *)(&g_byte_7E95F0 + v1) = kDeadTorizo_TileData[v2 + 120]; + *(uint16 *)(&g_byte_7E9600 + v1) = kDeadTorizo_TileData[v2 + 128]; + *(uint16 *)(&g_byte_7E9610 + v1) = kDeadTorizo_TileData[v2 + 136]; +} + +void DeadSidehopper_Init(void) { // 0xA9D7B6 + uint16 dsr_parameter_1 = Get_DeadSidehopper(cur_enemy_index)->dsr_parameter_1; + if (dsr_parameter_1) { + if (dsr_parameter_1 != 2) { + Unreachable(); + while (1) + ; + } + DeadSidehopper_Init_1(); + } else { + DeadSidehopper_Init_0(); + } +} + +void DeadSidehopper_Init_0(void) { // 0xA9D7C4 + Enemy_DeadSidehopper *E = Get_DeadSidehopper(cur_enemy_index); + E->base.properties = E->base.properties & 0x77FF | kEnemyProps_ProcessedOffscreen; + if ((Get_DeadSidehopper(0)->base.properties & kEnemyProps_Invisible) != 0) + E->base.properties |= kEnemyProps_Deleted; + E->dsr_var_08 = 0; + E->dsr_var_0A = 96; + E->dsr_var_0B = 256; + E->base.x_pos = 488; + E->base.y_pos = 184; + E->dsr_var_A = FUNC16(DeadSidehopper_Alive_WaitForActivate); + E->base.palette_index = 512; + E->base.y_height = 21; + Enemy_SetInstrList(cur_enemy_index, addr_kDeadMonsters_Ilist_ECE3); + InitializeEnemyCorpseRotting(cur_enemy_index, addr_stru_A9DD68); +} + +void DeadSidehopper_Init_1(void) { // 0xA9D825 + Enemy_DeadSidehopper *E = Get_DeadSidehopper(cur_enemy_index); + E->dsr_var_08 = -1; + E->dsr_var_A = FUNC16(DeadSidehopper_WaitForSamusColl); + E->base.palette_index = 3584; + Enemy_SetInstrList(cur_enemy_index, addr_kDeadMonsters_Ilist_ECEF); + InitializeEnemyCorpseRotting(cur_enemy_index, addr_stru_A9DD78); +} + +void DeadZoomer_Init(void) { // 0xA9D849 + EnemyData *v1 = gEnemyData(cur_enemy_index); + v1->palette_index = 3584; + v1->ai_var_A = FUNC16(DeadZoomer_WaitForSamusColl); + int v2 = v1->parameter_1 >> 1; + Enemy_SetInstrList(cur_enemy_index, g_off_A9D86A[v2]); + InitializeEnemyCorpseRotting(cur_enemy_index, g_off_A9D870[v2]); +} + +void DeadRipper_Init(void) { // 0xA9D876 + EnemyData *v1 = gEnemyData(cur_enemy_index); + v1->palette_index = 3584; + v1->ai_var_A = FUNC16(DeadRipper_WaitForSamusColl); + int v2 = v1->parameter_1 >> 1; + Enemy_SetInstrList(cur_enemy_index, g_off_A9D897[v2]); + InitializeEnemyCorpseRotting(cur_enemy_index, g_off_A9D89B[v2]); +} + +void DeadSkree_Init(void) { // 0xA9D89F + EnemyData *v1 = gEnemyData(cur_enemy_index); + v1->palette_index = 3584; + v1->ai_var_A = FUNC16(DeadSkree_WaitForSamusColl); + int v2 = v1->parameter_1 >> 1; + Enemy_SetInstrList(cur_enemy_index, g_off_A9D8C0[v2]); + InitializeEnemyCorpseRotting(cur_enemy_index, g_off_A9D8C6[v2]); +} + +void DeadSidehopper_Powerbomb(void) { // 0xA9D8CC + if (Get_DeadSidehopper(cur_enemy_index)->dsr_var_08 >= 8u) + DeadSidehopper_Shot(); + else + DeadSidehopper_Main(); +} + +void CallDeadSidehopperFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnDeadSidehopper_Activated: DeadSidehopper_Activated(k); return; + case fnDeadSidehopper_Alive_WaitForActivate: DeadSidehopper_Alive_WaitForActivate(k); return; + + case fnDeadSidehopper_WaitForSamusColl: DeadSidehopper_WaitForSamusColl(k); return; + case fnDeadZoomer_WaitForSamusColl: DeadZoomer_WaitForSamusColl(k); return; + case fnDeadSkree_WaitForSamusColl: DeadSkree_WaitForSamusColl(k); return; + case fnDeadRipper_WaitForSamusColl: DeadRipper_WaitForSamusColl(k); return; + + case fnDeadSidehopper_PreRotDelay: DeadSidehopper_PreRotDelay(k); return; + case fnDeadZoomer_PreRotDelay: DeadZoomer_PreRotDelay(k); return; + case fnDeadSkree_PreRotDelay: DeadSkree_PreRotDelay(k); return; + case fnDeadRipper_PreRotDelay: DeadRipper_PreRotDelay(k); return; + + case fnDeadSidehopper_Rotting: DeadSidehopper_Rotting(k); return; + case fnDeadZoomer_Rotting: DeadZoomer_Rotting(k); return; + case fnDeadSkree_Rotting: DeadSkree_Rotting(k); return; + case fnDeadRipper_Rotting: DeadRipper_Rotting(k); return; + + case fnDeadMonsters_Func_1: DeadMonsters_Func_1(k); return; + case fnDeadMonsters_Func_2: DeadMonsters_Func_2(k); return; + case fnDeadMonsters_Func_5: DeadMonsters_Func_5(k); return; + + case fnnullsub_362: return; + case fnnullsub_268: return; + + default: Unreachable(); + } +} +void DeadSidehopper_Main(void) { // 0xA9D8DB + Enemy_DeadSidehopper *E = Get_DeadSidehopper(cur_enemy_index); + CallDeadSidehopperFunc(E->dsr_var_A | 0xA90000, cur_enemy_index); +} + +void DeadSidehopper_Alive_WaitForActivate(uint16 k) { // 0xA9D8E2 + if (sign16(layer1_x_pos - 513)) { + Get_DeadSidehopper(k)->dsr_var_A = FUNC16(DeadSidehopper_Activated); + DeadSidehopper_Activated(k); + } +} + +void DeadSidehopper_Activated(uint16 k) { // 0xA9D8F1 + if (DeadMonsters_Func_3(k) & 1) { + Enemy_DeadSidehopper *E = Get_DeadSidehopper(k); + E->dsr_var_06 = ((uint8)E->dsr_var_06 + 1) & 3; + Enemy_SetInstrList(k, addr_kDeadMonsters_Ilist_ECAC); + E->dsr_var_A = FUNC16(nullsub_362); + } +} + +void DeadMonsters_Func_1(uint16 k) { // 0xA9D910 + Enemy_DeadMonsters *E = Get_DeadMonsters(k); + E->dms_var_A = FUNC16(DeadMonsters_Func_2); + E->dms_var_F = 64; +} + +void DeadMonsters_Func_2(uint16 k) { // 0xA9D91D + Enemy_DeadMonsters *E = Get_DeadMonsters(k); + if ((--E->dms_var_F & 0x8000u) != 0) { + if (E->dms_var_08) { + E->dms_var_A = FUNC16(DeadMonsters_Func_5); + } else { + E->dms_var_A = FUNC16(DeadSidehopper_Activated); + Enemy_SetInstrList(k, addr_kDeadMonsters_Ilist_ECE3); + int v3 = (uint16)(2 * E->dms_var_06) >> 1; + E->dms_var_0B = g_word_A9D951[v3]; + E->dms_var_0A = g_word_A9D959[v3]; + } + } +} + +uint8 DeadMonsters_Func_3(uint16 k) { // 0xA9D961 + int16 v2; + int16 v5; + uint16 v6; + char v7; // t0 + int16 v9; + int16 v10; + char v11; // t1 + + Enemy_DeadMonsters *E = Get_DeadMonsters(k); + DeadMonsters_Func_4(k, E->dms_var_0A); + v2 = 32; + if ((E->dms_var_0B & 0x8000u) == 0) + v2 = 128; + uint16 v3 = E->dms_var_0B + v2; + E->dms_var_0B = v3; + R18_ = v3; + if (sign16(E->base.x_pos - 544)) { + HIBYTE(v9) = HIBYTE(R18_); + int full = HIBYTE(E->base.y_subpos) + LOBYTE(R18_); + LOBYTE(v9) = full; + HIBYTE(E->base.y_subpos) = v9; + v9 &= 0xFF00u; + v11 = v9; + LOBYTE(v10) = HIBYTE(v9); + HIBYTE(v10) = v11; + if ((v10 & 0x80) != 0) + v10 |= 0xFF00u; + uint16 v12 = E->base.y_pos + v10 + (full >> 8); + E->base.y_pos = v12; + return sign16(v12 - 184) == 0; + } else { + uint16 v4 = R18_; + HIBYTE(R18_) = R18_; + LOBYTE(R18_) = 0; + v5 = v4 & 0xFF00; + if (v5 < 0) + v5 |= 0xFFu; + v7 = v5; + LOBYTE(v6) = HIBYTE(v5); + HIBYTE(v6) = v7; + R20_ = v6; + return Enemy_MoveDown(k); + } +} + +void DeadMonsters_Func_4(uint16 k, uint16 a) { // 0xA9D9C7 + int16 v4; + uint16 v5; + char v6; // t0 + int16 v7; + int16 v8; + char v9; // t1 + + R18_ = a; + Enemy_DeadMonsters *E = Get_DeadMonsters(k); + if (sign16(E->base.x_pos - 544)) { + HIBYTE(v7) = HIBYTE(R18_); + int full = HIBYTE(E->base.x_subpos) + LOBYTE(R18_); + LOBYTE(v7) = full; + HIBYTE(E->base.x_subpos) = v7; + v7 &= 0xFF00u; + v9 = v7; + LOBYTE(v8) = HIBYTE(v7); + HIBYTE(v8) = v9; + if ((v8 & 0x80) != 0) + v8 |= 0xFF00u; + E->base.x_pos += v8 + (full >> 8); + } else { + uint16 v3 = R18_; + HIBYTE(R18_) = R18_; + LOBYTE(R18_) = 0; + v4 = v3 & 0xFF00; + if (v4 < 0) + v4 |= 0xFFu; + v6 = v4; + LOBYTE(v5) = HIBYTE(v4); + HIBYTE(v5) = v6; + R20_ = v5; + Enemy_MoveRight_IgnoreSlopes(k); + } +} + +void DeadMonsters_Func_5(uint16 k) { // 0xA9DA08 + Enemy_DeadMonsters *E = Get_DeadMonsters(k); + uint16 v2 = E->dms_var_07 + 1; + E->dms_var_07 = v2; + if (v2 >= 8u) { + E->dms_var_07 = 0; + WriteColorsToPalette( + 0x122u, + 0xa9, 32 * (E->dms_var_08 - 1) - 0x1434, + 0xFu); + uint16 v3 = cur_enemy_index; + uint16 v5 = E->dms_var_08 + 1; + E->dms_var_08 = v5; + if (v5 >= 8u) { + Enemy_SetInstrList(v3, addr_kDeadMonsters_Ilist_ECE9); + E->dms_var_A = FUNC16(DeadSidehopper_WaitForSamusColl); + E->base.properties |= 0x8000u; + E->base.y_height = 12; + } + } +} + +void DeadSidehopper_WaitForSamusColl(uint16 k) { // 0xA9DA64 + DeadMonsters_WaitForSamusColl(k, FUNC16(DeadSidehopper_PreRotDelay)); +} + +void DeadZoomer_WaitForSamusColl(uint16 k) { // 0xA9DA69 + DeadMonsters_WaitForSamusColl(k, FUNC16(DeadZoomer_PreRotDelay)); +} + +void DeadSkree_WaitForSamusColl(uint16 k) { // 0xA9DA6E + DeadMonsters_WaitForSamusColl(k, FUNC16(DeadSkree_PreRotDelay)); +} + +void DeadRipper_WaitForSamusColl(uint16 k) { // 0xA9DA73 + DeadMonsters_WaitForSamusColl(k, FUNC16(DeadRipper_PreRotDelay)); +} + +void DeadMonsters_WaitForSamusColl(uint16 k, uint16 j) { // 0xA9DA76 + if (k == enemy_index_colliding_dirs[0] + || k == enemy_index_colliding_dirs[1] + || k == enemy_index_colliding_dirs[2] + || k == enemy_index_colliding_dirs[3]) { + Get_DeadMonsters(k)->dms_var_A = j; + } +} + +void DeadSidehopper_PreRotDelay(uint16 k) { // 0xA9DA8F + DeadMonsters_PreRotDelay_Common(k, FUNC16(DeadSidehopper_Rotting)); +} + +void DeadZoomer_PreRotDelay(uint16 k) { // 0xA9DA94 + DeadMonsters_PreRotDelay_Common(k, FUNC16(DeadZoomer_Rotting)); +} + +void DeadRipper_PreRotDelay(uint16 k) { // 0xA9DA99 + DeadMonsters_PreRotDelay_Common(k, FUNC16(DeadRipper_Rotting)); +} + +void DeadSkree_PreRotDelay(uint16 k) { // 0xA9DA9E + DeadMonsters_PreRotDelay_Common(k, FUNC16(DeadSkree_Rotting)); +} + +void DeadMonsters_PreRotDelay_Common(uint16 k, uint16 j) { // 0xA9DAA1 + Enemy_DeadMonsters *E = Get_DeadMonsters(k); + if (++E->dms_var_B >= 0x10u) { + E->dms_var_A = j; + E->base.properties |= kEnemyProps_Tangible; + } +} + +void DeadSidehopper_Rotting(uint16 k) { // 0xA9DABA + uint8 v1 = ProcessCorpseRotting(k); + if (!(v1 & 1)) + Get_DeadMonsters(cur_enemy_index)->dms_var_A = FUNC16(DeadSidehopper_WaitForSamusColl); + uint16 dms_var_53 = Get_DeadMonsters(cur_enemy_index)->dms_var_53; + ProcessCorpseRottingVramTransfers(dms_var_53); +} + +void DeadZoomer_Rotting(uint16 k) { // 0xA9DAD0 + uint8 v1 = ProcessCorpseRotting(k); + if (!(v1 & 1)) + Get_DeadMonsters(cur_enemy_index)->dms_var_A = FUNC16(nullsub_268); + uint16 dms_var_53 = Get_DeadMonsters(cur_enemy_index)->dms_var_53; + ProcessCorpseRottingVramTransfers(dms_var_53); +} + +void DeadRipper_Rotting(uint16 k) { // 0xA9DAE6 + uint8 v1 = ProcessCorpseRotting(k); + if (!(v1 & 1)) + Get_DeadMonsters(cur_enemy_index)->dms_var_A = FUNC16(nullsub_268); + uint16 dms_var_53 = Get_DeadMonsters(cur_enemy_index)->dms_var_53; + ProcessCorpseRottingVramTransfers(dms_var_53); +} + +void DeadSkree_Rotting(uint16 k) { // 0xA9DAFC + uint8 v1 = ProcessCorpseRotting(k); + if (!(v1 & 1)) + Get_DeadMonsters(cur_enemy_index)->dms_var_A = FUNC16(nullsub_268); + uint16 dms_var_53 = Get_DeadMonsters(cur_enemy_index)->dms_var_53; + ProcessCorpseRottingVramTransfers(dms_var_53); +} + +uint8 ProcessCorpseRotting(uint16 k) { // 0xA9DB12 + int16 *v5; + int16 v7; + int16 v8; + + Enemy_DeadMonsters *EK = Get_DeadMonsters(k); + Enemy_DeadMonsters *E0 = Get_DeadMonsters(0); + E0->dms_var_45 = EK->dms_var_57; + E0->dms_var_46 = EK->dms_var_58; + E0->dms_var_47 = EK->dms_var_59; + E0->dms_var_48 = EK->dms_var_5A; + E0->dms_var_49 = EK->dms_var_5B; + E0->dms_var_44 = EK->dms_var_56; + E0->dms_var_42 = EK->dms_var_54; + E0->dms_var_43 = EK->dms_var_55; + uint16 dms_var_52 = EK->dms_var_52; + uint16 v4 = 0; + uint16 v15; + uint16 *v6; + while (1) { + v15 = v4; + v5 = (int16 *)RomPtr_7E(dms_var_52); + v6 = (uint16 *)v5; + if (*v5 >= 0) + break; +LABEL_12: + dms_var_52 += 4; + v4 = v15 + 1; + E0 = Get_DeadMonsters(0); + if ((int16)(v15 + 1 - E0->dms_var_45) >= 0) + return (uint16)(v15 + 1) >= E0->dms_var_45; + } + v7 = v5[1]; + if (v7) { + v8 = v7 - 1; + v5[1] = v8; + if ((uint16)v8 < 4u) { + E0 = Get_DeadMonsters(0); + R18_ = E0->dms_var_42; + if (v15 >= E0->dms_var_47) + R18_ = E0->dms_var_43; + R20_ = E0->dms_var_44; + R22_ = 169; + CopyMoveCorpseRottingRotEntry(*v6); + } + goto LABEL_12; + } + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + R18_ = E->dms_var_43; + R20_ = E->dms_var_44; + R22_ = 169; + uint16 *v11 = (uint16 *)RomPtr_7E(dms_var_52); + CopyMoveCorpseRottingRotEntry(*v11); + uint16 v12 = *(uint16 *)RomPtr_7E(dms_var_52) + 2; + if (v12 < E->dms_var_46) { +LABEL_11: + *(uint16 *)RomPtr_7E(dms_var_52) = v12; + goto LABEL_12; + } + R18_ = E->dms_var_49; + CallCorpseRottingFinish(R18_ | 0xA90000); + if (v15 < Get_DeadMonsters(0)->dms_var_46) { + v12 = -1; + goto LABEL_11; + } + return 0; +} + +void CopyMoveCorpseRottingRotEntry(uint16 a) { // 0xA9DBE0 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + E->dms_var_41 = a; + uint16 v1 = (uint16)(a & 0xFFF8) >> 2; + uint16 v2 = a & 7; + uint8 *v4 = IndirPtr(&R20_, v1); + if (v2 >= 6u) { + uint16 v6 = *(uint16 *)v4 + 2 * v2; + CallCorpseRottingMove(R18_ | 0xA90000, E->dms_var_48 + v6, v6); + } else { + uint16 v5 = *(uint16 *)v4 + 2 * v2; + CallCorpseRottingMove(R18_ | 0xA90000, v5, v5); + } +} + +void CorpseRottingRotEntryFinishedHook(void) { // 0xA9DC08 + EnemyData *v0 = gEnemyData(cur_enemy_index); + R18_ = v0->x_pos + (random_number & 0x1A) - 14; + R20_ = v0->y_pos + 16; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0xAu); + if ((enemy_damage_routine_exec_count & 7) == 0) + QueueSfx2_Max3(0x10u); +} + +void InitializeCorpseRottingDataTable(uint16 k, uint16 a) { // 0xA9DC40 + int16 v2; + + v2 = a - 1; + R18_ = 0; + do { + *(uint16 *)RomPtr_7E(k) = v2; + uint16 v3 = k + 2; + *(uint16 *)RomPtr_7E(v3) = R18_; + k = v3 + 2; + R18_ += 2; + --v2; + } while (v2 >= 0); +} + +void InitializeEnemyCorpseRotting(uint16 k, uint16 j) { // 0xA9DC5F + uint8 *v2 = RomPtr_A9(j); + Enemy_DeadMonsters *E = Get_DeadMonsters(k); + E->dms_var_52 = *(uint16 *)v2; + E->dms_var_53 = *((uint16 *)v2 + 1); + E->dms_var_54 = *((uint16 *)v2 + 2); + E->dms_var_55 = *((uint16 *)v2 + 3); + E->dms_var_5B = *((uint16 *)v2 + 7); + uint16 v4 = *((uint16 *)v2 + 6); + E->dms_var_56 = v4; + E->dms_var_5A = *((uint16 *)RomPtr_A9(v4) + 1) - 12; + uint16 *v5 = (uint16 *)RomPtr_A9(j); + uint16 v6 = v5[4]; + E->dms_var_57 = v6--; + E->dms_var_58 = v6; + E->dms_var_59 = v6 - 1; + InitializeCorpseRottingDataTable(*v5, v5[4]); + R18_ = v5[5]; + CallCorpseRottingInit(R18_ | 0xA90000); +} + +void ProcessCorpseRottingVramTransfers(uint16 k) { // 0xA9DCB9 + VramWriteEntry *v3; + + uint16 v1 = vram_write_queue_tail; + uint16 v2 = *(uint16 *)RomPtr_A9(k); + do { + v3 = gVramWriteEntry(v1); + v3->size = v2; + uint8 *v4 = RomPtr_A9(k); + *(VoidP *)((char *)&v3->src.addr + 1) = *((uint16 *)v4 + 1); + v3->src.addr = *((uint16 *)v4 + 2); + v3->vram_dst = *((uint16 *)v4 + 3); + v1 += 7; + k += 8; + v2 = *(uint16 *)RomPtr_A9(k); + } while (v2); + Get_DeadEnemy(0)->dey_var_22 = 0; + vram_write_queue_tail = v1; +} + +void DeadZoomer_Powerbomb(void) { // 0xA9DCED + if ((gEnemyData(cur_enemy_index)->properties & kEnemyProps_Tangible) == 0) + DeadZoomer_Shot(); +} + +void DeadZoomer_Shot(void) { // 0xA9DCF8 + DeadSidehopper_DD34(FUNC16(DeadZoomer_Rotting)); +} + +void DeadRipper_Powerbomb(void) { // 0xA9DCFD + if ((gEnemyData(cur_enemy_index)->properties & kEnemyProps_Tangible) == 0) + DeadRipper_Shot(); +} + +void DeadRipper_Shot(void) { // 0xA9DD08 + DeadSidehopper_DD34(FUNC16(DeadRipper_Rotting)); +} + +void DeadSkree_Powerbomb(void) { // 0xA9DD0D + if ((gEnemyData(cur_enemy_index)->properties & kEnemyProps_Tangible) == 0) + DeadSkree_Shot(); +} + +void DeadSkree_Shot(void) { // 0xA9DD18 + DeadSidehopper_DD34(FUNC16(DeadSkree_Rotting)); +} + +void DeadSidehopper_Shot(void) { // 0xA9DD1D + Enemy_DeadSidehopper *E = Get_DeadSidehopper(cur_enemy_index); + if ((E->base.properties & kEnemyProps_Tangible) != 0 || E->dsr_var_08 < 8u) + ; + else + DeadSidehopper_DD31(); +} + +void DeadSidehopper_DD31(void) { // 0xA9DD31 + DeadSidehopper_DD34(FUNC16(DeadSidehopper_Rotting)); +} + +void DeadSidehopper_DD34(uint16 a) { // 0xA9DD34 + Enemy_DeadSidehopper *E = Get_DeadSidehopper(cur_enemy_index); + E->dsr_var_A = a; + E->base.properties |= kEnemyProps_ProcessedOffscreen | kEnemyProps_Tangible; +} + +void DeadSidehopper_Touch(void) { // 0xA9DD44 + if (Get_DeadSidehopper(cur_enemy_index)->dsr_var_08 < 8u) + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); + else + DeadSidehopper_DD31(); +} + +void Torizo_CorpseRottingInitFunc(void) { // 0xA9DE18 + uint8 *v0 = RomPtr_7E(0x2060u); + uint8 *v1 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__288); + MemCpy(v0, v1, 0xC0u); + uint8 *v2 = RomPtr_7E(0x21A0u); + uint8 *v3 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__800); + MemCpy(v2, v3, 0xC0u); + uint8 *v4 = RomPtr_7E(0x22C0u); + uint8 *v5 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__1280); + MemCpy(v4, v5, 0x100u); + uint8 *v6 = RomPtr_7E(0x2400u); + uint8 *v7 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__1792); + MemCpy(v6, v7, 0x100u); + uint8 *v8 = RomPtr_7E(0x2540u); + uint8 *v9 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__2304); + MemCpy(v8, v9, 0x100u); + uint8 *v10 = RomPtr_7E(0x2680u); + uint8 *v11 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__2816); + MemCpy(v10, v11, 0x100u); + uint8 *v12 = RomPtr_7E(0x27C0u); + uint8 *v13 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__3328); + MemCpy(v12, v13, 0x100u); + uint8 *v14 = RomPtr_7E(0x2900u); + uint8 *v15 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__3840); + MemCpy(v14, v15, 0x100u); + uint8 *v16 = RomPtr_7E(0x2A40u); + uint8 *v17 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__4352); + MemCpy(v16, v17, 0x100u); + uint8 *v18 = RomPtr_7E(0x2B60u); + uint8 *v19 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__4832); + MemCpy(v18, v19, 0x120u); + uint8 *v20 = RomPtr_7E(0x2C80u); + uint8 *v21 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__5312); + MemCpy(v20, v21, 0x140u); + uint8 *v22 = RomPtr_7E(0x2DC0u); + uint8 *v23 = RomPtr_B7(addr_kDeadTorizo_TileData__plus__5824); + MemCpy(v22, v23, 0x140u); +} + +void Sidehopper_CorpseRottingInitFunc_0(void) { // 0xA9DEC1 + uint8 *v0 = RomPtr_7E(0x2040u); + uint8 *v1 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__64); + MemCpy(v0, v1, 0x60u); + uint8 *v2 = RomPtr_7E(0x20A0u); + uint8 *v3 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__512); + MemCpy(v2, v3, 0xA0u); + uint8 *v4 = RomPtr_7E(0x2140u); + uint8 *v5 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__1024); + MemCpy(v4, v5, 0xA0u); + uint8 *v6 = RomPtr_7E(0x21E0u); + uint8 *v7 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__1536); + MemCpy(v6, v7, 0xA0u); + uint8 *v8 = RomPtr_7E(0x2280u); + uint8 *v9 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__2048); + MemCpy(v8, v9, 0xA0u); +} + +void Sidehopper_CorpseRottingInitFunc_2(void) { // 0xA9DF08 + uint8 *v0 = RomPtr_7E(0x2320u); + uint8 *v1 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__288); + MemCpy(v0, v1, 0x40u); + uint8 *v2 = RomPtr_7E(0x23C0u); + uint8 *v3 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__800); + MemCpy(v2, v3, 0xA0u); + uint8 *v4 = RomPtr_7E(0x2460u); + uint8 *v5 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__1312); + MemCpy(v4, v5, 0xA0u); + uint8 *v6 = RomPtr_7E(0x2500u); + uint8 *v7 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__1824); + MemCpy(v6, v7, 0xA0u); + uint8 *v8 = RomPtr_7E(0x25A0u); + uint8 *v9 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__2336); + MemCpy(v8, v9, 0xA0u); +} + +void Zoomer_CorpseRottingInitFunc_0(void) { // 0xA9DF4F + uint8 *v0 = RomPtr_7E(0x2940u); + uint8 *v1 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__2656); + MemCpy(v0, v1, 0x60u); + uint8 *v2 = RomPtr_7E(0x29A0u); + uint8 *v3 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__3168); + MemCpy(v2, v3, 0x60u); +} + +void Zoomer_CorpseRottingInitFunc_2(void) { // 0xA9DF6C + uint8 *v0 = RomPtr_7E(0x2A00u); + uint8 *v1 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__2752); + MemCpy(v0, v1, 0x60u); + uint8 *v2 = RomPtr_7E(0x2A60u); + uint8 *v3 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__3264); + MemCpy(v2, v3, 0x60u); +} + +void Zoomer_CorpseRottingInitFunc_4(void) { // 0xA9DF89 + uint8 *v0 = RomPtr_7E(0x2AC0u); + uint8 *v1 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__2848); + MemCpy(v0, v1, 0x60u); + uint8 *v2 = RomPtr_7E(0x2B20u); + uint8 *v3 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__3360); + MemCpy(v2, v3, 0x60u); +} + +void Ripper_CorpseRottingInitFunc_0(void) { // 0xA9DFA6 + uint8 *v0 = RomPtr_7E(0x2B80u); + uint8 *v1 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__2560); + MemCpy(v0, v1, 0x60u); + uint8 *v2 = RomPtr_7E(0x2BE0u); + uint8 *v3 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__3072); + MemCpy(v2, v3, 0x60u); +} + +void Ripper_CorpseRottingInitFunc_2(void) { // 0xA9DFC3 + uint8 *v0 = RomPtr_7E(0x2C40u); + uint8 *v1 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__2944); + MemCpy(v0, v1, 0x60u); + uint8 *v2 = RomPtr_7E(0x2CA0u); + uint8 *v3 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__3456); + MemCpy(v2, v3, 0x60u); +} + +void Skree_CorpseRottingInitFunc_0(void) { // 0xA9DFE0 + uint8 *v0 = RomPtr_7E(0x2640u); + uint8 *v1 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__672); + MemCpy(v0, v1, 0x40u); + uint8 *v2 = RomPtr_7E(0x2680u); + uint8 *v3 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__1184); + MemCpy(v2, v3, 0x40u); + uint8 *v4 = RomPtr_7E(0x26C0u); + uint8 *v5 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__1696); + MemCpy(v4, v5, 0x40u); + uint8 *v6 = RomPtr_7E(0x2700u); + uint8 *v7 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__2208); + MemCpy(v6, v7, 0x40u); +} + +void Skree_CorpseRottingInitFunc_2(void) { // 0xA9E019 + uint8 *v0 = RomPtr_7E(0x2740u); + uint8 *v1 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__224); + MemCpy(v0, v1, 0x40u); + uint8 *v2 = RomPtr_7E(0x2780u); + uint8 *v3 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__736); + MemCpy(v2, v3, 0x40u); + uint8 *v4 = RomPtr_7E(0x27C0u); + uint8 *v5 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__1248); + MemCpy(v4, v5, 0x40u); + uint8 *v6 = RomPtr_7E(0x2800u); + uint8 *v7 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__1760); + MemCpy(v6, v7, 0x40u); +} + +void Skree_CorpseRottingInitFunc_4(void) { // 0xA9E052 + uint8 *v0 = RomPtr_7E(0x2840u); + uint8 *v1 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__448); + MemCpy(v0, v1, 0x40u); + uint8 *v2 = RomPtr_7E(0x2880u); + uint8 *v3 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__960); + MemCpy(v2, v3, 0x40u); + uint8 *v4 = RomPtr_7E(0x28C0u); + uint8 *v5 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__1472); + MemCpy(v4, v5, 0x40u); + uint8 *v6 = RomPtr_7E(0x2900u); + uint8 *v7 = RomPtr_B7(addr_kDeadMonsters_TileData__plus__1984); + MemCpy(v6, v7, 0x40u); +} + +void MotherBrain_CorpseRottingInitFunc(void) { // 0xA9E08B + uint8 *v0 = RomPtr_7E(0x9000u); + uint8 *v1 = RomPtr_B7(addr_kMotherBrain_Misc_TileData__plus__192); + MemCpy(v0, v1, 0xC0u); + uint8 *v2 = RomPtr_7E(0x90E0u); + uint8 *v3 = RomPtr_B7(addr_kMotherBrain_Misc_TileData__plus__704); + MemCpy(v2, v3, 0xC0u); + uint8 *v4 = RomPtr_7E(0x91C0u); + uint8 *v5 = RomPtr_B7(addr_kMotherBrain_Misc_TileData__plus__1216); + MemCpy(v4, v5, 0xC0u); + uint8 *v6 = RomPtr_7E(0x92A0u); + uint8 *v7 = RomPtr_B7(addr_kMotherBrain_Misc_TileData__plus__1728); + MemCpy(v6, v7, 0xC0u); + uint8 *v8 = RomPtr_7E(0x9380u); + uint8 *v9 = RomPtr_B7(addr_kMotherBrain_Misc_TileData__plus__2240); + MemCpy(v8, v9, 0xE0u); + uint8 *v10 = RomPtr_7E(0x9460u); + uint8 *v11 = RomPtr_B7(addr_kMotherBrain_Misc_TileData__plus__2752); + MemCpy(v10, v11, 0xE0u); +} + +void Torizo_CorpseRottingMoveFunc(uint16 j, uint16 k) { // 0xA9E272 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (E->dms_var_41 >= 0x50u) { + if (sign16(E->dms_var_41 - 94)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1] = tilemap_stuff[v3]; + tilemap_stuff[v4 + 9] = tilemap_stuff[v3 + 8]; + } + int v5 = k >> 1; + tilemap_stuff[v5] = 0; + tilemap_stuff[v5 + 8] = 0; + } + if (E->dms_var_41 >= 0x48u) { + if (sign16(E->dms_var_41 - 94)) { + int v6 = k >> 1; + int v7 = j >> 1; + tilemap_stuff[v7 + 17] = tilemap_stuff[v6 + 16]; + tilemap_stuff[v7 + 25] = tilemap_stuff[v6 + 24]; + } + int v8 = k >> 1; + tilemap_stuff[v8 + 16] = 0; + tilemap_stuff[v8 + 24] = 0; + } + if (E->dms_var_41 >= 0x10u) { + if (sign16(E->dms_var_41 - 94)) { + int v9 = k >> 1; + int v10 = j >> 1; + tilemap_stuff[v10 + 33] = tilemap_stuff[v9 + 32]; + tilemap_stuff[v10 + 41] = tilemap_stuff[v9 + 40]; + } + int v11 = k >> 1; + tilemap_stuff[v11 + 32] = 0; + tilemap_stuff[v11 + 40] = 0; + } + if (sign16(E->dms_var_41 - 94)) { + int v12 = k >> 1; + int v13 = j >> 1; + tilemap_stuff[v13 + 49] = tilemap_stuff[v12 + 48]; + tilemap_stuff[v13 + 57] = tilemap_stuff[v12 + 56]; + } + int v14 = k >> 1; + tilemap_stuff[v14 + 48] = 0; + tilemap_stuff[v14 + 56] = 0; + if (sign16(E->dms_var_41 - 94)) { + int v15 = j >> 1; + tilemap_stuff[v15 + 65] = tilemap_stuff[v14 + 64]; + tilemap_stuff[v15 + 73] = tilemap_stuff[v14 + 72]; + } + tilemap_stuff[v14 + 64] = 0; + tilemap_stuff[v14 + 72] = 0; + if (sign16(E->dms_var_41 - 94)) { + int v16 = j >> 1; + tilemap_stuff[v16 + 81] = tilemap_stuff[v14 + 80]; + tilemap_stuff[v16 + 89] = tilemap_stuff[v14 + 88]; + } + tilemap_stuff[v14 + 80] = 0; + tilemap_stuff[v14 + 88] = 0; + if (sign16(E->dms_var_41 - 94)) { + int v17 = j >> 1; + tilemap_stuff[v17 + 97] = tilemap_stuff[v14 + 96]; + tilemap_stuff[v17 + 105] = tilemap_stuff[v14 + 104]; + } + tilemap_stuff[v14 + 96] = 0; + tilemap_stuff[v14 + 104] = 0; + if (sign16(E->dms_var_41 - 94)) { + int v18 = j >> 1; + tilemap_stuff[v18 + 113] = tilemap_stuff[v14 + 112]; + tilemap_stuff[v18 + 121] = tilemap_stuff[v14 + 120]; + } + tilemap_stuff[v14 + 112] = 0; + tilemap_stuff[v14 + 120] = 0; + if (sign16(E->dms_var_41 - 94)) { + int v19 = j >> 1; + tilemap_stuff[v19 + 129] = tilemap_stuff[v14 + 128]; + tilemap_stuff[v19 + 137] = tilemap_stuff[v14 + 136]; + } + tilemap_stuff[v14 + 128] = 0; + tilemap_stuff[v14 + 136] = 0; + if (E->dms_var_41 >= 0x10u) { + if (sign16(E->dms_var_41 - 94)) { + int v20 = j >> 1; + tilemap_stuff[v20 + 145] = tilemap_stuff[v14 + 144]; + tilemap_stuff[v20 + 153] = tilemap_stuff[v14 + 152]; + } + tilemap_stuff[v14 + 144] = 0; + tilemap_stuff[v14 + 152] = 0; + } +} + +void Torizo_CorpseRottingCopyFunc(uint16 j, uint16 k) { // 0xA9E38B + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (E->dms_var_41 >= 0x50u && sign16(E->dms_var_41 - 94)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1] = tilemap_stuff[v3]; + tilemap_stuff[v4 + 9] = tilemap_stuff[v3 + 8]; + } + if (E->dms_var_41 >= 0x48u && sign16(E->dms_var_41 - 94)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 17] = tilemap_stuff[v5 + 16]; + tilemap_stuff[v6 + 25] = tilemap_stuff[v5 + 24]; + } + if (E->dms_var_41 >= 0x10u && sign16(E->dms_var_41 - 94)) { + int v7 = k >> 1; + int v8 = j >> 1; + tilemap_stuff[v8 + 33] = tilemap_stuff[v7 + 32]; + tilemap_stuff[v8 + 41] = tilemap_stuff[v7 + 40]; + } + if (sign16(E->dms_var_41 - 94)) { + int v9 = k >> 1; + int v10 = j >> 1; + tilemap_stuff[v10 + 49] = tilemap_stuff[v9 + 48]; + tilemap_stuff[v10 + 57] = tilemap_stuff[v9 + 56]; + } + if (sign16(E->dms_var_41 - 94)) { + int v11 = k >> 1; + int v12 = j >> 1; + tilemap_stuff[v12 + 65] = tilemap_stuff[v11 + 64]; + tilemap_stuff[v12 + 73] = tilemap_stuff[v11 + 72]; + } + if (sign16(E->dms_var_41 - 94)) { + int v13 = k >> 1; + int v14 = j >> 1; + tilemap_stuff[v14 + 81] = tilemap_stuff[v13 + 80]; + tilemap_stuff[v14 + 89] = tilemap_stuff[v13 + 88]; + } + if (sign16(E->dms_var_41 - 94)) { + int v15 = k >> 1; + int v16 = j >> 1; + tilemap_stuff[v16 + 97] = tilemap_stuff[v15 + 96]; + tilemap_stuff[v16 + 105] = tilemap_stuff[v15 + 104]; + } + if (sign16(E->dms_var_41 - 94)) { + int v17 = k >> 1; + int v18 = j >> 1; + tilemap_stuff[v18 + 113] = tilemap_stuff[v17 + 112]; + tilemap_stuff[v18 + 121] = tilemap_stuff[v17 + 120]; + } + if (sign16(E->dms_var_41 - 94)) { + int v19 = k >> 1; + int v20 = j >> 1; + tilemap_stuff[v20 + 129] = tilemap_stuff[v19 + 128]; + tilemap_stuff[v20 + 137] = tilemap_stuff[v19 + 136]; + } + if (E->dms_var_41 >= 0x10u) { + if (sign16(E->dms_var_41 - 94)) { + int v21 = k >> 1; + int v22 = j >> 1; + tilemap_stuff[v22 + 145] = tilemap_stuff[v21 + 144]; + tilemap_stuff[v22 + 153] = tilemap_stuff[v21 + 152]; + } + } +} + +void Sidehopper_CorpseRottingMoveFunc_0(uint16 j, uint16 k) { // 0xA9E468 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (E->dms_var_41 >= 8u) { + if (sign16(E->dms_var_41 - 38)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1] = tilemap_stuff[v3]; + tilemap_stuff[v4 + 9] = tilemap_stuff[v3 + 8]; + } + int v5 = k >> 1; + tilemap_stuff[v5] = 0; + tilemap_stuff[v5 + 8] = 0; + } + if (E->dms_var_41 >= 8u) { + if (sign16(E->dms_var_41 - 38)) { + int v6 = k >> 1; + int v7 = j >> 1; + tilemap_stuff[v7 + 17] = tilemap_stuff[v6 + 16]; + tilemap_stuff[v7 + 25] = tilemap_stuff[v6 + 24]; + } + int v8 = k >> 1; + tilemap_stuff[v8 + 16] = 0; + tilemap_stuff[v8 + 24] = 0; + } + if (sign16(E->dms_var_41 - 38)) { + int v9 = k >> 1; + int v10 = j >> 1; + tilemap_stuff[v10 + 33] = tilemap_stuff[v9 + 32]; + tilemap_stuff[v10 + 41] = tilemap_stuff[v9 + 40]; + } + int v11 = k >> 1; + tilemap_stuff[v11 + 32] = 0; + tilemap_stuff[v11 + 40] = 0; + if (sign16(E->dms_var_41 - 38)) { + int v12 = j >> 1; + tilemap_stuff[v12 + 49] = tilemap_stuff[v11 + 48]; + tilemap_stuff[v12 + 57] = tilemap_stuff[v11 + 56]; + } + tilemap_stuff[v11 + 48] = 0; + tilemap_stuff[v11 + 56] = 0; + if (sign16(E->dms_var_41 - 38)) { + int v13 = j >> 1; + tilemap_stuff[v13 + 65] = tilemap_stuff[v11 + 64]; + tilemap_stuff[v13 + 73] = tilemap_stuff[v11 + 72]; + } + tilemap_stuff[v11 + 64] = 0; + tilemap_stuff[v11 + 72] = 0; +} + +void Sidehopper_CorpseRottingCopyFunc_0(uint16 j, uint16 k) { // 0xA9E4F5 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (E->dms_var_41 >= 8u && sign16(E->dms_var_41 - 38)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1] = tilemap_stuff[v3]; + tilemap_stuff[v4 + 9] = tilemap_stuff[v3 + 8]; + } + if (E->dms_var_41 >= 8u && sign16(E->dms_var_41 - 38)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 17] = tilemap_stuff[v5 + 16]; + tilemap_stuff[v6 + 25] = tilemap_stuff[v5 + 24]; + } + if (sign16(E->dms_var_41 - 38)) { + int v7 = k >> 1; + int v8 = j >> 1; + tilemap_stuff[v8 + 33] = tilemap_stuff[v7 + 32]; + tilemap_stuff[v8 + 41] = tilemap_stuff[v7 + 40]; + } + if (sign16(E->dms_var_41 - 38)) { + int v9 = k >> 1; + int v10 = j >> 1; + tilemap_stuff[v10 + 49] = tilemap_stuff[v9 + 48]; + tilemap_stuff[v10 + 57] = tilemap_stuff[v9 + 56]; + } + if (sign16(E->dms_var_41 - 38)) { + int v11 = k >> 1; + int v12 = j >> 1; + tilemap_stuff[v12 + 65] = tilemap_stuff[v11 + 64]; + tilemap_stuff[v12 + 73] = tilemap_stuff[v11 + 72]; + } +} + +void Sidehopper_CorpseRottingMoveFunc_2(uint16 j, uint16 k) { // 0xA9E564 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 38)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 401] = tilemap_stuff[v3 + 400]; + tilemap_stuff[v4 + 409] = tilemap_stuff[v3 + 408]; + } + int v5 = k >> 1; + tilemap_stuff[v5 + 400] = 0; + tilemap_stuff[v5 + 408] = 0; + if (sign16(E->dms_var_41 - 38)) { + int v6 = j >> 1; + tilemap_stuff[v6 + 417] = tilemap_stuff[v5 + 416]; + tilemap_stuff[v6 + 425] = tilemap_stuff[v5 + 424]; + } + tilemap_stuff[v5 + 416] = 0; + tilemap_stuff[v5 + 424] = 0; + if (E->dms_var_41 >= 8u) { + if (sign16(E->dms_var_41 - 38)) { + int v7 = j >> 1; + tilemap_stuff[v7 + 433] = tilemap_stuff[v5 + 432]; + tilemap_stuff[v7 + 441] = tilemap_stuff[v5 + 440]; + } + tilemap_stuff[v5 + 432] = 0; + tilemap_stuff[v5 + 440] = 0; + } + if (E->dms_var_41 >= 8u) { + if (sign16(E->dms_var_41 - 38)) { + int v8 = j >> 1; + tilemap_stuff[v8 + 449] = tilemap_stuff[v5 + 448]; + tilemap_stuff[v8 + 457] = tilemap_stuff[v5 + 456]; + } + tilemap_stuff[v5 + 448] = 0; + tilemap_stuff[v5 + 456] = 0; + } + if (E->dms_var_41 >= 8u) { + if (sign16(E->dms_var_41 - 38)) { + int v9 = j >> 1; + tilemap_stuff[v9 + 465] = tilemap_stuff[v5 + 464]; + tilemap_stuff[v9 + 473] = tilemap_stuff[v5 + 472]; + } + tilemap_stuff[v5 + 464] = 0; + tilemap_stuff[v5 + 472] = 0; + } +} + +void Sidehopper_CorpseRottingCopyFunc_2(uint16 j, uint16 k) { // 0xA9E5F6 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 38)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 401] = tilemap_stuff[v3 + 400]; + tilemap_stuff[v4 + 409] = tilemap_stuff[v3 + 408]; + } + if (sign16(E->dms_var_41 - 38)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 417] = tilemap_stuff[v5 + 416]; + tilemap_stuff[v6 + 425] = tilemap_stuff[v5 + 424]; + } + if (E->dms_var_41 >= 8u && sign16(E->dms_var_41 - 38)) { + int v7 = k >> 1; + int v8 = j >> 1; + tilemap_stuff[v8 + 433] = tilemap_stuff[v7 + 432]; + tilemap_stuff[v8 + 441] = tilemap_stuff[v7 + 440]; + } + if (E->dms_var_41 >= 8u && sign16(E->dms_var_41 - 38)) { + int v9 = k >> 1; + int v10 = j >> 1; + tilemap_stuff[v10 + 449] = tilemap_stuff[v9 + 448]; + tilemap_stuff[v10 + 457] = tilemap_stuff[v9 + 456]; + } + if (E->dms_var_41 >= 8u) { + if (sign16(E->dms_var_41 - 38)) { + int v11 = k >> 1; + int v12 = j >> 1; + tilemap_stuff[v12 + 465] = tilemap_stuff[v11 + 464]; + tilemap_stuff[v12 + 473] = tilemap_stuff[v11 + 472]; + } + } +} + +void Zoomer_CorpseRottingMoveFunc_0(uint16 j, uint16 k) { // 0xA9E66A + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 14)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1185] = tilemap_stuff[v3 + 1184]; + tilemap_stuff[v4 + 1193] = tilemap_stuff[v3 + 1192]; + } + int v5 = k >> 1; + tilemap_stuff[v5 + 1184] = 0; + tilemap_stuff[v5 + 1192] = 0; + if (sign16(E->dms_var_41 - 14)) { + int v6 = j >> 1; + tilemap_stuff[v6 + 1201] = tilemap_stuff[v5 + 1200]; + tilemap_stuff[v6 + 1209] = tilemap_stuff[v5 + 1208]; + } + tilemap_stuff[v5 + 1200] = 0; + tilemap_stuff[v5 + 1208] = 0; + if (sign16(E->dms_var_41 - 14)) { + int v7 = j >> 1; + tilemap_stuff[v7 + 1217] = tilemap_stuff[v5 + 1216]; + tilemap_stuff[v7 + 1225] = tilemap_stuff[v5 + 1224]; + } + tilemap_stuff[v5 + 1216] = 0; + tilemap_stuff[v5 + 1224] = 0; +} + +void Zoomer_CorpseRottingCopyFunc_0(uint16 j, uint16 k) { // 0xA9E6B9 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 14)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1185] = tilemap_stuff[v3 + 1184]; + tilemap_stuff[v4 + 1193] = tilemap_stuff[v3 + 1192]; + } + if (sign16(E->dms_var_41 - 14)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 1201] = tilemap_stuff[v5 + 1200]; + tilemap_stuff[v6 + 1209] = tilemap_stuff[v5 + 1208]; + } + if (sign16(E->dms_var_41 - 14)) { + int v7 = k >> 1; + int v8 = j >> 1; + tilemap_stuff[v8 + 1217] = tilemap_stuff[v7 + 1216]; + tilemap_stuff[v8 + 1225] = tilemap_stuff[v7 + 1224]; + } +} + +void Zoomer_CorpseRottingMoveFunc_2(uint16 j, uint16 k) { // 0xA9E6F6 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 14)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1281] = tilemap_stuff[v3 + 1280]; + tilemap_stuff[v4 + 1289] = tilemap_stuff[v3 + 1288]; + } + int v5 = k >> 1; + tilemap_stuff[v5 + 1280] = 0; + tilemap_stuff[v5 + 1288] = 0; + if (sign16(E->dms_var_41 - 14)) { + int v6 = j >> 1; + tilemap_stuff[v6 + 1297] = tilemap_stuff[v5 + 1296]; + tilemap_stuff[v6 + 1305] = tilemap_stuff[v5 + 1304]; + } + tilemap_stuff[v5 + 1296] = 0; + tilemap_stuff[v5 + 1304] = 0; + if (sign16(E->dms_var_41 - 14)) { + int v7 = j >> 1; + tilemap_stuff[v7 + 1313] = tilemap_stuff[v5 + 1312]; + tilemap_stuff[v7 + 1321] = tilemap_stuff[v5 + 1320]; + } + tilemap_stuff[v5 + 1312] = 0; + tilemap_stuff[v5 + 1320] = 0; +} + +void Zoomer_CorpseRottingCopyFunc_2(uint16 j, uint16 k) { // 0xA9E745 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 14)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1281] = tilemap_stuff[v3 + 1280]; + tilemap_stuff[v4 + 1289] = tilemap_stuff[v3 + 1288]; + } + if (sign16(E->dms_var_41 - 14)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 1297] = tilemap_stuff[v5 + 1296]; + tilemap_stuff[v6 + 1305] = tilemap_stuff[v5 + 1304]; + } + if (sign16(E->dms_var_41 - 14)) { + int v7 = k >> 1; + int v8 = j >> 1; + tilemap_stuff[v8 + 1313] = tilemap_stuff[v7 + 1312]; + tilemap_stuff[v8 + 1321] = tilemap_stuff[v7 + 1320]; + } +} + +void Zoomer_CorpseRottingMoveFunc_4(uint16 j, uint16 k) { // 0xA9E782 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 14)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1377] = tilemap_stuff[v3 + 1376]; + tilemap_stuff[v4 + 1385] = tilemap_stuff[v3 + 1384]; + } + int v5 = k >> 1; + tilemap_stuff[v5 + 1376] = 0; + tilemap_stuff[v5 + 1384] = 0; + if (sign16(E->dms_var_41 - 14)) { + int v6 = j >> 1; + tilemap_stuff[v6 + 1393] = tilemap_stuff[v5 + 1392]; + tilemap_stuff[v6 + 1401] = tilemap_stuff[v5 + 1400]; + } + tilemap_stuff[v5 + 1392] = 0; + tilemap_stuff[v5 + 1400] = 0; + if (sign16(E->dms_var_41 - 14)) { + int v7 = j >> 1; + tilemap_stuff[v7 + 1409] = tilemap_stuff[v5 + 1408]; + tilemap_stuff[v7 + 1417] = tilemap_stuff[v5 + 1416]; + } + tilemap_stuff[v5 + 1408] = 0; + tilemap_stuff[v5 + 1416] = 0; +} + +void Zoomer_CorpseRottingCopyFunc_4(uint16 j, uint16 k) { // 0xA9E7D1 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 14)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1377] = tilemap_stuff[v3 + 1376]; + tilemap_stuff[v4 + 1385] = tilemap_stuff[v3 + 1384]; + } + if (sign16(E->dms_var_41 - 14)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 1393] = tilemap_stuff[v5 + 1392]; + tilemap_stuff[v6 + 1401] = tilemap_stuff[v5 + 1400]; + } + if (sign16(E->dms_var_41 - 14)) { + int v7 = k >> 1; + int v8 = j >> 1; + tilemap_stuff[v8 + 1409] = tilemap_stuff[v7 + 1408]; + tilemap_stuff[v8 + 1417] = tilemap_stuff[v7 + 1416]; + } +} + +void Ripper_CorpseRottingMoveFunc_0(uint16 j, uint16 k) { // 0xA9E80E + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 14)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1473] = tilemap_stuff[v3 + 1472]; + tilemap_stuff[v4 + 1481] = tilemap_stuff[v3 + 1480]; + } + int v5 = k >> 1; + tilemap_stuff[v5 + 1472] = 0; + tilemap_stuff[v5 + 1480] = 0; + if (sign16(E->dms_var_41 - 14)) { + int v6 = j >> 1; + tilemap_stuff[v6 + 1489] = tilemap_stuff[v5 + 1488]; + tilemap_stuff[v6 + 1497] = tilemap_stuff[v5 + 1496]; + } + tilemap_stuff[v5 + 1488] = 0; + tilemap_stuff[v5 + 1496] = 0; + if (sign16(E->dms_var_41 - 14)) { + int v7 = j >> 1; + tilemap_stuff[v7 + 1505] = tilemap_stuff[v5 + 1504]; + tilemap_stuff[v7 + 1513] = tilemap_stuff[v5 + 1512]; + } + tilemap_stuff[v5 + 1504] = 0; + tilemap_stuff[v5 + 1512] = 0; +} + +void Ripper_CorpseRottingCopyFunc_0(uint16 j, uint16 k) { // 0xA9E85D + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 14)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1473] = tilemap_stuff[v3 + 1472]; + tilemap_stuff[v4 + 1481] = tilemap_stuff[v3 + 1480]; + } + if (sign16(E->dms_var_41 - 14)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 1489] = tilemap_stuff[v5 + 1488]; + tilemap_stuff[v6 + 1497] = tilemap_stuff[v5 + 1496]; + } + if (sign16(E->dms_var_41 - 14)) { + int v7 = k >> 1; + int v8 = j >> 1; + tilemap_stuff[v8 + 1505] = tilemap_stuff[v7 + 1504]; + tilemap_stuff[v8 + 1513] = tilemap_stuff[v7 + 1512]; + } +} + +void Ripper_CorpseRottingMoveFunc_2(uint16 j, uint16 k) { // 0xA9E89A + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 14)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1569] = tilemap_stuff[v3 + 1568]; + tilemap_stuff[v4 + 1577] = tilemap_stuff[v3 + 1576]; + } + int v5 = k >> 1; + tilemap_stuff[v5 + 1568] = 0; + tilemap_stuff[v5 + 1576] = 0; + if (sign16(E->dms_var_41 - 14)) { + int v6 = j >> 1; + tilemap_stuff[v6 + 1585] = tilemap_stuff[v5 + 1584]; + tilemap_stuff[v6 + 1593] = tilemap_stuff[v5 + 1592]; + } + tilemap_stuff[v5 + 1584] = 0; + tilemap_stuff[v5 + 1592] = 0; + if (sign16(E->dms_var_41 - 14)) { + int v7 = j >> 1; + tilemap_stuff[v7 + 1601] = tilemap_stuff[v5 + 1600]; + tilemap_stuff[v7 + 1609] = tilemap_stuff[v5 + 1608]; + } + tilemap_stuff[v5 + 1600] = 0; + tilemap_stuff[v5 + 1608] = 0; +} + +void Ripper_CorpseRottingCopyFunc_2(uint16 j, uint16 k) { // 0xA9E8E9 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 14)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1569] = tilemap_stuff[v3 + 1568]; + tilemap_stuff[v4 + 1577] = tilemap_stuff[v3 + 1576]; + } + if (sign16(E->dms_var_41 - 14)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 1585] = tilemap_stuff[v5 + 1584]; + tilemap_stuff[v6 + 1593] = tilemap_stuff[v5 + 1592]; + } + if (sign16(E->dms_var_41 - 14)) { + int v7 = k >> 1; + int v8 = j >> 1; + tilemap_stuff[v8 + 1601] = tilemap_stuff[v7 + 1600]; + tilemap_stuff[v8 + 1609] = tilemap_stuff[v7 + 1608]; + } +} + +void Skree_CorpseRottingMoveFunc_0(uint16 j, uint16 k) { // 0xA9E926 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 30)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 801] = tilemap_stuff[v3 + 800]; + tilemap_stuff[v4 + 809] = tilemap_stuff[v3 + 808]; + } + int v5 = k >> 1; + tilemap_stuff[v5 + 800] = 0; + tilemap_stuff[v5 + 808] = 0; + if (sign16(E->dms_var_41 - 30)) { + int v6 = j >> 1; + tilemap_stuff[v6 + 817] = tilemap_stuff[v5 + 816]; + tilemap_stuff[v6 + 825] = tilemap_stuff[v5 + 824]; + } + tilemap_stuff[v5 + 816] = 0; + tilemap_stuff[v5 + 824] = 0; +} + +void Skree_CorpseRottingCopyFunc_0(uint16 j, uint16 k) { // 0xA9E95B + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 30)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 801] = tilemap_stuff[v3 + 800]; + tilemap_stuff[v4 + 809] = tilemap_stuff[v3 + 808]; + } + if (sign16(E->dms_var_41 - 30)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 817] = tilemap_stuff[v5 + 816]; + tilemap_stuff[v6 + 825] = tilemap_stuff[v5 + 824]; + } +} + +void Skree_CorpseRottingMoveFunc_2(uint16 j, uint16 k) { // 0xA9E984 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 30)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 929] = tilemap_stuff[v3 + 928]; + tilemap_stuff[v4 + 937] = tilemap_stuff[v3 + 936]; + } + int v5 = k >> 1; + tilemap_stuff[v5 + 928] = 0; + tilemap_stuff[v5 + 936] = 0; + if (sign16(E->dms_var_41 - 30)) { + int v6 = j >> 1; + tilemap_stuff[v6 + 945] = tilemap_stuff[v5 + 944]; + tilemap_stuff[v6 + 953] = tilemap_stuff[v5 + 952]; + } + tilemap_stuff[v5 + 944] = 0; + tilemap_stuff[v5 + 952] = 0; +} + +void Skree_CorpseRottingCopyFunc_2(uint16 j, uint16 k) { // 0xA9E9B9 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 30)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 929] = tilemap_stuff[v3 + 928]; + tilemap_stuff[v4 + 937] = tilemap_stuff[v3 + 936]; + } + if (sign16(E->dms_var_41 - 30)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 945] = tilemap_stuff[v5 + 944]; + tilemap_stuff[v6 + 953] = tilemap_stuff[v5 + 952]; + } +} + +void Skree_CorpseRottingMoveFunc_4(uint16 j, uint16 k) { // 0xA9E9E2 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 30)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1057] = tilemap_stuff[v3 + 1056]; + tilemap_stuff[v4 + 1065] = tilemap_stuff[v3 + 1064]; + } + int v5 = k >> 1; + tilemap_stuff[v5 + 1056] = 0; + tilemap_stuff[v5 + 1064] = 0; + if (sign16(E->dms_var_41 - 30)) { + int v6 = j >> 1; + tilemap_stuff[v6 + 1073] = tilemap_stuff[v5 + 1072]; + tilemap_stuff[v6 + 1081] = tilemap_stuff[v5 + 1080]; + } + tilemap_stuff[v5 + 1072] = 0; + tilemap_stuff[v5 + 1080] = 0; +} + +void Skree_CorpseRottingCopyFunc_4(uint16 j, uint16 k) { // 0xA9EA17 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (sign16(E->dms_var_41 - 30)) { + int v3 = k >> 1; + int v4 = j >> 1; + tilemap_stuff[v4 + 1057] = tilemap_stuff[v3 + 1056]; + tilemap_stuff[v4 + 1065] = tilemap_stuff[v3 + 1064]; + } + if (sign16(E->dms_var_41 - 30)) { + int v5 = k >> 1; + int v6 = j >> 1; + tilemap_stuff[v6 + 1073] = tilemap_stuff[v5 + 1072]; + tilemap_stuff[v6 + 1081] = tilemap_stuff[v5 + 1080]; + } +} + +void MotherBrain_CorpseRottingMoveFunc(uint16 j, uint16 k) { // 0xA9EA40 + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (E->dms_var_41 >= 0x10u) { + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E9002 + j) = *(uint16 *)((char *)&kraid_unk9000 + k); + *(uint16 *)((char *)&g_word_7E9012 + j) = *(uint16 *)((char *)&g_word_7E900F + k + 1); + } + *(uint16 *)((char *)&kraid_unk9000 + k) = 0; + *(uint16 *)((char *)&g_word_7E900F + k + 1) = 0; + } + if (E->dms_var_41 >= 8u) { + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E9022 + j) = *(uint16 *)((char *)&g_word_7E9020 + k); + *(uint16 *)((char *)&g_word_7E9032 + j) = *(uint16 *)((char *)&g_word_7E9030 + k); + } + *(uint16 *)((char *)&g_word_7E9020 + k) = 0; + *(uint16 *)((char *)&g_word_7E9030 + k) = 0; + } + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E9042 + j) = *(uint16 *)((char *)&g_word_7E9040 + k); + *(uint16 *)((char *)&g_word_7E9052 + j) = *(uint16 *)((char *)&g_word_7E9050 + k); + } + *(uint16 *)((char *)&g_word_7E9040 + k) = 0; + *(uint16 *)((char *)&g_word_7E9050 + k) = 0; + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E9062 + j) = *(uint16 *)((char *)&g_word_7E9060 + k); + *(uint16 *)((char *)&g_word_7E9072 + j) = *(uint16 *)((char *)&g_word_7E9070 + k); + } + *(uint16 *)((char *)&g_word_7E9060 + k) = 0; + *(uint16 *)((char *)&g_word_7E9070 + k) = 0; + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E9082 + j) = *(uint16 *)((char *)&g_word_7E9080 + k); + *(uint16 *)((char *)&g_word_7E9092 + j) = *(uint16 *)((char *)&g_word_7E9090 + k); + } + *(uint16 *)((char *)&g_word_7E9080 + k) = 0; + *(uint16 *)((char *)&g_word_7E9090 + k) = 0; + if (E->dms_var_41 >= 8u) { + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E90A2 + j) = *(uint16 *)((char *)&g_word_7E90A0 + k); + *(uint16 *)((char *)&g_word_7E90B2 + j) = *(uint16 *)((char *)&g_word_7E90B0 + k); + } + *(uint16 *)((char *)&g_word_7E90A0 + k) = 0; + *(uint16 *)((char *)&g_word_7E90B0 + k) = 0; + } + if (E->dms_var_41 >= 0x20u) { + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E90C2 + j) = *(uint16 *)((char *)&g_word_7E90C0 + k); + *(uint16 *)((char *)&g_word_7E90D2 + j) = *(uint16 *)((char *)&g_word_7E90D0 + k); + } + *(uint16 *)((char *)&g_word_7E90C0 + k) = 0; + *(uint16 *)((char *)&g_word_7E90D0 + k) = 0; + } +} + +void MotherBrain_CorpseRottingCopyFunc(uint16 j, uint16 k) { // 0xA9EB0B + Enemy_DeadMonsters *E = Get_DeadMonsters(0); + if (E->dms_var_41 >= 0x10u && sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E9002 + j) = *(uint16 *)((char *)&kraid_unk9000 + k); + *(uint16 *)((char *)&g_word_7E9012 + j) = *(uint16 *)((char *)&g_word_7E900F + k + 1); + } + if (E->dms_var_41 >= 8u && sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E9022 + j) = *(uint16 *)((char *)&g_word_7E9020 + k); + *(uint16 *)((char *)&g_word_7E9032 + j) = *(uint16 *)((char *)&g_word_7E9030 + k); + } + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E9042 + j) = *(uint16 *)((char *)&g_word_7E9040 + k); + *(uint16 *)((char *)&g_word_7E9052 + j) = *(uint16 *)((char *)&g_word_7E9050 + k); + } + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E9062 + j) = *(uint16 *)((char *)&g_word_7E9060 + k); + *(uint16 *)((char *)&g_word_7E9072 + j) = *(uint16 *)((char *)&g_word_7E9070 + k); + } + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E9082 + j) = *(uint16 *)((char *)&g_word_7E9080 + k); + *(uint16 *)((char *)&g_word_7E9092 + j) = *(uint16 *)((char *)&g_word_7E9090 + k); + } + if (E->dms_var_41 >= 8u && sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E90A2 + j) = *(uint16 *)((char *)&g_word_7E90A0 + k); + *(uint16 *)((char *)&g_word_7E90B2 + j) = *(uint16 *)((char *)&g_word_7E90B0 + k); + } + if (E->dms_var_41 >= 0x20u) { + if (sign16(E->dms_var_41 - 46)) { + *(uint16 *)((char *)&g_word_7E90C2 + j) = *(uint16 *)((char *)&g_word_7E90C0 + k); + *(uint16 *)((char *)&g_word_7E90D2 + j) = *(uint16 *)((char *)&g_word_7E90D0 + k); + } + } +} + +uint16 sub_A9ECD0(uint16 k, uint16 j) { // 0xA9ECD0 + uint16 v2 = FUNC16(DeadMonsters_Func_1); + Enemy_DeadMonsters *E = Get_DeadMonsters(k); + if (E->dms_var_08) + v2 = FUNC16(DeadMonsters_Func_5); + E->dms_var_A = v2; + return j; +} + +uint8 Shitroid_Func_1(uint16 k, uint16 j) { // 0xA9EED1 + Enemy_Shitroid *E = Get_Shitroid(j); + Enemy_Shitroid *G = Get_Shitroid(k); + R18_ = G->base.x_width + E->base.x_width + 1; + uint16 v4 = abs16(E->base.x_pos - G->base.x_pos); + bool v5 = v4 >= R18_; + if (v4 < R18_) { + R18_ = G->base.y_height + E->base.y_height + 1; + return abs16(E->base.y_pos - G->base.y_pos) >= R18_; + } + return v5; +} + +uint8 Shitroid_Func_2(uint16 k) { // 0xA9EF06 + Enemy_Shitroid *E = Get_Shitroid(k); + R26_ = E->base.x_width + R22_ + 1; + uint16 v2 = abs16(R18_ - E->base.x_pos); + bool v3 = v2 >= R26_; + if (v2 < R26_) { + R26_ = E->base.y_height + R24_ + 1; + return abs16(R20_ - E->base.y_pos) >= R26_; + } + return v3; +} + +void Shitroid_Init(void) { // 0xA9EF37 + for (int i = 4094; i >= 0; i -= 2) + tilemap_stuff[i >> 1] = 0; + Enemy_Shitroid *E = Get_Shitroid(cur_enemy_index); + E->base.properties |= kEnemyProps_DisableSamusColl | kEnemyProps_BlockPlasmaBeam; + E->base.palette_index = 1024; + E->base.current_instruction = addr_kShitroid_Ilist_F90E; + E->base.instruction_timer = 1; + E->base.timer = 0; + uint16 v2 = FUNC16(Shitroid_Func_4); + if ((layer1_x_pos & 0x8000u) != 0) { + E->base.properties |= kEnemyProps_Tangible | kEnemyProps_Invisible; + v2 = FUNC16(Shitroid_Func_3); + } + E->shitr_var_A = v2; + E->shitr_var_B = 0; + E->shitr_var_C = 0; + E->shitr_var_E = 10; + E->shitr_parameter_2 = 0; + WriteColorsToTargetPalette(0xa9, 0x120u, addr_word_A9F8C6, 0x10u); + WriteColorsToTargetPalette(0xa9, 0x140u, addr_kShitroidInCutscene_Palette, 0x10u); + WriteColorsToTargetPalette(0xa9, 0x1E0u, addr_kDeadSidehopper_Palette_0, 0x10u); +} + +void Shitroid_Powerbomb(void) { // 0xA9EFBA + if (Get_Shitroid(cur_enemy_index)->shitr_parameter_2) + Shitroid_Func_26(cur_enemy_index); + Shitroid_Main(); +} + +void CallShitroidFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnShitroid_Func_3: Shitroid_Func_3(k); return; + case fnShitroid_Func_4: Shitroid_Func_4(); return; + case fnShitroid_Func_5: Shitroid_Func_5(k); return; + case fnShitroid_Func_6: Shitroid_Func_6(k); return; + case fnShitroid_Func_7: Shitroid_Func_7(k); return; + case fnShitroid_Func_8: Shitroid_Func_8(k); return; + case fnShitroid_Func_9: Shitroid_Func_9(k); return; + case fnShitroid_Func_10: Shitroid_Func_10(k); return; + case fnShitroid_Func_11: Shitroid_Func_11(k); return; + case fnShitroid_Func_12: Shitroid_Func_12(k); return; + case fnShitroid_Func_13: Shitroid_Func_13(k); return; + case fnShitroid_Func_14: Shitroid_Func_14(k); return; + case fnShitroid_Func_15: Shitroid_Func_15(k); return; + case fnShitroid_Func_16: Shitroid_Func_16(k); return; + case fnShitroid_Func_17: Shitroid_Func_17(k); return; + case fnShitroid_Func_18: Shitroid_Func_18(k); return; + case fnShitroid_Func_19: Shitroid_Func_19(k); return; + case fnShitroid_Func_20: Shitroid_Func_20(); return; + case fnShitroid_Func_21: Shitroid_Func_21(); return; + case fnShitroid_Func_22: Shitroid_Func_22(k); return; + case fnShitroid_Func_23: Shitroid_Func_23(); return; + case fnShitroid_Func_24: Shitroid_Func_24(k); return; + case fnShitroid_Func_25: Shitroid_Func_25(k); return; + default: Unreachable(); + } +} + +void Shitroid_Main(void) { // 0xA9EFC5 + Enemy_Shitroid *E = Get_Shitroid(cur_enemy_index); + E->base.health = 0x7FFF; + CallShitroidFunc(E->shitr_var_A | 0xA90000, cur_enemy_index); + MoveEnemyWithVelocity(); + if (!palette_change_num) + Shitroid_HandleNormalPalette(); +} + +void Shitroid_Func_3(uint16 k) { // 0xA9EFDF + Enemy_Shitroid *E = Get_Shitroid(k); + E->shitr_var_B = 0; + E->shitr_var_C = 0; +} + +static const SpawnHardcodedPlmArgs unk_A9F00E = { 0x30, 0x03, 0xb767 }; +static const SpawnHardcodedPlmArgs unk_A9F016 = { 0x1f, 0x03, 0xb767 }; + +void Shitroid_Func_4(void) { // 0xA9EFE6 + if (sign16(layer1_x_pos - 513)) { + layer1_x_pos = 512; + *(uint16 *)scrolls = scrolls[0]; + *(uint16 *)&scrolls[2] = scrolls[2]; + SpawnHardcodedPlm(&unk_A9F00E); + SpawnHardcodedPlm(&unk_A9F016); + Enemy_Shitroid *E = Get_Shitroid(cur_enemy_index); + E->shitr_var_A = FUNC16(Shitroid_Func_5); + E->shitr_var_04 = 1; + } +} + +void Shitroid_Func_5(uint16 k) { // 0xA9F02B + Enemy_Shitroid *E = Get_Shitroid(k); + E->shitr_var_A = FUNC16(Shitroid_Func_6); + E->shitr_var_F = 464; + Shitroid_Func_6(k); +} + +void Shitroid_Func_6(uint16 k) { // 0xA9F037 + Enemy_Shitroid *E = Get_Shitroid(k); + if ((--E->shitr_var_F & 0x8000u) != 0) { + QueueMusic_Delayed8(5u); + E->shitr_var_A = FUNC16(Shitroid_Func_7); + Shitroid_Func_7(k); + } +} + +void Shitroid_Func_7(uint16 k) { // 0xA9F049 + R18_ = 584; + R20_ = 74; + Shitroid_Func_GraduallyAccelerateTowards0x400(k, 0xFu); + R22_ = 1; + R24_ = 1; + if (!(Shitroid_Func_2(k) & 1)) + Get_Shitroid(k)->shitr_var_A = FUNC16(Shitroid_Func_8); +} + +void Shitroid_Func_8(uint16 k) { // 0xA9F06D + Enemy_Shitroid *E = Get_Shitroid(k + 64); + R18_ = E->base.x_pos; + R20_ = E->base.y_pos - 32; + Shitroid_Func_GraduallyAccelerateTowards0x400(k, 0xFu); + if (!(Shitroid_Func_1(k, k + 64) & 1)) + Get_Shitroid(k)->shitr_var_A = FUNC16(Shitroid_Func_9); +} + +void Shitroid_Func_9(uint16 k) { // 0xA9F094 + Enemy_Shitroid *E1 = Get_Shitroid(k + 64); + R18_ = E1->base.x_pos; + R20_ = E1->base.y_pos - 32; + if (Shitroid_AccelerateTowardsPoint(k, 0x200u) & 1) { + Enemy_Shitroid *E = Get_Shitroid(k); + E->shitr_var_B = 0; + E->shitr_var_C = 0; + E->base.x_pos = E1->base.x_pos; + E->base.y_pos = E1->base.y_pos - 32; + E->base.current_instruction = addr_kShitroid_Ilist_F924; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->shitr_var_A = FUNC16(Shitroid_Func_10); + E->shitr_var_E = 1; + E->shitr_parameter_2 = 0; + E->shitr_var_F = 320; + } +} + +void Shitroid_Func_10(uint16 k) { // 0xA9F0E6 + Enemy_Shitroid *E = Get_Shitroid(k); + int v2 = (uint8)(E->base.frame_counter & 6) >> 1; + Enemy_Shitroid *E1 = Get_Shitroid(k + 64); + E->base.x_pos = E1->base.x_pos + g_word_A993BB[v2]; + E->base.y_pos = E1->base.y_pos + g_word_A993C3[v2] - 32; + if (E->shitr_var_F-- == 1) { + E->shitr_var_A = FUNC16(Shitroid_Func_11); + E->base.current_instruction = addr_kShitroid_Ilist_F906; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->shitr_var_E = 10; + } +} + +void Shitroid_Func_11(uint16 k) { // 0xA9F125 + Get_Shitroid(0x40u)->shitr_var_08 = 1; + Enemy_Shitroid *E = Get_Shitroid(k); + E->shitr_var_A = FUNC16(Shitroid_Func_12); + E->shitr_var_F = 192; + Shitroid_Func_12(k); +} + +static const SpawnHardcodedPlmArgs unk_A9F173 = { 0x30, 0x03, 0xb763 }; +static const SpawnHardcodedPlmArgs unk_A9F17B = { 0x1f, 0x03, 0xb763 }; + +void Shitroid_Func_12(uint16 k) { // 0xA9F138 + Enemy_Shitroid *E = Get_Shitroid(k); + R18_ = E->base.x_pos; + R20_ = 104; + Shitroid_Func_GraduallyAccelerateTowards0x400(k, 0); + if ((--E->shitr_var_F & 0x8000u) != 0) { + E->shitr_var_A = FUNC16(Shitroid_Func_13); + E->shitr_parameter_2 = 1; + *(uint16 *)scrolls |= 0x100u; + *(uint16 *)&scrolls[2] |= 0x100u; + SpawnHardcodedPlm(&unk_A9F173); + SpawnHardcodedPlm(&unk_A9F17B); + } +} + +void Shitroid_Func_13(uint16 k) { // 0xA9F180 + Enemy_Shitroid *E = Get_Shitroid(k); + uint16 v2 = abs16(E->base.x_pos - samus_x_pos); + uint16 shitro_var_02; + if (v2 >= 8u) { + shitro_var_02 = E->shitr_var_02; + if (shitro_var_02) { + if ((--shitro_var_02 & 0x8000u) != 0) + shitro_var_02 = 0; + } + } else { + shitro_var_02 = (v2 >= 8u) + E->shitr_var_02 + 2; + } + E->shitr_var_02 = shitro_var_02; + if (shitro_var_02 >= 0x100u || sign16(samus_x_pos - 512)) { + Get_Shitroid(cur_enemy_index)->shitr_var_A = FUNC16(Shitroid_Func_14); + } else { + uint16 shitro_var_01 = E->shitr_var_01; + uint16 v5; + if (shitro_var_01) { + E->shitr_var_01 = shitro_var_01 - 1; + v5 = samus_y_pos; + } else { + v5 = 80; + if ((random_number & 0xFFFu) >= 0xFE0) + E->shitr_var_01 = 32; + } + R20_ = v5; + R18_ = samus_x_pos; + Shitroid_Func_GraduallyAccelerateTowards0x400(cur_enemy_index, 0xAu); + } +} + +void Shitroid_Func_14(uint16 k) { // 0xA9F1FA + R18_ = samus_x_pos; + R20_ = samus_y_pos - 32; + Shitroid_Func_GraduallyAccelerateTowards0x400(k, 0xFu); +} + +void Shitroid_Func_15(uint16 k) { // 0xA9F20E + CallSomeSamusCode(0x12u); + Get_Shitroid(0)->shitr_var_A = FUNC16(Shitroid_Func_16); + Shitroid_Func_16(k); +} + +void Shitroid_Func_16(uint16 k) { // 0xA9F21B + Enemy_Shitroid *E = Get_Shitroid(k); + if (samus_health < 2u) { + samus_x_speed_divisor = 0; + bomb_counter = 0; + E->shitr_var_A = FUNC16(Shitroid_Func_17); + E->shitr_var_B = 0; + E->shitr_var_C = 0; + Enemy_SetInstrList(k, addr_kShitroid_Ilist_F906); + E->shitr_var_E = 10; + CallSomeSamusCode(0x13u); + SomeMotherBrainScripts(0); + E->shitr_var_04 = 0; + QueueMusic_Delayed8(7u); + } else { + cooldown_timer = 8; + bomb_counter = 5; + samus_x_speed_divisor = 2; + if (!sign16(samus_y_speed - 4)) + samus_y_speed = 2; + int v2 = (uint8)(E->base.frame_counter & 6) >> 1; + E->base.x_pos = samus_x_pos + g_word_A993BB[v2]; + E->base.y_pos = samus_y_pos + g_word_A993C3[v2] - 20; + Samus_DamageDueToShitroid(); + } +} + +void Shitroid_Func_17(uint16 k) { // 0xA9F2A2 + Enemy_Shitroid *E = Get_Shitroid(k); + E->shitr_var_A = FUNC16(Shitroid_Func_18); + E->shitr_var_F = 120; + Shitroid_Func_18(k); +} + +void Shitroid_Func_18(uint16 k) { // 0xA9F2AE + Enemy_Shitroid *E = Get_Shitroid(k); + if ((--E->shitr_var_F & 0x8000u) != 0) { + E->shitr_var_A = FUNC16(Shitroid_Func_19); + E->shitr_var_F = 192; + Shitroid_Func_19(k); + } +} + +void Shitroid_Func_19(uint16 k) { // 0xA9F2C0 + R18_ = samus_x_pos; + R20_ = 104; + Shitroid_Func_GraduallyAccelerateTowards0x400(cur_enemy_index, 0); + Enemy_Shitroid *E = Get_Shitroid(cur_enemy_index); + if ((--E->shitr_var_F & 0x8000u) != 0) { + QueueSfx2_Max6(0x7Du); + E->shitr_var_A = FUNC16(Shitroid_Func_20); + E->shitr_var_F = 88; + E->base.current_instruction = addr_kShitroid_Ilist_F924; + E->base.instruction_timer = 1; + E->base.timer = 0; + Shitroid_Func_20(); + } +} + +void Shitroid_Func_20(void) { // 0xA9F2FB + R18_ = samus_x_pos - 64; + R20_ = 100; + Shitroid_Func_GraduallyAccelerateTowards0x400(cur_enemy_index, 0); + Enemy_Shitroid *E = Get_Shitroid(cur_enemy_index); + if ((--E->shitr_var_F & 0x8000u) != 0) { + E->shitr_var_A = FUNC16(Shitroid_Func_21); + E->shitr_var_F = 88; + Shitroid_Func_21(); + } +} + +void Shitroid_Func_21(void) { // 0xA9F324 + R18_ = samus_x_pos + 96; + R20_ = 104; + Shitroid_Func_GraduallyAccelerateTowards0x400(cur_enemy_index, 0); + Enemy_Shitroid *E = Get_Shitroid(cur_enemy_index); + if ((--E->shitr_var_F & 0x8000u) != 0) { + E->shitr_var_A = FUNC16(Shitroid_Func_24); + E->shitr_var_F = 256; + E->base.current_instruction = addr_kShitroid_Ilist_F93A; + E->base.instruction_timer = 1; + E->base.timer = 0; + } +} + +void Shitroid_Func_22(uint16 k) { // 0xA9F360 + QueueSfx2_Max6(0x52u); + Get_Shitroid(k)->shitr_var_A = FUNC16(Shitroid_Func_23); + Shitroid_Func_23(); +} + +void Shitroid_Func_23(void) { // 0xA9F36D + R18_ = -128; + R20_ = 64; + Shitroid_Func_GraduallyAccelerateTowards0x400(cur_enemy_index, 0); + R22_ = 8; + R24_ = 8; + if (!(Shitroid_Func_2(cur_enemy_index) & 1)) { + Enemy_Shitroid *E = Get_Shitroid(cur_enemy_index); + E->shitr_var_B = 0; + E->shitr_var_C = 0; + E->base.properties &= ~(kEnemyProps_DisableSamusColl | kEnemyProps_Invisible); + E->shitr_var_A = FUNC16(Shitroid_Func_3); + } +} + +void Shitroid_Func_24(uint16 k) { // 0xA9F3A3 + Enemy_Shitroid *E = Get_Shitroid(k); + if ((--E->shitr_var_F & 0x8000u) != 0) { + SomeMotherBrainScripts(2u); + E->shitr_parameter_2 = 1; + E->shitr_var_A = FUNC16(Shitroid_Func_25); + Shitroid_Func_25(k); + } else { + Shitroid_Func_27(k); + } +} + +void Shitroid_Func_25(uint16 k) { // 0xA9F3BE + if (Shitroid_Func_27(k) & 1) + Shitroid_F3C4(k); +} + +void Shitroid_F3C4(uint16 k) { // 0xA9F3C4 + Get_Shitroid(k)->shitr_var_A = FUNC16(Shitroid_Func_22); +} + +void Shitroid_Func_26(uint16 k) { // 0xA9F3CB + if (Get_Shitroid(k)->shitr_var_A == (uint16)FUNC16(Shitroid_Func_25)) + Shitroid_F3C4(k); +} + +uint8 Shitroid_Func_27(uint16 k) { // 0xA9F3D4 + Enemy_Shitroid *E = Get_Shitroid(k); + uint16 v2 = abs16(E->base.x_pos - samus_x_pos); + uint16 shitro_var_02; + if (v2 >= 2u) { + shitro_var_02 = E->shitr_var_02; + if (shitro_var_02) { + if ((--shitro_var_02 & 0x8000u) != 0) + shitro_var_02 = 0; + } + } else { + shitro_var_02 = (v2 >= 2u) + E->shitr_var_02 + 2; + } + E->shitr_var_02 = shitro_var_02; + uint16 shitro_var_01 = E->shitr_var_01; + uint16 v5; + if (shitro_var_01) { + E->shitr_var_01 = shitro_var_01 - 1; + v5 = samus_y_pos - 18; + } else { + v5 = 80; + if ((random_number & 0xFFFu) >= 0xFE0) + E->shitr_var_01 = 32; + } + R20_ = v5; + R18_ = samus_x_pos; + Shitroid_Func_GraduallyAccelerateTowards0x400(cur_enemy_index, 8u); + return Get_Shitroid(cur_enemy_index)->shitr_var_02 >= 0x400u || sign16(samus_x_pos - 128); +} + +void Shitroid_Func_GraduallyAccelerateTowards0x400(uint16 k, uint16 j) { // 0xA9F451 + R26_ = 1024; + Shitroid_GraduallyAccelerateTowardsPt(k, j); +} + +void Shitroid_GraduallyAccelerateTowards0x4(uint16 k, uint16 j) { // 0xA9F458 + R26_ = 4; + Shitroid_GraduallyAccelerateTowardsPt(k, j); +} + +void Shitroid_GraduallyAccelerateTowards0x8(uint16 k, uint16 j) { // 0xA9F45F + R26_ = 8; + Shitroid_GraduallyAccelerateTowardsPt(k, j); +} + +void Shitroid_GraduallyAccelerateTowards0x10(uint16 k, uint16 j) { // 0xA9F466 + R26_ = 16; + Shitroid_GraduallyAccelerateTowardsPt(k, j); +} + +void Shitroid_GraduallyAccelerateTowardsPt(uint16 k, uint16 j) { // 0xA9F46B + int16 v3; + int16 v5; + int16 v6; + int16 shitr_var_C; + int16 v9; + + R24_ = g_byte_A9F56A[j]; + Shitroid_GraduallyAccelerateHoriz(k); + Enemy_Shitroid *E = Get_Shitroid(k); + v3 = E->base.y_pos - R20_; + if (v3) { + if (v3 >= 0) { + uint16 RegWord = SnesDivide(v3, R24_); + if (!RegWord) + RegWord = 1; + R22_ = RegWord; + shitr_var_C = E->shitr_var_C; + if (shitr_var_C >= 0) + shitr_var_C = shitr_var_C - 8 - R22_; + v9 = shitr_var_C - R22_; + if (sign16(v9 + 1280)) + v9 = -1280; + E->shitr_var_C = v9; + } else { + uint16 v4 = SnesDivide(R20_ - E->base.y_pos, R24_); + if (!v4) + v4 = 1; + R22_ = v4; + v5 = E->shitr_var_C; + if (v5 < 0) + v5 += R22_ + 8; + v6 = R22_ + v5; + if (!sign16(v6 - 1280)) + v6 = 1280; + E->shitr_var_C = v6; + } + } +} + +void Shitroid_GraduallyAccelerateHoriz(uint16 k) { // 0xA9F4E6 + int16 v2; + int16 v4; + char v5; // cf + int16 v7; + int16 shitr_var_B; + int16 v11; + + Enemy_Shitroid *E = Get_Shitroid(k); + v2 = E->base.x_pos - R18_; + if (v2) { + if (v2 >= 0) { + uint16 RegWord = SnesDivide(v2, R24_); + if (!RegWord) + RegWord = 1; + R22_ = RegWord; + shitr_var_B = E->shitr_var_B; + if (shitr_var_B >= 0) { + uint16 v13 = E->shitr_var_B; + v5 = Shitroid_CheckIfOnScreen(k) & 1; + uint16 v10 = v13; + if (v5) + v10 = v13 - R26_; + shitr_var_B = v10 - 8 - R22_; + } + v11 = shitr_var_B - R22_; + if (sign16(v11 + 2048)) + v11 = -2048; + E->shitr_var_B = v11; + } else { + uint16 v3 = SnesDivide(R18_ - E->base.x_pos, R24_); + if (!v3) + v3 = 1; + R22_ = v3; + v4 = E->shitr_var_B; + if (v4 < 0) { + uint16 v12 = E->shitr_var_B; + v5 = Shitroid_CheckIfOnScreen(k) & 1; + uint16 v6 = v12; + if (v5) + v6 = R26_ + v12; + v4 = R22_ + v6 + 8; + } + v7 = R22_ + v4; + if (!sign16(v7 - 2048)) + v7 = 2048; + E->shitr_var_B = v7; + } + } +} + + +uint8 Shitroid_CheckIfOnScreen(uint16 k) { // 0xA9F57A + int16 y_pos; + int16 v3; + int16 x_pos; + int16 v5; + + Enemy_Shitroid *E = Get_Shitroid(k); + y_pos = E->base.y_pos; + uint8 result = 1; + if (y_pos >= 0) { + v3 = y_pos + 96 - layer1_y_pos; + if (v3 >= 0) { + if (sign16(v3 - 416)) { + x_pos = E->base.x_pos; + if (x_pos >= 0) { + v5 = x_pos + 16 - layer1_x_pos; + if (v5 >= 0) { + if (sign16(v5 - 288)) + return 0; + } + } + } + } + } + return result; +} + +uint8 Shitroid_AccelerateTowardsPoint(uint16 k, uint16 a) { // 0xA9F5A6 + R22_ = a; + R28_ = 0; + Shitroid_AccelerateTowardsX(k); + Shitroid_AccelerateTowardsY(k); + R28_ >>= 1; + uint8 v2 = R28_ & 1; + R28_ >>= 1; + return v2; +} + +void Shitroid_AccelerateTowardsY(uint16 k) { // 0xA9F5B5 + int16 v2; + int16 v3; + int16 v4; + int16 v5; + char v6; // t0 + int16 v7; + int16 v8; + int16 v9; + char v10; // t1 + int16 v11; + + Enemy_Shitroid *E = Get_Shitroid(k); + v2 = E->base.y_pos - R20_; + if (!v2) + goto LABEL_9; + if (v2 >= 0) { + v7 = E->shitr_var_C - R22_; + if (sign16(v7 + 1280)) + v7 = -1280; + E->shitr_var_C = v7; + v8 = v7 & 0xFF00; + v10 = v8; + LOBYTE(v9) = HIBYTE(v8); + HIBYTE(v9) = v10; + if ((v9 & 0x80) != 0) + v9 |= 0xFF00u; + v11 = E->base.y_pos + v9; + if (v11 == R20_ || (int16)(v11 - R20_) < 0) { + E->shitr_var_C = 0; + ++R28_; + } + } else { + v3 = R22_ + E->shitr_var_C; + if (!sign16(v3 - 1280)) + v3 = 1280; + E->shitr_var_C = v3; + v4 = v3 & 0xFF00; + v6 = v4; + LOBYTE(v5) = HIBYTE(v4); + HIBYTE(v5) = v6; + if ((v5 & 0x80) != 0) + v5 |= 0xFF00u; + if (!sign16(E->base.y_pos + v5 - R20_)) { + E->shitr_var_C = 0; +LABEL_9: + ++R28_; + } + } +} + +void Shitroid_AccelerateTowardsX(uint16 k) { // 0xA9F615 + int16 v2; + int16 v3; + int16 v4; + char v5; // t0 + int16 v6; + int16 v7; + int16 v8; + char v9; // t1 + int16 v10; + + Enemy_Shitroid *E = Get_Shitroid(k); + if ((int16)(E->base.x_pos - R18_) >= 0) { + v6 = E->shitr_var_B - R22_; + if (sign16(v6 + 1280)) + v6 = -1280; + E->shitr_var_B = v6; + v7 = v6 & 0xFF00; + v9 = v7; + LOBYTE(v8) = HIBYTE(v7); + HIBYTE(v8) = v9; + if ((v8 & 0x80) != 0) + v8 |= 0xFF00u; + v10 = E->base.x_pos + v8; + if (v10 == R18_ || (int16)(v10 - R18_) < 0) { + E->shitr_var_B = 0; + ++R28_; + } + } else { + v2 = R22_ + E->shitr_var_B; + if (!sign16(v2 - 1280)) + v2 = 1280; + E->shitr_var_B = v2; + v3 = v2 & 0xFF00; + v5 = v3; + LOBYTE(v4) = HIBYTE(v3); + HIBYTE(v4) = v5; + if ((v4 & 0x80) != 0) + v4 |= 0xFF00u; + if (!sign16(E->base.x_pos + v4 - R18_)) { + E->shitr_var_B = 0; + ++R28_; + } + } +} + +void Shitroid_HandleNormalPalette(void) { // 0xA9F677 + R18_ = 330; + R22_ = addr_word_A9F6D1; + Shitroid_HandleCutscenePalette_Common(); +} + +void Shitroid_HandleCutscenePalette(void) { // 0xA9F683 + R18_ = 490; + R22_ = addr_word_A9F6D1; + Shitroid_HandleCutscenePalette_Common(); +} + +void Shitroid_HandleCutscenePalette_LowHealth(void) { // 0xA9F68F + R18_ = 490; + R22_ = addr_word_A9F711; + Shitroid_HandleCutscenePalette_Common(); +} + +void Shitroid_HandleCutscenePalette_Common(void) { // 0xA9F699 + char shitro_var_D_high; + + Enemy_Shitroid *E = Get_Shitroid(cur_enemy_index); + shitro_var_D_high = HIBYTE(E->shitr_var_D); + if (shitro_var_D_high) { + HIBYTE(E->shitr_var_D) = shitro_var_D_high - 1; + } else { + HIBYTE(E->shitr_var_D) = E->shitr_var_E; + uint8 v3 = (LOBYTE(E->shitr_var_D) + 1) & 7; + LOBYTE(E->shitr_var_D) = v3; + uint16 v4 = Shitroid_HandleCrySoundEffect(cur_enemy_index, v3); + WriteColorsToPalette(R18_, 0xa9, R22_ + 8 * v4, 4u); + } +} + +uint16 Shitroid_HandleCrySoundEffect(uint16 k, uint16 a) { // 0xA9F751 + if (a == 5) { + Enemy_Shitroid *E = Get_Shitroid(k); + if (E->shitr_var_04) { + uint16 v3 = E->shitr_var_05 + 1; + E->shitr_var_05 = v3; + if (v3 >= 4u) { + E->shitr_var_05 = 0; + uint16 v4 = 114; + if (E->shitr_var_E < 0xAu) + v4 = 120; + QueueSfx2_Max6(v4); + } + } + return 5; + } + return a; +} + +void Shitroid_Touch(void) { // 0xA9F789 + Enemy_Shitroid *E = Get_Shitroid(cur_enemy_index); + if (E->shitr_parameter_2) { + Shitroid_Func_26(cur_enemy_index); + if (samus_movement_type == 3 && !sign16(samus_x_pos - 512)) { + R18_ = samus_x_pos - E->base.x_pos; + R20_ = samus_y_pos - E->base.y_pos; + R18_ = (uint8)(0x80 - CalculateAngleFromXY() + 0x80); + uint16 v4 = Math_MultBySin(0x40u); + E->shitr_var_B += v4; + uint16 v6 = Math_MultByCos(0x40u); + E->shitr_var_C += v6; + } else if (E->shitr_var_A == (uint16)FUNC16(Shitroid_Func_14)) { + R18_ = samus_x_pos; + R20_ = samus_y_pos - 32; + if (Shitroid_AccelerateTowardsPoint(cur_enemy_index, 0x200u) & 1) { + E->base.current_instruction = addr_kShitroid_Ilist_F924; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->shitr_var_E = 1; + E->shitr_parameter_2 = 0; + E->shitr_var_B = 0; + E->shitr_var_C = 0; + E->shitr_var_A = FUNC16(Shitroid_Func_15); + } + } else if (E->shitr_var_A == (uint16)FUNC16(Shitroid_Func_13)) { + E->shitr_var_A = FUNC16(Shitroid_Func_14); + } + } +} + +void Shitroid_Shot(void) { // 0xA9F842 + Enemy_Shitroid *E = Get_Shitroid(cur_enemy_index); + if (E->shitr_parameter_2) { + Shitroid_Func_26(cur_enemy_index); + R18_ = projectile_x_pos[0] - E->base.x_pos; + R20_ = projectile_y_pos[0] - E->base.y_pos; + R18_ = (uint8)-CalculateAngleFromXY(); + uint16 v1 = 8 * projectile_damage[collision_detection_index]; + if (v1 >= 0xF0u) + v1 = 240; + uint16 a = v1; + uint16 v2 = Math_MultBySin(v1); + E->shitr_var_B += v2; + uint16 v4 = Math_MultByCos(a); + E->shitr_var_C += v4; + } +} + +uint16 Shitroid_Instr_3(uint16 k, uint16 j) { // 0xA9F920 + return addr_kShitroid_Ilist_F90E; +} + +uint16 Shitroid_Instr_4(uint16 k, uint16 j) { // 0xA9F936 + return addr_kShitroid_Ilist_F924; +} + +uint16 Shitroid_Instr_6(uint16 k, uint16 j) { // 0xA9F990 + return addr_kShitroid_Ilist_F93A; +} + +uint16 Shitroid_Instr_5(uint16 k, uint16 j) { // 0xA9F994 + if ((random_number & 0x8000u) == 0) + return *(uint16 *)RomPtr_A9(j); + QueueSfx2_Max6(0x52u); + return j + 2; +} diff --git a/src/sm_aa.c b/src/sm_aa.c new file mode 100644 index 0000000..4023ff5 --- /dev/null +++ b/src/sm_aa.c @@ -0,0 +1,1715 @@ +// Enemy AI - inc. Torizo & Tourian statue +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" + +static const uint16 g_word_AAB096 = 6; +static const uint16 g_word_AAB098 = 5; +static const uint16 g_word_AAB09A = 3; + +static const int16 g_word_AAC3EE[16] = { -9, -6, -7, 5, -16, -7, 0, 0, 9, 6, 7, -5, 16, 7, 0, 0 }; +static const int16 g_word_AAC40E[8] = { 0, -6, -6, -7, 0, 0, 0, 0 }; +static const int16 g_word_AAC440[16] = { -9, -6, -7, 5, -16, -7, 0, 0, 9, 6, 7, -5, 16, 7, 0, 0 }; +static const int16 g_word_AAC460[8] = { 0, -6, -6, -7, 0, 0, 0, 0 }; +static const int16 g_word_AAC4BD[20] = { + -5, 0, -5, -19, -16, -7, 0, -7, -17, -18, 5, 0, 5, 19, 16, 7, + 0, 7, 17, 18, +}; +static const int16 g_word_AAC532[20] = { + -5, 0, -5, -0x13, -0x10, -7, 0, -7, -0x11, -0x12, 5, 0, 5, 0x13, 0x10, 7, + 0, 7, 0x11, 0x12, +}; +static const int16 g_word_AAC95F[2] = { 0xdb, 0x1a8 }; +static const int16 g_word_AAC963[2] = { 0xb3, 0x90 }; +#define g_off_AAC967 ((uint16*)RomPtr(0xaac967)) +static const int16 g_word_AAC96B[2] = { 0x2800, 0x2800 }; +static const int16 g_word_AAC96F[2] = { 0x12, 0x12 }; +static const int16 g_word_AAC973[2] = { 0x30, 0x29 }; + +static const uint16 kTorizo_Palette[16] = { 0x3800, 0x3ff, 0x33b, 0x216, 0x113, 0x6b1e, 0x4a16, 0x3591, 0x20e9, 0x1580, 0x1580, 0x1580, 0x1580, 0x1580, 0x1580, 0x1580 }; +static const uint16 kTorizo_Palettes_1[16] = { 0x3800, 0x2df, 0x1d7, 0xac, 0x5a73, 0x41ad, 0x2d08, 0x1863, 0x1486, 0x145, 0x145, 0x145, 0x7fff, 0x145, 0x145, 0 }; +static const uint16 kTorizo_Palettes_2[16] = { 0x3800, 0x679f, 0x5299, 0x252e, 0x14aa, 0x5efc, 0x4657, 0x35b2, 0x2d70, 0x5b7f, 0x3df8, 0x2d0e, 0x5f5f, 0x5e1a, 0x5d35, 0xc63 }; +static const uint16 kTorizo_Palettes_3[16] = { 0x3800, 0x4aba, 0x35b2, 0x847, 3, 0x4215, 0x2970, 0x18cb, 0x1089, 0x463a, 0x28b3, 0x1809, 0x6f7f, 0x51fd, 0x4113, 0xc63 }; +static const uint16 kTorizo_Palettes_4[16] = { 0x3800, 0x56ba, 0x41b2, 0x1447, 0x403, 0x4e15, 0x3570, 0x24cb, 0x1868, 0x6f7f, 0x51f8, 0x410e, 0x31f, 0x1da, 0xf5, 0xc63 }; +static const uint16 kTorizo_Palettes_5[16] = { 0x3800, 0x4215, 0x2d0d, 2, 0, 0x3970, 0x20cb, 0xc26, 0x403, 0x463a, 0x28b3, 0x1809, 0x6f7f, 0x51fd, 0x4113, 0xc63 }; +static const uint16 kTorizo_Palettes_6[16] = { 0x3800, 0x6ab5, 0x49b0, 0x1c45, 0xc01, 0x5613, 0x416d, 0x2cc9, 0x2066, 0x5714, 0x31cc, 0x14e3, 0x5630, 0x3569, 0x1883, 0xc66 }; +static const uint16 kTorizo_Palettes_7[16] = { 0x3800, 0x5610, 0x350b, 0x800, 0, 0x416e, 0x2cc8, 0x1823, 0xc01, 0x6a31, 0x4caa, 0x2406, 0x7f7b, 0x75f4, 0x4d10, 0xc63 }; +static const uint16 kTorizo_Palettes_8[16] = { 0x3800, 0x4bbe, 0x6b9, 0xa8, 0, 0x173a, 0x276, 0x1f2, 0x14d, 0x73e0, 0x4f20, 0x2a20, 0x7fe0, 0x5aa0, 0x5920, 0x43 }; +static const uint16 kTorizo_Palettes_10[16] = { 0x3800, 0x3719, 0x214, 3, 0, 0x295, 0x1d1, 0x14d, 0xa8, 0x4b40, 0x25e0, 0xe0, 0x6b40, 0x4600, 0x4480, 0 }; +static const int16 g_word_AAD59A[20] = { + -5, 0, -5, -19, -16, -7, 0, -7, -17, -18, 5, 0, 5, 19, 16, 7, + 0, 7, 17, 18, +}; +#define g_off_AAD810 ((uint16*)RomPtr(0xaad810)) +#define g_word_AAD765 ((uint16*)RomPtr(0xaad765)) +#define g_word_AAD785 ((uint16*)RomPtr(0xaad785)) +#define g_off_AADF13 ((uint16*)RomPtr(0xaadf13)) +#define g_off_AADF21 ((uint16*)RomPtr(0xaadf21)) +#define kSine ((uint16*)RomPtr(0xaae0bd)) +#define kCosine ((uint16*)RomPtr(0xaae13d)) +#define kNegativeSine ((uint16*)RomPtr(0xaae1bd)) +#define kNegativeCosine_0 ((uint16*)RomPtr(0xaae23d)) +#define kNegativeCosine ((uint16*)RomPtr(0xaae03d)) +#define g_off_AADD15 ((uint16*)RomPtr(0xaadd15)) +#define g_word_AADE95 ((uint16*)RomPtr(0xaade95)) +#define g_word_AADEA3 ((uint16*)RomPtr(0xaadea3)) +#define g_word_AADEB1 ((uint16*)RomPtr(0xaadeb1)) +#define g_off_AADEDB ((uint16*)RomPtr(0xaadedb)) +static const uint16 g_word_AADEE9[7] = { 0, 0x20, 0x60, 0xc0, 0x140, 0x1a0, 0x1e0 }; +#define g_word_AADEF7 ((uint16*)RomPtr(0xaadef7)) +#define g_word_AADECD ((uint16*)RomPtr(0xaadecd)) +#define g_word_AAE630 ((uint16*)RomPtr(0xaae630)) +#define g_word_AAE670 ((uint16*)RomPtr(0xaae670)) +#define g_word_AAE6B0 ((uint16*)RomPtr(0xaae6b0)) +#define kN00bTubeCracks_Palette2 ((uint16*)RomPtr(0xaae2dd)) +#define g_off_AAE7A2 ((uint16*)RomPtr(0xaae7a2)) +static const uint16 kChozoStatue_Palette[16] = { 0x3800, 0x633f, 0x4a9f, 0x2ddf, 0x6739, 0x4e73, 0x318c, 0x18c6, 0x27ff, 0x1af7, 0xdce, 0xc6, 0x3fff, 0x2b39, 0x7fff, 0 }; +static const int16 kChozoStatue_Palettes[16] = { + 0x3800, 0x633f, 0x4a9f, 0x2ddf, 0x4210, 0x318c, 0x2108, 0x1084, + 0x27ff, 0x1af7, 0xdce, 0xc6, 0x3fff, 0x2b39, 0x5294, 0, +}; +static const int16 kChozoStatue_Palettes2[16] = { + 0x3800, 0x633f, 0x4a9f, 0x2ddf, 0x2f7c, 0x2295, 0x118d, 0x8e8, + 0x27ff, 0x1af7, 0xdce, 0xc6, 0x3fff, 0x2b39, 0x73df, 0x43, +}; +static const int16 kChozoStatue_Palettes3[16] = { + 0x3800, 0x633f, 0x4a9f, 0x2ddf, 0x2295, 0x118d, 0x8e8, 0x85, + 0x27ff, 0x1af7, 0xdce, 0xc6, 0x3fff, 0x2b39, 0x5294, 1, +}; + +void Enemy_GrappleReact_CancelBeam_AA(void) { // 0xAA800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_NormalFrozenAI_AA(void) { // 0xAA8041 + NormalEnemyFrozenAI(); +} + +uint16 Enemy_ClearAiPreInstr_AA(uint16 k, uint16 j) { // 0xAA8074 + gEnemyData(k)->ai_preinstr = FUNC16(nullsub_171_AA); + return j; +} + +uint16 Enemy_SetAiPreInstr_AA(uint16 k, uint16 j) { // 0xAA806B + gEnemyData(k)->ai_preinstr = *(uint16 *)RomPtr_AA(j); + return j + 2; +} + +uint16 EnemyInstr_StopScript_AA(uint16 k, uint16 j) { // 0xAA807C + EnemyData *v2 = gEnemyData(k); + v2->properties |= kEnemyProps_Deleted; + return 0; +} + +uint16 EnemyInstr_Goto_AA(uint16 k, uint16 j) { // 0xAA80ED + return *(uint16 *)RomPtr_AA(j); +} + +uint16 EnemyInstr_DecTimerAndGoto2_AA(uint16 k, uint16 j) { // 0xAA8110 + EnemyData *v2 = gEnemyData(k); + if (v2->timer-- == 1) + return j + 2; + else + return EnemyInstr_Goto_AA(k, j); +} + +uint16 EnemyInstr_SetTimer_AA(uint16 k, uint16 j) { // 0xAA8123 + uint16 v2 = *(uint16 *)RomPtr_AA(j); + gEnemyData(k)->timer = v2; + return j + 2; +} + +uint16 EnemyInstr_Sleep_AA(uint16 k, uint16 j) { // 0xAA812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + +uint16 EnemyInstr_WaitNframes_AA(uint16 k, uint16 j) { // 0xAA813A + uint16 v2 = *(uint16 *)RomPtr_AA(j); + EnemyData *v3 = gEnemyData(k); + v3->instruction_timer = v2; + v3->current_instruction = j + 2; + return 0; +} + +uint16 EnemyInstr_CopyToVram_AA(uint16 k, uint16 j) { // 0xAA814B + VramWriteEntry *v4; + + uint16 v2 = vram_write_queue_tail; + uint8 *v3 = RomPtr_AA(j); + v4 = gVramWriteEntry(vram_write_queue_tail); + v4->size = *(uint16 *)v3; + v4->src.addr = *((uint16 *)v3 + 1); + *(VoidP *)((char *)&v4->src.addr + 1) = *(uint16 *)(v3 + 3); + v4->vram_dst = *(uint16 *)(v3 + 5); + vram_write_queue_tail = v2 + 7; + return j + 7; +} + +uint16 Torizo_Instr_3(uint16 k, uint16 j) { // 0xAAB09C + uint16 v2 = *(uint16 *)RomPtr_AA(j); + Get_Torizo(k)->toriz_var_E = v2; + return j + 2; +} + +uint16 Torizo_Instr_31(uint16 k, uint16 j) { // 0xAAB11D + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_parameter_2 = E->toriz_parameter_2 | 0x8000; + SpawnEnemyProjectileWithGfx(0, k, addr_stru_86A95B); + SpawnEnemyProjectileWithGfx(0, k, addr_stru_86A95B); + SpawnEnemyProjectileWithGfx(0, k, addr_stru_86A95B); + SpawnEnemyProjectileWithGfx(0, k, addr_stru_86A95B); + SpawnEnemyProjectileWithGfx(0, k, addr_stru_86A95B); + SpawnEnemyProjectileWithGfx(0, k, addr_stru_86A95B); + return j; +} + +uint16 Torizo_Instr_33(uint16 k, uint16 j) { // 0xAAB1BE + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_parameter_2 |= 0x4000u; + return j; +} + +uint16 Torizo_Instr_36(uint16 k, uint16 j) { // 0xAAB224 + Enemy_Torizo *E = Get_Torizo(k); + E->base.properties &= ~kEnemyProps_Invisible; + return j; +} + +uint16 Torizo_Instr_37(uint16 k, uint16 j) { // 0xAAB22E + Enemy_Torizo *E = Get_Torizo(k); + E->base.properties |= kEnemyProps_Invisible; + return j; +} + +uint16 Torizo_Instr_35(uint16 k, uint16 j) { // 0xAAB238 + for (int i = 30; i >= 0; i -= 2) { + int v3 = i >> 1; + target_palettes[v3 + 160] = 0; + target_palettes[v3 + 144] = 0; + } + return j; +} + +uint16 Torizo_Instr_38(uint16 k, uint16 j) { // 0xAAB24D + SetBossBitForCurArea(4u); + QueueMusic_Delayed8(g_word_AAB09A); + if (area_index) + Enemy_ItemDrop_GoldenTorizo(k); + else + Enemy_ItemDrop_BombTorizo(k); + return j; +} + +uint16 Torizo_Instr_6(uint16 k, uint16 j) { // 0xAAB271 + sub_82DAF7(0x600u); + return j; +} + +uint16 Torizo_Instr_5(uint16 k, uint16 j) { // 0xAAB94D + Torizo_C268(); + return j; +} + +uint16 Torizo_Instr_9(uint16 k, uint16 j) { // 0xAAB951 + QueueMusic_Delayed8(g_word_AAB098); + SpawnPalfxObject(addr_stru_8DF759); + return j; +} + +void Torizo_C20A(uint16 k) { // 0xAAC20A + int16 v2; + + Enemy_Torizo *E = Get_Torizo(k); + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v2 = 512; + else + v2 = -512; + E->toriz_var_A = v2; + E->toriz_var_B = -1472; + E->toriz_var_C = 40; + E->base.instruction_timer = 1; +} + +void Torizo_C22D(uint16 k) { // 0xAAC22D + int16 v2; + + Enemy_Torizo *E = Get_Torizo(k); + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v2 = -768; + else + v2 = 768; + E->toriz_var_A = v2; + E->toriz_var_B = -1152; + E->toriz_var_C = 40; + E->base.instruction_timer = 1; +} + +void Torizo_C250(void) { // 0xAAC250 + for (int i = 30; i >= 0; i -= 2) { + int v1 = i >> 1; + target_palettes[v1 + 160] = kTorizo_Palettes_3[v1]; + target_palettes[v1 + 144] = kTorizo_Palettes_2[v1]; + } +} + +void Torizo_C268(void) { // 0xAAC268 + for (int i = 30; i >= 0; i -= 2) { + int v1 = i >> 1; + target_palettes[v1 + 160] = kTorizo_Palettes_5[v1]; + target_palettes[v1 + 144] = kTorizo_Palettes_4[v1]; + } +} + +void Torizo_C280(void) { // 0xAAC280 + for (int i = 30; i >= 0; i -= 2) { + int v1 = i >> 1; + target_palettes[v1 + 160] = kTorizo_Palettes_7[v1]; + target_palettes[v1 + 144] = kTorizo_Palettes_6[v1]; + } +} + +void Torizo_C298(void) { // 0xAAC298 + for (int i = 30; i >= 0; i -= 2) { + int v1 = i >> 1; + target_palettes[v1 + 160] = kTorizo_Palettes_10[v1]; + target_palettes[v1 + 144] = kTorizo_Palettes_8[v1]; + } +} + +void Torizo_C2B0(void) { // 0xAAC2B0 + for (int i = 30; i >= 0; i -= 2) { + int v1 = i >> 1; + palette_buffer[v1 + 160] = kTorizo_Palettes_5[v1]; + palette_buffer[v1 + 144] = kTorizo_Palettes_4[v1]; + } +} + +uint16 Torizo_Instr_7(uint16 k, uint16 j) { // 0xAAC2C8 + return j; +} + +uint16 Torizo_Instr_2(uint16 k, uint16 j) { // 0xAAC2C9 + Get_Torizo(k)->toriz_var_04 = 30583; + return j; +} + +uint16 Torizo_Instr_8(uint16 k, uint16 j) { // 0xAAC2D1 + Get_Torizo(k)->toriz_var_04 = 0; + return j; +} + +uint16 Torizo_Instr_25(uint16 k, uint16 j) { // 0xAAC2D9 + if ((Get_Torizo(k)->toriz_parameter_2 & 0x4000) != 0) + return *(uint16 *)RomPtr_AA(j); + j += 2; + if (area_index) + return *(uint16 *)RomPtr_AA(j); + else + return j + 2; +} + +uint16 Torizo_Instr_22(uint16 k, uint16 j) { // 0xAAC2ED + uint16 v2 = *(uint16 *)RomPtr_AA(j); + Get_Torizo(k)->toriz_var_00 = v2; + return j + 2; +} + +uint16 Torizo_Instr_19(uint16 k, uint16 j) { // 0xAAC2F7 + return Get_Torizo(k)->toriz_var_00; +} + +uint16 Torizo_Instr_32(uint16 k, uint16 j) { // 0xAAC2FD + return Get_Torizo(k)->toriz_var_01; +} + +uint16 Torizo_Instr_30(uint16 k, uint16 j) { // 0xAAC303 + uint16 a = *(uint16 *)RomPtr_AA(j); + for (int i = 5; i >= 0; --i) + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_BombTorizoLowHealthExplode, a); + Enemy_Torizo *E = Get_Torizo(k); + E->base.current_instruction = j + 2; + E->base.flash_timer = 40; + E->base.instruction_timer = 40; + return 0; +} + +uint16 Torizo_Instr_34(uint16 k, uint16 j) { // 0xAAC32F + printf("A undefined\n"); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_BombTorizoDeathExplosion, 0); + Enemy_Torizo *E = Get_Torizo(k); + E->base.current_instruction = j; + E->base.flash_timer = 1; + E->base.instruction_timer = 1; + return 0; +} + +uint16 Torizo_Instr_24(uint16 k, uint16 j) { // 0xAAC34A + printf("A undefined\n"); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianLandingDustCloudsRightFoot, 0); + SpawnEnemyProjectileWithRoomGfx(addr_stru_86AFF3, 0); + return j; +} + +uint16 Torizo_Instr_12(uint16 k, uint16 j) { // 0xAAC35B + uint16 health = Get_Torizo(k)->base.health; + if (health < 0x15Eu) + SpawnEnemyProjectileWithGfx(health, k, addr_kEproj_BombTorizoLowHealthInitialDrool); + return j; +} + +uint16 Torizo_Instr_10(uint16 k, uint16 j) { // 0xAAC36D + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_parameter_1 |= 0x4000u; + return j; +} + +uint16 Torizo_Instr_11(uint16 k, uint16 j) { // 0xAAC377 + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_parameter_1 &= 0x1FFFu; + ++E->toriz_var_09; + return j; +} + +uint16 Torizo_Instr_29(uint16 k, uint16 j) { // 0xAAC38A + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_parameter_1 = E->toriz_parameter_1 & 0x1FFF | 0x8000; + ++E->toriz_var_09; + return j; +} + +uint16 Torizo_Instr_1(uint16 k, uint16 j) { // 0xAAC3A0 + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_parameter_1 = E->toriz_parameter_1 & 0x1FFF | 0x2000; + ++E->toriz_var_09; + return j; +} + +uint16 Torizo_Instr_28(uint16 k, uint16 j) { // 0xAAC3B6 + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_parameter_1 = E->toriz_parameter_1 & 0x1FFF | 0xA000; + ++E->toriz_var_09; + return j; +} + +uint16 Torizo_Instr_4(uint16 k, uint16 j) { // 0xAAC3CC + uint16 v2 = *(uint16 *)RomPtr_AA(j); + Enemy_Torizo *E = Get_Torizo(k); + E->base.x_pos += g_word_AAC3EE[v2 >> 1]; + E->base.y_pos += g_word_AAC40E[(uint8)(v2 & 0xF) >> 1]; + return j + 2; +} + +uint16 Torizo_Instr_40(uint16 k, uint16 j) { // 0xAAC41E + uint16 v2 = *(uint16 *)RomPtr_AA(j); + Enemy_Torizo *E = Get_Torizo(k); + E->base.x_pos -= g_word_AAC440[v2 >> 1]; + E->base.y_pos -= g_word_AAC460[(uint8)(v2 & 0xF) >> 1]; + return j + 2; +} + +uint16 Torizo_Instr_16(uint16 k, uint16 j) { // 0xAAC470 + R18_ = 0; + R20_ = g_word_AAC4BD[*(uint16 *)RomPtr_AA(j) >> 1]; + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_var_A = R20_; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->toriz_var_03 = 0; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + return addr_kTorizo_Ilist_B962; + else + return addr_kTorizo_Ilist_BDD8; + } else { + EnemyFunc_C8AD(k); + if (((E->toriz_parameter_1 ^ (samus_x_pos - E->base.x_pos)) & 0x8000u) == 0) { + if (!E->toriz_var_03) + E->toriz_var_03 = 72; + return j + 2; + } else { + return j + 2; + } + } +} + +uint16 Torizo_Instr_27(uint16 k, uint16 j) { // 0xAAC4E5 + R18_ = 0; + R20_ = g_word_AAC532[*(uint16 *)RomPtr_AA(j) >> 1]; + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_var_A = R20_; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->toriz_var_03 = 0; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + return addr_kTorizo_Ilist_BD0E; + else + return addr_kTorizo_Ilist_C188; + } else { + EnemyFunc_C8AD(k); + if (((E->toriz_parameter_1 ^ (samus_x_pos - E->base.x_pos)) & 0x8000u) == 0) { + if (!E->toriz_var_03) + E->toriz_var_03 = 72; + return j + 2; + } else { + return j + 2; + } + } +} + +uint16 Torizo_Instr_23(uint16 k, uint16 j) { // 0xAAC55A + if ((Get_Torizo(k)->toriz_var_B & 0x8000u) != 0) + return *(uint16 *)RomPtr_AA(j); + else + return j + 2; +} + +uint16 Torizo_Instr_14(uint16 k, uint16 j) { // 0xAAC567 + if (CompareDistToSamus_X(k, 0x38u) & 1) + return j + 2; + Enemy_Torizo *E = Get_Torizo(k); + if (((E->toriz_parameter_1 ^ (samus_x_pos - E->base.x_pos)) & 0x8000u) == 0) + return j + 2; + E->toriz_var_00 = j + 2; + return *(uint16 *)RomPtr_AA(j); +} + +uint16 Torizo_Instr_15(uint16 k, uint16 j) { // 0xAAC58B + if (CompareDistToSamus_X(k, 0x20u) & 1 || (Torizo_Func_12(k) & 0x8000u) != 0) + return j + 2; + Torizo_C22D(k); + return *(uint16 *)RomPtr_AA(j); +} + +uint16 Torizo_Instr_26(uint16 k, uint16 j) { // 0xAAC5A4 + Get_Torizo(k)->toriz_var_00 = j + 4; + if (samus_missiles < 5u || ((nmi_frame_counter_word + (samus_x_pos & 1) + (samus_x_pos >> 1)) & 8) != 0) + return *(uint16 *)RomPtr_AA(j); + else + return *((uint16 *)RomPtr_AA(j) + 1); +} + +uint16 Torizo_Instr_18(uint16 k, uint16 j) { // 0xAAC5CB + printf("A unknown\n"); + SpawnEnemyProjectileWithGfx(0, k, addr_kEproj_BombTorizosChozoOrbs); + SpawnEnemyProjectileWithGfx(0, k, addr_kEproj_BombTorizosChozoOrbs); + SpawnEnemyProjectileWithGfx(0, k, addr_kEproj_BombTorizosChozoOrbs); + return j; +} + +uint16 Torizo_Instr_20(uint16 k, uint16 j) { // 0xAAC5E3 + uint16 *v2 = (uint16 *)RomPtr_AA(j); + SpawnEnemyProjectileWithGfx(*v2, k, addr_kEproj_BombTorizoSonicBoom); + return j + 2; +} + +uint16 Torizo_Instr_44(uint16 k, uint16 j) { // 0xAAC5F2 + uint16 *v2 = (uint16 *)RomPtr_AA(j); + SpawnEnemyProjectileWithGfx(*v2, k, addr_kEproj_GoldenTorizoSonicBoom); + return j + 2; +} + +uint16 Torizo_Instr_21(uint16 k, uint16 j) { // 0xAAC601 + uint16 *v2 = (uint16 *)RomPtr_AA(j); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_BombTorizoExplosiveSwipe, *v2); + return j + 2; +} + +uint16 Torizo_Instr_17(uint16 k, uint16 j) { // 0xAAC610 + QueueSfx2_Max6(0x27u); + return j; +} + +uint16 Torizo_Instr_13(uint16 k, uint16 j) { // 0xAAC618 + QueueSfx2_Max6(0x4Bu); + return j; +} + +void Torizo_C620(uint16 k) { // 0xAAC620 + if (!area_index && (random_number & 0x8142) == 0) { + uint16 health = Get_Torizo(k)->base.health; + if (health) { + if (health < 0x15Eu) + SpawnEnemyProjectileWithGfx(health, k, addr_kEproj_BombTorizoLowHealthInitialDrool); + } + } +} + +void Torizo_C643(uint16 k) { // 0xAAC643 + int16 torizo_var_B; + int16 v3; + + R18_ = 0; + R20_ = 0; + Enemy_Torizo *E = Get_Torizo(k); + torizo_var_B = E->toriz_var_B; + if (torizo_var_B < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = torizo_var_B; + if (Enemy_MoveDown(k) & 1) { + v3 = E->toriz_var_B; + if (v3 >= 0 && v3 != 256) { + earthquake_type = 4; + earthquake_timer = 32; + E->toriz_var_B = 256; + } + } else { + E->toriz_var_B += 40; + } +} + +void Torizo_Hurt(void) { // 0xAAC67E + Torizo_C620(cur_enemy_index); + if (Get_Torizo(cur_enemy_index)->base.flash_timer & 1) { + for (int i = 30; i >= 0; i -= 2) { + int v2 = i >> 1; + palette_buffer[v2 + 160] = 0x7FFF; + palette_buffer[v2 + 144] = 0x7FFF; + } + } else { + Torizo_C2B0(); + } +} + +void CallTorizoFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnnullsub_270: return; + case fnTorizo_Func_3: Torizo_Func_3(k); return; + case fnTorizo_Func_4: Torizo_Func_4(k); return; + case fnTorizo_Func_1: Torizo_Func_1(k); return; + case fnTorizo_Func_9: Torizo_Func_9(k); return; + case fnTorizo_Func_10: Torizo_Func_10(k); return; + case fnTorizo_D5E6: Torizo_D5E6(k); return; + default: Unreachable(); + } +} + + +void Torizo_Main(void) { // 0xAAC6A4 + Enemy_Torizo *E = Get_Torizo(cur_enemy_index); + CallTorizoFunc(E->toriz_var_E | 0xAA0000, cur_enemy_index); +} + +void Torizo_Func_2(uint16 k) { // 0xAAC6AC + Torizo_C643(k); + if (!(sub_82DAF7(0x600u) & 1)) + Get_Torizo(k)->toriz_var_E = FUNC16(nullsub_270); +} + +void Torizo_Func_3(uint16 k) { // 0xAAC6BF + Torizo_C620(k); + Torizo_C643(k); +} + +void Torizo_Func_4(uint16 k) { // 0xAAC6C6 + Enemy_Torizo *E = Get_Torizo(k); + E->base.properties |= kEnemyProps_Tangible; + uint16 v2 = 78; + while (plm_header_ptr[v2 >> 1] != (uint16)addr_kPlmHeader_D6EA) { + v2 -= 2; + if ((v2 & 0x8000u) != 0) { + QueueMusic_Delayed8(g_word_AAB096); + E->base.properties &= ~kEnemyProps_Tangible; + ++E->base.current_instruction; + ++E->base.current_instruction; + E->base.instruction_timer = 1; + return; + } + } +} + +void Torizo_Func_1(uint16 k) { // 0xAAC6FF + Torizo_C620(k); + Enemy_Torizo *E = Get_Torizo(k); + if ((E->toriz_parameter_2 & 0x8000u) != 0 || E->base.health >= 0x15Eu) { + if ((E->toriz_parameter_2 & 0x4000) != 0 || E->base.health >= 0x64u) { + CallEnemyPreInstr(E->toriz_var_F | 0xAA0000); + } else { + uint16 v2; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v2 = addr_kTorizo_Ilist_BD0E; + else + v2 = addr_kTorizo_Ilist_C188; + E->toriz_var_00 = v2; + E->base.current_instruction = addr_kTorizo_Ilist_B155; + E->base.instruction_timer = 1; + } + } else { + E->toriz_var_01 = E->base.current_instruction; + E->base.current_instruction = addr_kTorizo_Ilist_B0E5; + E->base.instruction_timer = 1; + } +} + +void Torizo_Func_5(uint16 k) { // 0xAAC752 + uint16 v3; + uint16 v8; + + Enemy_Torizo *E = Get_Torizo(k); + if ((E->toriz_parameter_2 & 0x4000) != 0) { + uint16 torizo_var_03 = E->toriz_var_03; + if (!torizo_var_03 || (v8 = torizo_var_03 - 1, (E->toriz_var_03 = v8) != 0)) { + R18_ = 0; + uint16 v10 = abs16(E->toriz_var_A) + 1; + if (v10 >= 0x10u) + v10 = 15; + R20_ = v10; + if (!(Enemy_MoveDown(k) & 1)) { + uint16 v11; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v11 = addr_off_AAC0F2; + else + v11 = addr_off_AABC78; + E->base.current_instruction = v11; + E->base.instruction_timer = 1; + E->toriz_var_B = 256; + E->toriz_var_A = 0; + } + } else { + E->toriz_var_03 = 0; + uint16 v9; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v9 = addr_kTorizo_Ilist_BD0E; + else + v9 = addr_kTorizo_Ilist_C188; + E->base.current_instruction = v9; + E->base.instruction_timer = 1; + } + } else { + uint16 v2 = E->toriz_var_03; + if (!v2 || (v3 = v2 - 1, (E->toriz_var_03 = v3) != 0)) { + R18_ = 0; + uint16 v5 = abs16(E->toriz_var_A) + 1; + if (v5 >= 0x10u) + v5 = 15; + R20_ = v5; + if (!(Enemy_MoveDown(k) & 1)) { + uint16 v6; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v6 = addr_off_AAC0F2; + else + v6 = addr_off_AABC78; + E->base.current_instruction = v6; + E->base.instruction_timer = 1; + E->toriz_var_B = 256; + E->toriz_var_A = 0; + } + } else { + E->toriz_var_03 = 0; + uint16 v4; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v4 = addr_kTorizo_Ilist_B962; + else + v4 = addr_kTorizo_Ilist_BDD8; + E->base.current_instruction = v4; + E->base.instruction_timer = 1; + } + } +} + +void Torizo_Func_6(uint16 k) { // 0xAAC828 + Torizo_C643(k); +} + +void Torizo_Func_7(uint16 k) { // 0xAAC82C + int16 torizo_var_A; + int16 torizo_var_B; + + R18_ = 0; + R20_ = 0; + Enemy_Torizo *E = Get_Torizo(k); + torizo_var_A = E->toriz_var_A; + if (torizo_var_A < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = torizo_var_A; + Enemy_MoveRight_IgnoreSlopes(k); + EnemyFunc_C8AD(k); + R18_ = 0; + R20_ = 0; + torizo_var_B = E->toriz_var_B; + if (torizo_var_B < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = torizo_var_B; + if (Enemy_MoveDown(k) & 1) { + E->base.current_instruction = E->toriz_var_00; + E->base.instruction_timer = 1; + E->toriz_var_B = 256; + earthquake_type = 4; + earthquake_timer = 32; + } else { + E->toriz_var_B += E->toriz_var_C; + } +} + +void Torizo_Init(void) { // 0xAAC87F + Enemy_Torizo *E = Get_Torizo(cur_enemy_index); + if (CheckBossBitForCurArea(4u) & 1) { + E->base.properties |= kEnemyProps_Deleted; + } else { + int v2 = area_index >> 1; + E->base.properties |= g_word_AAC96B[v2]; + E->base.extra_properties |= 4u; + E->base.x_width = g_word_AAC96F[v2]; + E->base.y_height = g_word_AAC973[v2]; + E->toriz_var_E = FUNC16(Torizo_Func_3); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.palette_index = 0; + E->toriz_var_F = addr_locret_AAC95E; + E->base.current_instruction = g_off_AAC967[v2]; + E->base.spritemap_pointer = addr_kTorizo_ExtSprmap_87D0; + E->base.x_pos = g_word_AAC95F[v2]; + E->base.y_pos = g_word_AAC963[v2]; + E->toriz_var_A = 0; + E->toriz_var_B = 256; + for (int i = 30; i >= 0; i -= 2) { + int v4 = i >> 1; + target_palettes[v4 + 240] = kTorizo_Palettes_1[v4]; + target_palettes[v4 + 176] = kTorizo_Palette[v4]; + } + if (area_index) { + Torizo_C280(); + if (joypad1_lastkeys == 0xC0C0) { + samus_health = 700; + samus_max_health = 700; + samus_max_reserve_health = 300; + samus_reserve_health = 300; + samus_missiles = 100; + samus_max_missiles = 100; + samus_super_missiles = 20; + samus_max_super_missiles = 20; + samus_power_bombs = 20; + samus_max_power_bombs = 20; + equipped_items = -3273; + collected_items = -3273; + equipped_beams = 4111; + collected_beams = 4111; + } + } else { + Torizo_C250(); + SpawnBombTorizoHaze(); + } + } +} + +void GoldTorizo_Touch(void) { // 0xAAC977 + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); +} + +void Torizo_Shot(void) { // 0xAAC97C + if (area_index) { + GoldTorizo_Shot(); + } else { + Enemy_Torizo *E = Get_Torizo(cur_enemy_index); + if (!(E->toriz_var_04 | E->base.flash_timer)) { + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + if (!E->base.health) { + E->toriz_var_E = FUNC16(nullsub_270); + E->base.current_instruction = addr_kTorizo_Ilist_B1C8; + E->base.instruction_timer = 1; + E->toriz_parameter_2 |= 0xC000u; + E->base.properties |= kEnemyProps_Tangible; + } + } + } +} + +void Torizo_Func_8(void) { // 0xAAC9C2 + if (area_index) + Torizo_D658(); +} + +uint16 Torizo_Instr_39(uint16 k, uint16 j) { // 0xAACACE + if (Get_Torizo(k)->base.y_pos == 375) + return j + 2; + else + return *(uint16 *)RomPtr_AA(j); +} + +uint16 Torizo_Instr_41(uint16 k, uint16 j) { // 0xAACADE + Torizo_C298(); + return j; +} + +uint16 Torizo_Instr_42(uint16 k, uint16 j) { // 0xAACAE2 + QueueMusic_Delayed8(5u); + Enemy_Torizo *E = Get_Torizo(k); + E->base.x_width = 18; + E->base.y_height = 48; + SpawnPalfxObject(addr_stru_8DF75D); + return j; +} + +uint16 Torizo_Instr_48(uint16 k, uint16 j) { // 0xAACDD7 + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_parameter_2 &= ~0x1000u; + return j; +} + +uint16 Torizo_Instr_57(uint16 k, uint16 j) { // 0xAAD0E9 + printf("A unknown\n"); + SpawnEnemyProjectileWithRoomGfx(addr_stru_86B1C0, 0); + return j; +} + +uint16 Torizo_Instr_58(uint16 k, uint16 j) { // 0xAAD0F3 + int16 v2; + + v2 = 34; + while (*(uint16 *)((char *)enemy_projectile_id + (uint16)v2) != 0xB1C0) { + v2 -= 2; + if (v2 < 0) + return j + 2; + } + return *(uint16 *)RomPtr_AA(j); +} + +uint16 Torizo_Instr_59(uint16 k, uint16 j) { // 0xAAD17B + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_var_06 &= ~0x8000u; + return j; +} + +uint16 Torizo_Instr_62(uint16 k, uint16 j) { // 0xAAD187 + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_var_06 |= 0x8000u; + return j; +} + +uint16 Torizo_Instr_63(uint16 k, uint16 j) { // 0xAAD1E7 + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_parameter_2 &= ~0x2000u; + return j; +} + + +void GoldTorizo_Main(void) { // 0xAAD369 + Enemy_Torizo *E = Get_Torizo(cur_enemy_index); + + if (samus_pose == kPose_1B_FaceR_SpaceJump || samus_pose == kPose_1C_FaceL_SpaceJump) { + ++E->toriz_var_07; + } else { + E->toriz_var_07 = 0; + } + CallTorizoFunc(E->toriz_var_E | 0xAA0000, cur_enemy_index); +} + +uint16 Torizo_Instr_56(uint16 k, uint16 j) { // 0xAAD38F + QueueSfx2_Max6(0x34u); + return j; +} + +uint16 Torizo_Instr_60(uint16 k, uint16 j) { // 0xAAD397 + QueueSfx2_Max6(0x67u); + return j; +} + +uint16 Torizo_Instr_46(uint16 k, uint16 j) { // 0xAAD39F + QueueSfx2_Max6(0x48u); + return j; +} + +uint16 Torizo_Func_12(uint16 k) { // 0xAAD3A7 + Enemy_Torizo *E = Get_Torizo(k); + return E->toriz_parameter_1 ^ (E->base.x_pos - samus_x_pos); +} + +void Torizo_Func_11(uint16 k) { // 0xAAD3B2 + Enemy_Torizo *E = Get_Torizo(k); + SetGoldenTorizoPalette(E->base.health); +} + +void GoldTorizo_Hurt(void) { // 0xAAD3BA + Torizo_C620(cur_enemy_index); + if (gEnemyData(cur_enemy_index)->flash_timer & 1) { + for (int i = 30; i >= 0; i -= 2) { + int v2 = i >> 1; + palette_buffer[v2 + 160] = 0x7FFF; + palette_buffer[v2 + 144] = 0x7FFF; + } + } else { + Torizo_Func_11(cur_enemy_index); + } +} + +uint16 Torizo_Instr_47(uint16 k, uint16 j) { // 0xAAD3E0 + uint16 v2 = 0; + printf("A unknown\n"); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_GoldenTorizoSuperMissile, v2); + return j; +} + +uint16 Torizo_Instr_49(uint16 k, uint16 j) { // 0xAAD3EA + if ((Torizo_Func_12(k) & 0x8000u) == 0 + || !(CompareDistToSamus_X(k, 4u) & 1) + || CompareDistToSamus_X(k, 0x28u) & 1 + || samus_pose != kPose_1D_FaceR_Morphball_Ground + && samus_pose != kPose_1E_MoveR_Morphball_Ground + && samus_pose != kPose_1F_MoveL_Morphball_Ground + && samus_pose != kPose_79_FaceR_Springball_Ground + && samus_pose != kPose_7A_FaceL_Springball_Ground + && samus_pose != kPose_7B_MoveR_Springball_Ground + && samus_pose != kPose_7C_MoveL_Springball_Ground) { + return j + 2; + } + Get_Torizo(k)->toriz_var_09 = 0; + return *(uint16 *)RomPtr_AA(j); +} + +uint16 Torizo_Instr_61(uint16 k, uint16 j) { // 0xAAD436 + uint16 *v2 = (uint16 *)RomPtr_AA(j); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_GoldenTorizoEyeBeam, *v2); + return j + 2; +} + +uint16 Torizo_Instr_53(uint16 k, uint16 j) { // 0xAAD445 + if ((Torizo_Func_12(k) & 0x8000u) != 0 + || !(CompareDistToSamus_X(k, 0x20u) & 1) + || CompareDistToSamus_X(k, 0x60u) & 1 + || (NextRandom() & 0x110) != 0) { + return j + 2; + } + Get_Torizo(k)->toriz_var_00 = j + 2; + return *(uint16 *)RomPtr_AA(j); +} + +uint16 Torizo_Instr_55(uint16 k, uint16 j) { // 0xAAD474 + Enemy_Torizo *E = Get_Torizo(k); + if (E->base.health > 0x788u || (NextRandom() & 0x102) != 0) + return j + 2; + E->toriz_var_09 = 0; + E->toriz_var_00 = j + 2; + return *(uint16 *)RomPtr_AA(j); +} + +uint16 Torizo_Instr_52(uint16 k, uint16 j) { // 0xAAD49B + Enemy_Torizo *E = Get_Torizo(k); + if (E->base.health <= 0x2A30u || (E->toriz_parameter_2 & 0x2000) == 0) + return j + 2; + E->toriz_var_00 = j + 2; + return *(uint16 *)RomPtr_AA(j); +} + +uint16 Torizo_Instr_50(uint16 k, uint16 j) { // 0xAAD4BA + if (!(CompareDistToSamus_X(k, 0x70u) & 1)) + return j + 2; + if ((Torizo_Func_12(k) & 0x8000u) != 0) + return j + 2; + Enemy_Torizo *E = Get_Torizo(k); + if (E->toriz_var_07 <= 0x168u && ((joypad1_lastkeys & 0x300) == 0 || (NextRandom() & 0x101) == 0)) + return j + 2; + E->toriz_var_09 = 0; + Torizo_C20A(k); + return *(uint16 *)RomPtr_AA(j); +} + +uint16 Torizo_Instr_43(uint16 k, uint16 j) { // 0xAAD4F3 + uint16 v2; + printf("A unknown\n"); v2 = 0; + SpawnEnemyProjectileWithGfx(v2, k, addr_kEproj_GoldenTorizosChozoOrbs); + return j; +} + +uint16 Torizo_Instr_51(uint16 k, uint16 j) { // 0xAAD4FD + Enemy_Torizo *E = Get_Torizo(k); + if (E->toriz_var_09 < 8u && (CompareDistToSamus_X(k, 0x20u) & 1 || (Torizo_Func_12(k) & 0x8000u) != 0)) + return j + 2; + E->toriz_var_09 = 0; + Torizo_C22D(k); + return *(uint16 *)RomPtr_AA(j); +} + +uint16 Torizo_Instr_45(uint16 k, uint16 j) { // 0xAAD526 + Get_Torizo(k)->toriz_var_00 = j + 4; + if (samus_missiles < 0x20u + || (((uint8)nmi_frame_counter_word + (samus_x_pos & 1) + (uint8)(samus_x_pos >> 1)) & 8) != 0) { + return *(uint16 *)RomPtr_AA(j); + } else { + return *((uint16 *)RomPtr_AA(j) + 1); + } +} + +uint16 Torizo_Instr_54(uint16 k, uint16 j) { // 0xAAD54D + R18_ = 0; + R20_ = g_word_AAD59A[*(uint16 *)RomPtr_AA(j) >> 1]; + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_var_A = R20_; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->toriz_var_03 = 0; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + return addr_kTorizo_Ilist_D203; + else + return addr_kTorizo_Ilist_D2BF; + } else { + EnemyFunc_C8AD(k); + if (((E->toriz_parameter_1 ^ (samus_x_pos - E->base.x_pos)) & 0x8000u) == 0) { + if (!E->toriz_var_03) + E->toriz_var_03 = 16; + return j + 2; + } else { + return j + 2; + } + } +} + +void Torizo_Func_9(uint16 k) { // 0xAAD5C2 + Enemy_Torizo *E = Get_Torizo(cur_enemy_index); + if (samus_y_pos > 0x140u && samus_x_pos > 0x170u) { + ++E->base.current_instruction; + ++E->base.current_instruction; + E->base.instruction_timer = 1; + } +} + +void Torizo_Func_10(uint16 k) { // 0xAAD5DF + Torizo_C620(k); + Torizo_C643(k); +} + +void Torizo_D5E6(uint16 k) { // 0xAAD5E6 + Torizo_C620(k); + Enemy_Torizo *E = Get_Torizo(k); + CallEnemyPreInstr(E->toriz_var_F | 0xAA0000); +} + +void Torizo_D5ED(uint16 k) { // 0xAAD5ED + Torizo_C643(k); +} + +void Torizo_D5F1(uint16 k) { // 0xAAD5F1 + uint16 v3; + + Enemy_Torizo *E = Get_Torizo(k); + uint16 torizo_var_03 = E->toriz_var_03; + if (!torizo_var_03 || (v3 = torizo_var_03 - 1, (E->toriz_var_03 = v3) != 0)) { + R18_ = 0; + uint16 v5 = abs16(E->toriz_var_A) + 1; + if (v5 >= 0x10u) + v5 = 15; + R20_ = v5; + if (!(Enemy_MoveDown(k) & 1)) { + uint16 v6; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v6 = addr_off_AAC0F2; + else + v6 = addr_off_AABC78; + E->base.current_instruction = v6; + E->base.instruction_timer = 1; + E->toriz_var_B = 256; + E->toriz_var_A = 0; + } + } else { + E->toriz_var_03 = 0; + uint16 v4; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v4 = addr_kTorizo_Ilist_D203; + else + v4 = addr_kTorizo_Ilist_D2BF; + E->base.current_instruction = v4; + E->base.instruction_timer = 1; + } +} + +void Torizo_D658(void) { // 0xAAD658 + Enemy_Torizo *E = Get_Torizo(cur_enemy_index); + if (!E->base.flash_timer && !E->toriz_var_04) + Torizo_D6A6(); +} + +void GoldTorizo_Shot(void) { // 0xAAD667 + Enemy_Torizo *E = Get_Torizo(cur_enemy_index); + if (!E->base.flash_timer) { + if (E->toriz_var_04) { + Torizo_D6A6(); + return; + } + if ((E->toriz_parameter_2 & 0x1000) != 0) + goto LABEL_11; + uint16 v2, v3; + v2 = 2 * collision_detection_index; + v3 = projectile_type[collision_detection_index] & 0xF00; + E->toriz_var_05 = v3; + if (v3 == 256) { + Torizo_D6D1(cur_enemy_index, v2); + return; + } + if (v3 != 512) { +LABEL_11: + E->toriz_parameter_2 |= 0x2000u; + Torizo_D6A6(); + } else { + Torizo_D6F7(cur_enemy_index, v2); + } + } +} + +void Torizo_D6A6(void) { // 0xAAD6A6 + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + Enemy_Torizo *E = Get_Torizo(cur_enemy_index); + if (!E->base.health) { + E->base.current_instruction = addr_kTorizo_Ilist_B1C8; + E->base.instruction_timer = 1; + E->toriz_parameter_2 |= 0xC000u; + E->base.properties |= kEnemyProps_Tangible; + } +} + +void Torizo_D6D1(uint16 k, uint16 j) { // 0xAAD6D1 + projectile_dir[j >> 1] &= ~0x10u; + Enemy_Torizo *E = Get_Torizo(k); + E->toriz_var_E = FUNC16(nullsub_270); + E->base.instruction_timer = 1; + uint16 v3; + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v3 = addr_kTorizo_Ilist_D2AD; + else + v3 = addr_kTorizo_Ilist_D1F1; + E->base.current_instruction = v3; +} + +void Torizo_D6F7(uint16 k, uint16 j) { // 0xAAD6F7 + Enemy_Torizo *E = Get_Torizo(cur_enemy_index); + + if ((Torizo_Func_12(k) & 0x8000u) == 0) { + E->toriz_parameter_2 |= 0x1000u; + E->toriz_var_E = FUNC16(nullsub_270); + projectile_dir[j >> 1] |= 0x10u; + E->base.instruction_timer = 1; + uint16 v3; + if ((E->toriz_parameter_1 & 0x2000) != 0) { + if ((E->toriz_parameter_1 & 0x8000u) != 0) + v3 = addr_kTorizo_Ilist_CEFF; + else + v3 = addr_kTorizo_Ilist_CE43; + } else if ((E->toriz_parameter_1 & 0x8000u) != 0) { + v3 = addr_kTorizo_Ilist_CEA5; + } else { + v3 = addr_kTorizo_Ilist_CDE1; + } + E->base.current_instruction = v3; + } else { + Torizo_D6A6(); + } +} + +void TourianEntranceStatue_Init(void) { // 0xAAD7C8 + EnemyData *v0 = gEnemyData(cur_enemy_index); + v0->palette_index = 0; + v0->instruction_timer = 1; + v0->timer = 0; + uint16 v1 = g_off_AAD810[v0->parameter_1 >> 1]; + v0->current_instruction = v1; + if (!v0->parameter_1) { + printf("A unknown\n"); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatueBaseDecoration, 0); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatueRidley, 0); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_TourianStatuePhantoon, 0); + } + for (int i = 30; i >= 0; i -= 2) { + int v5 = i >> 1; + target_palettes[v5 + 240] = g_word_AAD785[v5]; + target_palettes[v5 + 160] = g_word_AAD765[v5]; + } +} + +uint16 Shaktool_Instr_2(uint16 k, uint16 j) { // 0xAAD931 + Enemy_Shaktool *E = Get_Shaktool(k); + Enemy_Shaktool *EX = Get_Shaktool(E->shakt_var_E + 192); + return Shaktool_D956(k, j, EX->shakt_var_D ^ 0x80); +} + +uint16 Shaktool_Instr_3(uint16 k, uint16 j) { // 0xAAD93F + Enemy_Shaktool *E = Get_Shaktool(k); + Enemy_Shaktool *EX = Get_Shaktool(E->shakt_var_E + 192); + return Shaktool_D956(k, j, EX->shakt_var_D); +} + +uint16 Shaktool_Instr_4(uint16 k, uint16 j) { // 0xAAD94A + Enemy_Shaktool *E = Get_Shaktool(k); + return Shaktool_D956(k, j, *(uint16 *)((char *)&E->shakt_var_A + 1) ^ 0x80); +} + +uint16 Shaktool_Instr_5(uint16 k, uint16 j) { // 0xAAD953 + Enemy_Shaktool *E = Get_Shaktool(k); + return Shaktool_D956(k, j, *(uint16 *)((char *)&E->shakt_var_A + 1)); +} + +uint16 Shaktool_D956(uint16 k, uint16 j, uint16 a) { // 0xAAD956 + int16 v4; + int16 v8; + + R18_ = 0; + R20_ = 0; + int v3 = (uint16)(2 * (uint8)a) >> 1; + v4 = kSinCosTable8bit_Sext[v3 + 64]; + if (v4 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v4; + Enemy_Shaktool *E = Get_Shaktool(k); + uint16 x_subpos = E->base.x_subpos; + bool v7 = __CFADD__uint16(R18_, x_subpos); + E->base.x_subpos = R18_ + x_subpos; + E->base.x_pos += R20_ + v7; + R18_ = 0; + R20_ = 0; + v8 = kSinCosTable8bit_Sext[v3]; + if (v8 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v8; + uint16 y_subpos = E->base.y_subpos; + v7 = __CFADD__uint16(R18_, y_subpos); + E->base.y_subpos = R18_ + y_subpos; + E->base.y_pos += R20_ + v7; + return j; +} + +uint16 Shaktool_Instr_6(uint16 k, uint16 j) { // 0xAAD99F + return j; +} + +void Shaktool_Func_2(uint16 k) { // 0xAAD9A0 + printf("A unknown!\n"); + SpawnEnemyProjectileWithGfx(0, k, addr_kEproj_ShaktoolAttackFrontCircle); + SpawnEnemyProjectileWithGfx(0, k, addr_kEproj_ShaktoolAttackMiddleCircle); + SpawnEnemyProjectileWithGfx(0, k, addr_kEproj_ShaktoolAttackBackCircle); +} + +uint16 Shaktool_Instr_1(uint16 k, uint16 j) { // 0xAAD9BA + uint16 shakt_var_E = Get_Shaktool(k)->shakt_var_E; + Get_Shaktool(shakt_var_E)->shakt_var_F = g_off_AADEDB[0]; + Get_Shaktool(shakt_var_E + 64)->shakt_var_F = g_off_AADEDB[1]; + Get_Shaktool(shakt_var_E + 128)->shakt_var_F = g_off_AADEDB[2]; + Get_Shaktool(shakt_var_E + 192)->shakt_var_F = g_off_AADEDB[3]; + Get_Shaktool(shakt_var_E + 256)->shakt_var_F = g_off_AADEDB[4]; + Get_Shaktool(shakt_var_E + 320)->shakt_var_F = g_off_AADEDB[5]; + Get_Shaktool(shakt_var_E + 384)->shakt_var_F = g_off_AADEDB[6]; + return j; +} + +void Shaktool_DAE5(uint16 k) { // 0xAADAE5 + if ((NextRandom() & 0x8431) == 0) { + for (int i = 12; i >= 0; i -= 2) { + Enemy_Shaktool *E = Get_Shaktool(k); + E->shakt_var_F = FUNC16(nullsub_274); + E->base.current_instruction = g_off_AADF21[i >> 1]; + E->base.instruction_timer = 1; + k -= 64; + } + } +} + +void Shaktool_DB0E(uint16 k, uint16 a) { // 0xAADB0E + uint16 shakt_var_E = Get_Shaktool(k)->shakt_var_E; + Get_Shaktool(shakt_var_E)->shakt_parameter_1 = a; + Get_Shaktool(shakt_var_E + 64)->shakt_parameter_1 = a; + Get_Shaktool(shakt_var_E + 128)->shakt_parameter_1 = a; + Get_Shaktool(shakt_var_E + 192)->shakt_parameter_1 = a; + Get_Shaktool(shakt_var_E + 256)->shakt_parameter_1 = a; + Get_Shaktool(shakt_var_E + 320)->shakt_parameter_1 = a; + Get_Shaktool(shakt_var_E + 384)->shakt_parameter_1 = a; +} + +void Shaktool_DB27(uint16 k, uint16 a) { // 0xAADB27 + uint16 shakto_var_E = Get_Shaktool(k)->shakt_var_E; + Get_Shaktool(shakto_var_E)->shakt_var_A = a; + Get_Shaktool(shakto_var_E + 64)->shakt_var_A = a; + Get_Shaktool(shakto_var_E + 128)->shakt_var_A = a; + Get_Shaktool(shakto_var_E + 192)->shakt_var_A = a; + Get_Shaktool(shakto_var_E + 256)->shakt_var_A = a; + Get_Shaktool(shakto_var_E + 320)->shakt_var_A = a; + Get_Shaktool(shakto_var_E + 384)->shakt_var_A = a; +} + +void Shaktool_DB40(uint16 k, uint16 a) { // 0xAADB40 + uint16 shakto_var_E = Get_Shaktool(k)->shakt_var_E; + Get_Shaktool(shakto_var_E)->shakt_var_B = a; + Get_Shaktool(shakto_var_E + 64)->shakt_var_B = a; + Get_Shaktool(shakto_var_E + 128)->shakt_var_B = a; + Get_Shaktool(shakto_var_E + 192)->shakt_var_B = a; + Get_Shaktool(shakto_var_E + 256)->shakt_var_B = a; + Get_Shaktool(shakto_var_E + 320)->shakt_var_B = a; + Get_Shaktool(shakto_var_E + 384)->shakt_var_B = a; +} + +void Shaktool_DB59(uint16 k) { // 0xAADB59 + uint16 shakto_var_E; + uint16 shakto_var_B; + uint16 v7; + uint16 v10; + uint16 x_subpos; + uint16 y_subpos; + uint16 x_pos; + uint16 y_pos; + + shakto_var_E = Get_Shaktool(k)->shakt_var_E; + Enemy_Shaktool *Shaktool = Get_Shaktool(shakto_var_E + 192); + Shaktool->shakt_var_D ^= 0x8000u; + Enemy_Shaktool *v3 = Get_Shaktool(shakto_var_E + 384); + shakto_var_B = v3->shakt_var_B; + Enemy_Shaktool *v5 = Get_Shaktool(shakto_var_E + 64); + v3->shakt_var_B = (v5->shakt_var_B ^ 0x8000) & 0xFF00; + v5->shakt_var_B = (shakto_var_B ^ 0x8000) & 0xFF00; + Enemy_Shaktool *v6 = Get_Shaktool(shakto_var_E + 320); + v7 = v6->shakt_var_B; + Enemy_Shaktool *v8 = Get_Shaktool(shakto_var_E + 128); + v6->shakt_var_B = (v8->shakt_var_B ^ 0x8000) & 0xFF00; + v8->shakt_var_B = (v7 ^ 0x8000) & 0xFF00; + Enemy_Shaktool *v9 = Get_Shaktool(shakto_var_E + 256); + v10 = v9->shakt_var_B; + Enemy_Shaktool *v11 = Get_Shaktool(shakto_var_E + 192); + v9->shakt_var_B = (v11->shakt_var_B ^ 0x8000) & 0xFF00; + v11->shakt_var_B = (v10 ^ 0x8000) & 0xFF00; + Enemy_Shaktool *v12 = Get_Shaktool(shakto_var_E + 384); + x_subpos = v12->base.x_subpos; + Enemy_Shaktool *v14 = Get_Shaktool(shakto_var_E); + v12->base.x_subpos = v14->base.x_subpos; + v14->base.x_subpos = x_subpos; + y_subpos = v12->base.y_subpos; + v12->base.y_subpos = v14->base.y_subpos; + v14->base.y_subpos = y_subpos; + x_pos = v12->base.x_pos; + v12->base.x_pos = v14->base.x_pos; + v14->base.x_pos = x_pos; + y_pos = v12->base.y_pos; + v12->base.y_pos = v14->base.y_pos; + v14->base.y_pos = y_pos; + Get_Shaktool(shakto_var_E + 64)->base.x_subpos = 0x8000; + Get_Shaktool(shakto_var_E + 128)->base.x_subpos = 0x8000; + Get_Shaktool(shakto_var_E + 192)->base.x_subpos = 0x8000; + Get_Shaktool(shakto_var_E + 256)->base.x_subpos = 0x8000; + Get_Shaktool(shakto_var_E + 320)->base.x_subpos = 0x8000; + Get_Shaktool(shakto_var_E + 64)->base.y_subpos = 0x8000; + Get_Shaktool(shakto_var_E + 128)->base.y_subpos = 0x8000; + Get_Shaktool(shakto_var_E + 192)->base.y_subpos = 0x8000; + Get_Shaktool(shakto_var_E + 256)->base.y_subpos = 0x8000; + Get_Shaktool(shakto_var_E + 320)->base.y_subpos = 0x8000; +} + +void Shaktool_DC07(uint16 k) { // 0xAADC07 + Enemy_Shaktool *E = Get_Shaktool(k); + uint16 v2; + if ((E->shakt_parameter_1 & 0x8000u) != 0) + v2 = E->shakt_var_B - E->shakt_var_A; + else + v2 = E->shakt_var_A - E->shakt_var_B; + E->shakt_var_C = 4 * HIBYTE(v2); +} + +void Shaktool_DC2A(uint16 k) { // 0xAADC2A + int16 v4; + int16 v7; + + Enemy_Shaktool *E = Get_Shaktool(k); + uint16 v2 = 2 * HIBYTE(E->shakt_var_B); + R18_ = 0; + R20_ = 0; + int v3 = v2 >> 1; + v4 = kSine[v3]; + if (v4 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v4; + int v5 = k >> 1; + bool v6 = __CFADD__uint16(enemy_drawing_queue[v5 + 92], R18_); + E->base.x_subpos = enemy_drawing_queue[v5 + 92] + R18_; + E->base.x_pos = enemy_drawing_queue[v5 + 91] + v6 + R20_; + R18_ = 0; + R20_ = 0; + v7 = kNegativeCosine[v3]; + if (v7 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v7; + v6 = __CFADD__uint16(enemy_drawing_queue[v5 + 94], R18_); + E->base.y_subpos = enemy_drawing_queue[v5 + 94] + R18_; + E->base.y_pos = enemy_drawing_queue[v5 + 93] + v6 + R20_; +} + +void Shaktool_DC6F(uint16 k) { // 0xAADC6F + Enemy_Shaktool *E = Get_Shaktool(k); + Shaktool_DB40(k, E->shakt_var_A); + uint16 shakto_var_E = E->shakt_var_E; + Get_Shaktool(shakto_var_E)->shakt_var_C = g_word_AADEE9[0]; + Get_Shaktool(shakto_var_E + 64)->shakt_var_C = g_word_AADEE9[1]; + Get_Shaktool(shakto_var_E + 128)->shakt_var_C = g_word_AADEE9[2]; + Get_Shaktool(shakto_var_E + 192)->shakt_var_C = g_word_AADEE9[3]; + Get_Shaktool(shakto_var_E + 256)->shakt_var_C = g_word_AADEE9[4]; + Get_Shaktool(shakto_var_E + 320)->shakt_var_C = g_word_AADEE9[5]; + Get_Shaktool(shakto_var_E + 384)->shakt_var_C = g_word_AADEE9[6]; +} + +void Shaktool_Hurt(void) { // 0xAADCA3 + Enemy_Shaktool *E = Get_Shaktool(cur_enemy_index); + CallEnemyPreInstr(E->shakt_var_F | 0xAA0000); +} + +void Shaktool_DCAC(uint16 k) { // 0xAADCAC + Shaktool_DC2A(k); + Enemy_Shaktool *E = Get_Shaktool(k); + uint16 shakto_var_C; + if ((E->shakt_parameter_1 & 0x4000) != 0) { + E->shakt_var_A += 256; + shakto_var_C = 256; + } else { + shakto_var_C = E->shakt_var_C; + } + E->shakt_var_B += sign16(E->shakt_parameter_1) ? -shakto_var_C : shakto_var_C; +} + +void Shaktool_DCD7(uint16 k) { // 0xAADCD7 + int16 v2; + + Shaktool_DCAC(k); + Enemy_Shaktool *E = Get_Shaktool(k); + R18_ = E->shakt_var_B ^ 0x8000; + v2 = R18_ + ((uint16)(Get_Shaktool(k + 64)->shakt_var_B - R18_) >> 1); + if ((E->shakt_var_D & 0x8000u) != 0) + HIBYTE(v2) ^= 0x80; + uint16 v3 = (HIBYTE(v2) + 8) & 0xE0; + LOBYTE(E->shakt_var_D) = v3; + E->base.current_instruction = g_off_AADD15[(uint16)(v3 >> 4) >> 1]; + E->base.instruction_timer = 1; +} + +void Shaktool_DD25(uint16 k) { // 0xAADD25 + char v6; // t0 + int16 v7; + + Enemy_Shaktool *E = Get_Shaktool(k); + uint16 y_pos = E->base.y_pos; + uint16 x_pos = E->base.x_pos; + Shaktool_DCAC(k); + uint16 v12 = E->base.y_pos; + uint16 v11 = E->base.x_pos; + E->base.x_pos = x_pos; + E->base.y_pos = y_pos; + R18_ = 0; + R20_ = v11 - x_pos; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1 + || (E->base.y_pos = y_pos, R18_ = 0, R20_ = v12 - y_pos, Enemy_MoveDown(k) & 1)) { + if ((E->shakt_parameter_1 & 0x2000) != 0) { + Shaktool_DB0E(k, (E->shakt_parameter_1 ^ 0x8000) & 0x8FFF); + } else { + E->base.x_pos = x_pos; + E->base.y_pos = y_pos; + Shaktool_DB59(k); + Shaktool_DB0E(cur_enemy_index, E->shakt_parameter_1 | 0x2000); + Shaktool_DB0E(cur_enemy_index, E->shakt_parameter_1 & 0xBFFF); + } + E->shakt_var_D = 0; + uint16 v5 = CalculateAngleOfEnemyXfromEnemyY(k, E->shakt_var_E); + v6 = v5; + LOBYTE(v5) = HIBYTE(v5); + HIBYTE(v5) = v6; + v7 = v5 & 0xFF00; + uint16 v8; + if ((E->shakt_parameter_1 & 0x8000u) != 0) + v8 = v7 - 0x4000; + else + v8 = v7 + 0x4000; + Shaktool_DB27(k, v8); + for (int i = 12; i >= 0; i -= 2) { + Shaktool_DC07(k); + E->shakt_var_F = FUNC16(nullsub_274); + E->base.current_instruction = g_off_AADF13[i >> 1]; + E->base.instruction_timer = 1; + k -= 64; + } + } else { + E->base.x_pos = v11; + E->base.y_pos = v12; + if ((E->shakt_parameter_1 & 0x4000) != 0) { + E->shakt_var_A += 256; + } else { + if (((E->shakt_var_A ^ E->shakt_var_B) & 0xFF00) == 0) { + Shaktool_DC6F(k); + E->shakt_var_D = 30720; + Shaktool_DB0E(k, E->shakt_parameter_1 & 0xDFFF); + E->shakt_var_D = HIBYTE(E->shakt_var_D) << 8; + } + uint16 v2 = E->shakt_var_D + E->shakt_var_C; + E->shakt_var_D = v2; + if (v2 >= 0xF000u) + Shaktool_DB0E(k, E->shakt_parameter_1 | 0x4000); + } + } +} + +void Shaktool_Init(void) { // 0xAADE43 + Enemy_Shaktool *E = Get_Shaktool(cur_enemy_index); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->shakt_var_A = 0; + E->shakt_var_D = 0; + uint16 shakto_parameter_2 = E->shakt_parameter_2; + int v3 = shakto_parameter_2 >> 1; + E->base.properties |= g_word_AADE95[v3]; + E->shakt_var_E = cur_enemy_index - g_word_AADEA3[v3]; + E->shakt_var_F = *(uint16 *)((char *)g_off_AADEDB + shakto_parameter_2); + E->shakt_var_C = *(uint16 *)((char *)g_word_AADEE9 + shakto_parameter_2) - g_word_AADEF7[v3]; + E->shakt_var_B = g_word_AADEB1[v3]; + E->base.current_instruction = g_word_AADEB1[v3 + 7]; + E->base.layer = g_word_AADECD[v3]; + if (shakto_parameter_2) + Shaktool_DC2A(cur_enemy_index); +} + +void Shaktool_Touch(void) { // 0xAADF2F + NormalEnemyTouchAi(); +} + +void Shaktool_Shot(void) { // 0xAADF34 + NormalEnemyShotAi(); + Enemy_Shaktool *E = Get_Shaktool(cur_enemy_index); + if (!E->base.health) { + uint16 shakto_var_E = E->shakt_var_E; + Get_Shaktool(shakto_var_E)->base.properties = 512; + Get_Shaktool(shakto_var_E + 64)->base.properties = 512; + Get_Shaktool(shakto_var_E + 128)->base.properties = 512; + Get_Shaktool(shakto_var_E + 192)->base.properties = 512; + Get_Shaktool(shakto_var_E + 256)->base.properties = 512; + Get_Shaktool(shakto_var_E + 320)->base.properties = 512; + Get_Shaktool(shakto_var_E + 384)->base.properties = 512; + } +} + +uint16 Shaktool_Instr_9(uint16 k, uint16 j) { // 0xAAE429 + fx_timer = 32; + fx_y_vel = 64; + return j; +} + +uint16 Shaktool_Instr_11(uint16 k, uint16 j) { // 0xAAE436 + fx_base_y_pos = 722; + return j; +} + +uint16 Shaktool_Instr_10(uint16 k, uint16 j) { // 0xAAE43D + CallSomeSamusCode(1u); + return j; +} + +void sub_AAE445(uint16 k) { // 0xAAE445 + EnemyData *v1 = gEnemyData(k); + if (v1->parameter_1) { + v1->current_instruction = addr_kShaktool_Ilist_E3A7; + v1->instruction_timer = 1; + } +} + +uint16 Shaktool_Instr_8(uint16 k, uint16 j) { // 0xAAE57F + QueueSfx2_Max6(0x1Cu); + return j; +} + +uint16 Shaktool_Instr_13(uint16 k, uint16 j) { // 0xAAE587 + QueueSfx2_Max6(0x4Bu); + return j; +} + +uint16 Shaktool_Instr_12(uint16 k, uint16 j) { // 0xAAE58F + Enemy_Shaktool *e = Get_Shaktool(k); + uint16 arg = *(uint16 *)RomPtr_AA(j); + + CalculateBlockContainingPixelPos(e->base.x_pos + arg, e->base.y_pos + 28); + if ((level_data[room_width_in_blocks + cur_block_index] & 0xF000) == 0xA000) { + SpawnPLM(addr_kPlmHeader_D113); + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_WreckedShipChozoSpikeFootsteps_1, arg); + } + return j + 2; +} + +uint16 Shaktool_Instr_7(uint16 k, uint16 j) { // 0xAAE5D8 + int16 v4; + int16 v5; + + uint16 v2 = *(uint16 *)RomPtr_AA(j); + Enemy_Shaktool *E = Get_Shaktool(k); + E->shakt_var_C = v2; + R18_ = 0; + R20_ = 0; + v4 = g_word_AAE630[E->shakt_var_C >> 1]; + if (v4 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v4; + Enemy_MoveRight_IgnoreSlopes(k); + R18_ = 0; + R20_ = 0; + v5 = abs16(g_word_AAE630[E->shakt_var_C >> 1]); + if (v5 < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = v5; + Enemy_MoveDown(k); + EnemyFunc_C8AD(k); + int v6 = E->shakt_var_C >> 1; + samus_x_pos = g_word_AAE670[v6] + E->base.x_pos; + samus_y_pos = g_word_AAE6B0[v6] + E->base.y_pos; + return j + 2; +} + +uint16 Shaktool_Instr_14(uint16 k, uint16 j) { // 0xAAE6F0 + CallSomeSamusCode(1u); + *(uint16 *)&scrolls[6] = 0; + *(uint16 *)&scrolls[8] = 0; + *(uint16 *)&scrolls[9] = 0; + *(uint16 *)&scrolls[13] = 1; + static const SpawnHardcodedPlmArgs unk_AAE711 = { 0x17, 0x1d, 0xd6fc }; + SpawnHardcodedPlm(&unk_AAE711); + return j; +} + +void N00bTubeCracks_Init(void) { // 0xAAE716 + for (int i = 62; i >= 0; i -= 2) + target_palettes[(i >> 1) + 144] = kN00bTubeCracks_Palette2[i >> 1]; +} + +void ChozoStatue_Init(void) { // 0xAAE725 + EnemyData *v0 = gEnemyData(cur_enemy_index); + v0->properties |= kEnemyProps_DisableSamusColl | kEnemyProps_ProcessedOffscreen | 0x8000; + v0->spritemap_pointer = addr_kSpritemap_Nothing_AA; + v0->instruction_timer = 1; + v0->timer = 0; + v0->ai_preinstr = FUNC16(nullsub_276); + v0->parameter_1 = 0; + v0->palette_index = 0; + gEnemyData(0)->layer = 0; + uint16 parameter_2 = v0->parameter_2; + v0->current_instruction = g_off_AAE7A2[parameter_2 >> 1]; + if (parameter_2) { + sub_AAE784(); + } else { + for (int i = 30; i >= 0; i -= 2) { + int v3 = i >> 1; + target_palettes[v3 + 160] = kChozoStatue_Palettes[v3]; + target_palettes[v3 + 144] = kChozoStatue_Palette[v3]; + } + static const SpawnHardcodedPlmArgs unk_AAE77F = { 0x17, 0x1d, 0xd6fc }; + static const SpawnHardcodedPlmArgs unk_AAE777 = { 0x4a, 0x17, 0xd6ee }; + SpawnHardcodedPlm(&unk_AAE777); + SpawnHardcodedPlm(&unk_AAE77F); + } +} + +static const SpawnHardcodedPlmArgs unk_AAE79D = { 0x0c, 0x1d, 0xd6d6 }; + +void sub_AAE784(void) { // 0xAAE784 + for (int i = 30; i >= 0; i -= 2) { + int v1 = i >> 1; + target_palettes[v1 + 160] = kChozoStatue_Palettes3[v1]; + target_palettes[v1 + 144] = kChozoStatue_Palettes2[v1]; + } + SpawnHardcodedPlm(&unk_AAE79D); +} + +void ChozoStatue_Main(void) { // 0xAAE7A7 + EnemyData *v0 = gEnemyData(cur_enemy_index); + CallEnemyPreInstr(v0->ai_preinstr | 0xAA0000); +} + +void Shaktool_PreInstr_0(uint16 k) { // 0xAAE7AE + if ((*(uint16 *)&boss_bits_for_area[area_index] & 1) != 0) { + Enemy_Shaktool *E = Get_Shaktool(k); + if (E->shakt_parameter_1) { + E->base.current_instruction = addr_kShaktool_Ilist_E461; + E->base.instruction_timer = 1; + E->shakt_var_A = -256; + E->shakt_var_B = 256; + } + } +} diff --git a/src/sm_ad.c b/src/sm_ad.c new file mode 100644 index 0000000..d62e59d --- /dev/null +++ b/src/sm_ad.c @@ -0,0 +1,528 @@ +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" + +void nullsub_341(void) {} + +static Func_V *const funcs_BE56D[16] = { + MotherBrain_CalcHdma_Down, MotherBrain_CalcHdma_BeamAimedRight2, 0, 0, + 0, MotherBrain_CalcHdma_BeamAimedUp, MotherBrain_CalcHdma_BeamAimedUp, 0, + 0, 0, MotherBrain_CalcHdma_BeamAimedUp, nullsub_341, + MotherBrain_CalcHdma_Down, 0, 0, MotherBrain_CalcHdma_Down, +}; + +#define kMotherBrain_HealthBasedPalettes_Brain ((uint16*)RomPtr(0xade6a2)) +#define kMotherBrain_HealthBasedPalettes_BackLeg ((uint16*)RomPtr(0xade742)) +#define kMotherBrain_FadePalToBlack ((uint16*)RomPtr(0xade9e8)) +#define kMotherBrain_TransitionToFromGrey_Incr ((uint16*)RomPtr(0xaded8a)) +#define kMotherBrain_TransitionToFromGrey_Decr ((uint16*)RomPtr(0xaded9c)) +#define kMotherBrain_FadeToGray_Drained ((uint16*)RomPtr(0xadef87)) +#define kMotherBrain_FadeToGray_RealDeath ((uint16*)RomPtr(0xadf107)) +#define kMotherBrain_Phase3_TurnLightsBackOn ((uint16*)RomPtr(0xadf273)) + + +void MotherBrain_CalcHdma(void) { // 0xADDE00 + Enemy_MotherBrain *E = Get_MotherBrain(0); + Enemy_MotherBrain *E1 = Get_MotherBrain(0x40); + R18_ = HIBYTE(E->mbn_var_33) >> 1; + E->mbn_var_3A = E->mbn_var_31 - R18_; + E->mbn_var_3B = R18_ + E->mbn_var_31; + uint16 v2 = (*(uint16 *)((char *)&E1->base.enemy_ptr + 1) + 3584) & 0xFF00; + E->mbn_var_3C = v2; + E->mbn_var_3E = v2; + uint16 v3 = E1->base.y_pos + 5; + E->mbn_var_3D = v3; + E->mbn_var_3F = v3; + R18_ = 4 * (E->mbn_var_3A & 0xC0); + int i = (R18_ | E->mbn_var_3B & 0xC0) >> 6; + funcs_BE56D[i](); +} + +void MotherBrain_CalcHdma_BeamAimedRight2(void) { // 0xADDE7F + Enemy_MotherBrain *E = Get_MotherBrain(0); + R22_ = E->mbn_var_3C; + R24_ = E->mbn_var_3E; + MotherBrain_CalcHdma_BeamAimedRight(); + *(uint16 *)mother_brain_indirect_hdma = 16; + *(uint16 *)&mother_brain_indirect_hdma[1] = -25600; + *(uint16 *)&mother_brain_indirect_hdma[3] = 16; + *(uint16 *)&mother_brain_indirect_hdma[4] = -25597; + *(uint16 *)&mother_brain_indirect_hdma[6] = 240; + *(uint16 *)&mother_brain_indirect_hdma[7] = -25340; + *(uint16 *)&mother_brain_indirect_hdma[9] = 244; + *(uint16 *)&mother_brain_indirect_hdma[10] = -25108; + *(uint16 *)&mother_brain_indirect_hdma[12] = 0; +} + +void MotherBrain_CalcHdma_BeamAimedRight(void) { // 0xADDECE + hdma_table_2[0] = 255; + hdma_table_2[1] = 255; + Enemy_MotherBrain *E = Get_MotherBrain(0); + R18_ = kTanTable[(uint16)(2 * LOBYTE(E->mbn_var_3A)) >> 1]; + R20_ = kTanTable[(uint16)(2 * LOBYTE(E->mbn_var_3B)) >> 1]; + uint16 mbn_var_3F = E->mbn_var_3F; + uint16 v2 = 2 * (mbn_var_3F - 32) - 25342; + uint8 *v3 = RomPtr_7E(v2); + *((uint16 *)v3 + 1) = 255; + *((uint16 *)v3 + 2) = 255; + uint16 v8 = v2; + do { + uint16 v4 = R20_ + R24_; + if (__CFADD__uint16(R20_, R24_)) + break; + R24_ += R20_; + *(uint16 *)RomPtr_7E(v2) = HIBYTE(v4) | 0xFF00; + v2 -= 2; + --mbn_var_3F; + } while (mbn_var_3F != 32); + do { + *(uint16 *)RomPtr_7E(v2) = 255; + v2 -= 2; + --mbn_var_3F; + } while (mbn_var_3F != 32); + uint16 v5 = v8 + 2; + uint16 var_3F = gRam8000_Default(0)->var_3F; + while (1) { + uint16 v7 = R18_ + R22_; + if (__CFADD__uint16(R18_, R22_)) + break; + R22_ += R18_; + *(uint16 *)RomPtr_7E(v5) = HIBYTE(v7) | 0xFF00; + v5 += 2; + if (++var_3F == 232) + return; + } + do { + *(uint16 *)RomPtr_7E(v5) = 255; + v5 += 2; + ++var_3F; + } while (var_3F != 232); +} + +static Func_V *const off_ADE024[4] = { // 0xADDF6E + MotherBrain_CalcHdma_Up_UpRight, + MotherBrain_CalcHdma_Up_Up, + 0, + MotherBrain_CalcHdma_Up_UpLeft, +}; + +void MotherBrain_CalcHdma_BeamAimedUp(void) { + Enemy_MotherBrain *E = Get_MotherBrain(0); + R22_ = E->mbn_var_3C; + R24_ = E->mbn_var_3E; + + R18_ = (E->mbn_var_3A >> 6) & 2 | (E->mbn_var_3B >> 7) & 1; + + off_ADE024[R18_ & 3](); + *(uint16 *)mother_brain_indirect_hdma = 16; + *(uint16 *)&mother_brain_indirect_hdma[1] = -25344; + *(uint16 *)&mother_brain_indirect_hdma[3] = 16; + *(uint16 *)&mother_brain_indirect_hdma[4] = -25342; + + uint16 v2 = E->mbn_var_3D - 32; + printf("Carry crap!\n"); + if (v2 >= 0x80) { + R18_ = E->mbn_var_3D - 159; + *(uint16 *)&mother_brain_indirect_hdma[6] = (v2 - 127) | 0x80; + *(uint16 *)&mother_brain_indirect_hdma[7] = -25340; + *(uint16 *)&mother_brain_indirect_hdma[9] = 255; + *(uint16 *)&mother_brain_indirect_hdma[10] = 2 * (v2 - 127) - 25340; + *(uint16 *)&mother_brain_indirect_hdma[12] = 127; + *(uint16 *)&mother_brain_indirect_hdma[13] = 2 * (v2 - 127) - 25340 + 254; + *(uint16 *)&mother_brain_indirect_hdma[15] = 0; + } else { + *(uint16 *)&mother_brain_indirect_hdma[6] = v2 | 0x80; + *(uint16 *)&mother_brain_indirect_hdma[7] = -25340; + *(uint16 *)&mother_brain_indirect_hdma[9] = 127; + *(uint16 *)&mother_brain_indirect_hdma[10] = 2 * v2 - 25340; + *(uint16 *)&mother_brain_indirect_hdma[12] = 0; + } +} + +void MotherBrain_CalcHdma_Up_UpRight(void) { // 0xADE02C + char v6; // t0 + int16 v8; + + hdma_table_2[0] = 255; + hdma_table_2[1] = 255; + Enemy_MotherBrain *E = Get_MotherBrain(0); + R18_ = kTanTable[(uint16)(2 * LOBYTE(E->mbn_var_3B)) >> 1]; + R20_ = kTanTable[(uint16)(2 * LOBYTE(E->mbn_var_3A)) >> 1]; + uint16 mbn_var_3D = E->mbn_var_3D; + uint16 v2 = 2 * (mbn_var_3D - 32) - 25342; + uint8 *v3 = RomPtr_7E(v2); + *((uint16 *)v3 + 1) = 255; + *((uint16 *)v3 + 2) = 255; + do { + uint16 v4 = R18_ + R22_; + if (__CFADD__uint16(R18_, R22_)) + v4 = -1; + R22_ = v4; + uint16 v5 = v4 & 0xFF00; + v6 = v5; + LOBYTE(v5) = HIBYTE(v5); + HIBYTE(v5) = v6; + R36 = v5; + uint16 v7 = R20_ + R24_; + if (__CFADD__uint16(R20_, R24_)) + v7 = -1; + R24_ = v7; + v8 = R36 | v7 & 0xFF00; + if (v8 == -1) + v8 = 255; + *(uint16 *)RomPtr_7E(v2) = v8; + v2 -= 2; + --mbn_var_3D; + } while (mbn_var_3D != 32); +} + +void MotherBrain_CalcHdma_Up_Up(void) { // 0xADE0A6 + char v6; // t0 + int16 v8; + + hdma_table_2[0] = 255; + hdma_table_2[1] = 255; + Enemy_MotherBrain *E = Get_MotherBrain(0); + R18_ = kTanTable[(uint8)-LOBYTE(E->mbn_var_3B)]; + R20_ = kTanTable[(uint16)(2 * LOBYTE(E->mbn_var_3A)) >> 1]; + uint16 mbn_var_3D = E->mbn_var_3D; + uint16 v2 = 2 * (mbn_var_3D - 32) - 25342; + uint8 *v3 = RomPtr_7E(v2); + *((uint16 *)v3 + 1) = 255; + *((uint16 *)v3 + 2) = 255; + do { + uint16 v4 = R22_ - R18_; + if (R22_ < R18_) + v4 = 0; + R22_ = v4; + uint16 v5 = v4 & 0xFF00; + v6 = v5; + LOBYTE(v5) = HIBYTE(v5); + HIBYTE(v5) = v6; + R26_ = v5; + uint16 v7 = R20_ + R24_; + if (__CFADD__uint16(R20_, R24_)) + v7 = -1; + R24_ = v7; + v8 = R26_ | v7 & 0xFF00; + if (v8 == -1) + v8 = 255; + *(uint16 *)RomPtr_7E(v2) = v8; + v2 -= 2; + --mbn_var_3D; + } while (mbn_var_3D != 32); +} + +void MotherBrain_CalcHdma_Up_UpLeft(void) { // 0xADE124 + char v6; // t0 + int16 v8; + + hdma_table_2[0] = 255; + hdma_table_2[1] = 255; + Enemy_MotherBrain *E = Get_MotherBrain(0); + R18_ = kTanTable[(uint8)-LOBYTE(E->mbn_var_3B)]; + R20_ = kTanTable[(uint8)-LOBYTE(E->mbn_var_3A)]; + uint16 mbn_var_3D = E->mbn_var_3D; + uint16 v2 = 2 * (mbn_var_3D - 32) - 25342; + uint8 *v3 = RomPtr_7E(v2); + *((uint16 *)v3 + 1) = 255; + *((uint16 *)v3 + 2) = 255; + do { + uint16 v4 = R22_ - R18_; + if (R22_ < R18_) + v4 = 0; + R22_ = v4; + uint16 v5 = v4 & 0xFF00; + v6 = v5; + LOBYTE(v5) = HIBYTE(v5); + HIBYTE(v5) = v6; + R36 = v5; + uint16 v7 = R24_ - R20_; + if (R24_ < R20_) + v7 = 0; + R24_ = v7; + v8 = R36 | v7 & 0xFF00; + if (v8 == -1) + v8 = 255; + *(uint16 *)RomPtr_7E(v2) = v8; + v2 -= 2; + --mbn_var_3D; + } while (mbn_var_3D != 32); +} +static Func_V *const g_off_ADE20E[4] = { MotherBrain_CalcHdma_Down_DownRight, 0, MotherBrain_CalcHdma_Down_Down, MotherBrain_CalcHdma_Down_DownLeft }; +void MotherBrain_CalcHdma_Down(void) { // 0xADE1A6 + Enemy_MotherBrain *E = Get_MotherBrain(0); + R22_ = E->mbn_var_3C; + R24_ = E->mbn_var_3E; + + R18_ = (E->mbn_var_3A >> 6) & 2 | (E->mbn_var_3B >> 7) & 1; + + g_off_ADE20E[R18_ & 3](); + *(uint16 *)mother_brain_indirect_hdma = 16; + *(uint16 *)&mother_brain_indirect_hdma[1] = -25600; + *(uint16 *)&mother_brain_indirect_hdma[3] = 16; + *(uint16 *)&mother_brain_indirect_hdma[4] = -25597; + *(uint16 *)&mother_brain_indirect_hdma[6] = 240; + *(uint16 *)&mother_brain_indirect_hdma[7] = -25340; + *(uint16 *)&mother_brain_indirect_hdma[9] = 244; + *(uint16 *)&mother_brain_indirect_hdma[10] = -25114; + *(uint16 *)&mother_brain_indirect_hdma[12] = 0; +} + +void MotherBrain_CalcHdma_Down_DownRight(void) { // 0xADE216 + int16 v1; + char v6; // t0 + int16 v8; + + hdma_table_2[0] = 255; + hdma_table_2[1] = 255; + Enemy_MotherBrain *E = Get_MotherBrain(0); + R18_ = kTanTable[(uint16)(2 * LOBYTE(E->mbn_var_3A)) >> 1]; + R20_ = kTanTable[(uint16)(2 * LOBYTE(E->mbn_var_3B)) >> 1]; + v1 = E->mbn_var_3D - 32; + uint16 v2 = 0x9D04; + do { + *(uint16 *)RomPtr_7E(v2) = 255; + v2 += 2; + --v1; + } while (v1); + uint16 mbn_var_3D = Get_MotherBrain(0)->mbn_var_3D; + do { + uint16 v4 = R18_ + R22_; + if (__CFADD__uint16(R18_, R22_)) + v4 = -1; + R22_ = v4; + uint16 v5 = v4 & 0xFF00; + v6 = v5; + LOBYTE(v5) = HIBYTE(v5); + HIBYTE(v5) = v6; + R26_ = v5; + uint16 v7 = R20_ + R24_; + if (__CFADD__uint16(R20_, R24_)) + v7 = -1; + R24_ = v7; + v8 = R26_ | v7 & 0xFF00; + if (v8 == -1) + v8 = 255; + *(uint16 *)RomPtr_7E(v2) = v8; + v2 += 2; + ++mbn_var_3D; + } while (mbn_var_3D != 232); +} + +void MotherBrain_CalcHdma_Down_Down(void) { // 0xADE293 + int16 v1; + char v6; // t0 + int16 v8; + + hdma_table_2[0] = 255; + hdma_table_2[1] = 255; + Enemy_MotherBrain *E = Get_MotherBrain(0); + R18_ = kTanTable[(uint8)-LOBYTE(E->mbn_var_3A)]; + R20_ = kTanTable[(uint16)(2 * LOBYTE(E->mbn_var_3B)) >> 1]; + v1 = E->mbn_var_3D - 32; + uint16 v2 = -25340; + do { + *(uint16 *)RomPtr_7E(v2) = 255; + v2 += 2; + --v1; + } while (v1); + uint16 mbn_var_3D = Get_MotherBrain(0)->mbn_var_3D; + do { + uint16 v4 = R22_ - R18_; + if (R22_ < R18_) + v4 = 0; + R22_ = v4; + uint16 v5 = v4 & 0xFF00; + v6 = v5; + LOBYTE(v5) = HIBYTE(v5); + HIBYTE(v5) = v6; + R26_ = v5; + uint16 v7 = R20_ + R24_; + if (__CFADD__uint16(R20_, R24_)) + v7 = -1; + R24_ = v7; + v8 = R26_ | v7 & 0xFF00; + if (v8 == -1) + v8 = 255; + *(uint16 *)RomPtr_7E(v2) = v8; + v2 += 2; + ++mbn_var_3D; + } while (mbn_var_3D != 232); +} + +void MotherBrain_CalcHdma_Down_DownLeft(void) { // 0xADE314 + int16 v1; + char v6; // t0 + int16 v8; + + hdma_table_2[0] = 255; + hdma_table_2[1] = 255; + Enemy_MotherBrain *E = Get_MotherBrain(0); + R18_ = kTanTable[(uint8)-LOBYTE(E->mbn_var_3A)]; + R20_ = kTanTable[(uint8)-LOBYTE(E->mbn_var_3B)]; + v1 = E->mbn_var_3D - 32; + uint16 v2 = -25340; + do { + *(uint16 *)RomPtr_7E(v2) = 255; + v2 += 2; + --v1; + } while (v1); + uint16 mbn_var_3D = Get_MotherBrain(0)->mbn_var_3D; + do { + uint16 v4 = R22_ - R18_; + if (R22_ < R18_) + v4 = 0; + R22_ = v4; + uint16 v5 = v4 & 0xFF00; + v6 = v5; + LOBYTE(v5) = HIBYTE(v5); + HIBYTE(v5) = v6; + R26_ = v5; + uint16 v7 = R24_ - R20_; + if (R24_ < R20_) + v7 = 0; + R24_ = v7; + v8 = R26_ | v7 & 0xFF00; + if (!v8) + v8 = 255; + *(uint16 *)RomPtr_7E(v2) = v8; + v2 += 2; + ++mbn_var_3D; + } while (mbn_var_3D != 232); +} + +void MotherBrain_SealWall(void) { // 0xADE396 + R18_ = 248; + R20_ = 72; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 9u); + R18_ = 248; + R20_ = 152; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 9u); + static const SpawnHardcodedPlmArgs unk_ADE3C2 = { 0x0f, 0x04, 0xb673 }; + static const SpawnHardcodedPlmArgs unk_ADE3CA = { 0x0f, 0x09, 0xb673 }; + SpawnHardcodedPlm(&unk_ADE3C2); + SpawnHardcodedPlm(&unk_ADE3CA); + Get_MotherBrain(0)->mbn_var_A = FUNC16(MotherBrainBody_FakeDeath_Descent_0_Pause); +} + +void MotherBrain_HealthBasedPaletteHandling(void) { // 0xADE3D5 + if (Get_MotherBrain(0)->mbn_var_1F >= 2u) { + uint16 v0 = 0; + uint16 health = Get_MotherBrain(0x40u)->base.health; + if (health < 0x2328u) { + v0 = 2; + if (health < 0x1518u) { + v0 = 4; + if (health < 0x708u) + v0 = 6; + } + } + WriteColorsToPalette(0x82u, 0xad, kMotherBrain_HealthBasedPalettes_Brain[v0 >> 1], 0xFu); + WriteColorsToPalette(0x122u, 0xad, kMotherBrain_HealthBasedPalettes_Brain[v0 >> 1], 0xFu); + WriteColorsToPalette(0x162u, 0xad, kMotherBrain_HealthBasedPalettes_BackLeg[v0 >> 1], 0xFu); + } +} + +uint8 MotherBrain_FadePalToBlack(uint16 a) { // 0xADE9B4 + int v1 = a; + if (!kMotherBrain_FadePalToBlack[v1]) + return 1; + uint16 j = kMotherBrain_FadePalToBlack[v1]; + WriteColorsToPalette(0x82u, 0xad, j, 14); + WriteColorsToPalette(0x122u, 0xad, j, 14); + WriteColorsToPalette(0x162u, 0xad, j + 28, 14); + return 0; +} + +uint8 MotherBrain_FadeToGray_FakeDeath(uint16 a) { // 0xADEEDE + uint16 v1 = kMotherBrain_TransitionToFromGrey_Incr[a]; + if (v1) + return MotherBrain_EEF6(v1) & 1; + else + return 1; +} + +uint8 MotherBrain_FadeFromGray_FakeDeath(uint16 a) { // 0xADEEEA + uint16 v1 = kMotherBrain_TransitionToFromGrey_Decr[a]; + if (v1) + return MotherBrain_EEF6(v1) & 1; + else + return 1; +} + +uint8 MotherBrain_EEF6(uint16 a) { // 0xADEEF6 + WriteColorsToPalette(0x122u, 0xad, a, 3u); + return 0; +} + +uint8 MotherBrain_FadeFromGray_Drained(uint16 a) { // 0xADEF0D + int16 v3; + + int v1 = a; + if (!kMotherBrain_TransitionToFromGrey_Decr[v1]) + return 1; + uint16 j = kMotherBrain_TransitionToFromGrey_Decr[v1]; + WriteColorsToPalette(0x82u, 0xad, j, 13); + WriteColorsToPalette(0x122u, 0xad, j, 13); + WriteColorsToPalette(0x168u, 0xad, j + 26, 5); + v3 = *(uint16 *)RomPtr_AD(j + 36); + *(uint16 *)&g_ram[0x17C] = v3; + return 0; +} + +uint8 MotherBrain_FadeToGray_Drained(uint16 a) { // 0xADEF4A + int16 v3; + + int v1 = a; + if (!kMotherBrain_FadeToGray_Drained[v1]) + return 1; + uint16 j = kMotherBrain_FadeToGray_Drained[v1]; + WriteColorsToPalette(0x82u, 0xad, j, 15); + WriteColorsToPalette(0x122u, 0xad, j, 15); + WriteColorsToPalette(0x168u, 0xad, j + 30, 5); + v3 = *(uint16 *)RomPtr_AD(j + 40); + *(uint16 *)&g_ram[0x17C] = v3; + return 0; +} + +uint8 MotherBrain_FadeToGray_RealDeath(uint16 a) { // 0xADF0E9 + int v1 = a; + if (!kMotherBrain_FadeToGray_RealDeath[v1]) + return 1; + WriteColorsToPalette(0x1E2u, 0xad, kMotherBrain_FadeToGray_RealDeath[v1], 0xFu); + return 0; +} + +void TurnOffLightsForShitroidDeath(void) { // 0xADF209 + WriteColorsToPalette(0x62u, 0xad, addr_kTurnOffLightsForShitroidDeath, 14); + WriteColorsToPalette(0xA2u, 0xad, addr_kTurnOffLightsForShitroidDeath, 14); +} + +uint8 MotherBrain_Phase3_TurnLightsBackOn(uint16 a) { // 0xADF24B + int v1 = a; + if (!kMotherBrain_Phase3_TurnLightsBackOn[v1]) + return 1; + uint16 v3 = kMotherBrain_Phase3_TurnLightsBackOn[v1]; + WriteColorsToPalette(0x62u, 0xad, v3, 14); + WriteColorsToPalette(0xA2u, 0xad, v3 + 28, 14); + return 0; +} + +void EnableEarthquakeAframes(uint16 a) { // 0xADF40B + earthquake_type = a; + earthquake_timer = 20; + QueueSfx2_Max6(0x25u); +} + +void HandleMotherBrainBodyFlickering(void) { // 0xADF41C + EnemyData *v0 = gEnemyData(0); + if (v0->frame_counter & 1) { + *(uint16 *)®_TM |= 2u; + v0->properties &= ~kEnemyProps_Invisible; + } else { + *(uint16 *)®_TM &= ~2u; + v0->properties |= kEnemyProps_Invisible; + } +} diff --git a/src/sm_b2.c b/src/sm_b2.c new file mode 100644 index 0000000..a6084ca --- /dev/null +++ b/src/sm_b2.c @@ -0,0 +1,879 @@ +// $B2 - Enemy AI - space pirates +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" + +#define kWallSpacePirates_Palette_3 ((uint16*)RomPtr(0xb28727)) +#define g_off_B2F959 ((uint16*)RomPtr(0xb2f959)) + +void Enemy_GrappleReact_CancelBeam_B2(void) { // 0xB2800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_NormalFrozenAI_B2(void) { // 0xB28041 + NormalEnemyFrozenAI(); +} + +uint16 EnemyInstr_Goto_B2(uint16 k, uint16 j) { // 0xB280ED + return *(uint16 *)RomPtr_B2(j); +} + +uint16 EnemyInstr_DecTimerAndGoto2_B2(uint16 k, uint16 j) { // 0xB28110 + EnemyData *v2 = gEnemyData(k); + if (v2->timer-- != 1) + return EnemyInstr_Goto_B2(k, j); + return j + 2; +} + +uint16 EnemyInstr_SetTimer_B2(uint16 k, uint16 j) { // 0xB28123 + gEnemyData(k)->timer = *(uint16 *)RomPtr_B2(j); + return j + 2; +} + +uint16 EnemyInstr_Sleep_B2(uint16 k, uint16 j) { // 0xB2812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + +uint16 EnemyInstr_WaitNframes_B2(uint16 k, uint16 j) { // 0xB2813A + EnemyData *v3 = gEnemyData(k); + v3->instruction_timer = *(uint16 *)RomPtr_B2(j); + v3->current_instruction = j + 2; + return 0; +} + +void WalkingSpacePirates_Powerbomb(void) { // 0xB28767 + NormalEnemyPowerBombAi(); +} + +void WalkingSpacePirates_Touch(void) { // 0xB2876C + if (!Get_SpacePirates(cur_enemy_index)->base.frozen_timer) + NormalEnemyTouchAi(); +} + +void WalkingSpacePirates_Shot(void) { // 0xB28779 + if (Get_SpacePirates(cur_enemy_index)->base.enemy_ptr == (uint16)addr_kEnemyDef_F593) + WalkingSpacePirates_8789(); + else + NormalEnemyShotAi(); +} + +void WalkingSpacePirates_8789(void) { // 0xB28789 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + special_death_item_drop_x_origin_pos = E->base.x_pos; + special_death_item_drop_y_origin_pos = E->base.y_pos; + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); + if (!E->base.health) { + uint16 v1 = cur_enemy_index; + if (E->base.enemy_ptr == (uint16)addr_kEnemyDef_F593) { + E->sps_var_B = 0; + EnemyDeathAnimation(v1, 4u); + Enemy_ItemDrop_LowerNorfairSpacePirate(v1); + } else { + E->sps_var_B = 0; + EnemyDeathAnimation(v1, 4u); + } + } +} + +void WalkingSpacePirates_87C8(void) { // 0xB287C8 + Vulnerability *v2; + int16 v3; + Vulnerability *Vulnerability; + + if (Get_SpacePirates(cur_enemy_index)->base.enemy_ptr != (uint16)addr_kEnemyDef_F593) + goto LABEL_2; + R18_ = projectile_type[collision_detection_index]; + if (sign16((R18_ & kProjectileType_TypeMask) - kProjectileType_PowerBomb)) { + uint16 enemy_ptr; + uint16 vulnerability_ptr; + enemy_ptr = Get_SpacePirates(cur_enemy_index)->base.enemy_ptr; + vulnerability_ptr = get_EnemyDef_A2(enemy_ptr)->vulnerability_ptr; + if (!vulnerability_ptr) + vulnerability_ptr = addr_stru_B4EC1C; + R20_ = vulnerability_ptr; + if ((R18_ & kProjectileType_TypeMask) != 0) { + if ((R18_ & kProjectileType_TypeMask) != kProjectileType_Missile + && (R18_ & kProjectileType_TypeMask) != kProjectileType_SuperMissile) { + goto LABEL_2; + } + LOBYTE(v3) = (uint16)(R18_ & kProjectileType_TypeMask) >> 8; + HIBYTE(v3) = 0; + Vulnerability = get_Vulnerability(R20_ + v3); + if ((Vulnerability->plasma_ice_wave & 0xF) != 0 && (Vulnerability->plasma_ice_wave & 0xF) != 15) + goto LABEL_2; + } else { + v2 = get_Vulnerability(R20_ + ((uint8)R18_ & 0xFu)); + if ((v2->power & 0xF) != 0 && (v2->power & 0xF) != 15) { +LABEL_2: + WalkingSpacePirates_8789(); + return; + } + } + WalkingSpacePirates_883E(); + } +} + +void WalkingSpacePirates_883E(void) { // 0xB2883E + if (Get_SpacePirates(cur_enemy_index)->base.enemy_ptr != (uint16)addr_kEnemyDef_F593) { + WalkingSpacePirates_8789(); + return; + } + uint16 v0 = 2 * collision_detection_index; + int v1 = collision_detection_index; + R18_ = projectile_type[v1]; + if ((R18_ & kProjectileType_TypeMask) == kProjectileType_SuperMissile) { + if (!projectile_variables[v1]) + return; + } else if (!sign16((R18_ & kProjectileType_TypeMask) - kProjectileType_PowerBomb)) { + return; + } + Get_SpacePirates(cur_enemy_index)->base.invincibility_timer = 10; + uint16 v2; + if ((projectile_dir[v1] & 0xF) == 7) { + v2 = 1; + } else if ((projectile_dir[v1] & 0xF) == 2) { + v2 = 8; + } else { + v2 = 5; + } + projectile_dir[v1] = v2; + R20_ = v0; + ProjectileReflection(); + QueueSfx2_Max6(0x66u); +} + +uint16 SpacePirates_Instr_MovePixelsDownAndChangeDirFaceRight(uint16 k, uint16 j) { // 0xB2EE40 + R18_ = 0; + R20_ = *(uint16 *)RomPtr_B2(j); + if (!(Enemy_MoveDown(cur_enemy_index) & 1)) + return j + 2; + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + E->sps_var_C ^= 1u; + uint16 result = addr_kSpacePirates_Ilist_ED36; + if (E->sps_var_C) + return addr_off_B2ECEC; + return result; +} + +uint16 SpacePirates_Instr_MovePixelsDownAndChangeDirFaceLeft(uint16 k, uint16 j) { // 0xB2EE72 + R18_ = 0; + R20_ = *(uint16 *)RomPtr_B2(j); + if (!(Enemy_MoveDown(cur_enemy_index) & 1)) + return j + 2; + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + E->sps_var_C ^= 1u; + uint16 result = addr_off_B2EDAC; + if (E->sps_var_C) + return addr_kSpacePirates_Ilist_EDF6; + return result; +} + +uint16 SpacePirates_Instr_RandomNewDirFaceR(uint16 k, uint16 j) { // 0xB2EEA4 + uint16 result = addr_kSpacePirates_Ilist_ED36; + uint16 v4 = NextRandom() & 1; + Get_SpacePirates(cur_enemy_index)->sps_var_C = v4; + if (v4) + return addr_off_B2ECEC; + return result; +} + +uint16 SpacePirates_Instr_RandomNewDirFaceL(uint16 k, uint16 j) { // 0xB2EEBC + uint16 result = addr_off_B2EDAC; + uint16 v4 = NextRandom() & 1; + Get_SpacePirates(cur_enemy_index)->sps_var_C = v4; + if (v4) + return addr_kSpacePirates_Ilist_EDF6; + return result; +} + +uint16 SpacePirates_Instr_PrepareWallJumpR(uint16 k, uint16 j) { // 0xB2EED4 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + E->sps_var_B = E->base.x_pos + E->sps_parameter_2; + E->sps_var_D = E->base.x_pos + (E->sps_parameter_2 >> 1); + E->sps_var_E = E->base.y_pos; + E->sps_var_F = 64; + return j; +} + +uint16 SpacePirates_Instr_PrepareWallJumpL(uint16 k, uint16 j) { // 0xB2EEFD + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + E->sps_var_B = E->base.x_pos - E->sps_parameter_2; + R18_ = E->sps_parameter_2 >> 1; + E->sps_var_D = E->base.x_pos - R18_; + E->sps_var_E = E->base.y_pos; + E->sps_var_F = 192; + return j; +} + +uint16 SpacePirates_Instr_FireLaserL(uint16 k, uint16 j) { // 0xB2EF2A + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + enemy_projectile_init_param = *((uint16 *)RomPtr_A0(E->base.enemy_ptr) + 3); + R18_ = E->base.x_pos - 24; + R20_ = E->base.y_pos - 16; + R22_ = 0; + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A17B, 0); + return j; +} + +uint16 SpacePirates_Instr_FireLaserR(uint16 k, uint16 j) { // 0xB2EF5D + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + R18_ = E->base.x_pos + 24; + R20_ = E->base.y_pos - 16; + R22_ = 1; + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A17B, 1u); + return j; +} + +uint16 SpacePirates_Instr_SetEnemyFunc(uint16 k, uint16 j) { // 0xB2EF83 + uint16 v2 = *(uint16 *)RomPtr_B2(j); + Get_SpacePirates(cur_enemy_index)->sps_var_A = v2; + return j + 2; +} + +uint16 SpacePirates_Instr_PlaySfx(uint16 k, uint16 j) { // 0xB2EF93 + QueueSfx2_Max6(0x66u); + return j; +} + +void WallSpacePirates_Init(void) { // 0xB2EF9F + uint16 v0 = addr_kSpacePirates_Ilist_ED36; + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + if ((E->sps_parameter_1 & 1) != 0) + v0 = addr_off_B2EDAC; + E->base.current_instruction = v0; + E->sps_var_20 = 190; + E->sps_var_21 = 66; + E->sps_var_22 = 2; + if ((E->sps_parameter_1 & 0x8000u) == 0) { + E->sps_var_20 += 2; + E->sps_var_21 -= 2; + E->sps_var_22 += 2; + } + uint16 v2 = FUNC16(SpacePirates_Func_1); + if ((E->sps_parameter_1 & 1) != 0) + v2 = FUNC16(SpacePirates_Func_3); + E->sps_var_A = v2; + uint16 v3; + if (sign16((E->base.x_pos & 0xF) - 11)) + v3 = E->base.x_pos & 0xFFF8; + else + v3 = (E->base.x_pos & 0xFFF0) + 16; + E->base.x_pos = v3; +} + +void CallSpacePiratesEnemyFunc(uint32 ea, uint16 k) { + switch (ea) { + case fnnullsub_169_B2: return; // 0xb2804b + case fnSpacePirates_Func_1: SpacePirates_Func_1(k); return; // 0xb2f034 + case fnnullsub_279: return; // 0xb2f04f + case fnSpacePirates_Func_2: SpacePirates_Func_2(k); return; // 0xb2f050 + case fnSpacePirates_Func_3: SpacePirates_Func_3(k); return; // 0xb2f0c8 + case fnnullsub_281: return; // 0xb2f0e3 + case fnnullsub_282: return; + case fnSpacePirates_Func_4: SpacePirates_Func_4(k); return; // 0xb2f0e4 + case fnSpacePirates_Func_5: SpacePirates_Func_5(k); return; // 0xb2f6a9 + case fnSpacePirates_Func_6: SpacePirates_Func_6(k); return; // 0xb2f6e4 + case fnSpacePirates_Func_11: SpacePirates_Func_11(k); return; // 0xb2f817 + case fnSpacePirates_Func_12: SpacePirates_Func_12(k); return; + case fnSpacePirates_Func_13: SpacePirates_Func_13(k); return; // 0xb2f890 + case fnSpacePirates_Func_14: SpacePirates_Func_14(k); return; + case fnSpacePirates_Func_15: SpacePirates_Func_15(k); return; // 0xb2f909 + case fnSpacePirates_F985: SpacePirates_F985(k); return; // 0xb2f985 + case fnSpacePirates_F9C1: SpacePirates_F9C1(k); return; // 0xb2f9c1 + case fnSpacePirates_FA15: SpacePirates_FA15(k); return; // 0xb2fa15 + case fnSpacePirates_FA59: SpacePirates_FA59(k); return; // 0xb2fa59 + case fnSpacePirates_FA95: SpacePirates_FA95(k); return; // 0xb2fa95 + case fnSpacePirates_FAE9: SpacePirates_FAE9(k); return; // 0xb2fae9 + case fnWalkingSpacePirates_FD44: WalkingSpacePirates_FD44(); return; + case fnWalkingSpacePirates_FDCE: WalkingSpacePirates_FDCE(); return; + default: Unreachable(); + } +} + +void WallSpacePirates_Main(void) { // 0xB2F02D + EnemyData *v0 = gEnemyData(cur_enemy_index); + CallSpacePiratesEnemyFunc(v0->ai_var_A | 0xB20000, cur_enemy_index); +} + +void SpacePirates_Func_1(uint16 k) { // 0xB2F034 + if (IsSamusWithinEnemy_Y(cur_enemy_index, 0x20u)) { + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + E->base.current_instruction = addr_kSpacePirates_Ilist_ED80; + E->base.instruction_timer = 1; + } +} + +void SpacePirates_Func_2(uint16 k) { // 0xB2F050 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + draw_enemy_layer = E->sps_parameter_2 >> 1; + E->base.x_pos = E->sps_var_D + SineMult8bitNegative(E->sps_var_F); + draw_enemy_layer = E->sps_parameter_2 >> 2; + E->base.y_pos = E->sps_var_E - CosineMult8bit(E->sps_var_F); + uint16 v1 = (uint8)(LOBYTE(E->sps_var_F) - LOBYTE(E->sps_var_22)); + E->sps_var_F = v1; + if (v1 == E->sps_var_20) { + E->base.current_instruction = addr_kSpacePirates_Ilist_EDA4; + E->base.instruction_timer = 1; + uint16 v2; + if (sign16((E->base.x_pos & 0xF) - 11)) + v2 = E->base.x_pos & 0xFFF8; + else + v2 = (E->base.x_pos & 0xFFF0) + 16; + E->base.x_pos = v2; + } +} + +void SpacePirates_Func_3(uint16 k) { // 0xB2F0C8 + if (IsSamusWithinEnemy_Y(cur_enemy_index, 0x20u)) { + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + E->base.current_instruction = addr_kSpacePirates_Ilist_ECC0; + E->base.instruction_timer = 1; + } +} + +void SpacePirates_Func_4(uint16 k) { // 0xB2F0E4 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + draw_enemy_layer = E->sps_parameter_2 >> 1; + E->base.x_pos = E->sps_var_D + SineMult8bitNegative(E->sps_var_F); + draw_enemy_layer = E->sps_parameter_2 >> 2; + E->base.y_pos = E->sps_var_E - CosineMult8bit(E->sps_var_F); + uint16 v1 = (uint8)(LOBYTE(E->sps_var_22) + LOBYTE(E->sps_var_F)); + E->sps_var_F = v1; + if (v1 == E->sps_var_21) { + E->base.current_instruction = addr_kSpacePirates_Ilist_ECE4; + E->base.instruction_timer = 1; + uint16 v2; + if (sign16((E->base.x_pos & 0xF) - 11)) + v2 = E->base.x_pos & 0xFFF8; + else + v2 = (E->base.x_pos & 0xFFF0) + 16; + E->base.x_pos = v2; + } +} + +uint16 SpacePirates_Instr_20(uint16 k, uint16 j) { // 0xB2F536 + uint16 v2 = *(uint16 *)RomPtr_B2(j); + Get_SpacePirates(cur_enemy_index)->base.palette_index = v2; + return j + 2; +} + +uint16 SpacePirates_Instr_16(uint16 k, uint16 j) { // 0xB2F546 + uint16 *v2 = (uint16 *)RomPtr_B2(j); + QueueSfx2_Max6(*v2); + return j + 2; +} + +void sub_B2F554(void) { // 0xB2F554 + gEnemyData(cur_enemy_index)->instruction_timer = 1; +} + +uint16 SpacePirates_Instr_15(uint16 k, uint16 j) { // 0xB2F564 + uint16 *v2 = (uint16 *)RomPtr_B2(j); + R22_ = v2[1]; + R24_ = v2[2]; + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + SpawnEnemyProjectileWithGfx(*v2, cur_enemy_index, addr_kEproj_PirateClaw); + return j + 6; +} + +uint16 SpacePirates_Instr_18(uint16 k, uint16 j) { // 0xB2F590 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + R18_ = E->base.x_pos - samus_x_pos; + E->base.instruction_timer = 1; + uint16 result = addr_kSpacePirates_Ilist_F22E; + if ((R18_ & 0x8000u) != 0) + result = addr_kSpacePirates_Ilist_F420; + E->sps_var_C = result; + return result; +} + +void sub_B2F5B3(void) { // 0xB2F5B3 + EnemyData *v0 = gEnemyData(cur_enemy_index); + R18_ = v0->x_pos - samus_x_pos; + v0->instruction_timer = 1; + uint16 v1 = addr_kSpacePirates_Ilist_F32E; + if ((R18_ & 0x8000u) != 0) + v1 = addr_kSpacePirates_Ilist_F51A; + v0->ai_var_C = v1; +} + +uint16 SpacePirates_Instr_17(uint16 k, uint16 j) { // 0xB2F5D6 + Get_SpacePirates(k)->sps_var_00 = 0; + return j; +} + +void NinjaSpacePirates_Init(void) { // 0xB2F5DE + uint16 v1 = addr_kSpacePirates_Ilist_F2DA; + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + if ((E->sps_parameter_1 & 1) != 0) + v1 = addr_kSpacePirates_Ilist_F4CC; + E->base.current_instruction = v1; + E->sps_var_C = v1; + uint16 x_pos = E->base.x_pos; + if ((E->sps_parameter_1 & 1) != 0) { + E->sps_var_E = x_pos; + E->sps_var_F = E->sps_parameter_2 + x_pos; + } else { + E->sps_var_F = x_pos; + E->sps_var_E = x_pos - E->sps_parameter_2; + } + R20_ = (uint16)(E->sps_var_F - E->sps_var_E) >> 1; + E->sps_var_D = E->sps_var_E + R20_; + R18_ = 0; + R22_ = 0; + R20_ = (uint8)R20_ << 8; + do { + R18_ += 32; + R22_ += R18_; + } while (sign16(R22_ - R20_)); + E->sps_var_B = R18_; + R24_ = (uint8)((uint16)(R22_ & 0xFF00) >> 8); + E->sps_var_F = E->sps_var_D + R24_; + E->sps_var_E = E->sps_var_D - R24_; + uint16 sps_var_E = E->sps_var_E; + if ((E->sps_parameter_1 & 1) == 0) + sps_var_E = E->sps_var_F; + E->base.x_pos = sps_var_E; + E->sps_var_A = FUNC16(nullsub_169_B2); + E->sps_var_08 = E->base.y_pos; + uint16 v6 = 0; + uint16 v7 = 0; + R18_ = 15; + do { + target_palettes[(v7 >> 1) + 240] = kWallSpacePirates_Palette_3[v6 >> 1]; + v6 += 2; + v7 += 2; + --R18_; + } while ((R18_ & 0x8000u) == 0); +} + +void NinjaSpacePirates_Main(void) { // 0xB2F6A2 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + CallSpacePiratesEnemyFunc(E->sps_var_A | 0xB20000, cur_enemy_index); +} + +void SpacePirates_Func_5(uint16 k) { // 0xB2F6A9 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + if ((int16)(abs16(E->base.x_pos - samus_x_pos) - 128) >= 0) { + SpacePirates_Func_8(); + } else { + R18_ = E->base.x_pos - samus_x_pos; + uint16 v1 = addr_kSpacePirates_Ilist_F22E; + if ((R18_ & 0x8000u) != 0) + v1 = addr_kSpacePirates_Ilist_F420; + E->base.current_instruction = v1; + E->sps_var_C = v1; + E->base.instruction_timer = 1; + } +} + +void SpacePirates_Func_6(uint16 k) { // 0xB2F6E4 + if (!SpacePirates_Func_8() && !SpacePirates_Func_10() && !SpacePirates_Func_9()) + SpacePirates_Func_7(k); +} + +void SpacePirates_Func_7(uint16 k) { // 0xB2F6F7 + Enemy_SpacePirates *E = Get_SpacePirates(k); + if ((E->base.frame_counter & 0x3F) == 0) { + if (E->base.x_pos == E->sps_var_E) { + if ((int16)(E->base.x_pos - samus_x_pos) < 0) + return; + E->base.current_instruction = addr_kSpacePirates_Ilist_F15C; + } else { + if ((int16)(E->base.x_pos - samus_x_pos) >= 0) + return; + E->base.current_instruction = addr_kSpacePirates_Ilist_F34A; + } + E->base.instruction_timer = 1; + } +} + +uint16 SpacePirates_Func_8(void) { // 0xB2F72E + uint16 v0 = 8; + while (!projectile_type[v0 >> 1]) { + v0 -= 2; + if ((v0 & 0x8000u) != 0) + return 0; + } + int v1 = v0 >> 1; + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + if ((int16)(abs16(projectile_x_pos[v1] - E->base.x_pos) - 32) >= 0 + || (int16)(abs16(projectile_y_pos[v1] - E->base.y_pos) - 32) >= 0) { + return 0; + } + R18_ = E->base.x_pos - samus_x_pos; + uint16 v3 = addr_kSpacePirates_Ilist_F270; + if ((R18_ & 0x8000u) != 0) + v3 = addr_kSpacePirates_Ilist_F462; + E->base.current_instruction = v3; + E->base.instruction_timer = 1; + return 1; +} + +uint16 SpacePirates_Func_9(void) { // 0xB2F78D + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + if ((int16)(abs16(E->sps_var_D - samus_x_pos) - 32) >= 0) + return 0; + uint16 v1 = addr_kSpacePirates_Ilist_F1C4; + if (E->base.x_pos == E->sps_var_E) + v1 = addr_kSpacePirates_Ilist_F3B2; + E->base.current_instruction = v1; + E->base.instruction_timer = 1; + return 1; +} + +uint16 SpacePirates_Func_10(void) { // 0xB2F7C6 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + if ((int16)(abs16(samus_x_pos - E->base.x_pos) - 40) >= 0 + || (int16)(abs16(samus_y_pos - E->base.y_pos) - 40) >= 0) { + return 0; + } + R18_ = E->base.x_pos - samus_x_pos; + uint16 v1 = addr_kSpacePirates_Ilist_F32E; + if ((R18_ & 0x8000u) != 0) + v1 = addr_kSpacePirates_Ilist_F51A; + E->base.current_instruction = v1; + E->base.instruction_timer = 1; + return 1; +} + +void SpacePirates_Func_11(uint16 k) { // 0xB2F817 + Enemy_SpacePirates *E = Get_SpacePirates(k); + R18_ = HIBYTE(E->sps_var_00); + E->base.x_pos -= R18_; + --E->base.y_pos; + --E->base.y_pos; + E->sps_var_00 += 32; + if ((int16)(E->base.x_pos - E->sps_var_D) < 0) + E->sps_var_A = FUNC16(SpacePirates_Func_12); +} + +void SpacePirates_Func_12(uint16 k) { // 0xB2F84C + Enemy_SpacePirates *E = Get_SpacePirates(k); + R18_ = HIBYTE(E->sps_var_00); + E->base.x_pos -= R18_; + ++E->base.y_pos; + ++E->base.y_pos; + uint16 v2 = E->sps_var_00 - 32; + E->sps_var_00 = v2; + if (!v2) { + E->sps_var_A = FUNC16(nullsub_169_B2); + E->base.current_instruction = addr_kSpacePirates_Ilist_F2F8; + E->base.instruction_timer = 1; + E->base.x_pos = E->sps_var_E; + SpacePirates_FB11(k); + } +} + +void SpacePirates_Func_13(uint16 k) { // 0xB2F890 + Enemy_SpacePirates *E = Get_SpacePirates(k); + R18_ = HIBYTE(E->sps_var_00); + E->base.x_pos += R18_; + --E->base.y_pos; + --E->base.y_pos; + E->sps_var_00 += 32; + if ((int16)(E->base.x_pos - E->sps_var_D) >= 0) + E->sps_var_A = FUNC16(SpacePirates_Func_14); +} + +void SpacePirates_Func_14(uint16 k) { // 0xB2F8C5 + Enemy_SpacePirates *E = Get_SpacePirates(k); + R18_ = HIBYTE(E->sps_var_00); + E->base.x_pos += R18_; + ++E->base.y_pos; + ++E->base.y_pos; + uint16 v2 = E->sps_var_00 - 32; + E->sps_var_00 = v2; + if (!v2) { + E->sps_var_A = FUNC16(nullsub_169_B2); + E->base.current_instruction = addr_kSpacePirates_Ilist_F4EA; + E->base.instruction_timer = 1; + E->base.x_pos = E->sps_var_F; + SpacePirates_FB11(k); + } +} + +void SpacePirates_Func_15(uint16 k) { // 0xB2F909 + if (!SpacePirates_Func_8() && !SpacePirates_Func_10()) + SpacePirates_Func_16(); +} + +void SpacePirates_Func_16(void) { // 0xB2F917 + int16 v3; + + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + if ((int16)(abs16(E->sps_var_D - samus_x_pos) - 32) < 0) { + uint16 v2; + do + v2 = NextRandom() & 3; + while (!v2); + R18_ = v2; + v3 = 0; + if (E->base.x_pos == E->sps_var_E) + v3 = 4; + E->base.current_instruction = g_off_B2F959[R18_ + v3]; + E->base.instruction_timer = 1; + } +} + +uint16 SpacePirates_Instr_19(uint16 k, uint16 j) { // 0xB2F969 + Enemy_SpacePirates *E = Get_SpacePirates(k); + E->sps_var_00 = 1536; + E->sps_var_03 = E->sps_var_D + + ((uint16)(E->sps_var_F - E->sps_var_D) >> 1); + return j; +} + +void SpacePirates_F985(uint16 k) { // 0xB2F985 + int16 v2; + + Enemy_SpacePirates *E = Get_SpacePirates(k); + R18_ = HIBYTE(E->sps_var_00); + E->base.y_pos -= R18_; + v2 = E->sps_var_00 - 64; + E->sps_var_00 = v2; + if (v2 < 0) { + E->sps_var_A = FUNC16(SpacePirates_F9C1); + E->base.current_instruction = addr_kSpacePirates_Ilist_F2A0; + E->base.instruction_timer = 1; + E->sps_var_00 = 1536; + } +} + +void SpacePirates_F9C1(uint16 k) { // 0xB2F9C1 + int16 v2; + + Enemy_SpacePirates *E = Get_SpacePirates(k); + E->base.x_pos -= 5; + R20_ = HIBYTE(E->sps_var_00); + R18_ = LOBYTE(E->sps_var_00); + if (Enemy_MoveDown(k) & 1 + || (v2 = E->sps_var_00 - 64, E->sps_var_00 = v2, v2 < 0) + || (v2 & 0xFF00) == 0) { + E->sps_var_A = FUNC16(SpacePirates_FA15); + E->base.current_instruction = addr_kSpacePirates_Ilist_F2B2; + E->base.instruction_timer = 1; + E->base.y_pos = E->sps_var_08; + SpacePirates_FB11(k); + } +} + +void SpacePirates_FA15(uint16 k) { // 0xB2FA15 + Enemy_SpacePirates *E = Get_SpacePirates(k); + uint16 v2 = E->base.x_pos - 2; + E->base.x_pos = v2; + if ((int16)(v2 - E->sps_var_E) < 0) { + E->base.x_pos = E->sps_var_E; + E->base.current_instruction = addr_kSpacePirates_Ilist_F2F8; + E->base.instruction_timer = 1; + E->sps_var_A = FUNC16(nullsub_169_B2); + } +} + +uint16 SpacePirates_Instr_21(uint16 k, uint16 j) { // 0xB2FA3D + Enemy_SpacePirates *E = Get_SpacePirates(k); + E->sps_var_00 = 1536; + E->sps_var_03 = E->sps_var_E + + ((uint16)(E->sps_var_D - E->sps_var_E) >> 1); + return j; +} + +void SpacePirates_FA59(uint16 k) { // 0xB2FA59 + int16 v2; + + Enemy_SpacePirates *E = Get_SpacePirates(k); + R18_ = HIBYTE(E->sps_var_00); + E->base.y_pos -= R18_; + v2 = E->sps_var_00 - 64; + E->sps_var_00 = v2; + if (v2 < 0) { + E->sps_var_A = FUNC16(SpacePirates_FA95); + E->base.current_instruction = addr_kSpacePirates_Ilist_F492; + E->base.instruction_timer = 1; + E->sps_var_00 = 1536; + } +} + +void SpacePirates_FA95(uint16 k) { // 0xB2FA95 + int16 v2; + + Enemy_SpacePirates *E = Get_SpacePirates(k); + E->base.x_pos += 5; + R20_ = HIBYTE(E->sps_var_00); + R18_ = LOBYTE(E->sps_var_00); + if (Enemy_MoveDown(k) & 1 + || (v2 = E->sps_var_00 - 64, E->sps_var_00 = v2, v2 < 0) + || (v2 & 0xFF00) == 0) { + E->sps_var_A = FUNC16(SpacePirates_FAE9); + E->base.current_instruction = addr_kSpacePirates_Ilist_F4A4; + E->base.instruction_timer = 1; + E->base.y_pos = E->sps_var_08; + SpacePirates_FB11(k); + } +} + +void SpacePirates_FAE9(uint16 k) { // 0xB2FAE9 + Enemy_SpacePirates *E = Get_SpacePirates(k); + uint16 v2 = E->base.x_pos + 2; + E->base.x_pos = v2; + if ((int16)(v2 - E->sps_var_F) >= 0) { + E->base.x_pos = E->sps_var_F; + E->base.current_instruction = addr_kSpacePirates_Ilist_F4EA; + E->base.instruction_timer = 1; + E->sps_var_A = FUNC16(nullsub_169_B2); + } +} + +void SpacePirates_FB11(uint16 k) { // 0xB2FB11 + Enemy_SpacePirates *E = Get_SpacePirates(k); + R18_ = E->base.x_pos - 8; + R20_ = E->base.y_pos + 28; + R22_ = 10; + R24_ = 0; + CreateSpriteAtPos(); + R18_ = E->base.x_pos + 8; + R20_ = E->base.y_pos + 28; + R22_ = 10; + R24_ = 0; + CreateSpriteAtPos(); +} + +uint16 SpacePirates_Instr_12(uint16 k, uint16 j) { // 0xB2FC68 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + R18_ = E->base.x_pos - 24; + R20_ = E->base.y_pos - *(uint16 *)RomPtr_B2(j); + R22_ = 0; + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A17B, 0); + return j + 2; +} + +uint16 SpacePirates_Instr_14(uint16 k, uint16 j) { // 0xB2FC90 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + R18_ = E->base.x_pos + 24; + R20_ = E->base.y_pos - *(uint16 *)RomPtr_B2(j); + R22_ = 1; + SpawnEnemyProjectileWithRoomGfx(addr_stru_86A17B, 1u); + return j + 2; +} + +uint16 SpacePirates_Instr_11(uint16 k, uint16 j) { // 0xB2FCB8 + uint16 v2 = *(uint16 *)RomPtr_B2(j); + Get_SpacePirates(cur_enemy_index)->sps_var_A = v2; + return j + 2; +} + +uint16 SpacePirates_Instr_13(uint16 k, uint16 j) { // 0xB2FCC8 + uint16 result; + if (IsSamusWithinEnemy_Y(cur_enemy_index, 0x10u)) { + result = addr_kSpacePirates_Ilist_FB8C; + if ((int16)(samus_x_pos - Get_SpacePirates(cur_enemy_index)->base.x_pos) >= 0) + return addr_kSpacePirates_Ilist_FC0E; + } else { + result = addr_kSpacePirates_Ilist_FBE6; + if ((int16)(samus_x_pos - Get_SpacePirates(cur_enemy_index)->base.x_pos) >= 0) + return addr_kSpacePirates_Ilist_FB64; + } + return result; +} + +void WalkingSpacePirates_Init(void) { // 0xB2FD02 + uint16 v0 = addr_kSpacePirates_Ilist_FB64; + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + if ((E->sps_parameter_1 & 1) != 0) + v0 = addr_kSpacePirates_Ilist_FBE6; + E->base.current_instruction = v0; + E->sps_var_A = FUNC16(nullsub_169_B2); + E->sps_var_F = E->sps_parameter_2 + E->base.x_pos; + E->sps_var_E = E->base.x_pos - E->sps_parameter_2; +} + +void WalkingSpacePirates_Main(void) { // 0xB2FD32 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + CallSpacePiratesEnemyFunc(E->sps_var_A | 0xB20000, cur_enemy_index); + if ((Get_SpacePirates(cur_enemy_index)->sps_parameter_1 & 0x8000u) != 0) + WalkingSpacePirates_FE4B(); +} + +void WalkingSpacePirates_FD44(void) { // 0xB2FD44 + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + + if (IsSamusWithinEnemy_Y(cur_enemy_index, 0x10u)) { + uint16 v1 = addr_kSpacePirates_Ilist_FB8C; + if ((int16)(samus_x_pos - E->base.x_pos) >= 0) + v1 = addr_kSpacePirates_Ilist_FC0E; + E->base.current_instruction = v1; + E->base.instruction_timer = 1; + } else { + R20_ = 1; + R18_ = 0; + if (Enemy_MoveDown(cur_enemy_index)) { + uint16 x_pos = E->base.x_pos; + E->sps_var_00 = x_pos; + E->base.x_pos = x_pos - 17; + R20_ = 1; + R18_ = 0; + uint8 result = Enemy_MoveDown(cur_enemy_index); + E->base.x_pos = E->sps_var_00; + if (!result + || (R18_ = 0, R20_ = -9, EnemyFunc_BBBF(cur_enemy_index), R18_ = -14337, R20_ = -1, Enemy_MoveRight_IgnoreSlopes(cur_enemy_index)) + || (int16)(E->base.x_pos - E->sps_var_E) < 0) { + E->base.current_instruction = addr_kSpacePirates_Ilist_FBC6; + E->base.instruction_timer = 1; + } + } + } +} + +void WalkingSpacePirates_FDCE(void) { // 0xB2FDCE + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + + if (IsSamusWithinEnemy_Y(cur_enemy_index, 0x10u)) { + uint16 v1 = addr_kSpacePirates_Ilist_FB8C; + if ((int16)(samus_x_pos - E->base.x_pos) >= 0) + v1 = addr_kSpacePirates_Ilist_FC0E; + E->base.current_instruction = v1; + E->base.instruction_timer = 1; + } else { + R20_ = 1; + R18_ = 0; + if (Enemy_MoveDown(cur_enemy_index)) { + uint16 x_pos = E->base.x_pos; + E->sps_var_00 = x_pos; + E->base.x_pos = x_pos + 16; + R20_ = 1; + R18_ = 0; + uint8 result = Enemy_MoveDown(cur_enemy_index); + E->base.x_pos = E->sps_var_00; + if (!result || + (R18_ = 14336, R20_ = 0, Enemy_MoveRight_IgnoreSlopes(cur_enemy_index)) || + (int16)(E->base.x_pos - E->sps_var_F) >= 0) { + E->base.current_instruction = addr_kSpacePirates_Ilist_FC48; + E->base.instruction_timer = 1; + } + } + } +} + +void WalkingSpacePirates_FE4B(void) { // 0xB2FE4B + uint16 v0 = 8; + while (!projectile_type[v0 >> 1]) { + v0 -= 2; + if ((v0 & 0x8000u) != 0) + return; + } + int v1 = v0 >> 1; + Enemy_SpacePirates *E = Get_SpacePirates(cur_enemy_index); + if ((int16)(abs16(projectile_x_pos[v1] - E->base.x_pos) - 32) < 0 + && (int16)(abs16(projectile_y_pos[v1] - E->base.y_pos) - 32) < 0) { + R18_ = E->base.x_pos - samus_x_pos; + uint16 v3 = addr_kSpacePirates_Ilist_FB4C; + if ((R18_ & 0x8000u) != 0) + v3 = addr_kSpacePirates_Ilist_FB58; + E->base.current_instruction = v3; + E->base.instruction_timer = 1; + } +} diff --git a/src/sm_b3.c b/src/sm_b3.c new file mode 100644 index 0000000..5e4c428 --- /dev/null +++ b/src/sm_b3.c @@ -0,0 +1,1553 @@ +// $B3 - Enemy AI - inc. Botwoon +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" + + +#define g_off_B3882B ((uint16*)RomPtr(0xb3882b)) +#define g_off_B38833 ((uint16*)RomPtr(0xb38833)) +#define g_word_B3949B ((uint16*)RomPtr(0xb3949b)) +#define g_word_B394BB ((uint16*)RomPtr(0xb394bb)) +#define g_word_B39675 ((uint16*)RomPtr(0xb39675)) +#define kBotwoonHealthThresForPalChange ((uint16*)RomPtr(0xb3981b)) +#define kBotwoonHealthBasedPalette ((uint16*)RomPtr(0xb3971b)) +#define g_off_B3946B ((uint16*)RomPtr(0xb3946b)) +#define g_off_B3948B ((uint16*)RomPtr(0xb3948b)) +static const int16 g_word_B39E77[3] = { 2, 3, 4 }; +#define g_word_B3E718 ((uint16*)RomPtr(0xb3e718)) +#define g_word_B3E71E ((uint16*)RomPtr(0xb3e71e)) +#define g_off_B3E72A ((uint16*)RomPtr(0xb3e72a)) +#define g_off_B3E724 ((uint16*)RomPtr(0xb3e724)) +#define g_word_B3E730 ((uint16*)RomPtr(0xb3e730)) + +void Enemy_GrappleReact_NoInteract_B3(void) { // 0xB38000 + SwitchEnemyAiToMainAi(); +} + +void Enemy_GrappleReact_KillEnemy_B3(void) { // 0xB3800A + EnemyGrappleDeath(); +} + +void Enemy_GrappleReact_CancelBeam_B3(void) { // 0xB3800F + Enemy_SwitchToFrozenAi(); +} + +void Enemy_NormalTouchAI_B3(void) { // 0xB38023 + NormalEnemyTouchAi(); +} + +void Enemy_NormalTouchAI_SkipDeathAnim_B3(void) { // 0xB38028 + NormalEnemyTouchAiSkipDeathAnim_CurEnemy(); +} + +void Enemy_NormalShotAI_B3(void) { // 0xB3802D + NormalEnemyShotAi(); +} + +void Enemy_NormalShotAI_SkipSomeParts_B3(void) { // 0xB38032 + NormalEnemyShotAiSkipDeathAnim_CurEnemy(); +} + +void Enemy_NormalPowerBombAI_SkipDeathAnim_B3(void) { // 0xB3803C + NormalEnemyPowerBombAiSkipDeathAnim_CurEnemy(); +} + +void Enemy_NormalFrozenAI_B3(void) { // 0xB38041 + NormalEnemyFrozenAI(); +} + +uint16 Enemy_SetAiPreInstr_B3(uint16 k, uint16 j) { // 0xB3806B + uint16 v2 = *(uint16 *)RomPtr_B3(j); + gEnemyData(k)->ai_preinstr = v2; + return j + 2; +} + +uint16 Enemy_ClearAiPreInstr_B3(uint16 k, uint16 j) { // 0xB38074 + gEnemyData(k)->ai_preinstr = FUNC16(nullsub_171_B3); + return j; +} + +uint16 EnemyInstr_Goto_B3(uint16 k, uint16 j) { // 0xB380ED + return *(uint16 *)RomPtr_B3(j); +} + +uint16 EnemyInstr_DecTimerAndGoto2_B3(uint16 k, uint16 j) { // 0xB38110 + EnemyData *v2 = gEnemyData(k); + if (v2->timer-- == 1) + return j + 2; + else + return EnemyInstr_Goto_B3(k, j); +} + +uint16 EnemyInstr_SetTimer_B3(uint16 k, uint16 j) { // 0xB38123 + uint16 v2 = *(uint16 *)RomPtr_B3(j); + gEnemyData(k)->timer = v2; + return j + 2; +} + +uint16 EnemyInstr_Sleep_B3(uint16 k, uint16 j) { // 0xB3812F + gEnemyData(k)->current_instruction = j - 2; + return 0; +} + +void UnusedSpinningTurtleEye_Init(void) { // 0xB386FB + EnemyData *v0 = gEnemyData(cur_enemy_index); + v0->properties |= kEnemyProps_DisableSamusColl; + v0->current_instruction = addr_kUnusedSpinningTurtleEye_Ilist_86A7; +} + +void UnusedSpinningTurtleEye_Main(void) { // 0xB3870E + ; +} + +void BrinstarPipeBug_Init(void) { // 0xB3883B + Enemy_PipeBug *PipeBug = Get_PipeBug(cur_enemy_index); + PipeBug->pbg_var_B = PipeBug->base.x_pos; + uint16 y_pos = PipeBug->base.y_pos; + PipeBug->pbg_var_C = y_pos; + PipeBug->pbg_var_00 = y_pos - 16; + PipeBug->pbg_var_F = FUNC16(BrinstarPipeBug_PreInstr_1); + PipeBug->pbg_var_D = 48; + PipeBug->pbg_var_E = 0; + PipeBug->pbg_var_01 = 0; + PipeBug->base.current_instruction = addr_kBrinstarPipeBug_Ilist_87AB; + if (PipeBug->pbg_parameter_1) + PipeBug->base.current_instruction = addr_kBrinstarPipeBug_Ilist_8A1D; +} + +void BrinstarPipeBug_Main(void) { // 0xB3887A + Enemy_PipeBug *PipeBug = Get_PipeBug(cur_enemy_index); + CallEnemyPreInstr(PipeBug->pbg_var_F | 0xB30000); +} + +void BrinstarPipeBug_PreInstr_1(uint16 k) { // 0xB38880 + if (!CheckIfEnemyIsOnScreen()) + Get_PipeBug(cur_enemy_index)->pbg_var_F = FUNC16(BrinstarPipeBug_PreInstr_2); +} + +void BrinstarPipeBug_PreInstr_2(uint16 k) { // 0xB38890 + int16 SamusEnemyDelta_Y; + + SamusEnemyDelta_Y = GetSamusEnemyDelta_Y(k); + if (SamusEnemyDelta_Y < 0 && !sign16(SamusEnemyDelta_Y + 96)) { + Enemy_PipeBug *PipeBug = Get_PipeBug(k); + + uint16 a = GetSamusEnemyDelta_X(k); + PipeBug->pbg_var_A = PipeBug->pbg_var_A & 0x7fff | sign16(a); + + if (abs16(PipeBug->base.x_pos - samus_x_pos) < 0x40u) { + PipeBug->pbg_var_F = FUNC16(BrinstarPipeBug_PreInstr_3); + PipeBug->base.properties &= ~kEnemyProps_Invisible; + PipeBug->base.timer = 0; + uint16 v4; + if ((PipeBug->pbg_var_A & 0x8000u) != 0) + v4 = 0; + else + v4 = 2; + PipeBug->pbg_var_E = v4; + BrinstarPipeBug_Func_1(); + } + } +} + +void BrinstarPipeBug_PreInstr_3(uint16 k) { // 0xB388E3 + Enemy_PipeBug *PipeBug = Get_PipeBug(k); + bool v2 = PipeBug->base.y_subpos-- != 0; + PipeBug->base.y_pos += v2 - 2; + if ((int16)(PipeBug->pbg_var_00 - PipeBug->base.y_pos) >= 0 && PipeBug->base.y_pos < samus_y_pos) { + PipeBug->pbg_var_E |= 1u; + BrinstarPipeBug_Func_1(); + PipeBug->pbg_var_F = FUNC16(BrinstarPipeBug_PreInstr_4); + } +} + +void BrinstarPipeBug_PreInstr_4(uint16 k) { // 0xB3891C + Enemy_PipeBug *PipeBug = Get_PipeBug(k); + if ((PipeBug->pbg_var_A & 0x8000u) == 0) { + PipeBug->base.x_subpos = PipeBug->base.x_subpos; + PipeBug->base.x_pos = PipeBug->base.x_pos + 2; + } else { + PipeBug->base.x_subpos = PipeBug->base.x_subpos; + PipeBug->base.x_pos = PipeBug->base.x_pos - 2; + } + if (IsEnemyLeavingScreen(k) & 1) { + PipeBug->base.x_pos = PipeBug->pbg_var_B; + PipeBug->base.x_subpos = 0; + uint16 pbg_var_C = PipeBug->pbg_var_C; + PipeBug->base.y_pos = pbg_var_C; + PipeBug->base.y_subpos = pbg_var_C; + PipeBug->pbg_var_E = 0; + BrinstarPipeBug_Func_1(); + PipeBug->base.properties |= kEnemyProps_Invisible; + PipeBug->pbg_var_D = 48; + PipeBug->pbg_var_F = FUNC16(BrinstarPipeBug_PreInstr_5); + } +} + +void BrinstarPipeBug_PreInstr_5(uint16 k) { // 0xB3897E + Enemy_PipeBug *E = Get_PipeBug(k); + if (E->pbg_var_D-- == 1) + E->pbg_var_F = FUNC16(BrinstarPipeBug_PreInstr_2); +} + +void BrinstarPipeBug_Func_1(void) { // 0xB3898B + Enemy_PipeBug *PipeBug = Get_PipeBug(cur_enemy_index); + uint16 pbg_var_E = PipeBug->pbg_var_E; + if (pbg_var_E != PipeBug->pbg_var_01) { + PipeBug->pbg_var_01 = pbg_var_E; + PipeBug->base.current_instruction = PipeBug->pbg_parameter_1 ? + g_off_B38833[pbg_var_E] : g_off_B3882B[pbg_var_E]; + PipeBug->base.instruction_timer = 1; + PipeBug->base.timer = 0; + } +} + +void NorfairPipeBug_Init(void) { // 0xB38B61 + Enemy_PipeBug *PipeBug = Get_PipeBug(cur_enemy_index); + PipeBug->pbg_var_D = PipeBug->base.x_pos; + PipeBug->pbg_var_E = PipeBug->base.y_pos; + PipeBug->base.properties |= kEnemyProps_Invisible; + PipeBug->pbg_var_B = 8 * HIBYTE(PipeBug->pbg_parameter_2); + PipeBug->pbg_var_C = 0; + PipeBug->base.instruction_timer = 1; + PipeBug->base.timer = 0; + PipeBug->base.current_instruction = addr_kNorfairPipeBug_Ilist_8AE1; + PipeBug->pbg_var_A = FUNC16(NorfairPipeBug_Func_1); +} + +void CallBugInstr(uint32 ea, uint16 k) { + switch (ea) { + case fnNorfairPipeBug_Func_1: NorfairPipeBug_Func_1(); return; // 0xb38bcd + case fnNorfairPipeBug_Func_2: NorfairPipeBug_Func_2(); return; // 0xb38bff + case fnNorfairPipeBug_Func_4: NorfairPipeBug_Func_4(); return; // 0xb38ca6 + case fnNorfairPipeBug_Func_5: NorfairPipeBug_Func_5(k); return; // 0xb38cff + case fnNorfairPipeBug_Func_6: NorfairPipeBug_Func_6(); return; // 0xb38d0c + case fnNorfairPipeBug_Func_7: NorfairPipeBug_Func_7(); return; // 0xb38d4e + case fnNorfairPipeBug_Func_8: NorfairPipeBug_Func_8(); return; // 0xb38d90 + case fnNorfairPipeBug_Func_9: NorfairPipeBug_Func_9(); return; // 0xb38dd2 + case fnNorfairPipeBug_Func_10: NorfairPipeBug_Func_10(); return; // 0xb38e14 + case fnNorfairPipeBug_Func_11: NorfairPipeBug_Func_11(); return; // 0xb38e35 + case fnNorfairPipeBug_Func_12: NorfairPipeBug_Func_12(); return; // 0xb38e5a + case fnBrinstarYellowPipeBug_Func_1: BrinstarYellowPipeBug_Func_1(); return; // 0xb38fb5 + case fnBrinstarYellowPipeBug_Func_2: BrinstarYellowPipeBug_Func_2(cur_enemy_index); return; // 0xb38ff5 + case fnBrinstarYellowPipeBug_Func_3: BrinstarYellowPipeBug_Func_3(); return; // 0xb39028 + case fnBrinstarYellowPipeBug_Func_5: BrinstarYellowPipeBug_Func_5(); return; // 0xb390bd + case fnBrinstarYellowPipeBug_Func_7: BrinstarYellowPipeBug_Func_7(); return; // 0xb3915a + case fnBrinstarYellowPipeBug_Func_8: BrinstarYellowPipeBug_Func_8(); return; // 0xb391d8 + default: Unreachable(); + } +} + +void NorfairPipeBug_Main(void) { // 0xB38B9E + Enemy_PipeBug *PipeBug = Get_PipeBug(cur_enemy_index); + CallBugInstr(PipeBug->pbg_var_A | 0xB30000, cur_enemy_index); + NorfairPipeBug_8BA8(); +} + +void NorfairPipeBug_8BA8(void) { // 0xB38BA8 + if (CheckIfEnemyIsOnScreen()) { + Enemy_PipeBug *PipeBug = Get_PipeBug(cur_enemy_index); + PipeBug->base.properties |= kEnemyProps_Invisible; + PipeBug->pbg_var_A = FUNC16(NorfairPipeBug_Func_1); + PipeBug->base.x_pos = PipeBug->pbg_var_D; + PipeBug->base.y_pos = PipeBug->pbg_var_E; + } +} + +void NorfairPipeBug_Func_1(void) { // 0xB38BCD + if (LOBYTE(Get_PipeBug(cur_enemy_index)->pbg_parameter_2) + && Get_PipeBug(cur_enemy_index + 64)->pbg_var_A == (uint16)FUNC16(NorfairPipeBug_Func_1) + && Get_PipeBug(cur_enemy_index + 128)->pbg_var_A == (uint16)FUNC16(NorfairPipeBug_Func_1) + && Get_PipeBug(cur_enemy_index + 192)->pbg_var_A == (uint16)FUNC16(NorfairPipeBug_Func_1) + && Get_PipeBug(cur_enemy_index + 256)->pbg_var_A == (uint16)FUNC16(NorfairPipeBug_Func_1)) { + Get_PipeBug(cur_enemy_index)->pbg_var_A = FUNC16(NorfairPipeBug_Func_2); + } +} + +void NorfairPipeBug_Func_2(void) { // 0xB38BFF + int k = cur_enemy_index; + Enemy_PipeBug *PipeBug = Get_PipeBug(cur_enemy_index); + if (IsSamusWithinEnemy_X(cur_enemy_index, LOBYTE(PipeBug->pbg_parameter_2)) + && (int16)(PipeBug->base.y_pos - samus_y_pos) >= 0) { + ++PipeBug->pbg_var_C; + PipeBug->base.instruction_timer = 1; + PipeBug->base.timer = 0; + if ((GetSamusEnemyDelta_X(k) & 0x8000u) == 0) { + Get_PipeBug(k)->base.current_instruction = addr_kNorfairPipeBug_Ilist_8B21; + Get_PipeBug(k + 64)->base.current_instruction = addr_kNorfairPipeBug_Ilist_8B21; + Get_PipeBug(k + 128)->base.current_instruction = addr_kNorfairPipeBug_Ilist_8B21; + Get_PipeBug(k + 192)->base.current_instruction = addr_kNorfairPipeBug_Ilist_8B21; + Get_PipeBug(k + 256)->base.current_instruction = addr_kNorfairPipeBug_Ilist_8B21; + } else { + PipeBug->base.current_instruction = addr_kNorfairPipeBug_Ilist_8AE1; + Get_PipeBug(k + 64)->base.current_instruction = addr_kNorfairPipeBug_Ilist_8AE1; + Get_PipeBug(k + 128)->base.current_instruction = addr_kNorfairPipeBug_Ilist_8AE1; + Get_PipeBug(k + 192)->base.current_instruction = addr_kNorfairPipeBug_Ilist_8AE1; + Get_PipeBug(k + 256)->base.current_instruction = addr_kNorfairPipeBug_Ilist_8AE1; + } + NorfairPipeBug_Func_3(k); + } +} + +void NorfairPipeBug_Func_3(uint16 k) { // 0xB38C52 + Get_PipeBug(k)->pbg_var_A = FUNC16(NorfairPipeBug_Func_4); + Get_PipeBug(k + 64)->pbg_var_A = FUNC16(NorfairPipeBug_Func_4); + Get_PipeBug(k + 128)->pbg_var_A = FUNC16(NorfairPipeBug_Func_4); + Get_PipeBug(k + 192)->pbg_var_A = FUNC16(NorfairPipeBug_Func_4); + Get_PipeBug(k + 256)->pbg_var_A = FUNC16(NorfairPipeBug_Func_4); + Get_PipeBug(k)->pbg_var_02 = 104; + Get_PipeBug(k + 64)->pbg_var_02 = 96; + Get_PipeBug(k + 128)->pbg_var_02 = 88; + Get_PipeBug(k + 192)->pbg_var_02 = 112; + Get_PipeBug(k + 256)->pbg_var_02 = 120; + Get_PipeBug(k)->pbg_var_F = FUNC16(NorfairPipeBug_Func_5); + Get_PipeBug(k + 64)->pbg_var_F = FUNC16(NorfairPipeBug_Func_6); + Get_PipeBug(k + 128)->pbg_var_F = FUNC16(NorfairPipeBug_Func_7); + Get_PipeBug(k + 192)->pbg_var_F = FUNC16(NorfairPipeBug_Func_8); + Get_PipeBug(k + 256)->pbg_var_F = FUNC16(NorfairPipeBug_Func_9); +} + +void NorfairPipeBug_Func_4(void) { // 0xB38CA6 + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + E->base.properties &= ~kEnemyProps_Invisible; + uint16 y_subpos = E->base.y_subpos; + bool v3 = __CFADD__uint16(kCommonEnemySpeeds_Linear[67], y_subpos); + uint16 v4 = kCommonEnemySpeeds_Linear[67] + y_subpos; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v4; + uint16 v5 = kCommonEnemySpeeds_Linear[66] + E->base.y_pos; + E->base.y_pos = v5; + if ((int16)(v5 - samus_y_pos) < 0) { + E->pbg_var_A = E->pbg_var_F; + E->pbg_var_01 = E->base.y_pos; + E->base.instruction_timer = 1; + E->base.timer = 0; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) + E->base.current_instruction = addr_kNorfairPipeBug_Ilist_8B21; + else + E->base.current_instruction = addr_kNorfairPipeBug_Ilist_8AE1; + } +} + +void NorfairPipeBug_Func_5(uint16 k) { // 0xB38CFF + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + ++E->pbg_var_C; + E->pbg_var_A = FUNC16(NorfairPipeBug_Func_12); +} + +void NorfairPipeBug_Func_6(void) { // 0xB38D0C + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + ++E->pbg_var_C; + uint16 y_subpos = E->base.y_subpos; + bool v2 = __CFADD__uint16(kCommonEnemySpeeds_Linear[67], y_subpos); + uint16 v3 = kCommonEnemySpeeds_Linear[67] + y_subpos; + if (v2) + ++E->base.y_pos; + E->base.y_subpos = v3; + uint16 v4 = kCommonEnemySpeeds_Linear[66] + E->base.y_pos; + E->base.y_pos = v4; + if ((int16)(v4 + 16 - E->pbg_var_01) < 0) { + E->base.y_pos = E->pbg_var_01 - 16; + E->base.y_subpos = 0; + E->pbg_var_A = FUNC16(NorfairPipeBug_Func_12); + } +} + +void NorfairPipeBug_Func_7(void) { // 0xB38D4E + + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + ++E->pbg_var_C; + uint16 y_subpos = E->base.y_subpos; + bool v2 = __CFADD__uint16(kCommonEnemySpeeds_Linear[67], y_subpos); + uint16 v3 = kCommonEnemySpeeds_Linear[67] + y_subpos; + if (v2) + ++E->base.y_pos; + E->base.y_subpos = v3; + uint16 v4 = kCommonEnemySpeeds_Linear[66] + E->base.y_pos; + E->base.y_pos = v4; + if ((int16)(v4 + 32 - E->pbg_var_01) < 0) { + E->base.y_pos = E->pbg_var_01 - 32; + E->base.y_subpos = 0; + E->pbg_var_A = FUNC16(NorfairPipeBug_Func_12); + } +} + +void NorfairPipeBug_Func_8(void) { // 0xB38D90 + + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + ++E->pbg_var_C; + uint16 y_subpos = E->base.y_subpos; + bool v2 = __CFADD__uint16(kCommonEnemySpeeds_Linear[65], y_subpos); + uint16 v3 = kCommonEnemySpeeds_Linear[65] + y_subpos; + if (v2) + ++E->base.y_pos; + E->base.y_subpos = v3; + uint16 v4 = kCommonEnemySpeeds_Linear[64] + E->base.y_pos; + E->base.y_pos = v4; + if ((int16)(v4 - 16 - E->pbg_var_01) >= 0) { + E->base.y_pos = E->pbg_var_01 + 16; + E->base.y_subpos = 0; + E->pbg_var_A = FUNC16(NorfairPipeBug_Func_12); + } +} + +void NorfairPipeBug_Func_9(void) { // 0xB38DD2 + + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + ++E->pbg_var_C; + uint16 y_subpos = E->base.y_subpos; + bool v2 = __CFADD__uint16(kCommonEnemySpeeds_Linear[65], y_subpos); + uint16 v3 = kCommonEnemySpeeds_Linear[65] + y_subpos; + if (v2) + ++E->base.y_pos; + E->base.y_subpos = v3; + uint16 v4 = kCommonEnemySpeeds_Linear[64] + E->base.y_pos; + E->base.y_pos = v4; + if ((int16)(v4 - 32 - E->pbg_var_01) >= 0) { + E->base.y_pos = E->pbg_var_01 + 32; + E->base.y_subpos = 0; + E->pbg_var_A = FUNC16(NorfairPipeBug_Func_12); + } +} + +void NorfairPipeBug_Func_10(void) { // 0xB38E14 + + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + uint16 x_subpos = E->base.x_subpos; + int v2 = E->pbg_var_B >> 1; + bool v3 = __CFADD__uint16(kCommonEnemySpeeds_Linear[v2 + 3], x_subpos); + uint16 v4 = kCommonEnemySpeeds_Linear[v2 + 3] + x_subpos; + if (v3) + ++E->base.x_pos; + E->base.x_subpos = v4; + E->base.x_pos += kCommonEnemySpeeds_Linear[v2 + 2]; +} + +void NorfairPipeBug_Func_11(void) { // 0xB38E35 + + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + uint16 x_subpos = E->base.x_subpos; + int v2 = E->pbg_var_B >> 1; + bool v3 = __CFADD__uint16(kCommonEnemySpeeds_Linear[v2 + 1], x_subpos); + uint16 v4 = kCommonEnemySpeeds_Linear[v2 + 1] + x_subpos; + if (v3) + ++E->base.x_pos; + E->base.x_subpos = v4; + E->base.x_pos += kCommonEnemySpeeds_Linear[v2]; +} + +void sub_B38E56(void) { // 0xB38E56 + ; +} + +void NorfairPipeBug_Func_12(void) { // 0xB38E5A + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + if ((int16)(++E->pbg_var_C - E->pbg_var_02) >= 0) { + E->pbg_var_C = 0; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->pbg_var_A = FUNC16(NorfairPipeBug_Func_10); + E->base.current_instruction = addr_kNorfairPipeBug_Ilist_8B05; + if ((GetSamusEnemyDelta_X(cur_enemy_index) & 0x8000u) == 0) { + E->pbg_var_A = FUNC16(NorfairPipeBug_Func_11); + E->base.current_instruction = addr_kNorfairPipeBug_Ilist_8B45; + } + } +} + +void BrinstarYellowPipeBug_Init(void) { // 0xB38F4C + + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + E->pbg_var_07 = E->base.x_pos; + E->pbg_var_08 = E->base.y_pos; + E->base.x_subpos = 0; + E->base.y_subpos = 0; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kBrinstarYellowPipeBug_Ilist_8EFC; + if (!E->pbg_parameter_1) + E->base.current_instruction = addr_kBrinstarYellowPipeBug_Ilist_8F24; + int v1 = (uint16)(8 * E->pbg_parameter_2) >> 1; + E->pbg_var_01 = kCommonEnemySpeeds_Linear[v1]; + E->pbg_var_00 = kCommonEnemySpeeds_Linear[v1 + 1]; + E->pbg_var_03 = kCommonEnemySpeeds_Linear[v1 + 2]; + E->pbg_var_02 = kCommonEnemySpeeds_Linear[v1 + 3]; + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_1); + E->pbg_var_06 = 0; +} + +void BrinstarYellowPipeBug_Main(void) { // 0xB38FAE + + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + CallBugInstr(E->pbg_var_A | 0xB30000, cur_enemy_index); +} + +void BrinstarYellowPipeBug_Func_1(void) { // 0xB38FB5 + int16 v2; + int16 SamusEnemyDelta_X; + + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + if (E->pbg_parameter_1) { + SamusEnemyDelta_X = GetSamusEnemyDelta_X(cur_enemy_index); + if (SamusEnemyDelta_X < 0 && !sign16(SamusEnemyDelta_X + 192)) + goto LABEL_7; + } else { + v2 = GetSamusEnemyDelta_X(cur_enemy_index); + if (v2 >= 0 && sign16(v2 - 192)) { +LABEL_7: + if (IsSamusWithinEnemy_Y(cur_enemy_index, 0x30u)) { + E->base.properties &= ~kEnemyProps_Invisible; + E->pbg_var_20 = 24; + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_2); + } + } + } +} + +void BrinstarYellowPipeBug_Func_2(uint16 k) { // 0xB38FF5 + + Enemy_PipeBug *E = Get_PipeBug(k); + uint16 v2 = E->pbg_var_20 - 1; + E->pbg_var_20 = v2; + if (!v2) { + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kBrinstarYellowPipeBug_Ilist_8EFC; + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_3); + if (!E->pbg_parameter_1) { + E->base.current_instruction = addr_kBrinstarYellowPipeBug_Ilist_8F24; + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_5); + } + } +} + +void BrinstarYellowPipeBug_Func_3(void) { // 0xB39028 + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + BrinstarYellowPipeBug_Func_4(cur_enemy_index); + if (CheckIfEnemyIsOnScreen()) { + E->base.x_pos = E->pbg_var_07; + E->base.y_pos = E->pbg_var_08; + E->base.x_subpos = 0; + E->base.y_subpos = 0; + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_1); + E->pbg_var_06 = 0; + E->base.properties |= kEnemyProps_Invisible; + } else { + if (!E->pbg_var_06) { + if (sign16(E->base.x_pos - samus_x_pos - 48)) { + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_7); + E->pbg_var_C = 0; + E->pbg_var_D = 0; + E->pbg_var_E = 40; + E->pbg_var_F = 1; + E->pbg_var_04 = E->base.x_pos; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kBrinstarYellowPipeBug_Ilist_8F10; + } + } + } +} + +void BrinstarYellowPipeBug_Func_4(uint16 k) { // 0xB390A1 + + Enemy_PipeBug *E = Get_PipeBug(k); + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->pbg_var_02, x_subpos); + uint16 v4 = E->pbg_var_02 + x_subpos; + if (v3) + ++E->base.x_pos; + E->base.x_subpos = v4; + E->base.x_pos += E->pbg_var_03; +} + +void BrinstarYellowPipeBug_Func_5(void) { // 0xB390BD + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + + BrinstarYellowPipeBug_Func_6(cur_enemy_index); + if (CheckIfEnemyIsOnScreen()) { + E->base.x_pos = E->pbg_var_07; + E->base.y_pos = E->pbg_var_08; + E->base.x_subpos = 0; + E->base.y_subpos = 0; + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_1); + E->pbg_var_06 = 0; + E->base.properties |= kEnemyProps_Invisible; + } else { + if (!E->pbg_var_06) { + if (sign16(samus_x_pos - E->base.x_pos - 48)) { + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_8); + E->pbg_var_C = 0; + E->pbg_var_D = 0; + E->pbg_var_E = 40; + E->pbg_var_F = 1; + E->pbg_var_04 = E->base.x_pos; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kBrinstarYellowPipeBug_Ilist_8F38; + } + } + } +} + +void BrinstarYellowPipeBug_Func_6(uint16 k) { // 0xB3913A + Enemy_PipeBug *E = Get_PipeBug(k); + uint16 x_subpos = E->base.x_subpos; + bool v3 = __CFADD__uint16(E->pbg_var_00, x_subpos); + uint16 v4 = E->pbg_var_00 + x_subpos; + if (v3) + ++E->base.x_pos; + E->base.x_subpos = v4; + E->base.x_pos += E->pbg_var_01; +} + +void BrinstarYellowPipeBug_Func_7(void) { // 0xB3915A + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + if (CheckIfEnemyIsOnScreen()) { + E->base.x_pos = E->pbg_var_07; + E->base.y_pos = E->pbg_var_08; + E->base.x_subpos = 0; + E->base.y_subpos = 0; + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_1); + E->pbg_var_06 = 0; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kBrinstarYellowPipeBug_Ilist_8EFC; + E->base.properties |= kEnemyProps_Invisible; + } else { + BrinstarYellowPipeBug_Func_4(cur_enemy_index); + if (E->pbg_var_F) { + BrinstarYellowPipeBug_Func_10(cur_enemy_index); + } else { + BrinstarYellowPipeBug_Func_9(cur_enemy_index); + if ((int16)(E->base.y_pos - E->pbg_var_08) < 0) { + E->pbg_var_06 = 1; + E->pbg_var_F = 1; + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_3); + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kBrinstarYellowPipeBug_Ilist_8EFC; + } + } + } +} + +void BrinstarYellowPipeBug_Func_8(void) { // 0xB391D8 + Enemy_PipeBug *E = Get_PipeBug(cur_enemy_index); + if (CheckIfEnemyIsOnScreen()) { + E->base.x_pos = E->pbg_var_07; + E->base.y_pos = E->pbg_var_08; + E->base.x_subpos = 0; + E->base.y_subpos = 0; + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_1); + E->pbg_var_06 = 0; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kBrinstarYellowPipeBug_Ilist_8F24; + E->base.properties |= kEnemyProps_Invisible; + } else { + BrinstarYellowPipeBug_Func_6(cur_enemy_index); + if (E->pbg_var_F) { + BrinstarYellowPipeBug_Func_10(cur_enemy_index); + } else { + BrinstarYellowPipeBug_Func_9(cur_enemy_index); + if ((int16)(E->pbg_var_08 - E->base.y_pos) >= 0) { + E->pbg_var_06 = 1; + E->pbg_var_F = 1; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kBrinstarYellowPipeBug_Ilist_8F24; + E->pbg_var_A = FUNC16(BrinstarYellowPipeBug_Func_5); + } + } + } +} + +void BrinstarYellowPipeBug_Func_9(uint16 k) { // 0xB39256 + Enemy_PipeBug *E = Get_PipeBug(k); + ++E->pbg_var_E; + uint16 y_subpos = E->base.y_subpos; + int v3 = (uint16)(8 * E->pbg_var_E) >> 1; + bool v4 = __CFADD__uint16(kCommonEnemySpeeds_Quadratic[v3 + 2], y_subpos); + uint16 v5 = kCommonEnemySpeeds_Quadratic[v3 + 2] + y_subpos; + if (v4) + ++E->base.y_pos; + E->base.y_subpos = v5; + E->base.y_pos += kCommonEnemySpeeds_Quadratic[v3 + 3]; +} + +void BrinstarYellowPipeBug_Func_10(uint16 k) { // 0xB3927A + Enemy_PipeBug *E = Get_PipeBug(k); + if ((--E->pbg_var_E & 0x8000u) != 0) { + E->pbg_var_E = 0; + E->pbg_var_F = 0; + } else { + uint16 y_subpos = E->base.y_subpos; + int v4 = (uint16)(8 * E->pbg_var_E) >> 1; + bool v5 = __CFADD__uint16(kCommonEnemySpeeds_Quadratic[v4], y_subpos); + uint16 v6 = kCommonEnemySpeeds_Quadratic[v4] + y_subpos; + if (v5) + ++E->base.y_pos; + E->base.y_subpos = v6; + E->base.y_pos += kCommonEnemySpeeds_Quadratic[v4 + 1]; + } +} + +uint16 Botwoon_Instr_1(uint16 k, uint16 j) { // 0xB394C7 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.x_width = 8; + E->base.y_height = 16; + return j; +} + +uint16 Botwoon_Instr_2(uint16 k, uint16 j) { // 0xB394D7 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.x_width = 12; + E->base.y_height = 12; + return j; +} + +uint16 Botwoon_Instr_3(uint16 k, uint16 j) { // 0xB394E7 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.x_width = 16; + E->base.y_height = 8; + return j; +} + +uint16 Botwoon_Instr_4(uint16 k, uint16 j) { // 0xB394F7 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.x_width = 12; + E->base.y_height = 12; + return j; +} + +uint16 Botwoon_Instr_5(uint16 k, uint16 j) { // 0xB39507 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.x_width = 8; + E->base.y_height = 16; + return j; +} + +uint16 Botwoon_Instr_6(uint16 k, uint16 j) { // 0xB39517 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.x_width = 8; + E->base.y_height = 16; + return j; +} + +uint16 Botwoon_Instr_7(uint16 k, uint16 j) { // 0xB39527 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.x_width = 12; + E->base.y_height = 12; + return j; +} + +uint16 Botwoon_Instr_8(uint16 k, uint16 j) { // 0xB39537 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.x_width = 16; + E->base.y_height = 8; + return j; +} + +uint16 Botwoon_Instr_9(uint16 k, uint16 j) { // 0xB39547 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.x_width = 12; + E->base.y_height = 12; + return j; +} + +uint16 Botwoon_Instr_10(uint16 k, uint16 j) { // 0xB39557 + + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.x_width = 8; + E->base.y_height = 16; + return j; +} + +uint16 Botwoon_Instr_SetSpitting(uint16 k, uint16 j) { // 0xB39567 + Get_Botwoon(cur_enemy_index)->botwoon_var_5A = 1; + return j; +} + +uint16 Botwoon_Instr_QueueSpitSfx(uint16 k, uint16 j) { // 0xB39572 + QueueSfx2_Max6(0x7Cu); + return j; +} + +void Botwoon_QueueExplosionSfx(void) { // 0xB3957B + QueueSfx2_Max6(0x24u); +} + +void Botwoon_Init(void) { // 0xB39583 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if ((boss_bits_for_area[4] & 2) != 0) { + static const SpawnHardcodedPlmArgs unk_B39593 = { 0x0f, 0x04, 0xb797 }; + SpawnHardcodedPlm(&unk_B39593); + *(uint16 *)scrolls = 257; + E->base.current_instruction = addr_kBotwoon_Ilist_9389; + E->base.properties |= kEnemyProps_Deleted; + } else { + uint16 v3 = 24; + E->botwoon_var_A = 24; + bool v5; + do { + SpawnEnemyProjectileWithGfx(v3, cur_enemy_index, addr_kEproj_BotwoonsBody); + v5 = (int16)(--E->botwoon_var_A - 1) < 0; + --E->botwoon_var_A; + } while (!v5); + E->base.current_instruction = addr_kBotwoon_Ilist_9389; + E->botwoon_var_3B = addr_kBotwoon_Ilist_9389; + E->botwoon_var_D = FUNC16(Botwoon_Func_6); + E->botwoon_var_E = FUNC16(Botwoon_Func_19); + E->botwoon_var_F = FUNC16(Botwoon_Func_26); + E->botwoon_var_20 = 256; + E->botwoon_var_38 = g_word_B394BB[0]; + E->botwoon_var_C = g_word_B394BB[1]; + E->botwoon_var_33 = 1; + E->botwoon_var_34 = 1; + E->botwoon_var_59 = 1; + E->botwoon_var_36 = -1; + E->botwoon_var_37 = 0; + E->base.properties |= kEnemyProps_Tangible; + uint16 health = E->base.health; + E->botwoon_var_5B = health; + health >>= 1; + E->botwoon_var_5C = health; + E->botwoon_var_5D = health >> 1; + uint16 x_pos = E->base.x_pos; + E->botwoon_var_50 = x_pos; + E->botwoon_var_52 = x_pos; + E->botwoon_var_54 = x_pos; + E->botwoon_var_56 = x_pos; + uint16 y_pos = E->base.y_pos; + E->botwoon_var_51 = y_pos; + E->botwoon_var_53 = y_pos; + E->botwoon_var_55 = y_pos; + E->botwoon_var_57 = y_pos; + E->botwoon_var_4E = (E->base.palette_index >> 4) + 256; + } +} + +void CallBotwoonFuncVarD(uint32 ea, uint16 k) { + switch (ea) { + case fnBotwoon_Func_6: Botwoon_Func_6(); return; + case fnBotwoon_Func_7: Botwoon_Func_7(); return; + case fnBotwoon_Func_12: Botwoon_Func_12(); return; + case fnBotwoon_Func_13: Botwoon_Func_13(); return; + case fnBotwoon_Func_14: Botwoon_Func_14(); return; + case fnBotwoon_Func_15: Botwoon_Func_15(); return; + case fnBotwoon_Func_16: Botwoon_Func_16(); return; + case fnBotwoon_Func_18: Botwoon_Func_18(k); return; + default: Unreachable(); + } +} +void CallBotwoonFuncVarE(uint32 ea) { + switch (ea) { + case fnBotwoon_Func_19: Botwoon_Func_19(); return; + case fnBotwoon_Func_32: Botwoon_Func_32(); return; + case fnBotwoon_Func_33: Botwoon_Func_33(); return; + default: Unreachable(); + } +} + +void Botwoon_Main(void) { // 0xB39668 + Botwoon_Func_3(); + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + CallBotwoonFuncVarD(E->botwoon_var_D | 0xB30000, cur_enemy_index); + Botwoon_HealthBasedPalHandling(); +} + +void Botwoon_Func_1(uint16 k) { // 0xB3967B + Enemy_Botwoon *E = Get_Botwoon(k); + R18_ = g_word_B39675[E->botwoon_var_3F]; + if ((R18_ & NextRandom()) == 0) + E->botwoon_var_2E = 1; +} + +void Botwoon_Func_2(void) { // 0xB39696 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if (!E->botwoon_var_2F && E->botwoon_var_2E && !E->botwoon_var_33 && !E->botwoon_var_21) { + E->botwoon_var_F = FUNC16(Botwoon_Func_27); + E->botwoon_var_21 = 24; + } + E->botwoon_var_2E = 0; +} + +void Botwoon_Func_3(void) { // 0xB396C6 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if (E->botwoon_var_2F) { + if (E->botwoon_var_3E) { + E->botwoon_var_30 = 1; + E->botwoon_var_D = FUNC16(Botwoon_Func_14); + E->botwoon_var_22 = 240; + E->botwoon_var_2F = 0; + E->botwoon_var_3E = 0; + } + } +} + +void Botwoon_Func_4(void) { // 0xB396F5 + Enemy_Botwoon *E = Get_Botwoon(0); + E->base.properties |= kEnemyProps_Tangible; +} + +void Botwoon_Func_5(void) { // 0xB396FF + uint16 v0 = 34; + do { + enemy_projectile_properties[v0 >> 1] |= 0x2000u; + enemy_projectile_flags[v0 >> 1] = 2; + v0 -= 2; + } while ((int16)(v0 - 10) >= 0); +} + +void Botwoon_HealthBasedPalHandling(void) { // 0xB3982B + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if (E->botwoon_var_4F != 16 + && (int16)(E->base.health - kBotwoonHealthThresForPalChange[E->botwoon_var_4F >> 1]) < 0) { + R18_ = 16 * E->botwoon_var_4F; + R20_ = E->botwoon_var_4E; + do { + palette_buffer[R20_ >> 1] = kBotwoonHealthBasedPalette[R18_++ >> 1]; + ++R18_; + ++R20_; + ++R20_; + } while (R20_ != 512); + E->botwoon_var_4F += 2; + } +} + +void Botwoon_Func_6(void) { // 0xB39878 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + uint16 v1 = E->botwoon_var_20 - 1; + E->botwoon_var_20 = v1; + if (!v1) + E->botwoon_var_D = FUNC16(Botwoon_Func_7); +} + +void Botwoon_Func_7(void) { // 0xB3989D + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if (E->botwoon_var_3C) { + E->botwoon_var_3C = 0; + R18_ = 0; + if (!E->botwoon_var_33 && !E->botwoon_var_59 && !E->botwoon_var_3F) { + LOBYTE(R18_) = NextRandom() & 0xE; + R18_ = (uint8)R18_; + } + E->botwoon_var_59 = 0; + if (!R18_ || R18_ == 2 || R18_ == 4) { + Botwoon_Func_8(); + } else { + if (R18_ != 6 && R18_ != 8 && R18_ != 10 && R18_ != 12 && R18_ != 14) { + Unreachable(); + while (1) + ; + } + Botwoon_Func_9(); + } + } else { + CallBotwoonFuncVarE(E->botwoon_var_E | 0xB30000); + Botwoon_Func_22(); + Botwoon_Func_23(); + CallEnemyPreInstr(E->botwoon_var_F | 0xB30000); + Botwoon_Func_25(); + Botwoon_Func_24(); + Botwoon_Func_31(cur_enemy_index); + } +} + +void Botwoon_Func_8(void) { // 0xB398EC + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->botwoon_var_D = FUNC16(Botwoon_Func_12); + E->botwoon_var_E = FUNC16(Botwoon_Func_32); + E->botwoon_var_21 = 0; + E->botwoon_var_F = FUNC16(Botwoon_Func_26); + E->botwoon_var_4B = 0; + Botwoon_Func_10(cur_enemy_index); +} + +void Botwoon_Func_9(void) { // 0xB39913 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->botwoon_var_D = FUNC16(Botwoon_Func_13); + E->botwoon_var_F = FUNC16(Botwoon_Func_27); + E->botwoon_var_21 = 48; + E->base.properties &= ~kEnemyProps_Tangible; +} + +void Botwoon_Func_10(uint16 k) { // 0xB39933 + Botwoon_Func_11(k); + R18_ = 0; + Enemy_Botwoon *E = Get_Botwoon(k); + if (E->botwoon_var_33) + R18_ = 128; + LOBYTE(R20_) = NextRandom() & 0x18; + R20_ = (uint8)R20_; + E->botwoon_var_40 = (uint8)R20_ + R18_ + 4 * E->botwoon_var_37; +} + +void Botwoon_Func_11(uint16 k) { // 0xB3995D + int16 health; + + Enemy_Botwoon *E = Get_Botwoon(k); + if (!E->botwoon_var_33) { + E->botwoon_var_3F = 0; + health = E->base.health; + if (health > 0 && (int16)(health - E->botwoon_var_5C) < 0) { + if ((int16)(health - E->botwoon_var_5D) < 0) + E->botwoon_var_3F = 2; + else + E->botwoon_var_3F = 1; + int v3 = (uint16)(4 * E->botwoon_var_3F) >> 1; + E->botwoon_var_38 = g_word_B394BB[v3]; + E->botwoon_var_C = g_word_B394BB[v3 + 1]; + } + } +} + +void Botwoon_Func_12(void) { // 0xB399A4 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if (E->botwoon_var_3C) { + E->botwoon_var_3C = 0; + E->botwoon_var_D = FUNC16(Botwoon_Func_7); + E->botwoon_var_E = FUNC16(Botwoon_Func_19); + if (E->botwoon_var_33) + E->botwoon_var_35 = 0; + } else { + CallBotwoonFuncVarE(E->botwoon_var_E | 0xB30000); + Botwoon_Func_22(); + Botwoon_Func_23(); + CallEnemyPreInstr(E->botwoon_var_F | 0xB30000); + Botwoon_Func_25(); + Botwoon_Func_24(); + } +} + +void Botwoon_Func_13(void) { // 0xB399E4 + uint16 v3; + + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if (E->botwoon_var_21) { + E->botwoon_var_2E = 0; + CallEnemyPreInstr(E->botwoon_var_F | 0xB30000); + } else { + E->botwoon_var_3C = 0; + E->botwoon_var_D = FUNC16(Botwoon_Func_12); + E->botwoon_var_E = FUNC16(Botwoon_Func_32); + E->botwoon_var_F = FUNC16(Botwoon_Func_26); + if (E->botwoon_var_2F || (v3 = NextRandom() & 1, E->botwoon_var_33 = v3, (E->botwoon_var_34 = v3) == 0)) { + E->botwoon_var_4B = 0; + } else { + E->botwoon_var_35 = 0; + E->botwoon_var_36 = -1; + } + Botwoon_Func_10(cur_enemy_index); + } +} + +void Botwoon_Func_14(void) { // 0xB39A46 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + uint16 v1 = E->botwoon_var_22 + 1; + E->botwoon_var_22 = v1; + if (!sign16(v1 - 256)) + E->botwoon_var_D = FUNC16(Botwoon_Func_15); +} + +void Botwoon_Func_15(void) { // 0xB39A5E + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + uint16 y_subpos = E->base.y_subpos; + int v2 = (uint16)(8 * HIBYTE(E->botwoon_var_28)) >> 1; + bool v3 = __CFADD__uint16(kCommonEnemySpeeds_Quadratic[v2], y_subpos); + uint16 v4 = kCommonEnemySpeeds_Quadratic[v2] + y_subpos; + if (v3) + ++E->base.y_pos; + E->base.y_subpos = v4; + uint16 v5 = kCommonEnemySpeeds_Quadratic[v2 + 1] + E->base.y_pos; + E->base.y_pos = v5; + if (sign16(v5 - 200)) { + E->botwoon_var_28 += 192; + } else { + E->base.y_pos = 200; + E->botwoon_var_D = FUNC16(Botwoon_Func_16); + R18_ = E->base.x_pos; + R20_ = E->base.y_pos; + SpawnEnemyProjectileWithRoomGfx(addr_kEproj_DustCloudExplosion, 0x1Du); + Botwoon_QueueExplosionSfx(); + E->base.properties |= 0x500u; + } +} + +void Botwoon_Func_16(void) { // 0xB39ACA + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if (E->botwoon_var_5F) { + E->botwoon_var_D = FUNC16(Botwoon_Func_18); + Botwoon_Func_17(cur_enemy_index); + } +} + +void Botwoon_Func_17(uint16 k) { // 0xB39ADD + static const SpawnHardcodedPlmArgs unk_B39AE1 = { 0x0f, 0x04, 0xb79b }; + SpawnHardcodedPlm(&unk_B39AE1); + Enemy_ItemDrop_Botwoon(k); + Enemy_Botwoon *E = Get_Botwoon(k); + E->botwoon_var_23 = 0; + E->botwoon_var_24 = 0; + E->botwoon_var_25 = 0; +} + +void Botwoon_Func_18(uint16 k) { // 0xB39AF9 + Enemy_Botwoon *E = Get_Botwoon(k); + if (sign16(E->botwoon_var_23 - 192)) { + if (!sign16(E->botwoon_var_23 - 64)) { + int16 v2 = E->botwoon_var_24 - 1; + E->botwoon_var_24 = v2; + if (v2 < 0) { + E->botwoon_var_24 = 12; + R18_ = (NextRandom() & 0x1F) + 232; + R20_ = E->botwoon_var_23 + (NextRandom() & 0x1F) - 8; + R22_ = 29; + R24_ = 2560; + CreateSpriteAtPos(); + Botwoon_QueueExplosionSfx(); + } + int16 v3 = E->botwoon_var_25 - 1; + E->botwoon_var_25 = v3; + if (v3 < 0) { + E->botwoon_var_25 = 4; + R36 = 2; + do { + R18_ = (NextRandom() & 0x3F) + 224; + int16 v4 = (NextRandom() & 0x1F) - 8; + R20_ = Get_Botwoon(k)->botwoon_var_23 + v4; + R22_ = 9; + R24_ = 2560; + CreateSpriteAtPos(); + --R36; + } while (R36); + } + } + ++E->botwoon_var_23; + } else { + E->base.properties |= kEnemyProps_Deleted; + SetBossBitForCurArea(2u); + QueueMusic_Delayed8(3u); + } +} + +void Botwoon_Func_19(void) { // 0xB39BB7 + Botwoon_Func_20(cur_enemy_index); + uint16 v1 = CalculateAngleFromXY(); + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->botwoon_var_39 = v1; + E->botwoon_var_3A = (uint8)(64 - v1); + if (E->botwoon_var_33 == E->botwoon_var_34) { + Botwoon_Func_21(); + } else { + E->botwoon_var_34 = E->botwoon_var_33; + E->botwoon_var_3C = 1; + } +} + +void Botwoon_Func_20(uint16 k) { // 0xB39BF8 + Enemy_Botwoon *E = Get_Botwoon(k); + int v2 = E->botwoon_var_37 >> 1; + uint16 v3 = g_word_B3949B[v2] + 4 - E->base.x_pos; + R18_ = v3; + if (sign16(v3 - 256)) { + if (sign16(v3 + 256)) + R18_ = -255; + } else { + R18_ = 255; + } + uint16 v4 = g_word_B3949B[v2 + 2] + 4 - E->base.y_pos; + R20_ = v4; + if (sign16(v4 - 256)) { + if (sign16(v4 + 256)) + R20_ = -255; + } else { + R20_ = 255; + } +} + +void Botwoon_Func_21(void) { // 0xB39C48 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + R18_ = E->botwoon_var_3A; + R20_ = E->botwoon_var_38; + ConvertAngleToXy(); + enemy_population_ptr = E->botwoon_var_3A; + varE24 = R22_; + varE26 = R24_; + varE28 = R26_; + varE2A = R28_; + EnemyFunc_B691(); +} + +void Botwoon_Func_22(void) { // 0xB39C7B + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + uint16 botwoon_var_B = E->botwoon_var_B; + *(uint16 *)((char *)&kraid_unk9000 + botwoon_var_B) = E->base.x_pos; + *(uint16 *)((char *)&g_word_7E9002 + botwoon_var_B) = E->base.y_pos; +} + +void Botwoon_Func_23(void) { // 0xB39C90 + unsigned int v6; + + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + R18_ = (E->botwoon_var_B - E->botwoon_var_C) & 0x3FF; + R20_ = 24; + do { + Enemy_Botwoon *ET = Get_Botwoon(R20_); + uint16 botwoo_var_00 = ET->botwoon_var_00; + if (Get_Botwoon(cur_enemy_index)->botwoon_var_36 == R18_) { + uint16 v2 = R20_; + bool v4 = ET->botwoon_var_10 == 1; + ET->botwoon_var_10 ^= 1u; + if (v4) { + enemy_projectile_properties[botwoo_var_00 >> 1] &= ~0x2000u; + enemy_projectile_flags[botwoo_var_00 >> 1] = 1; + } else { + enemy_projectile_properties[botwoo_var_00 >> 1] |= 0x2000u; + enemy_projectile_flags[botwoo_var_00 >> 1] = 2; + } + if (!v2) { + E->botwoon_var_35 = 0; + E->botwoon_var_3E = 0; + E->botwoon_var_36 = -1; + if (!E->botwoon_var_33) + E->botwoon_var_3E = 1; + } + } + v6 = R18_; + int v7 = botwoo_var_00 >> 1; + enemy_projectile_x_pos[v7] = *(uint16 *)((char *)&kraid_unk9000 + R18_); + enemy_projectile_y_pos[v7] = *(uint16 *)((char *)&g_word_7E9002 + v6); + R18_ = (R18_ - E->botwoon_var_C) & 0x3FF; + --R20_; + --R20_; + } while ((R20_ & 0x8000u) == 0); +} + +void Botwoon_Func_24(void) { // 0xB39D3C + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->botwoon_var_B = (E->botwoon_var_B + 4) & 0x3FF; +} + +void Botwoon_Func_25(void) { // 0xB39D4D + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + R22_ = 24; + do { + R24_ = 0; + Enemy_Botwoon *ERR = Get_Botwoon(R22_); + uint16 botwoo_var_00 = ERR->botwoon_var_00; + if (ERR->botwoon_var_10) + R24_ = 256; + if (R22_ == 24) { + int v4 = botwoo_var_00 >> 1; + R18_ = E->base.x_pos - enemy_projectile_x_pos[v4]; + R20_ = E->base.y_pos - enemy_projectile_y_pos[v4]; + } else { + if (!R22_) + R24_ += 512; + int v2 = botwoo_var_00 >> 1; + R18_ = enemy_projectile_x_pos[v2 + 1] - enemy_projectile_x_pos[v2]; + R20_ = enemy_projectile_y_pos[v2 + 1] - enemy_projectile_y_pos[v2]; + } + enemy_projectile_E[botwoo_var_00 >> 1] = 2 * ((uint16)(R24_ + CalculateAngleFromXY()) >> 5); + --R22_; + --R22_; + } while ((R22_ & 0x8000u) == 0); +} + +void Botwoon_Func_26(uint16 k) { // 0xB39DC0 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + R18_ = E->base.x_pos - E->botwoon_var_56; + R20_ = E->base.y_pos - E->botwoon_var_57; + R22_ = CalculateAngleFromXY(); + if (R18_ || R20_) { + if (E->botwoon_var_33) { + E->base.layer = 7; + E->base.properties |= kEnemyProps_Tangible; + R22_ += 256; + } else { + E->base.layer = 2; + E->base.properties &= ~kEnemyProps_Tangible; + } + uint16 v1 = g_off_B3946B[R22_ >> 5]; + if (v1 != E->botwoon_var_3B) { + E->base.current_instruction = v1; + E->botwoon_var_3B = v1; + E->base.instruction_timer = 1; + E->base.timer = 0; + } + } + E->botwoon_var_56 = E->botwoon_var_54; + E->botwoon_var_57 = E->botwoon_var_55; + E->botwoon_var_54 = E->botwoon_var_52; + E->botwoon_var_55 = E->botwoon_var_53; + E->botwoon_var_52 = E->botwoon_var_50; + E->botwoon_var_53 = E->botwoon_var_51; + E->botwoon_var_50 = E->base.x_pos; + E->botwoon_var_51 = E->base.y_pos; +} + +void Botwoon_Func_27(uint16 k) { // 0xB39E7D + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->base.layer = 2; + uint16 v2 = CalculateAngleOfSamusFromEnemy(cur_enemy_index); + E->botwoon_var_3D = v2; + uint16 v3 = g_off_B3948B[(uint8)(v2 + 16) >> 5]; + E->base.current_instruction = v3; + E->botwoon_var_3B = v3; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->botwoon_var_3D = (uint8)(64 - E->botwoon_var_3D); + E->botwoon_var_F = FUNC16(Botwoon_Func_28); + if (E->botwoon_var_D != 0x99E4) + E->botwoon_var_F = FUNC16(Botwoon_Func_29); + CallEnemyPreInstr(E->botwoon_var_F | 0xB30000); +} + +void Botwoon_Func_28(uint16 k) { // 0xB39EE0 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if (E->botwoon_var_5A) { + remaining_enemy_spritemap_entries = (uint8)(E->botwoon_var_3D - 32); + remaining_enemy_hitbox_entries = 5; + draw_enemy_layer = g_word_B39E77[E->botwoon_var_3F]; + do { + SpawnEnemyProjectileWithGfx(draw_enemy_layer, cur_enemy_index, addr_kEproj_BotwoonsSpit); + remaining_enemy_spritemap_entries = (uint8)(remaining_enemy_spritemap_entries + 16); + --remaining_enemy_hitbox_entries; + } while (remaining_enemy_hitbox_entries); + E->botwoon_var_5A = 0; + E->botwoon_var_F = FUNC16(Botwoon_Func_30); + } +} + +void Botwoon_Func_29(uint16 k) { // 0xB39F34 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + remaining_enemy_spritemap_entries = (uint8)(E->botwoon_var_3D - 16); + remaining_enemy_hitbox_entries = 3; + draw_enemy_layer = g_word_B39E77[E->botwoon_var_3F]; + do { + SpawnEnemyProjectileWithGfx(draw_enemy_layer, cur_enemy_index, addr_kEproj_BotwoonsSpit); + remaining_enemy_spritemap_entries = (uint8)(remaining_enemy_spritemap_entries + 16); + --remaining_enemy_hitbox_entries; + } while (remaining_enemy_hitbox_entries); + Get_Botwoon(cur_enemy_index)->botwoon_var_F = FUNC16(Botwoon_Func_30); +} + +void Botwoon_Func_30(uint16 k) { // 0xB39F7A + Enemy_Botwoon *E = Get_Botwoon(k); + int16 v2 = E->botwoon_var_21 - 1; + E->botwoon_var_21 = v2; + if (v2 < 0) { + E->botwoon_var_21 = 0; + E->botwoon_var_F = FUNC16(Botwoon_Func_26); + } +} + +void Botwoon_Func_31(uint16 k) { // 0xB39F93 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + + if (!Get_Botwoon(k)->botwoon_var_35) { + R18_ = 24; + while (1) { + int v2 = R18_ >> 1; + if ((int16)(E->base.x_pos - g_word_B3949B[v2]) >= 0 + && (int16)(E->base.x_pos - g_word_B3949B[v2 + 1]) < 0 + && (int16)(E->base.y_pos - g_word_B3949B[v2 + 2]) >= 0 + && (int16)(E->base.y_pos - g_word_B3949B[v2 + 3]) < 0) { + break; + } + E->botwoon_var_35 = 0; + R18_ -= 8; + if ((R18_ & 0x8000u) != 0) + return; + } + E->botwoon_var_35 = 1; + E->botwoon_var_33 ^= 1u; + E->botwoon_var_36 = E->botwoon_var_B; + --E->botwoon_var_26; + } +} + +void Botwoon_Touch(void) { // 0xB39FFF + Enemy_NormalTouchAI_SkipDeathAnim_B3(); + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if (!E->base.health) { + E->botwoon_var_2F = 1; + Botwoon_Func_4(); + } +} + +void Botwoon_Shot(void) { // 0xB3A016 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->botwoon_var_4C = E->base.health; + Enemy_NormalShotAI_SkipSomeParts_B3(); + if (!E->base.health) { + E->botwoon_var_2F = 1; + Botwoon_Func_4(); + } +} + +void Botwoon_Powerbomb(void) { // 0xB3A041 + Enemy_NormalPowerBombAI_SkipDeathAnim_B3(); + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + if (!E->base.health) { + E->botwoon_var_2F = 1; + Botwoon_Func_4(); + } +} + +void Botwoon_Func_32(void) { // 0xB3E250 + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + E->botwoon_var_E = addr_loc_B3E28C; + E->botwoon_var_3C = 0; + uint8 *v1 = RomPtr_B3(E->botwoon_var_40 - 7856); + E->botwoon_var_42 = *(uint16 *)v1; + E->botwoon_var_37 = *((uint16 *)v1 + 2); + int16 v2 = *((uint16 *)v1 + 1); + E->botwoon_var_44 = v2; + if (v2 < 0) + E->botwoon_var_42 -= 4; + Botwoon_Func_33(); +} + +void Botwoon_Func_33(void) { // 0xB3E28C + R18_ = 0; + R20_ = 0; + Enemy_Botwoon *E = Get_Botwoon(cur_enemy_index); + R24_ = E->botwoon_var_38; + R22_ = 2; + if ((E->botwoon_var_44 & 0x8000u) != 0) + R22_ = -2; + do { + uint8 *v6 = RomPtr_B3(E->botwoon_var_42); + uint16 v7 = SignExtend8(*v6), v8; + if (v7 == 0xFF80 || (R18_ += v7, v8 = SignExtend8(v6[1]), v8 == 0xFF80)) { + E->botwoon_var_41 = 0; + E->botwoon_var_3C = 1; + return; + } + R20_ += v8; + E->botwoon_var_42 += R22_; + --R24_; + } while (R24_); + if ((E->botwoon_var_44 & 0x8000u) != 0) { + R18_ = -R18_; + R20_ = -R20_; + } + E->base.x_pos += R18_; + E->base.y_pos += R20_; +} + +uint16 EscapeEtecoon_Instr_1(uint16 k, uint16 j) { // 0xB3E545 + if (lava_acid_y_pos >= 0xCEu) + return j + 2; + else + return *(uint16 *)RomPtr_B3(j); +} + +uint16 EscapeEtecoon_Instr_2(uint16 k, uint16 j) { // 0xB3E610 + Enemy_EscapeEtecoon *E = Get_EscapeEtecoon(k); + E->base.x_pos += *(uint16 *)RomPtr_B3(j); + return j + 2; +} + +void EscapeEtecoon_Main(void) { // 0xB3E655 + Enemy_EscapeEtecoon *E = Get_EscapeEtecoon(cur_enemy_index); + CallEnemyPreInstr(E->een_var_F | 0xB30000); +} + +void EscapeEtecoon_E65C(uint16 k) { // 0xB3E65C + Enemy_EscapeEtecoon *E = Get_EscapeEtecoon(k); + uint16 x_subpos = E->base.x_subpos; + E->base.x_subpos = x_subpos + 0x8000; + E->base.x_pos += __CFADD__uint16(x_subpos, 0x8000) + 3; +} + +void EscapeEtecoon_E670(uint16 k) { // 0xB3E670 + if (CheckEventHappened(0xFu)) + Get_EscapeEtecoon(k)->base.current_instruction = addr_kEscapeEtecoon_Ilist_E5DA; +} + +void EscapeEtecoon_E680(uint16 k) { // 0xB3E680 + int16 een_var_A; + + R18_ = 0; + R20_ = 0; + Enemy_EscapeEtecoon *E = Get_EscapeEtecoon(k); + een_var_A = E->een_var_A; + if (een_var_A < 0) + --R20_; + *(uint16 *)((char *)&R18_ + 1) = een_var_A; + if (Enemy_MoveRight_IgnoreSlopes(k) & 1) { + E->base.instruction_timer = 1; + bool v3 = (-E->een_var_A & 0x8000u) != 0; + E->een_var_A = -E->een_var_A; + E->base.current_instruction = v3 ? + addr_kEscapeEtecoon_Ilist_E556 : addr_kEscapeEtecoon_Ilist_E582; + if (CheckEventHappened(0xFu)) + E->base.current_instruction = addr_kEscapeEtecoon_Ilist_E5AE; + } + R18_ = 0; + R20_ = 1; + Enemy_MoveDown(k); +} + +void EscapeEtecoon_Init(void) { // 0xB3E6CB + Enemy_EscapeEtecoon *E = Get_EscapeEtecoon(cur_enemy_index); + if (CheckEventHappened(0xFu)) { + E->base.properties |= kEnemyProps_Deleted; + } else { + E->base.properties |= kEnemyProps_DisableSamusColl | kEnemyProps_Tangible | 0x8000; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.palette_index = 0; + int v3 = E->een_parameter_1 >> 1; + E->base.x_pos = g_word_B3E718[v3]; + E->base.y_pos = g_word_B3E71E[v3]; + E->een_var_F = g_off_B3E724[v3]; + E->base.current_instruction = g_off_B3E72A[v3]; + E->een_var_A = g_word_B3E730[v3]; + } +} + +uint16 EscapeDachora_Instr_2(uint16 k, uint16 j) { // 0xB3EAA8 + if (lava_acid_y_pos >= 0xCEu) + return j + 2; + else + return *(uint16 *)RomPtr_B3(j); +} + +uint16 EscapeDachora_Instr_3(uint16 k, uint16 j) { // 0xB3EAB8 + if (CheckEventHappened(0xFu)) + return *(uint16 *)RomPtr_B3(j); + else + return j + 2; +} + +uint16 EscapeDachora_Instr_1(uint16 k, uint16 j) { // 0xB3EAC9 + Enemy_EscapeDachora *E = Get_EscapeDachora(cur_enemy_index); + E->base.x_pos -= 6; + return j; +} + +uint16 EscapeDachora_Instr_4(uint16 k, uint16 j) { // 0xB3EAD7 + Enemy_EscapeDachora *E = Get_EscapeDachora(cur_enemy_index); + E->base.x_pos += 6; + return j; +} + +void EscapeDachora_Init(void) { // 0xB3EAE5 + Enemy_EscapeDachora *E = Get_EscapeDachora(cur_enemy_index); + if (CheckEventHappened(0xFu)) { + E->base.properties |= kEnemyProps_Deleted; + } else { + E->base.properties |= kEnemyProps_DisableSamusColl; + E->base.spritemap_pointer = addr_kSpritemap_Nothing_B3; + E->base.instruction_timer = 1; + E->base.timer = 0; + E->base.current_instruction = addr_kEscapeDachora_Ilist_E964; + } +} diff --git a/src/sm_b4.c b/src/sm_b4.c new file mode 100644 index 0000000..8d77485 --- /dev/null +++ b/src/sm_b4.c @@ -0,0 +1,117 @@ +// B4 - Enemy instructions, sets, drop chances, resistances (complete) +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "enemy_types.h" + +#define kCreateSprite_Ilists ((uint16*)RomPtr(0xb4bda8)) + +void CreateSpriteAtPos(void) { // 0xB4BC26 + int v0 = 62; + while (sprite_instr_list_ptrs[v0 >> 1]) { + v0 -= 2; + if ((v0 & 0x8000u) != 0) + return; + } + int v1 = v0 >> 1; + sprite_palettes[v1] = 0; + sprite_x_subpos[v1] = 0; + sprite_y_subpos[v1] = 0; + sprite_disable_flag[v1] = 0; + sprite_x_pos[v1] = R18_; + sprite_y_pos[v1] = R20_; + sprite_palettes[v1] = R24_; + uint16 v2 = kCreateSprite_Ilists[R22_]; + sprite_instr_list_ptrs[v1] = v2; + sprite_instr_timer[v1] = *(uint16 *)RomPtr_B4(v2); + R18_ = v0; +} + +void CallSpriteObjectInstr(uint32 ea) { + switch (ea) { + case fnSpriteObject_Instr_RepeatLast: SpriteObject_Instr_RepeatLast(); return; // 0xb4bcf0 + case fnSpriteObject_Instr_Terminate: SpriteObject_Instr_Terminate(); return; // 0xb4bd07 + case fnSpriteObject_Instr_Goto: SpriteObject_Instr_Goto(); return; // 0xb4bd12 + default: Unreachable(); + } +} + +void HandleSpriteObjects(void) { // 0xB4BC82 + uint16 v1; + + if (!(debug_time_frozen_for_enemies | time_is_frozen_flag)) { + sprite_object_index = 62; + while (1) { + int v0; + v0 = sprite_object_index >> 1; + if (!sprite_instr_list_ptrs[v0] || (sprite_disable_flag[v0] & 1) != 0) + goto LABEL_9; + v1 = sprite_instr_timer[v0]; + if ((v1 & 0x8000u) != 0) + break; + sprite_instr_timer[v0] = v1 - 1; + if (v1 == 1) { + uint16 v3 = sprite_instr_list_ptrs[v0] + 4; + sprite_instr_list_ptrs[v0] = v3; + v1 = *(uint16 *)RomPtr_B4(v3); + if (!sign16(v1 + 0x8000)) + break; + sprite_instr_timer[sprite_object_index >> 1] = v1; + } +LABEL_9: + sprite_object_index -= 2; + if ((sprite_object_index & 0x8000u) != 0) + return; + } + R18_ = v1; + CallSpriteObjectInstr(v1 | 0xB40000); + goto LABEL_9; + } +} + +void SpriteObject_Instr_RepeatLast(void) { // 0xB4BCF0 + int v2 = sprite_object_index >> 1; + sprite_instr_list_ptrs[v2] -= 4; + sprite_instr_timer[v2] = 0x7FFF; +} + +void SpriteObject_Instr_Terminate(void) { // 0xB4BD07 + sprite_instr_list_ptrs[sprite_object_index >> 1] = 0; +} + +void SpriteObject_Instr_Goto(void) { // 0xB4BD12 + uint16 v2 = *((uint16 *)RomPtr_B4(sprite_instr_list_ptrs[sprite_object_index >> 1]) + 1); + sprite_instr_list_ptrs[sprite_object_index >> 1] = v2; + sprite_instr_timer[sprite_object_index >> 1] = *(uint16 *)RomPtr_B4(v2); +} + +void DrawSpriteObjects(void) { // 0xB4BD32 + for (int i = 62; i >= 0; i -= 2) { + int v1 = i >> 1; + if (sprite_instr_list_ptrs[v1]) { + R20_ = sprite_x_pos[v1] - layer1_x_pos; + if ((int16)(R20_ + 16) >= 0) { + if (sign16(R20_ - 272)) { + int16 v2 = sprite_y_pos[v1] - layer1_y_pos; + R18_ = v2; + if (v2 >= 0) { + if (sign16(v2 - 272)) { + R3_.addr = sprite_palettes[v1] & 0xE00; + R0_.addr = sprite_palettes[v1] & 0x1FF; + uint8 *v3 = RomPtr_B4(sprite_instr_list_ptrs[v1]); + DrawSpritemapWithBaseTile(0xB4u, *((uint16 *)v3 + 1)); + } + } + } + } + } + } +} + +void ClearSpriteObjects(void) { // 0xB4BD97 + int v0 = 1022; + do { + sprite_instr_list_ptrs[v0 >> 1] = 0; + v0 -= 2; + } while (v0); +} diff --git a/src/sm_cpu_infra.c b/src/sm_cpu_infra.c new file mode 100644 index 0000000..00902f0 --- /dev/null +++ b/src/sm_cpu_infra.c @@ -0,0 +1,829 @@ +#include "sm_cpu_infra.h" +#include "types.h" +#include "snes/cpu.h" +#include "snes/snes.h" +#include "tracing.h" + +#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "sm_rtl.h" +#include "util.h" + +#include + +void RtlRunFrameCompare(uint16 input, int run_what); + +enum RunMode { RM_BOTH, RM_MINE, RM_THEIRS }; +uint8 g_runmode = RM_BOTH; + +extern int g_got_mismatch_count; + +Snes *g_snes; +Cpu *g_cpu; + +bool g_calling_asm_from_c; +int g_calling_asm_from_c_ret; +bool g_fail; +bool g_use_my_apu_code = true; +extern bool g_other_image; + +typedef struct Snapshot { + uint16 a, x, y, sp, dp, pc; + uint8 k, db, flags; + + uint16_t vTimer; + + uint8 ram[0x20000]; + uint16 vram[0x8000]; + uint8 sram[0x2000]; + + uint16 oam[0x120]; +} Snapshot; + +static Snapshot g_snapshot_mine, g_snapshot_theirs, g_snapshot_before; +static uint32 hookmode, hookcnt, hookadr; +static uint32 hooked_func_pc; +static uint8 hook_orgbyte[1024]; +static uint8 hook_fixbug_orgbyte[1024]; + +static void VerifySnapshotsEq(Snapshot *b, Snapshot *a, Snapshot *prev); +static void MakeSnapshot(Snapshot *s); +static void RestoreSnapshot(Snapshot *s); + +void Call(uint32 addr) { + assert(addr & 0x8000); + RunAsmCode(addr, 0, 0, 0, 0); +} + +bool ProcessHook(uint32 v) { + uint8_t *rombyte = RomPtr(v); + switch (hookmode) { + case 0: // remove hooks + *rombyte = hook_orgbyte[hookcnt++]; + return false; + case 1: // install hooks + hook_orgbyte[hookcnt++] = *rombyte; + *rombyte = 0; + return false; + case 2: // run hook + if (v == hookadr) { + hookmode = 3; + return true; + } + return false; + } + return false; +} + +bool FixBugHook(uint32 addr) { + switch (hookmode) { + case 1: { // install hooks + uint8_t *rombyte = RomPtr(addr); + hook_fixbug_orgbyte[hookcnt++] = *rombyte; + *rombyte = 0; + return false; + } + case 2: // run hook + if (addr == hookadr) { + hookmode = 3; + return true; + } + hookcnt++; + return false; + } + return false; +} + +static const uint32 kPatchedCarrys[] = { + 0xa7ac33, + 0xa7ac36, + 0xa7ac39, + 0xa7ac42, + 0xa7ac45, + // Ridley_Func_107 + 0xa6d6d1, + 0xa6d6d3, + 0xa6d6d5, + 0xa6d700, + 0xa6d702, + 0xa6d704, + // Ridley_Func_106 + 0xa6d665, + 0xa6d667, + 0xa6d669, + 0xa6d694, + 0xa6d696, + 0xa6d698, + // DrawSpritemapWithBaseTile2 + 0x818b65, + 0x818b6B, + // DrawSpritemapWithBaseTileOffscreen + 0x818ba7, + 0x818bd9, + 0x818bdf, + + // EprojInit_BombTorizoLowHealthInitialDrool + 0x86a671, + 0x86a680, + 0x86a6a9, + 0x86a6ba, + // HandleEarthquakeSoundEffect + 0x88B245, + // Ridley_Func_104 + 0xA6D565, + 0xA6D567, + 0xA6D599, + 0xA6D59B, + // Ridley_Func_105 + 0xA6D5DB, + 0xA6D5DD, + 0xA6D60F, + 0xA6D611, + // Ridley_Func_86 + 0xA6CEFF, + // Shitroid_GraduallyAccelerateTowardsPt + 0xa9f4a5, + 0xa9f4a7, + 0xa9f4d6, + 0xa9f4d8, + // Shitroid_GraduallyAccelerateHoriz + 0xa9f519, + 0xa9f51f, + 0xa9f521, + 0xa9f554, + 0xa9f55a, + 0xa9f55c, + // Shitroid_Func_16 + 0xA9F24D, + + // Lots of ADC + 0x80AA6A, + 0x80A592, + 0x80A720, + 0x80A7D6, + 0x80A99B, + 0x818AA7, + + // room_width_in_blocks etc + 0x80ab5d, + 0x84865c, + 0x848d90, + 0x84ab60, + 0x84b567, + 0x84b588, + 0x84b606, + 0x84b615, + 0x84b624, + 0x84b9d3, + 0x84b9e2, + 0x84ba07, + 0x84ba1e, + 0x84ba35, + 0x84d6ae, + 0x84d6bf, + 0x84d7f4, + 0x84d803, + 0x84d812, + 0x84daae, + 0x84dbaa, + 0x84dbe1, + 0x84dc20, + 0x84dc52, + 0x84dc89, + 0x84dcc8, + 0x84deae, + 0x84dedd, + 0x84df0a, + 0x84df39, + 0x86893a, + 0x9483a7, + 0x948405, + 0x949592, + 0x94a13f, + 0x94a2b2, + 0x94a3d8, + 0xa0bc33, + 0xa0bdac, + 0xa0bf45, + 0xa0c725, + 0x88B486, + 0x88C578, + 0xA292E8, + 0x86F18E, + 0x888CB6, + 0x888FAA, + 0x88A483, + 0x91CC35, + 0x91CBFF, + 0xA09541, + 0xA09552, + 0xA49AE8, + 0xA6C297, + 0xA6C3AD, + 0xA9C5EC, + 0xA9D500, + 0xA9D537, + 0xA9DCDB, +}; +static uint8 kPatchedCarrysOrg[arraysize(kPatchedCarrys)]; + +void PatchBugs(uint32 mode, uint32 addr) { + hookmode = mode, hookadr = addr, hookcnt = 0; + if (FixBugHook(0x86EF35)) { + g_cpu->x = g_cpu->y; + } else if (FixBugHook(0x86EF45)) { + g_cpu->z = (g_cpu->a == 0); // EprojInit_F337 doesn't compare A and assumes Z is in it. + } else if (FixBugHook(0x818ab8)) { + if (g_cpu->y == 0) + g_cpu->pc = 0x8b1f; + } else if (FixBugHook(0xa794ba)) { // Kraid_Arm_Shot - y undefined + g_cpu->y = g_cpu->x; + } else if (FixBugHook(0xa7b968)) { // KraidEnemy_ProcessInstrEnemyTimer - X is undefined + g_cpu->x = cur_enemy_index; + } else if (FixBugHook(0xa7b963)) { // KraidFoot_FirstPhase_Thinking - X is undefined + g_cpu->x = cur_enemy_index; + } else if (FixBugHook(0xA496C8)) { // Crocomire_Func_67 assumes A is zero + g_cpu->a = 0; + } else if (FixBugHook(0x9085AA)) { // Samus_HandleSpeedBoosterAnimDelay doesn't preserve A + g_cpu->a = speed_boost_counter; + } else if (FixBugHook(0xA29044) || FixBugHook(0xA2905D)) { // MaridiaBeybladeTurtle_Func8 thinks INC sets carry + g_cpu->c = (g_cpu->a == 0); + } else if (FixBugHook(0xa29051)) { /// MaridiaBeybladeTurtle_Func8 does an INC too much + g_cpu->a--; + } else if (FixBugHook(0xA5931C)) { // Draygon_Func_35 needs cur_enemy_index in X + g_cpu->x = cur_enemy_index; + } else if (FixBugHook(0x80ADA4)) { // DoorTransitionScrollingSetup_Down + g_cpu->a = layer2_y_pos; + } else if (FixBugHook(0x80ADD9)) { // DoorTransitionScrollingSetup_Up + g_cpu->a = layer2_y_pos; + } else if (FixBugHook(0x80AD4d)) { // DoorTransitionScrollingSetup_Right + g_cpu->a = layer2_x_pos; + } else if (FixBugHook(0x80AD77)) { // DoorTransitionScrollingSetup_Left + g_cpu->a = layer2_x_pos; + } else if (FixBugHook(0x9381db)) { // ProjectileInsts_GetValue reading from invalid memory for newly started ones + int k = g_cpu->x; + int ip = projectile_bomb_instruction_ptr[k >> 1]; + int delta = (projectile_bomb_instruction_timers[k >> 1] == 1 && !sign16(get_ProjectileInstr(ip)->timer)) ? 0 : -8; + g_cpu->a += 8 + delta; + } else if (FixBugHook(0x86b701)) { // EprojPreInstr_EyeDoorProjectile using destroyed X + g_cpu->x = g_cpu->y; + } else if (FixBugHook(0x8FC1B0)) { // RoomCode_GenRandomExplodes X is garbage + g_cpu->x = g_cpu->a; + } else if (FixBugHook(0x80804F)) { + //for(int i = 0; i < 5000; i++) + // snes_readBBusOrg(g_snes, (uint8_t)APUI00); + } else if (FixBugHook(0x829325)) { + // forgot to change bank + g_cpu->db = 0x82; + } +} + +int RunPatchBugHook(uint32 addr) { + PatchBugs(2, addr); + return hookmode == 3 ? hook_fixbug_orgbyte[hookcnt] : -1; +} + +int CpuOpcodeHook(uint32 addr) { + for (size_t i = 0; i != arraysize(kPatchedCarrys); i++) { + if (addr == kPatchedCarrys[i]) + return kPatchedCarrysOrg[i]; + } + { + int i = RunPatchBugHook(addr); + if (i >= 0) return i; + } + assert(0); + return 0; +} + +bool HookedFunctionRts(int is_long) { + if (g_calling_asm_from_c) { + g_calling_asm_from_c_ret = is_long; + g_calling_asm_from_c = false; + return false; + } + assert(0); + return false; +} + +static void VerifySnapshotsEq(Snapshot *b, Snapshot *a, Snapshot *prev) { + memcpy(&b->ram[0x1f5b], &a->ram[0x1f5b], 0x100 - 0x5b); // stacck + memcpy(&b->ram[0x44], &a->ram[0x44], 3); // decompress_dst_tmp + memcpy(&b->ram[0x19b3], &a->ram[0x19b3], 1); // mode7_spawn_param + memcpy(&b->ram[0x12], &a->ram[0x12], 2); // R18 + memcpy(&b->ram[0x1993], &a->ram[0x1993], 2); // enemy_projectile_init_param + memcpy(&b->ram[0x49], &a->ram[0x49], 1); // decompress_src.bank + memcpy(&b->ram[0x1B9D], &a->ram[0x1B9D], 2); // cinematic_spawn_param + memcpy(&b->ram[0x1a93], &a->ram[0x1a93], 2); // cinematic_spawn_param + memcpy(&b->ram[0xA82], &a->ram[0xA82], 2); // xray_angle + memcpy(&b->ram[0xad], &a->ram[0xad], 2); // ptr_to_retaddr_parameters + memcpy(&b->ram[0x641], &a->ram[0x641], 2); // apu_attempts_countdown + memcpy(&b->ram[0x0], &a->ram[0x0], 3); // R0 + memcpy(&b->ram[0x5e9], &a->ram[0x5e9], 4); // mult_tmp + memcpy(&b->ram[0x19b3], &a->ram[0x19b3], 2); // mode7_spawn_param + + memcpy(&a->ram[0x611], &b->ram[0x611], 6); // coroutine_state (copy from mine to theirs) + memcpy(&a->ram[0x77e], &b->ram[0x77e], 5); // my counter + + + if (memcmp(b->ram, a->ram, 0x20000)) { + fprintf(stderr, "@%d: Memory compare failed (mine != theirs, prev):\n", snes_frame_counter); + int j = 0; + for (size_t i = 0; i < 0x20000; i++) { + if (a->ram[i] != b->ram[i]) { + if (++j < 256) { + if (/* (i & 1) == 0 && */a->ram[i + 1] != b->ram[i + 1]) { + fprintf(stderr, "0x%.6X: %.4X != %.4X (%.4X)\n", (int)i, + WORD(b->ram[i]), WORD(a->ram[i]), WORD(prev->ram[i])); + i++, j++; + } else { + fprintf(stderr, "0x%.6X: %.2X != %.2X (%.2X)\n", (int)i, b->ram[i], a->ram[i], prev->ram[i]); + } + } + } + } + if (j) + g_fail = true; + fprintf(stderr, " total of %d failed bytes\n", (int)j); + } + + if (memcmp(b->sram, a->sram, 0x2000)) { + fprintf(stderr, "@%d: SRAM compare failed (mine != theirs, prev):\n", snes_frame_counter); + int j = 0; + for (size_t i = 0; i < 0x2000; i++) { + if (a->sram[i] != b->sram[i]) { + if (++j < 128) { + if ((i & 1) == 0 && a->sram[i + 1] != b->sram[i + 1]) { + fprintf(stderr, "0x%.6X: %.4X != %.4X (%.4X)\n", (int)i, + WORD(b->sram[i]), WORD(a->sram[i]), WORD(prev->sram[i])); + i++, j++; + } else { + fprintf(stderr, "0x%.6X: %.2X != %.2X (%.2X)\n", (int)i, b->sram[i], a->sram[i], prev->sram[i]); + } + } + } + } + if (j) + g_fail = true; + fprintf(stderr, " total of %d failed bytes\n", (int)j); + } +#if 1 + if (memcmp(b->vram, a->vram, sizeof(uint16) * 0x8000)) { + fprintf(stderr, "@%d: VRAM compare failed (mine != theirs, prev):\n", snes_frame_counter); + for (size_t i = 0, j = 0; i < 0x8000; i++) { + if (a->vram[i] != b->vram[i]) { + fprintf(stderr, "0x%.6X: %.4X != %.4X (%.4X)\n", (int)i, b->vram[i], a->vram[i], prev->vram[i]); + g_fail = true; + if (++j >= 32) + break; + } + } + } + if (memcmp(b->oam, a->oam, sizeof(uint16) * 0x120)) { + fprintf(stderr, "@%d: VRAM OAM compare failed (mine != theirs, prev):\n", snes_frame_counter); + for (size_t i = 0, j = 0; i < 0x120; i++) { + if (a->oam[i] != b->oam[i]) { + fprintf(stderr, "0x%.6X: %.4X != %.4X (%.4X)\n", (int)i, b->oam[i], a->oam[i], prev->oam[i]); + g_fail = true; + if (++j >= 16) + break; + } + } + } + +#endif +} + +static void MakeSnapshot(Snapshot *s) { + Cpu *c = g_cpu; + s->a = c->a, s->x = c->x, s->y = c->y; + s->sp = c->sp, s->dp = c->dp, s->db = c->db; + s->pc = c->pc, s->k = c->k; + s->flags = cpu_getFlags(c); + s->vTimer = g_snes->vTimer; + memcpy(s->ram, g_snes->ram, 0x20000); + memcpy(s->sram, g_snes->cart->ram, g_snes->cart->ramSize); + memcpy(s->vram, g_snes->ppu->vram, sizeof(uint16) * 0x8000); + memcpy(s->oam, g_snes->ppu->oam, sizeof(uint16) * 0x120); +} + +static void MakeMySnapshot(Snapshot *s) { + memcpy(s->ram, g_snes->ram, 0x20000); + memcpy(s->sram, g_snes->cart->ram, g_snes->cart->ramSize); + memcpy(s->vram, g_snes->ppu->vram, sizeof(uint16) * 0x8000); + memcpy(s->oam, g_snes->ppu->oam, sizeof(uint16) * 0x120); +} + +static void RestoreSnapshot(Snapshot *s) { + Cpu *c = g_cpu; + c->a = s->a, c->x = s->x, c->y = s->y; + c->sp = s->sp, c->dp = s->dp, c->db = s->db; + c->pc = s->pc, c->k = s->k; + g_snes->vTimer = s->vTimer; + cpu_setFlags(c, s->flags); + memcpy(g_snes->ram, s->ram, 0x20000); + memcpy(g_snes->cart->ram, s->sram, 0x2000); + memcpy(g_snes->ppu->vram, s->vram, sizeof(uint16) * 0x8000); + memcpy(g_snes->ppu->oam, s->oam, sizeof(uint16) * 0x120); +} + +int RunAsmCode(uint32 pc, uint16 a, uint16 x, uint16 y, int flags) { + uint16 org_sp = g_cpu->sp; + uint16 org_pc = g_cpu->pc; + uint8 org_b = g_cpu->db; + uint16 org_dp = g_cpu->dp; + + printf("RunAsmCode!\n"); + g_ram[0x1ffff] = 1; + + bool dc = g_snes->debug_cycles; + g_cpu->db = pc >> 16; + + g_cpu->a = a; + g_cpu->x = x; + g_cpu->y = y; + g_cpu->spBreakpoint = g_cpu->sp; + g_cpu->k = (pc >> 16); + g_cpu->pc = (pc & 0xffff); + g_cpu->mf = (flags & 1); + g_cpu->xf = (flags & 2) >> 1; + g_calling_asm_from_c = true; + while (g_calling_asm_from_c) { + uint32 pc = g_snes->cpu->k << 16 | g_snes->cpu->pc; + if (g_snes->debug_cycles) { + char line[80]; + getProcessorStateCpu(g_snes, line); + puts(line); + line[0] = 0; + } + cpu_runOpcode(g_cpu); + while (g_snes->dma->dmaBusy) + dma_doDma(g_snes->dma); + + if (flags & 1) { + for(int i = 0; i < 10; i++) + apu_cycle(g_snes->apu); + } + } + g_cpu->dp = org_dp; + g_cpu->sp = org_sp; + g_cpu->db = org_b; + g_cpu->pc = org_pc; + + g_snes->debug_cycles = dc; + + return g_calling_asm_from_c_ret; +} + +static bool loadRom(const char *name, Snes *snes) { + size_t length = 0; + uint8_t *file = NULL; + file = ReadWholeFile(name, &length); + if (file == NULL) { + puts("Failed to read file"); + return false; + } + bool result = snes_loadRom(snes, file, (int)length); + free(file); + return result; +} + +void PatchBytes(uint32 addr, const uint8 *value, size_t n) { + for(size_t i = 0; i != n; i++) + RomPtr(addr)[i] = value[i]; +} + +// Patches add/sub to ignore carry +void FixupCarry(uint32 addr) { + *RomPtr(addr) = 0; +} + +Snes *SnesInit(const char *filename) { + g_snes = snes_init(g_ram); + + g_cpu = g_snes->cpu; + + bool loaded = loadRom(filename, g_snes); + if (!loaded) { + char buf[256]; + snprintf(buf, sizeof(buf), "unable to load rom: %s", filename); + Die(buf); + } + + g_sram = g_snes->cart->ram; + + RtlSetupEmuCallbacks(NULL, &RtlRunFrameCompare, NULL); + + // Ensure it will run reset first. + coroutine_state_0 = 1; + +#if 1 + { uint8 t[3] = { 0x20, 0x0f, 0xf7 }; PatchBytes(0x82896b, t, 3); } + { uint8 t[3] = { 0x7c, 0x81, 0x89 }; PatchBytes(0x82F70F, t, 3); } + + // Some code called by GameState_37_CeresGoesBoomWithSamus_ forgets to clear the M flag + { uint8 t[] = { 0x5f, 0xf7 }; PatchBytes(0x8BA362, t, sizeof(t)); } + { uint8 t[] = { 0xc2, 0x20, 0x4c, 0x67, 0xa3 }; PatchBytes(0x8BF760, t, sizeof(t)); } + //{ uint8 t[3] = { 0x60 }; PatchBytes(0x808028, t, 1); } // Apu_UploadBank hangs + { uint8 t[4] = { 0x0a, 0x0a, 0x0a, 0x0a }; PatchBytes(0x82E915, t, 4); } // SpawnDoorClosingPLM reads from 0x12 + { uint8 t[2] = { 0x0a, 0x0a }; PatchBytes(0x8584B2, t, 2); } // HandleMessageBoxInteraction has a loop + + // LoadRoomPlmGfx passes bad value + { uint8 t[] = { 0xc0, 0x00, 0x00, 0xf0, 0x03, 0x20, 0x64, 0x87, 0x60}; PatchBytes(0x84efd3, t, sizeof(t)); } + { uint8 t[] = { 0xd3, 0xef }; PatchBytes(0x848243, t, sizeof(t)); } + + // EprojColl_8676 doesn't initialize Y + { uint8 t[] = { 0xac, 0x91, 0x19, 0x4c, 0x76, 0x86 }; PatchBytes(0x86f4a6, t, sizeof(t)); } + { uint8 t[] = { 0xa6, 0xf4 }; PatchBytes(0x8685bd, t, sizeof(t)); } + + // Fix so main code is in a function. + { uint8 t[] = { 0xc2, 0x30, 0x22, 0x59, 0x94, 0x80, 0x20, 0x48, 0x89, 0x22, 0x38, 0x83, 0x80, 0x4C, 0x13, 0xF7 }; PatchBytes(0x82f713, t, sizeof(t)); } + { uint8 t[] = { 0x58, 0x4c, 0x13, 0xf7 }; PatchBytes(0x828944, t, sizeof(t)); } + { uint8 t[] = { 0x28, 0x60 }; PatchBytes(0x82897a, t, sizeof(t)); } + + // Remove IO_HVBJOY loop in ReadJoypadInput + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x80945C, t, sizeof(t)); } + + // Fix so NorfairLavaMan_Func_12 initializes Y + { uint8 t[] = { 0xbc, 0xaa, 0x0f, 0xc9, 0x6c, 0x00, 0x10, 0x1a }; PatchBytes(0xa8b237, t, sizeof(t)); } + + // MaridiaBeybladeTurtle_Func8 negate + { uint8 t[] = { 0x49, 0xff, 0xff, 0x69, 0x00, 0x00 }; PatchBytes(0xa2904b, t, sizeof(t)); } + { uint8 t[] = { 0x49, 0xff, 0xff, 0x69, 0x00, 0x00 }; PatchBytes(0xa29065, t, sizeof(t)); } + + // Remove DebugLoadEnemySetData + { uint8 t[] = { 0x6b }; PatchBytes(0xA0896F, t, sizeof(t)); } + // MotherBrainsTubesFalling_Falling wrong X value + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0xA98C12, t, sizeof(t)); } + + { uint8 t[] = { 0x60 }; PatchBytes(0x8085F6, t, sizeof(t)); } + + // Remove 4 frames of delay in reset routine + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x80843C, t, sizeof(t)); } + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x808475, t, sizeof(t)); } + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x808525, t, sizeof(t)); } + + // Remove WaitUntilEndOfVblank in WaitUntilEndOfVblankAndClearHdma - We run frame by frame. + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x8882A1, t, sizeof(t)); } + + // Remove WaitForNMI in GameState_41_TransitionToDemo. + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x828533, t, sizeof(t)); } + + // WaitForNMI in ScreenOfWaitNmi / ScreenOnWaitNMI + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x80837B, t, sizeof(t)); } + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x80838E, t, sizeof(t)); } + + // WaitUntilEndOfVblankAndEnableIrq + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x82DF6C, t, sizeof(t)); } + + // Remove loops based on door_transition_vram_update_enabled + // Replace with a call to Irq_DoorTransitionVramUpdate + { uint8 t[] = { 0x20, 0x32, 0x96, 0x6b }; PatchBytes(0x80d000, t, sizeof(t)); } + { uint8 t[] = { 0x22, 0x00, 0xd0, 0x80, 0x18 }; PatchBytes(0x82E02C, t, sizeof(t)); } + { uint8 t[] = { 0x22, 0x00, 0xd0, 0x80, 0x18 }; PatchBytes(0x82E06B, t, sizeof(t)); } + { uint8 t[] = { 0x22, 0x00, 0xd0, 0x80, 0x18 }; PatchBytes(0x82E50D, t, sizeof(t)); } + { uint8 t[] = { 0x22, 0x00, 0xd0, 0x80, 0x18 }; PatchBytes(0x82E609, t, sizeof(t)); } + + // Remove infinite loop polling door_transition_flag (AD 31 09 10 FB) + { uint8 t[] = { 0x22, 0x04, 0xd0, 0x80, 0x18 }; PatchBytes(0x82E526, t, sizeof(t)); } + { uint8 t[] = { 0x22, 0x38, 0x83, 0x80, 0xad, 0x31, 0x09, 0x10, 0xf7, 0x6b }; PatchBytes(0x80d004, t, sizeof(t)); } + + // Remove WaitForNMI in DoorTransitionFunction_LoadMoreThings_Async + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x82E540, t, sizeof(t)); } + + // Remove WaitForNMI in CinematicFunctionBlackoutFromCeres + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x8BC11E, t, sizeof(t)); } + + // Remove WaitForNMI in CinematicFunctionEscapeFromCeres + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x8BD487, t, sizeof(t)); } + + // Patch InitializePpuForMessageBoxes + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x858148, t, sizeof(t)); } // WaitForLagFrame + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x8581b2, t, sizeof(t)); } // WaitForLagFrame + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x8581EA, t, sizeof(t)); } // HandleMusicQueue etc + + // Patch ClearMessageBoxBg3Tilemap + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x858203, t, sizeof(t)); } // WaitForLagFrame + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x858236, t, sizeof(t)); } // HandleMusicQueue etc + + // Patch WriteMessageTilemap + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x8582B8, t, sizeof(t)); } + + // Patch SetupPpuForActiveMessageBox + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x858321, t, sizeof(t)); } // WaitForLagFrame + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x85835A, t, sizeof(t)); } // InitializePpuForMessageBoxes + + // Patch ToggleSaveConfirmationSelection + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x858532, t, sizeof(t)); } // WaitForNMI_NoUpdate + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x85856b, t, sizeof(t)); } // HandleMusicQueue etc. + + // Remove WaitForLagFrame in various places + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x85861C, t, sizeof(t)); } // RestorePpuForMessageBox + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x858651, t, sizeof(t)); } // RestorePpuForMessageBox + + // Patch DisplayMessageBox + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x858096, t, sizeof(t)); } // Remove MsgBoxDelayFrames_2 + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x8580B4, t, sizeof(t)); } // Remove MsgBoxDelayFrames_2 + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x8580DC, t, sizeof(t)); } // Remove MsgBoxDelayFrames_2 + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x8580F2, t, sizeof(t)); } // Remove MsgBoxDelayFrames_2 + + // Patch HandleMessageBoxInteraction logic + { uint8 t[] = { 0x20, 0x50, 0x96, 0x60 }; PatchBytes(0x8584A3, t, sizeof(t)); } + { uint8 t[] = { 0x20, 0x36, 0x81, 0x22, 0x59, 0x94, 0x80, 0xc2, 0x30, 0xa5, 0x8f, 0xf0, 0xf3, 0x60 }; PatchBytes(0x859650, t, sizeof(t)); } + { uint8 t[] = { 0x18, 0x18 }; PatchBytes(0x8584CC, t, sizeof(t)); } // Don't wait 2 loops + + // Patch RestorePpuForMessageBox + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x85861C, t, sizeof(t)); } // WaitForNMI_NoUpdate + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x858651, t, sizeof(t)); } // WaitForNMI_NoUpdate + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x858692, t, sizeof(t)); } // HdmaObjectHandler + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x858696, t, sizeof(t)); } // HandleSoundEffects + + // Patch Fix_MsgBoxMakeHdmaTable_NoSleep + { uint8 t[] = { 0x08, 0xc2, 0x30, 0x4c, 0xa9, 0x85 }; PatchBytes(0x859660, t, sizeof(t)); } + { uint8 t[] = { 0x20, 0x60, 0x96 }; PatchBytes(0x8583BA, t, sizeof(t)); } // MsgBoxMakeHdmaTable + + // Patch GunshipTop_13 to not block + { uint8 t[] = { 0x22, 0x81, 0x96, 0x85, 0xc9, 0xff, 0xff, 0xd0, 0x04, 0x5c, 0x5f, 0xab, 0xa2, 0x5c, 0x26, 0xab, 0xa2 }; PatchBytes(0x859670, t, sizeof(t)); } // DisplayMessageBox_DoubleRet + { uint8 t[] = { 0xcd, 0x1f, 0x1c, 0xd0, 0x08, 0x9c, 0x1f, 0x1c, 0xad, 0xf9, 0x05, 0x6b, 0xff, 0x8d, 0xc8, 0x0d, 0xa9, 0xff, 0xff, 0x6b }; PatchBytes(0x859681, t, sizeof(t)); } // DisplayMessageBox_Poll + { uint8 t[] = { 0x5c, 0x70, 0x96, 0x85 }; PatchBytes(0xa2ab22, t, sizeof(t)); } // GunshipTop_13 + + // EnemyMain_WithCheckMsgBox + { uint8 t[] = { 0x22, 0xd4, 0x8f, 0xa0, 0xad, 0xc8, 0x0d, 0xf0, 0x07, 0x22, 0x95, 0x96, 0x85, 0x9c, 0xc8, 0x0d, 0x6b }; PatchBytes(0x8596a0, t, sizeof(t)); } + { uint8 t[] = { 0x22, 0xa0, 0x96, 0x85 }; PatchBytes(0x828b65, t, sizeof(t)); } // EnemyMain -> EnemyMain_WithCheckMsgBox + + // CloseMessageBox_ResetMsgBoxIdx + { uint8 t[] = { 0x20, 0x89, 0x85, 0xa9, 0x1c, 0x00, 0x8d, 0x1f, 0x1c, 0x60 }; PatchBytes(0x8596C0, t, sizeof(t)); } + { uint8 t[] = { 0x20, 0xC0, 0x96 }; PatchBytes(0x8580E5, t, sizeof(t)); } + + // ProcessPlm_CheckMessage + { uint8 t[] = { 0xad, 0xc8, 0x0d, 0xf0, 0x11, 0x98, 0x9d, 0x27, 0x1d, 0xad, 0xc8, 0x0d, 0x22, 0x95, 0x96, 0x85, 0x9c, 0xc8, 0x0d, 0xbc, 0x27, 0x1d, 0x4c, 0xee, 0x85 }; PatchBytes(0x84EFDC, t, sizeof(t)); } + { uint8 t[] = { 0xf4, 0xdb, 0xef }; PatchBytes(0x8485f7, t, sizeof(t)); } + + // Hook DisplayMessageBox so it writes to queued_message_box_index instead + { uint8 t[] = { 0x08, 0x8b, 0xda, 0x5a, 0x5c, 0x84, 0x80, 0x85 }; PatchBytes(0x859695, t, sizeof(t)); } // DisplayMessageBox_Org + { uint8 t[] = { 0x8d, 0xc8, 0x0d, 0x6b }; PatchBytes(0x858080, t, sizeof(t)); } // Hook + + // PlmInstr_ActivateSaveStationAndGotoIfNo_Fixed + { uint8 t[] = { 0x22, 0x81, 0x96, 0x85, 0xc9, 0xff, 0xff, 0xf0, 0x04, 0x5c, 0xfa, 0x8c, 0x84, 0x7a, 0xfa, 0x88, 0x88, 0x60 }; PatchBytes(0x84f000, t, sizeof(t)); } // Restart if -1 + { uint8 t[] = { 0x5c, 0x00, 0xf0, 0x84 }; PatchBytes(0x848cf6, t, sizeof(t)); } // PlmInstr_ActivateSaveStationAndGotoIfNo + + // SoftReset + { uint8 t[] = { 0xa9, 0xff, 0xff, 0x8d, 0x98, 0x09, 0x60 }; PatchBytes(0x81F000, t, sizeof(t)); } + { uint8 t[] = { 0x5c, 0x00, 0xf0, 0x81 }; PatchBytes(0x819027, t, sizeof(t)); } + { uint8 t[] = { 0x5c, 0x00, 0xf0, 0x81 }; PatchBytes(0x819112, t, sizeof(t)); } + { uint8 t[] = { 0x5c, 0x00, 0xf0, 0x81 }; PatchBytes(0x8194e9, t, sizeof(t)); } + + // Remove ReadJoypadInputs from Vector_NMI + { uint8 t[] = { 0x18, 0x18, 0x18, 0x18 }; PatchBytes(0x8095E1, t, sizeof(t)); } // callf ReadJoypadInputs + + // Remove APU_UploadBank + if (g_use_my_apu_code) + { uint8 t[] = { 0x60 }; PatchBytes(0x808028, t, sizeof(t)); } + + // Remove reads from IO_APUI01 etc + { uint8 t[] = { 0x18, 0x18, 0x18, 0x80 }; PatchBytes(0x828A59, t, sizeof(t)); } // SfxHandlers_1_WaitForAck + { uint8 t[] = { 0x18, 0x18, 0x18 }; PatchBytes(0x828A72, t, sizeof(t)); } // SfxHandlers_2_ClearRequest + { uint8 t[] = { 0x18, 0x18, 0x18, 0x80 }; PatchBytes(0x828A80, t, sizeof(t)); } // SfxHandlers_3_WaitForAck + { uint8 t[] = { 0x06 }; PatchBytes(0x828A67, t, sizeof(t)); } // sfx_clear_delay + + for (size_t i = 0; i != arraysize(kPatchedCarrys); i++) { + uint8 t = *RomPtr(kPatchedCarrys[i]); + if (t) { + kPatchedCarrysOrg[i] = t; + FixupCarry(kPatchedCarrys[i]); + } else { + printf("0x%x double patched!\n", kPatchedCarrys[i]); + } + } + + PatchBugs(1, 0); +#endif + return g_snes; +} + +void DebugGameOverMenu(void) { + assert(0); +} + +uint32 RunCpuUntilPC(uint32 pc1, uint32 pc2) { + for(;;) { + if (g_snes->debug_cycles) { + char line[80]; + getProcessorStateCpu(g_snes, line); + puts(line); + } + cpu_runOpcode(g_cpu); + + uint32 addr = g_snes->cpu->k << 16 | g_snes->cpu->pc; + if (addr == pc1 || addr == pc2) + return addr; + } +} + +void RunOneFrameOfGame_Emulated(void) { + // Execute until either WaitForNMI or WaitForLagFrame + RunCpuUntilPC(0x808343, 0x85813C); + + // Trigger nmi, then run until WaitForNMI or WaitForLagFrame returns + g_snes->cpu->nmiWanted = true; + RunCpuUntilPC(0x80834A, 0x858142); +} + +void DrawFrameToPpu(void) { + g_snes->hPos = g_snes->vPos = 0; + while (!g_snes->cpu->nmiWanted) { + do { + snes_handle_pos_stuff(g_snes); + } while (g_snes->hPos != 0); + if (g_snes->vIrqEnabled && (g_snes->vPos - 1) == g_snes->vTimer) { + Vector_IRQ(); + } + } + g_snes->cpu->nmiWanted = false; +} + +void RunOneFrameOfGame_Both(void) { + g_snes->ppu = g_snes->snes_ppu; + MakeSnapshot(&g_snapshot_before); + + // Run orig version then snapshot +again_theirs: + g_snes->runningWhichVersion = 1; + RunOneFrameOfGame_Emulated(); + DrawFrameToPpu(); + MakeSnapshot(&g_snapshot_theirs); + + // Run my version and snapshot +again_mine: + g_snes->ppu = g_snes->my_ppu; + RestoreSnapshot(&g_snapshot_before); + + g_snes->runningWhichVersion = 2; + RunOneFrameOfGame(); + DrawFrameToPpu(); + MakeSnapshot(&g_snapshot_mine); + + g_snes->runningWhichVersion = 0xff; + + // Compare both snapshots + VerifySnapshotsEq(&g_snapshot_mine, &g_snapshot_theirs, &g_snapshot_before); + + if (g_fail) { + g_fail = false; + + printf("Verify failure!\n"); + + g_snes->ppu = g_snes->snes_ppu; + RestoreSnapshot(&g_snapshot_before); + + if (g_got_mismatch_count == 0) { + char buffer[64]; + snprintf(buffer, sizeof(buffer), "saves/bug-%d.sav", (int)time(NULL)); + RtlSaveSnapshot(buffer, true); + } + g_got_mismatch_count = 5 * 60; + +#if defined(_DEBUG) && 0 + goto again_theirs; +#else + RunOneFrameOfGame_Emulated(); + goto getout; +#endif + } + + g_snes->ppu = g_snes->snes_ppu; + RestoreSnapshot(&g_snapshot_theirs); +getout: + g_snes->ppu = g_other_image ? g_snes->my_ppu : g_snes->snes_ppu; + g_snes->runningWhichVersion = 0; + + // Trigger soft reset? + if (game_state == 0xffff) { + g_snes->cpu->k = 0x80; + g_snes->cpu->pc = 0x8462; + coroutine_state_0 = 3; + } + + if (g_got_mismatch_count) + g_got_mismatch_count--; +} + +void RtlRunFrameCompare(uint16 input, int run_what) { + g_snes->input1->currentState = input; + + if (g_runmode == RM_THEIRS) { + assert(0); + } else if (g_runmode == RM_MINE) { + g_use_my_apu_code = true; + g_snes->hPos = 1364 - 2, g_snes->vPos = 262 - 1; + snes_handle_pos_stuff(g_snes); + + g_snes->runningWhichVersion = 0xff; + RunOneFrameOfGame(); + g_snes->runningWhichVersion = 0; + } else { + g_use_my_apu_code = true; + RunOneFrameOfGame_Both(); + } +} \ No newline at end of file diff --git a/src/sm_cpu_infra.h b/src/sm_cpu_infra.h new file mode 100644 index 0000000..8ec4cc2 --- /dev/null +++ b/src/sm_cpu_infra.h @@ -0,0 +1,26 @@ +#ifndef SM_CPU_INFRA_H_ +#define SM_CPU_INFRA_H_ + +#include "types.h" +#include "snes/cpu.h" +#include "snes/snes.h" + +typedef struct Snes Snes; +extern Snes *g_snes; +extern bool g_fail; + +typedef struct Snes Snes; + +Snes *SnesInit(const char *filename); + +int RunAsmCode(uint32 pc, uint16 a, uint16 x, uint16 y, int flags); +bool ProcessHook(uint32 v); + +void Call(uint32 addr); + +void RunOneFrameOfGame(); +void ClearUnusedOam(); + +void RunOneFrameOfGame_Both(); + +#endif // SM_CPU_INFRA_H_ \ No newline at end of file diff --git a/src/sm_rtl.c b/src/sm_rtl.c new file mode 100644 index 0000000..0b9a1a2 --- /dev/null +++ b/src/sm_rtl.c @@ -0,0 +1,709 @@ +#include "sm_rtl.h" +#include "sm_cpu_infra.h" +#include "types.h" +//#include "ida_types.h" +#include "variables.h" +#include "funcs.h" +#include "spc_player.h" +#include "util.h" + +struct StateRecorder; + +static void RtlSaveMusicStateToRam_Locked(); +static void RtlRestoreMusicAfterLoad_Locked(bool is_reset); + +uint8 g_ram[0x20000]; +uint8 *g_sram; + +static uint8 *g_rtl_memory_ptr; +static RunFrameFunc *g_rtl_runframe; +static SyncAllFunc *g_rtl_syncall; + +void RtlSetupEmuCallbacks(uint8 *emu_ram, RunFrameFunc *func, SyncAllFunc *sync_all) { + g_rtl_memory_ptr = emu_ram; + g_rtl_runframe = func; + g_rtl_syncall = sync_all; +} + +static void RtlSynchronizeWholeState(void) { + if (g_rtl_syncall) + g_rtl_syncall(); +} + +// |ptr| must be a pointer into g_ram, will synchronize the RAM memory with the +// emulator. +static void RtlSyncMemoryRegion(void *ptr, size_t n) { + uint8 *data = (uint8 *)ptr; + assert(data >= g_ram && data < g_ram + 0x20000); + if (g_rtl_memory_ptr) + memcpy(g_rtl_memory_ptr + (data - g_ram), data, n); +} + +void ByteArray_AppendVl(ByteArray *arr, uint32 v) { + for (; v >= 255; v -= 255) + ByteArray_AppendByte(arr, 255); + ByteArray_AppendByte(arr, v); +} + +void saveFunc(void *ctx_in, void *data, size_t data_size) { + ByteArray_AppendData((ByteArray *)ctx_in, (uint8*)data, data_size); +} + +typedef struct LoadFuncState { + uint8 *p, *pend; +} LoadFuncState; + +void loadFunc(void *ctx, void *data, size_t data_size) { + LoadFuncState *st = (LoadFuncState *)ctx; + assert((size_t)(st->pend - st->p) >= data_size); + memcpy(data, st->p, data_size); + st->p += data_size; +} +static void LoadSnesState(SaveLoadFunc *func, void *ctx) { + // Do the actual loading + snes_saveload(g_snes, func, ctx); + + g_snes->cpu->e = false; + uint32 next = (g_snes->ram[g_snes->cpu->sp + 3] | g_snes->ram[g_snes->cpu->sp + 4] << 8 | g_snes->ram[g_snes->cpu->sp + 5] << 16) + 1; + if (next == 0x82897e) { + g_snes->ram[g_snes->cpu->sp + 3] = (0xF71B - 1) & 0xff; + g_snes->ram[g_snes->cpu->sp + 4] = (0xF71B - 1) >> 8; + } + RtlSynchronizeWholeState(); +} + +static void SaveSnesState(SaveLoadFunc *func, void *ctx) { + snes_saveload(g_snes, func, ctx); +} + +typedef struct StateRecorder { + uint16 last_inputs; + uint32 frames_since_last; + uint32 total_frames; + + // For replay + uint32 replay_pos, replay_pos_last_complete; + uint32 replay_frame_counter; + uint32 replay_next_cmd_at; + uint32 snapshot_flags; + uint8 replay_cmd; + bool replay_mode; + + ByteArray log; + ByteArray base_snapshot; +} StateRecorder; + +static StateRecorder state_recorder; + +void StateRecorder_Init(StateRecorder *sr) { + memset(sr, 0, sizeof(*sr)); +} + +void StateRecorder_RecordCmd(StateRecorder *sr, uint8 cmd) { + int frames = sr->frames_since_last; + sr->frames_since_last = 0; + int x = (cmd < 0xc0) ? 0xf : 0x1; + ByteArray_AppendByte(&sr->log, cmd | (frames < x ? frames : x)); + if (frames >= x) + ByteArray_AppendVl(&sr->log, frames - x); +} + +void StateRecorder_Record(StateRecorder *sr, uint16 inputs) { + uint16 diff = inputs ^ sr->last_inputs; + if (diff != 0) { + sr->last_inputs = inputs; + // printf("0x%.4x %d: ", diff, sr->frames_since_last); + // size_t lb = sr->log.size; + for (int i = 0; i < 12; i++) { + if ((diff >> i) & 1) + StateRecorder_RecordCmd(sr, i << 4); + } + // while (lb < sr->log.size) + // printf("%.2x ", sr->log.data[lb++]); + // printf("\n"); + } + sr->frames_since_last++; + sr->total_frames++; +} + +void StateRecorder_RecordPatchByte(StateRecorder *sr, uint32 addr, const uint8 *value, int num) { + assert(addr < 0x20000); + + printf("%d: PatchByte(0x%x, 0x%x. %d): ", sr->frames_since_last, addr, *value, num); + size_t lb = sr->log.size; + int lq = (num - 1) <= 3 ? (num - 1) : 3; + StateRecorder_RecordCmd(sr, 0xc0 | (addr & 0x10000 ? 2 : 0) | lq << 2); + if (lq == 3) + ByteArray_AppendVl(&sr->log, num - 1 - 3); + ByteArray_AppendByte(&sr->log, addr >> 8); + ByteArray_AppendByte(&sr->log, addr); + for (int i = 0; i < num; i++) + ByteArray_AppendByte(&sr->log, value[i]); + while (lb < sr->log.size) + printf("%.2x ", sr->log.data[lb++]); + printf("\n"); +} + +void ReadFromFile(FILE *f, void *data, size_t n) { + if (fread(data, 1, n, f) != n) + Die("fread failed\n"); +} + +void RtlReset(bool preserve_sram) { + snes_frame_counter = 0; + coroutine_state_0 = 1; + snes_reset(g_snes, true); + if (!preserve_sram) + memset(g_sram, 0, 0x2000); + RtlApuLock(); + RtlRestoreMusicAfterLoad_Locked(true); + RtlApuUnlock(); + + RtlSynchronizeWholeState(); +} + +int GetFileSize(FILE *f) { + fseek(f, 0, SEEK_END); + int r = ftell(f); + fseek(f, 0, SEEK_SET); + return r; +} + +void StateRecorder_Load(StateRecorder *sr, FILE *f, bool replay_mode) { + uint32 hdr[16] = { 0 }; + + bool is_old = false; + bool is_reset = false; + + ReadFromFile(f, hdr, 8 * sizeof(uint32)); + if (hdr[0] != 2) { + hdr[8] = hdr[7]; + hdr[7] = hdr[5] >> 1; + hdr[5] = (hdr[5] & 1) ? hdr[6] : 0; + } else if (hdr[0] == 2) { + ReadFromFile(f, hdr + 8, 8 * sizeof(uint32)); + + } else { + assert(0); + } + + sr->total_frames = hdr[1]; + ByteArray_Resize(&sr->log, hdr[2]); + ReadFromFile(f, sr->log.data, sr->log.size); + sr->last_inputs = hdr[3]; + sr->frames_since_last = hdr[4]; + + ByteArray_Resize(&sr->base_snapshot, hdr[5]); + ReadFromFile(f, sr->base_snapshot.data, sr->base_snapshot.size); + + sr->snapshot_flags = hdr[9]; + sr->replay_next_cmd_at = 0; + sr->replay_mode = replay_mode; + if (replay_mode) { + sr->frames_since_last = 0; + sr->last_inputs = 0; + sr->replay_pos = sr->replay_pos_last_complete = 0; + sr->replay_frame_counter = 0; + // Load snapshot from |base_snapshot_|, or reset if empty. + if (sr->base_snapshot.size > 8192 ) { + LoadFuncState state = { sr->base_snapshot.data, sr->base_snapshot.data + sr->base_snapshot.size }; + LoadSnesState(&loadFunc, &state); + assert(state.p == state.pend); + } else { + RtlReset(false); + if (sr->base_snapshot.size == 8192) + memcpy(g_sram, sr->base_snapshot.data, 8192); + is_reset = true; + } + } else { + // Resume replay from the saved position? + sr->replay_pos = sr->replay_pos_last_complete = hdr[7]; + sr->replay_frame_counter = hdr[8]; + sr->replay_mode = (sr->replay_frame_counter != 0); + + ByteArray arr = { 0 }; + ByteArray_Resize(&arr, hdr[6]); + ReadFromFile(f, arr.data, arr.size); + LoadFuncState state = { arr.data, arr.data + arr.size }; + LoadSnesState(&loadFunc, &state); + ByteArray_Destroy(&arr); + assert(state.p == state.pend); + + if (is_old) + RtlClearKeyLog(); + } + + if (!is_reset) + RtlRestoreMusicAfterLoad_Locked(false); + + // Temporarily fix reset state +// if (g_snes->cpu->k == 0x82 && g_snes->cpu->pc == 0xf716) +// g_snes->cpu->pc = 0xf71c; +} + +void StateRecorder_Save(StateRecorder *sr, FILE *f, bool saving_with_bug) { + uint32 hdr[16] = { 0 }; + ByteArray arr = { 0 }; + SaveSnesState(&saveFunc, &arr); + assert(sr->base_snapshot.size == 0 || sr->base_snapshot.size == arr.size || sr->base_snapshot.size == 8192); + + hdr[0] = 2; + hdr[1] = sr->total_frames; + hdr[2] = (uint32)sr->log.size; + hdr[3] = sr->last_inputs; + hdr[4] = sr->frames_since_last; + hdr[5] = (uint32)sr->base_snapshot.size; + hdr[6] = (uint32)arr.size; + // If saving while in replay mode, also need to persist + // sr->replay_pos_last_complete and sr->replay_frame_counter + // so the replaying can be resumed. + if (sr->replay_mode) { + hdr[7] = sr->replay_pos_last_complete; + hdr[8] = sr->replay_frame_counter; + } + hdr[9] = saving_with_bug * 1; + fwrite(hdr, 1, sizeof(hdr), f); + fwrite(sr->log.data, 1, sr->log.size, f); + fwrite(sr->base_snapshot.data, 1, sr->base_snapshot.size, f); + fwrite(arr.data, 1, arr.size, f); + + ByteArray_Destroy(&arr); +} + +void StateRecorder_ClearKeyLog(StateRecorder *sr) { + printf("Clearing key log!\n"); + sr->base_snapshot.size = 0; + SaveSnesState(&saveFunc, &sr->base_snapshot); + ByteArray old_log = sr->log; + int old_frames_since_last = sr->frames_since_last; + memset(&sr->log, 0, sizeof(sr->log)); + // If there are currently any active inputs, record them initially at timestamp 0. + sr->frames_since_last = 0; + if (sr->last_inputs) { + for (int i = 0; i < 12; i++) { + if ((sr->last_inputs >> i) & 1) + StateRecorder_RecordCmd(sr, i << 4); + } + } + if (sr->replay_mode) { + // When clearing the key log while in replay mode, we want to keep + // replaying but discarding all key history up until this point. + if (sr->replay_next_cmd_at != 0xffffffff) { + sr->replay_next_cmd_at -= old_frames_since_last; + sr->frames_since_last = sr->replay_next_cmd_at; + sr->replay_pos_last_complete = (uint32)sr->log.size; + StateRecorder_RecordCmd(sr, sr->replay_cmd); + int old_replay_pos = sr->replay_pos; + sr->replay_pos = (uint32)sr->log.size; + ByteArray_AppendData(&sr->log, old_log.data + old_replay_pos, old_log.size - old_replay_pos); + } + sr->total_frames -= sr->replay_frame_counter; + sr->replay_frame_counter = 0; + } else { + sr->total_frames = 0; + } + ByteArray_Destroy(&old_log); + sr->frames_since_last = 0; +} + +uint16 StateRecorder_ReadNextReplayState(StateRecorder *sr) { + assert(sr->replay_mode); + while (sr->frames_since_last >= sr->replay_next_cmd_at) { + int replay_pos = sr->replay_pos; + if (replay_pos != sr->replay_pos_last_complete) { + // Apply next command + sr->frames_since_last = 0; + if (sr->replay_cmd < 0xc0) { + sr->last_inputs ^= 1 << (sr->replay_cmd >> 4); + } else if (sr->replay_cmd < 0xd0) { + int nb = 1 + ((sr->replay_cmd >> 2) & 3); + uint8 t; + if (nb == 4) do { + nb += t = sr->log.data[replay_pos++]; + } while (t == 255); + uint32 addr = ((sr->replay_cmd >> 1) & 1) << 16; + addr |= sr->log.data[replay_pos++] << 8; + addr |= sr->log.data[replay_pos++]; + do { + g_ram[addr & 0x1ffff] = sr->log.data[replay_pos++]; + RtlSyncMemoryRegion(&g_ram[addr & 0x1ffff], 1); + } while (addr++, --nb); + } else { + assert(0); + } + } + sr->replay_pos_last_complete = replay_pos; + if (replay_pos >= sr->log.size) { + sr->replay_pos = replay_pos; + sr->replay_next_cmd_at = 0xffffffff; + break; + } + // Read the next one + uint8 cmd = sr->log.data[replay_pos++], t; + int mask = (cmd < 0xc0) ? 0xf : 0x1; + int frames = cmd & mask; + if (frames == mask) do { + frames += t = sr->log.data[replay_pos++]; + } while (t == 255); + sr->replay_next_cmd_at = frames; + sr->replay_cmd = cmd; + sr->replay_pos = replay_pos; + } + sr->frames_since_last++; + // Turn off replay mode after we reached the final frame position + if (++sr->replay_frame_counter >= sr->total_frames) { + sr->replay_mode = false; + } + return sr->last_inputs; +} + +void StateRecorder_StopReplay(StateRecorder *sr) { + if (!sr->replay_mode) + return; + sr->replay_mode = false; + sr->total_frames = sr->replay_frame_counter; + sr->log.size = sr->replay_pos_last_complete; +} + + +void RtlClearKeyLog(void) { + StateRecorder_ClearKeyLog(&state_recorder); +} + +void RtlStopReplay(void) { + StateRecorder_StopReplay(&state_recorder); +} + +bool RtlRunFrame(int inputs) { + // Avoid up/down and left/right from being pressed at the same time + if ((inputs & 0x30) == 0x30) inputs ^= 0x30; + if ((inputs & 0xc0) == 0xc0) inputs ^= 0xc0; + + bool is_replay = state_recorder.replay_mode; + + // Either copy state or apply state + if (is_replay) { + inputs = StateRecorder_ReadNextReplayState(&state_recorder); + } else { + // Loading a bug snapshot? + if (state_recorder.snapshot_flags & 1) { + state_recorder.snapshot_flags &= ~1; + inputs = state_recorder.last_inputs; + } + + StateRecorder_Record(&state_recorder, inputs); + } + + + g_rtl_runframe(inputs, 0); + + snes_frame_counter++; + + RtlPushApuState(); + return is_replay; +} + +void RtlSaveSnapshot(const char *filename, bool saving_with_bug) { + FILE *f = fopen(filename, "wb"); + RtlApuLock(); + RtlSaveMusicStateToRam_Locked(); + StateRecorder_Save(&state_recorder, f, saving_with_bug); + RtlApuUnlock(); + fclose(f); +} + +void RtlSaveLoad(int cmd, int slot) { + char name[128]; + sprintf(name, "saves/save%d.sav", slot); + printf("*** %s slot %d\n", + cmd == kSaveLoad_Save ? "Saving" : cmd == kSaveLoad_Load ? "Loading" : "Replaying", slot); + if (cmd != kSaveLoad_Save) { + FILE *f = fopen(name, "rb"); + RtlApuLock(); + StateRecorder_Load(&state_recorder, f, cmd == kSaveLoad_Replay); + ppu_copy(g_snes->my_ppu, g_snes->ppu); + RtlApuUnlock(); + RtlSynchronizeWholeState(); + fclose(f); + } else { + RtlSaveSnapshot(name, false); + } +} + +void MemCpy(void *dst, const void *src, int size) { + memcpy(dst, src, size); +} + +void Negate32(const uint16 *src_hi, const uint16 *src_lo, uint16 *dst_hi, uint16 *dst_lo) { + uint32 x = (uint32)*src_hi << 16 | *src_lo; + x = -(int)x; + *dst_lo = x; + *dst_hi = x >> 16; +} + +PairU16 MakePairU16(uint16 k, uint16 j) { + PairU16 r = { k, j }; + return r; +} + +void mov24(struct LongPtr *a, unsigned int d) { + a->addr = d & 0xffff; + a->bank = d >> 16; +} + +void copy24(LongPtr *dst, LongPtr *src) { + *dst = *src; +} + +uint32 Load24(void *a) { + return *(uint32 *)a & 0xffffff; +} + +void DecompressToMem_IpArg(const void *p) { + decompress_dst = *(LongPtr *)p; + DecompressToMem(); +} + +bool Unreachable(void) { + printf("Unreachable!\n"); + assert(0); + g_ram[0x1ffff] = 1; + return false; +} + +uint8_t *RomPtr(uint32_t addr) { + if (!(addr & 0x8000)) { + printf("RomPtr - Invalid access 0x%x!\n", addr); + g_fail = true; + } + return &g_snes->cart->rom[(((addr >> 16) << 15) | (addr & 0x7fff)) & (g_snes->cart->romSize - 1)]; +} + +uint8_t *IndirPtr(void *ptr, uint16 offs) { + uint32 a = (*(uint32 *)ptr & 0xffffff) + offs; + if ((a >> 16) >= 0x7e && (a >> 16) <= 0x7f || a < 0x2000) { + return &g_ram[a & 0x1ffff]; + } else { + return RomPtr(a); + } +} + +void IndirWriteWord(void *ptr, uint16 offs, uint16 value) { + *(uint16 *)IndirPtr(ptr, offs) = value; +} + +void IndirWriteByte(void *ptr, uint16 offs, uint8 value) { + *IndirPtr(ptr, offs) = value; +} + +void WriteReg(uint16 reg, uint8 value) { + snes_write(g_snes, reg, value); +} + +uint16 Mult8x8(uint8 a, uint8 b) { + return a * b; +} + +uint16 SnesDivide(uint16 a, uint8 b) { + return (b == 0) ? 0xffff : a / b; +} + +uint16 SnesModulus(uint16 a, uint8 b) { + return (b == 0) ? a : a % b; +} + + +uint8 ReadReg(uint16 reg) { + return snes_read(g_snes, reg); +} + +uint16 ReadRegWord(uint16 reg) { + uint16_t rv = ReadReg(reg); + rv |= ReadReg(reg + 1) << 8; + return rv; +} + +void WriteRegWord(uint16 reg, uint16 value) { + WriteReg(reg, (uint8)value); + WriteReg(reg + 1, value >> 8); +} + +// Maintain a queue cause the snes and audio callback are not in sync. +// If an entry is 255, it means unset. +typedef struct ApuWriteEnt { + uint8 ports[4]; +} ApuWriteEnt; + +enum { + kApuMaxQueueSize = 16, +}; + +static struct ApuWriteEnt g_apu_write_ents[kApuMaxQueueSize], g_apu_write; +static uint8 g_apu_write_ent_pos, g_apu_queue_size, g_apu_time_since_empty; + +void RtlApuWrite(uint32 adr, uint8 val) { + assert(adr >= APUI00 && adr <= APUI03); + + if (is_uploading_apu) { + snes_catchupApu(g_snes); // catch up the apu before writing + g_snes->apu->inPorts[adr & 0x3] = val; + return; + } + + if (g_snes->runningWhichVersion != 2) { + g_apu_write.ports[adr & 0x3] = val; + } +} + +static bool IsFrameEmpty(ApuWriteEnt *w) { + return (w->ports[0] == 255) && (w->ports[1] == 255) && (w->ports[2] == 255) && (w->ports[3] == 255); +} + +void RtlPushApuState(void) { + RtlApuLock(); + if (!is_uploading_apu) { + // Strive for the queue to be empty. + if (g_apu_queue_size == 0) { + g_apu_time_since_empty = 0; + } else { + if (g_apu_time_since_empty >= 32 && IsFrameEmpty(&g_apu_write)) { + g_apu_time_since_empty -= 4; + RtlApuUnlock(); + return; + } + g_apu_time_since_empty++; + } + + // Merge the two oldest to make space + ApuWriteEnt *w0 = &g_apu_write_ents[g_apu_write_ent_pos++ & (kApuMaxQueueSize - 1)]; + if (g_apu_queue_size == kApuMaxQueueSize) { + ApuWriteEnt *w1 = &g_apu_write_ents[g_apu_write_ent_pos & (kApuMaxQueueSize - 1)]; + for (int i = 0; i < 4; i++) + if (w1->ports[i] == 255) + w1->ports[i] = w0->ports[i]; + } else { + g_apu_queue_size++; + } + *w0 = g_apu_write; + memset(&g_apu_write, 0xff, sizeof(g_apu_write)); + } else { + g_apu_queue_size = 0; + } + RtlApuUnlock(); +} + +static void RtlPopApuState_Locked(void) { + if (is_uploading_apu) + return; + + uint8 *input_ports = g_use_my_apu_code ? g_spc_player->input_ports : g_snes->apu->inPorts; + if (g_apu_queue_size != 0) { + ApuWriteEnt *w = &g_apu_write_ents[(g_apu_write_ent_pos - g_apu_queue_size--) & (kApuMaxQueueSize - 1)]; + for (int i = 0; i != 4; i++) { + if (w->ports[i] != 255) + input_ports[i] = w->ports[i]; + } + } +} + +static void RtlResetApuQueue(void) { + g_apu_write_ent_pos = g_apu_time_since_empty = g_apu_queue_size = 0; + memset(&g_apu_write, 0xff, sizeof(g_apu_write)); +} + +void RtlApuUpload(const uint8 *p) { + RtlApuLock(); + RtlResetApuQueue(); + SpcPlayer_Upload(g_spc_player, p); + RtlApuUnlock(); +} + +void RtlRestoreMusicAfterLoad_Locked(bool is_reset) { + if (g_use_my_apu_code) { + memcpy(g_spc_player->ram, g_snes->apu->ram, 65536); + memcpy(g_spc_player->dsp->ram, g_snes->apu->dsp->ram, sizeof(Dsp) - offsetof(Dsp, ram)); + SpcPlayer_CopyVariablesFromRam(g_spc_player); + } + + if (is_reset) { + SpcPlayer_Initialize(g_spc_player); + } + + RtlResetApuQueue(); +} + +void RtlSaveMusicStateToRam_Locked(void) { + if (g_use_my_apu_code) { + // Apply the whole contents of the queue to input ports + SpcPlayer *spc_player = g_spc_player; + for (int i = g_apu_queue_size; i; i--) { + ApuWriteEnt *we = &g_apu_write_ents[(g_apu_write_ent_pos - i) & (kApuMaxQueueSize - 1)]; + for (int j = 0; j < 4; j++) { + if (we->ports[j] != 255) + spc_player->input_ports[j] = we->ports[j]; + } + } + SpcPlayer_CopyVariablesToRam(g_spc_player); + memcpy(g_snes->apu->dsp->ram, g_spc_player->dsp->ram, sizeof(Dsp) - offsetof(Dsp, ram)); + memcpy(g_snes->apu->ram, g_spc_player->ram, 65536); + } +} + +void RtlRenderAudio(int16 *audio_buffer, int samples, int channels) { + assert(channels == 2); + RtlApuLock(); + + RtlPopApuState_Locked(); + + if (!g_use_my_apu_code) { + if (!is_uploading_apu) { + while (g_snes->apu->dsp->sampleOffset < 534) + apu_cycle(g_snes->apu); + dsp_getSamples(g_snes->apu->dsp, audio_buffer, samples); + } + } else { + SpcPlayer_GenerateSamples(g_spc_player); + dsp_getSamples(g_spc_player->dsp, audio_buffer, samples); + } + + RtlApuUnlock(); +} + +void RtlCheat(char c) { + if (c == 'w') { + samus_health = samus_max_health; + StateRecorder_RecordPatchByte(&state_recorder, 0x9C2, (uint8 *)&samus_health, 2); + } else if (c == 'q' && 0) { + samus_y_pos -= 32; + samus_y_speed = 0; + StateRecorder_RecordPatchByte(&state_recorder, 0xafa, (uint8 *)&samus_y_pos, 2); + StateRecorder_RecordPatchByte(&state_recorder, 0xb2e, (uint8 *)&samus_y_speed, 2); + menu_index = 0; + } else if (c == 'q') { + japanese_text_flag = !japanese_text_flag; + StateRecorder_RecordPatchByte(&state_recorder, 0x9e2, (uint8 *)&japanese_text_flag, 2); + } +} + +void RtlReadSram(void) { + FILE *f = fopen("saves/sm.srm", "rb"); + if (f) { + if (fread(g_sram, 1, 8192, f) != 8192) + fprintf(stderr, "Error reading saves/sm.srm\n"); + fclose(f); + RtlSynchronizeWholeState(); + ByteArray_Resize(&state_recorder.base_snapshot, 8192); + memcpy(state_recorder.base_snapshot.data, g_sram, 8192); + } +} + +void RtlWriteSram(void) { + rename("saves/sm.srm", "saves/sm.srm.bak"); + FILE *f = fopen("saves/sm.srm", "wb"); + if (f) { + fwrite(g_sram, 1, 8192, f); + fclose(f); + } else { + fprintf(stderr, "Unable to write saves/sm.srm\n"); + } +} diff --git a/src/sm_rtl.h b/src/sm_rtl.h new file mode 100644 index 0000000..70e7ebc --- /dev/null +++ b/src/sm_rtl.h @@ -0,0 +1,460 @@ +#pragma once +#include "types.h" +#include +#include + +extern uint8 g_ram[0x20000]; +extern void RtlApuWrite(uint32 adr, uint8 val); +extern int snes_frame_counter; + +extern uint8 *g_sram; +extern bool g_use_my_apu_code; +#define LONGPTR(t) {(t) & 0xffff, (t) >> 16} + +typedef void HandlerFunc(void); +typedef uint8 Func_V_A(void); + +typedef void Func_V(void); + +typedef CoroutineRet Func_V_Coroutine(void); +typedef uint8 Func_U8(void); +typedef uint16 Func_U16(void); +typedef void Func_Y_V(uint16 j); +typedef uint8 Func_Y_U8(uint16 j); +typedef void Func_X_V(uint16 j); +typedef uint16 Func_Y_Y(uint16 j); +typedef uint16 Func_Y(); +typedef uint16 Func_XY_Y(uint16 k, uint16 j); + + +typedef void FuncXY_V(uint16 k, uint16 j); +typedef PairU16 Func_Y_To_PairU16(uint16 j); + +uint8_t *RomPtr(uint32_t addr); +uint8_t *IndirPtr(void *ptr, uint16 offs); +void IndirWriteWord(void *ptr, uint16 offs, uint16 value); +void IndirWriteByte(void *ptr, uint16 offs, uint8 value); + +struct LongPtr; +void mov24(LongPtr *dst, uint32 src); +void copy24(LongPtr *dst, LongPtr *src); +uint32 Load24(void *a); +void MemCpy(void *dst, const void *src, int size); +void Call(uint32 addr); + +static inline uint8_t *RomPtr_RAM(uint16_t addr) { assert(addr < 0x2000); return g_ram + addr; } + +static inline uint8_t *RomPtr_7E(uint16_t addr) { return g_ram + addr; } +static inline uint8_t *RomPtr_7F(uint16_t addr) { return g_ram + 0x10000 + addr; } +static inline uint8_t *RomPtr_80(uint16_t addr) { return RomPtr(0x800000 | addr); } +static inline uint8_t *RomPtr_81(uint16_t addr) { return RomPtr(0x810000 | addr); } +static inline uint8_t *RomPtr_82(uint16_t addr) { return RomPtr(0x820000 | addr); } +static inline uint8_t *RomPtr_83(uint16_t addr) { return RomPtr(0x830000 | addr); } +static inline uint8_t *RomPtr_84(uint16_t addr) { return RomPtr(0x840000 | addr); } +static inline uint8_t *RomPtr_85(uint16_t addr) { return RomPtr(0x850000 | addr); } +static inline uint8_t *RomPtr_86(uint16_t addr) { return RomPtr(0x860000 | addr); } +static inline uint8_t *RomPtr_87(uint16_t addr) { return RomPtr(0x870000 | addr); } +static inline uint8_t *RomPtr_88(uint16_t addr) { return RomPtr(0x880000 | addr); } +static inline uint8_t *RomPtr_89(uint16_t addr) { return RomPtr(0x890000 | addr); } +static inline uint8_t *RomPtr_8A(uint16_t addr) { return RomPtr(0x8a0000 | addr); } +static inline uint8_t *RomPtr_8B(uint16_t addr) { return RomPtr(0x8b0000 | addr); } +static inline uint8_t *RomPtr_8C(uint16_t addr) { return RomPtr(0x8c0000 | addr); } +static inline uint8_t *RomPtr_8D(uint16_t addr) { return RomPtr(0x8d0000 | addr); } +static inline uint8_t *RomPtr_8E(uint16_t addr) { return RomPtr(0x8e0000 | addr); } +static inline uint8_t *RomPtr_8F(uint16_t addr) { return RomPtr(0x8f0000 | addr); } +static inline uint8_t *RomPtr_90(uint16_t addr) { return RomPtr(0x900000 | addr); } +static inline uint8_t *RomPtr_91(uint16_t addr) { return RomPtr(0x910000 | addr); } +static inline uint8_t *RomPtr_92(uint16_t addr) { return RomPtr(0x920000 | addr); } +static inline uint8_t *RomPtr_93(uint16_t addr) { return RomPtr(0x930000 | addr); } +static inline uint8_t *RomPtr_94(uint16_t addr) { return RomPtr(0x940000 | addr); } +static inline uint8_t *RomPtr_95(uint16_t addr) { return RomPtr(0x950000 | addr); } +static inline uint8_t *RomPtr_96(uint16_t addr) { return RomPtr(0x960000 | addr); } +static inline uint8_t *RomPtr_97(uint16_t addr) { return RomPtr(0x970000 | addr); } +static inline uint8_t *RomPtr_98(uint16_t addr) { return RomPtr(0x980000 | addr); } +static inline uint8_t *RomPtr_99(uint16_t addr) { return RomPtr(0x990000 | addr); } +static inline uint8_t *RomPtr_9A(uint16_t addr) { return RomPtr(0x9a0000 | addr); } +static inline uint8_t *RomPtr_9B(uint16_t addr) { return RomPtr(0x9b0000 | addr); } +static inline uint8_t *RomPtr_9C(uint16_t addr) { return RomPtr(0x9c0000 | addr); } +static inline uint8_t *RomPtr_9D(uint16_t addr) { return RomPtr(0x9d0000 | addr); } +static inline uint8_t *RomPtr_9E(uint16_t addr) { return RomPtr(0x9e0000 | addr); } +static inline uint8_t *RomPtr_9F(uint16_t addr) { return RomPtr(0x9f0000 | addr); } +static inline uint8_t *RomPtr_A0(uint16_t addr) { return RomPtr(0xa00000 | addr); } +static inline uint8_t *RomPtr_A1(uint16_t addr) { return RomPtr(0xa10000 | addr); } +static inline uint8_t *RomPtr_A2(uint16_t addr) { return RomPtr(0xa20000 | addr); } +static inline uint8_t *RomPtr_A3(uint16_t addr) { return RomPtr(0xa30000 | addr); } +static inline uint8_t *RomPtr_A4(uint16_t addr) { return RomPtr(0xa40000 | addr); } +static inline uint8_t *RomPtr_A5(uint16_t addr) { return RomPtr(0xa50000 | addr); } +static inline uint8_t *RomPtr_A6(uint16_t addr) { return RomPtr(0xa60000 | addr); } +static inline uint8_t *RomPtr_A7(uint16_t addr) { return RomPtr(0xa70000 | addr); } +static inline uint8_t *RomPtr_A8(uint16_t addr) { return RomPtr(0xa80000 | addr); } +static inline uint8_t *RomPtr_A9(uint16_t addr) { return RomPtr(0xa90000 | addr); } +static inline uint8_t *RomPtr_AA(uint16_t addr) { return RomPtr(0xaa0000 | addr); } +static inline uint8_t *RomPtr_AB(uint16_t addr) { return RomPtr(0xab0000 | addr); } +static inline uint8_t *RomPtr_AC(uint16_t addr) { return RomPtr(0xac0000 | addr); } +static inline uint8_t *RomPtr_AD(uint16_t addr) { return RomPtr(0xad0000 | addr); } +static inline uint8_t *RomPtr_AE(uint16_t addr) { return RomPtr(0xae0000 | addr); } +static inline uint8_t *RomPtr_AF(uint16_t addr) { return RomPtr(0xaf0000 | addr); } +static inline uint8_t *RomPtr_B0(uint16_t addr) { return RomPtr(0xb00000 | addr); } +static inline uint8_t *RomPtr_B1(uint16_t addr) { return RomPtr(0xb10000 | addr); } +static inline uint8_t *RomPtr_B2(uint16_t addr) { return RomPtr(0xb20000 | addr); } +static inline uint8_t *RomPtr_B3(uint16_t addr) { return RomPtr(0xb30000 | addr); } +static inline uint8_t *RomPtr_B4(uint16_t addr) { return RomPtr(0xb40000 | addr); } +static inline uint8_t *RomPtr_B5(uint16_t addr) { return RomPtr(0xb50000 | addr); } +static inline uint8_t *RomPtr_B6(uint16_t addr) { return RomPtr(0xb60000 | addr); } +static inline uint8_t *RomPtr_B7(uint16_t addr) { return RomPtr(0xb70000 | addr); } +static inline uint8_t *RomPtr_B8(uint16_t addr) { return RomPtr(0xb80000 | addr); } +static inline uint8_t *RomPtr_B9(uint16_t addr) { return RomPtr(0xb90000 | addr); } +static inline uint8_t *RomPtr_BA(uint16_t addr) { return RomPtr(0xba0000 | addr); } +static inline uint8_t *RomPtr_BB(uint16_t addr) { return RomPtr(0xbb0000 | addr); } +static inline uint8_t *RomPtr_BC(uint16_t addr) { return RomPtr(0xbc0000 | addr); } +static inline uint8_t *RomPtr_BD(uint16_t addr) { return RomPtr(0xbd0000 | addr); } +static inline uint8_t *RomPtr_BE(uint16_t addr) { return RomPtr(0xbe0000 | addr); } +static inline uint8_t *RomPtr_BF(uint16_t addr) { return RomPtr(0xbf0000 | addr); } +static inline uint8_t *RomPtr_C0(uint16_t addr) { return RomPtr(0xc00000 | addr); } +static inline uint8_t *RomPtr_C1(uint16_t addr) { return RomPtr(0xc10000 | addr); } +static inline uint8_t *RomPtr_C2(uint16_t addr) { return RomPtr(0xc20000 | addr); } +static inline uint8_t *RomPtr_C3(uint16_t addr) { return RomPtr(0xc30000 | addr); } +static inline uint8_t *RomPtr_C4(uint16_t addr) { return RomPtr(0xc40000 | addr); } +static inline uint8_t *RomPtr_C5(uint16_t addr) { return RomPtr(0xc50000 | addr); } +static inline uint8_t *RomPtr_C6(uint16_t addr) { return RomPtr(0xc60000 | addr); } +static inline uint8_t *RomPtr_C7(uint16_t addr) { return RomPtr(0xc70000 | addr); } +static inline uint8_t *RomPtr_C8(uint16_t addr) { return RomPtr(0xc80000 | addr); } +static inline uint8_t *RomPtr_C9(uint16_t addr) { return RomPtr(0xc90000 | addr); } +static inline uint8_t *RomPtr_CA(uint16_t addr) { return RomPtr(0xca0000 | addr); } +static inline uint8_t *RomPtr_CB(uint16_t addr) { return RomPtr(0xcb0000 | addr); } +static inline uint8_t *RomPtr_CC(uint16_t addr) { return RomPtr(0xcc0000 | addr); } +static inline uint8_t *RomPtr_CD(uint16_t addr) { return RomPtr(0xcd0000 | addr); } +static inline uint8_t *RomPtr_CE(uint16_t addr) { return RomPtr(0xce0000 | addr); } +static inline uint8_t *RomPtr_CF(uint16_t addr) { return RomPtr(0xcf0000 | addr); } +static inline uint8_t *RomPtr_D0(uint16_t addr) { return RomPtr(0xd00000 | addr); } +static inline uint8_t *RomPtr_D1(uint16_t addr) { return RomPtr(0xd10000 | addr); } +static inline uint8_t *RomPtr_D2(uint16_t addr) { return RomPtr(0xd20000 | addr); } +static inline uint8_t *RomPtr_D3(uint16_t addr) { return RomPtr(0xd30000 | addr); } +static inline uint8_t *RomPtr_D4(uint16_t addr) { return RomPtr(0xd40000 | addr); } +static inline uint8_t *RomPtr_D5(uint16_t addr) { return RomPtr(0xd50000 | addr); } +static inline uint8_t *RomPtr_D6(uint16_t addr) { return RomPtr(0xd60000 | addr); } +static inline uint8_t *RomPtr_D7(uint16_t addr) { return RomPtr(0xd70000 | addr); } +static inline uint8_t *RomPtr_D8(uint16_t addr) { return RomPtr(0xd80000 | addr); } +static inline uint8_t *RomPtr_D9(uint16_t addr) { return RomPtr(0xd90000 | addr); } +static inline uint8_t *RomPtr_DA(uint16_t addr) { return RomPtr(0xda0000 | addr); } +static inline uint8_t *RomPtr_DB(uint16_t addr) { return RomPtr(0xdb0000 | addr); } +static inline uint8_t *RomPtr_DC(uint16_t addr) { return RomPtr(0xdc0000 | addr); } +static inline uint8_t *RomPtr_DD(uint16_t addr) { return RomPtr(0xdd0000 | addr); } +static inline uint8_t *RomPtr_DE(uint16_t addr) { return RomPtr(0xde0000 | addr); } +static inline uint8_t *RomPtr_DF(uint16_t addr) { return RomPtr(0xdf0000 | addr); } + +static inline uint8_t *RomPtrWithBank(uint8 bank, uint16_t addr) { return RomPtr((bank << 16) | addr); } + +void WriteReg(uint16 reg, uint8 value); +void WriteRegWord(uint16 reg, uint16 value); +uint16 ReadRegWord(uint16 reg); +uint8 ReadReg(uint16 reg); + + +typedef void RunFrameFunc(uint16 input, int run_what); +typedef void SyncAllFunc(); + +void RtlSetupEmuCallbacks(uint8 *emu_ram, RunFrameFunc *func, SyncAllFunc *sync_all); +void RtlClearKeyLog(); +void RtlStopReplay(); + +enum { + kSaveLoad_Save = 1, + kSaveLoad_Load = 2, + kSaveLoad_Replay = 3, +}; + +void RtlSaveLoad(int cmd, int slot); +void RtlCheat(char c); +void RtlApuLock(); +void RtlApuUnlock(); +void RtlApuUpload(const uint8 *p); +void RtlRenderAudio(int16 *audio_buffer, int samples, int channels); +void RtlPushApuState(); +bool RtlRunFrame(int inputs); +void RtlReadSram(); +void RtlWriteSram(); +void RtlSaveSnapshot(const char *filename, bool saving_with_bug); + +uint16 Mult8x8(uint8 a, uint8 b); +uint16 SnesDivide(uint16 a, uint8 b); +uint16 SnesModulus(uint16 a, uint8 b); + +typedef struct SpcPlayer SpcPlayer; +extern SpcPlayer *g_spc_player; + +enum { + kJoypadL_A = 0x80, + kJoypadL_X = 0x40, + kJoypadL_L = 0x20, + kJoypadL_R = 0x10, + + kJoypadH_B = 0x80, + kJoypadH_Y = 0x40, + kJoypadH_Select = 0x20, + kJoypadH_Start = 0x10, + + kJoypadH_Up = 0x8, + kJoypadH_Down = 0x4, + kJoypadH_Left = 0x2, + kJoypadH_Right = 0x1, + + kJoypadH_AnyDir = 0xf, +}; + +void Negate32(const uint16 *src_hi, const uint16 *src_lo, uint16 *dst_hi, uint16 *dst_lo); + +struct OamEnt; +struct VramWriteEntry; + + +PairU16 MakePairU16(uint16 k, uint16 j); + +#define R0_ (*(LongPtr*)(g_ram+0x0)) +#define R3_ (*(LongPtr*)(g_ram+0x3)) +#define byte_7E0002 R0_.bank + +#define kPoseParams ((SamusPoseParams*)RomPtr(0x91b629)) +#define kAtmosphericGraphicAnimationTimers ((uint16*)RomPtr(0x908b93)) +#define kAtmosphericTypeNumFrames ((uint16*)RomPtr(0x908bef)) +#define g_off_908BFF ((uint16*)RomPtr(0x908bff)) +#define g_stru_90A83A ((DisableMinimapAndMarkBossRoomAsExploredEnt*)RomPtr(0x90a83a)) +#define kPlayerPoseToPtr ((uint16*)RomPtr(0x90c7df)) +#define kDrawArmCannon_Tab2 ((uint16*)RomPtr(0x90c7a5)) +extern const int16 kSinCosTable8bit_Sext[320]; +#define kPoseTransitionTable ((uint16*)RomPtr(0x919ee2)) +#define kDemoSetDefPtrs ((uint16*)RomPtr(0x918885)) +#define kSpeedBoostToCtr ((uint16*)RomPtr(0x91b61f)) +#define kSpeedBoostToAnimFramePtr ((uint16 *)RomPtr(0x91B5DE)) +#define kSamusPoseToBaseSpritemapIndexTop ((uint16*)RomPtr(0x929263)) +#define kSamusPoseToBaseSpritemapIndexBottom ((uint16*)RomPtr(0x92945d)) +#define kSamusAnimationDelayData ((uint16*)RomPtr(0x91b010)) + +bool Unreachable(); + + +#define kCommonEnemySpeeds_Linear ((uint16*)RomPtr(0xa28187)) +#define kCommonEnemySpeeds_Quadratic ((uint16*)RomPtr(0xa2838f)) +#define kSine16bit ((uint16*)RomPtr(0xa0b1c3)) +#define kOamExtra_X8Small_And_Large ((uint16*)RomPtr(0x81839f)) +#define kOamExtra_Address_And_X8Large ((uint16*)RomPtr(0x81859f)) +#define kTanTable ((uint16*)RomPtr(0x91c9d4)) + +void CallEnemyAi(uint32 ea); +void CallEnemyPreInstr(uint32 ea); +uint16 CallEnemyInstr(uint32 ea, uint16 k, uint16 j); + +void CalculateBlockContainingPixelPos(uint16 xpos, uint16 ypos); + +/* 148 */ +typedef enum SnesRegs { + INIDISP = 0x2100, + OBSEL = 0x2101, + OAMADDL = 0x2102, + OAMADDH = 0x2103, + OAMDATA = 0x2104, + BGMODE = 0x2105, + MOSAIC = 0x2106, + BG1SC = 0x2107, + BG2SC = 0x2108, + BG3SC = 0x2109, + BG4SC = 0x210A, + BG12NBA = 0x210B, + BG34NBA = 0x210C, + BG1HOFS = 0x210D, + BG1VOFS = 0x210E, + BG2HOFS = 0x210F, + BG2VOFS = 0x2110, + BG3HOFS = 0x2111, + BG3VOFS = 0x2112, + BG4HOFS = 0x2113, + BG4VOFS = 0x2114, + VMAIN = 0x2115, + VMADDL = 0x2116, + VMADDH = 0x2117, + VMDATAL = 0x2118, + VMDATAH = 0x2119, + M7SEL = 0x211A, + M7A = 0x211B, + M7B = 0x211C, + M7C = 0x211D, + M7D = 0x211E, + M7X = 0x211F, + M7Y = 0x2120, + CGADD = 0x2121, + CGDATA = 0x2122, + W12SEL = 0x2123, + W34SEL = 0x2124, + WOBJSEL = 0x2125, + WH0 = 0x2126, + WH1 = 0x2127, + WH2 = 0x2128, + WH3 = 0x2129, + WBGLOG = 0x212A, + WOBJLOG = 0x212B, + TM = 0x212C, + TS = 0x212D, + TMW = 0x212E, + TSW = 0x212F, + CGWSEL = 0x2130, + CGADSUB = 0x2131, + COLDATA = 0x2132, + SETINI = 0x2133, + MPYL = 0x2134, + MPYM = 0x2135, + MPYH = 0x2136, + SLHV = 0x2137, + RDOAM = 0x2138, + RDVRAML = 0x2139, + RDVRAMH = 0x213A, + RDCGRAM = 0x213B, + OPHCT = 0x213C, + OPVCT = 0x213D, + STAT77 = 0x213E, + STAT78 = 0x213F, + APUI00 = 0x2140, + APUI01 = 0x2141, + APUI02 = 0x2142, + APUI03 = 0x2143, + WMDATA = 0x2180, + WMADDL = 0x2181, + WMADDM = 0x2182, + WMADDH = 0x2183, + JOYA = 0x4016, + JOYB = 0x4017, + NMITIMEN = 0x4200, + WRIO = 0x4201, + WRMPYA = 0x4202, + WRMPYB = 0x4203, + WRDIVL = 0x4204, + WRDIVH = 0x4205, + WRDIVB = 0x4206, + HTIMEL = 0x4207, + HTIMEH = 0x4208, + VTIMEL = 0x4209, + VTIMEH = 0x420A, + MDMAEN = 0x420B, + HDMAEN = 0x420C, + MEMSEL = 0x420D, + RDNMI = 0x4210, + TIMEUP = 0x4211, + HVBJOY = 0x4212, + RDIO = 0x4213, + RDDIVL = 0x4214, + RDDIVH = 0x4215, + RDMPYL = 0x4216, + RDMPYH = 0x4217, + JOY1L = 0x4218, + JOY1H = 0x4219, + JOY2L = 0x421A, + JOY2H = 0x421B, + JOY3L = 0x421C, + JOY3H = 0x421D, + JOY4L = 0x421E, + JOY4H = 0x421F, + DMAP0 = 0x4300, + BBAD0 = 0x4301, + A1T0L = 0x4302, + A1T0H = 0x4303, + A1B0 = 0x4304, + DAS0L = 0x4305, + DAS0H = 0x4306, + DAS00 = 0x4307, + A2A0L = 0x4308, + A2A0H = 0x4309, + NTRL0 = 0x430A, + UNUSED0 = 0x430B, + MIRR0 = 0x430F, + DMAP1 = 0x4310, + BBAD1 = 0x4311, + A1T1L = 0x4312, + A1T1H = 0x4313, + A1B1 = 0x4314, + DAS1L = 0x4315, + DAS1H = 0x4316, + DAS10 = 0x4317, + A2A1L = 0x4318, + A2A1H = 0x4319, + NTRL1 = 0x431A, + UNUSED1 = 0x431B, + MIRR1 = 0x431F, + DMAP2 = 0x4320, + BBAD2 = 0x4321, + A1T2L = 0x4322, + A1T2H = 0x4323, + A1B2 = 0x4324, + DAS2L = 0x4325, + DAS2H = 0x4326, + DAS20 = 0x4327, + A2A2L = 0x4328, + A2A2H = 0x4329, + NTRL2 = 0x432A, + UNUSED2 = 0x432B, + MIRR2 = 0x432F, + DMAP3 = 0x4330, + BBAD3 = 0x4331, + A1T3L = 0x4332, + A1T3H = 0x4333, + A1B3 = 0x4334, + DAS3L = 0x4335, + DAS3H = 0x4336, + DAS30 = 0x4337, + A2A3L = 0x4338, + A2A3H = 0x4339, + NTRL3 = 0x433A, + UNUSED3 = 0x433B, + MIRR3 = 0x433F, + DMAP4 = 0x4340, + BBAD4 = 0x4341, + A1T4L = 0x4342, + A1T4H = 0x4343, + A1B4 = 0x4344, + DAS4L = 0x4345, + DAS4H = 0x4346, + DAS40 = 0x4347, + A2A4L = 0x4348, + A2A4H = 0x4349, + NTRL4 = 0x434A, + UNUSED4 = 0x434B, + MIRR4 = 0x434F, + DMAP5 = 0x4350, + BBAD5 = 0x4351, + A1T5L = 0x4352, + A1T5H = 0x4353, + A1B5 = 0x4354, + DAS5L = 0x4355, + DAS5H = 0x4356, + DAS50 = 0x4357, + A2A5L = 0x4358, + A2A5H = 0x4359, + NTRL5 = 0x435A, + UNUSED5 = 0x435B, + MIRR5 = 0x435F, + DMAP6 = 0x4360, + BBAD6 = 0x4361, + A1T6L = 0x4362, + A1T6H = 0x4363, + A1B6 = 0x4364, + DAS6L = 0x4365, + DAS6H = 0x4366, + DAS60 = 0x4367, + A2A6L = 0x4368, + A2A6H = 0x4369, + NTRL6 = 0x436A, + UNUSED6 = 0x436B, + MIRR6 = 0x436F, + DMAP7 = 0x4370, + BBAD7 = 0x4371, + A1T7L = 0x4372, + A1T7H = 0x4373, + A1B7 = 0x4374, + DAS7L = 0x4375, + DAS7H = 0x4376, + DAS70 = 0x4377, + A2A7L = 0x4378, + A2A7H = 0x4379, + NTRL7 = 0x437A, + UNUSED7 = 0x437B, + MIRR7 = 0x437F, +} SnesRegs; + diff --git a/src/snes/apu.c b/src/snes/apu.c new file mode 100644 index 0000000..8dab5cc --- /dev/null +++ b/src/snes/apu.c @@ -0,0 +1,194 @@ + +#include +#include +#include +#include +#include +#include + + +#include "apu.h" +#include "snes.h" +#include "spc.h" +#include "dsp.h" +#include "../tracing.h" + +static const uint8_t bootRom[0x40] = { + 0xcd, 0xef, 0xbd, 0xe8, 0x00, 0xc6, 0x1d, 0xd0, 0xfc, 0x8f, 0xaa, 0xf4, 0x8f, 0xbb, 0xf5, 0x78, + 0xcc, 0xf4, 0xd0, 0xfb, 0x2f, 0x19, 0xeb, 0xf4, 0xd0, 0xfc, 0x7e, 0xf4, 0xd0, 0x0b, 0xe4, 0xf5, + 0xcb, 0xf4, 0xd7, 0x00, 0xfc, 0xd0, 0xf3, 0xab, 0x01, 0x10, 0xef, 0x7e, 0xf4, 0x10, 0xeb, 0xba, + 0xf6, 0xda, 0x00, 0xba, 0xf4, 0xc4, 0xf4, 0xdd, 0x5d, 0xd0, 0xdb, 0x1f, 0x00, 0x00, 0xc0, 0xff +}; + +Apu* apu_init(void) { + Apu* apu = malloc(sizeof(Apu)); + apu->spc = spc_init(apu); + apu->dsp = dsp_init(apu->ram); + return apu; +} + +void apu_free(Apu* apu) { + spc_free(apu->spc); + dsp_free(apu->dsp); + free(apu); +} + +void apu_reset(Apu* apu) { + apu->romReadable = true; // before resetting spc, because it reads reset vector from it + spc_reset(apu->spc); + dsp_reset(apu->dsp); + memset(apu->ram, 0, sizeof(apu->ram)); + apu->dspAdr = 0; + apu->cycles = 0; + memset(apu->inPorts, 0, sizeof(apu->inPorts)); + memset(apu->outPorts, 0, sizeof(apu->outPorts)); + for(int i = 0; i < 3; i++) { + apu->timer[i].cycles = 0; + apu->timer[i].divider = 0; + apu->timer[i].target = 0; + apu->timer[i].counter = 0; + apu->timer[i].enabled = false; + } + apu->cpuCyclesLeft = 7; + apu->hist.count = 0; +} + +void apu_saveload(Apu *apu, SaveLoadFunc *func, void *ctx) { + func(ctx, apu->ram, offsetof(Apu, hist) - offsetof(Apu, ram)); + dsp_saveload(apu->dsp, func, ctx); + spc_saveload(apu->spc, func, ctx); +} + +bool g_debug_apu_cycles; + +void apu_cycle(Apu* apu) { + if(apu->cpuCyclesLeft == 0) { + if (g_debug_apu_cycles) { + char line[80]; + getProcessorStateSpc(apu, line); + puts(line); + } + apu->cpuCyclesLeft = spc_runOpcode(apu->spc); + } + apu->cpuCyclesLeft--; + + if((apu->cycles & 0x1f) == 0) { + // every 32 cycles + dsp_cycle(apu->dsp); + } + + // handle timers + for(int i = 0; i < 3; i++) { + if(apu->timer[i].cycles == 0) { + apu->timer[i].cycles = i == 2 ? 16 : 128; + if(apu->timer[i].enabled) { + apu->timer[i].divider++; + if(apu->timer[i].divider == apu->timer[i].target) { + apu->timer[i].divider = 0; + apu->timer[i].counter++; + apu->timer[i].counter &= 0xf; + } + } + } + apu->timer[i].cycles--; + } + + apu->cycles++; +} + +uint8_t apu_cpuRead(Apu* apu, uint16_t adr) { + switch(adr) { + case 0xf0: + case 0xf1: + case 0xfa: + case 0xfb: + case 0xfc: { + return 0; + } + case 0xf2: { + return apu->dspAdr; + } + case 0xf3: { + return dsp_read(apu->dsp, apu->dspAdr & 0x7f); + } + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + case 0xf8: + case 0xf9: { + return apu->inPorts[adr - 0xf4]; + } + case 0xfd: + case 0xfe: + case 0xff: { + uint8_t ret = apu->timer[adr - 0xfd].counter; + apu->timer[adr - 0xfd].counter = 0; + return ret; + } + } + if(apu->romReadable && adr >= 0xffc0) { + return bootRom[adr - 0xffc0]; + } + return apu->ram[adr]; +} + +void apu_cpuWrite(Apu* apu, uint16_t adr, uint8_t val) { + switch(adr) { + case 0xf0: { + break; // test register + } + case 0xf1: { + for(int i = 0; i < 3; i++) { + if(!apu->timer[i].enabled && (val & (1 << i))) { + apu->timer[i].divider = 0; + apu->timer[i].counter = 0; + } + apu->timer[i].enabled = val & (1 << i); + } + if(val & 0x10) { + apu->inPorts[0] = 0; + apu->inPorts[1] = 0; + } + if(val & 0x20) { + apu->inPorts[2] = 0; + apu->inPorts[3] = 0; + } + apu->romReadable = val & 0x80; + break; + } + case 0xf2: { + apu->dspAdr = val; + break; + } + case 0xf3: { + int i = apu->hist.count; + if (i != 256) { + apu->hist.count = i + 1; + apu->hist.addr[i] = (uint8_t)apu->dspAdr; + apu->hist.val[i] = val; + } + if(apu->dspAdr < 0x80) dsp_write(apu->dsp, apu->dspAdr, val); + break; + } + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: { + apu->outPorts[adr - 0xf4] = val; + break; + } + case 0xf8: + case 0xf9: { + apu->inPorts[adr - 0xf4] = val; + break; + } + case 0xfa: + case 0xfb: + case 0xfc: { + apu->timer[adr - 0xfa].target = val; + break; + } + } + apu->ram[adr] = val; +} diff --git a/src/snes/apu.h b/src/snes/apu.h new file mode 100644 index 0000000..0de4d18 --- /dev/null +++ b/src/snes/apu.h @@ -0,0 +1,50 @@ + +#ifndef APU_H +#define APU_H + +#include +#include +#include +#include +#include + +typedef struct Apu Apu; + +#include "snes.h" +#include "spc.h" +#include "dsp.h" + +typedef struct Timer { + uint8_t cycles; + uint8_t divider; + uint8_t target; + uint8_t counter; + bool enabled; +} Timer; + +struct Apu { + Spc* spc; + Dsp* dsp; + uint8_t ram[0x10000]; + bool romReadable; + uint8_t dspAdr; + uint32_t cycles; + uint8_t inPorts[6]; // includes 2 bytes of ram + uint8_t outPorts[4]; + Timer timer[3]; + uint8_t cpuCyclesLeft; + + union { + struct DspRegWriteHistory hist; + void *padpad; + }; +}; + +Apu* apu_init(); +void apu_free(Apu* apu); +void apu_reset(Apu* apu); +void apu_cycle(Apu* apu); +uint8_t apu_cpuRead(Apu* apu, uint16_t adr); +void apu_cpuWrite(Apu* apu, uint16_t adr, uint8_t val); +void apu_saveload(Apu *apu, SaveLoadFunc *func, void *ctx); +#endif diff --git a/src/snes/cart.c b/src/snes/cart.c new file mode 100644 index 0000000..623f713 --- /dev/null +++ b/src/snes/cart.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include + +#include "cart.h" +#include "snes.h" + +static uint8_t cart_readLorom(Cart* cart, uint8_t bank, uint16_t adr); +static void cart_writeLorom(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val); +static uint8_t cart_readHirom(Cart* cart, uint8_t bank, uint16_t adr); +static void cart_writeHirom(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val); + +Cart* cart_init(Snes* snes) { + Cart* cart = malloc(sizeof(Cart)); + cart->snes = snes; + cart->type = 0; + cart->rom = NULL; + cart->romSize = 0; + cart->ram = NULL; + cart->ramSize = 0; + return cart; +} + +void cart_free(Cart* cart) { + free(cart); +} + +void cart_reset(Cart* cart) { + //if(cart->ramSize > 0 && cart->ram != NULL) memset(cart->ram, 0, cart->ramSize); // for now +} + +void cart_saveload(Cart *cart, SaveLoadFunc *func, void *ctx) { + func(ctx, cart->ram, cart->ramSize); +} + +void cart_load(Cart* cart, int type, uint8_t* rom, int romSize, int ramSize) { + cart->type = type; + if(cart->rom != NULL) free(cart->rom); + if(cart->ram != NULL) free(cart->ram); + cart->rom = malloc(romSize); + cart->romSize = romSize; + if(ramSize > 0) { + cart->ram = malloc(ramSize); + memset(cart->ram, 0, ramSize); + } else { + cart->ram = NULL; + } + cart->ramSize = ramSize; + memcpy(cart->rom, rom, romSize); +} + +uint8_t cart_read(Cart* cart, uint8_t bank, uint16_t adr) { + switch(cart->type) { + case 0: + assert(0); + return cart->snes->openBus; + case 1: return cart_readLorom(cart, bank, adr); + case 2: return cart_readHirom(cart, bank, adr); + } + assert(0); + return cart->snes->openBus; +} + +void cart_write(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val) { + switch(cart->type) { + case 0: break; + case 1: cart_writeLorom(cart, bank, adr, val); break; + case 2: cart_writeHirom(cart, bank, adr, val); break; + } +} + +static uint8_t cart_readLorom(Cart* cart, uint8_t bank, uint16_t adr) { + if(((bank >= 0x70 && bank < 0x7e) || bank >= 0xf0) && adr < 0x8000 && cart->ramSize > 0) { + // banks 70-7e and f0-ff, adr 0000-7fff + return cart->ram[(((bank & 0xf) << 15) | adr) & (cart->ramSize - 1)]; + } + bank &= 0x7f; + if(adr >= 0x8000 || bank >= 0x40) { + // adr 8000-ffff in all banks or all addresses in banks 40-7f and c0-ff + return cart->rom[((bank << 15) | (adr & 0x7fff)) & (cart->romSize - 1)]; + } + assert(0); + return cart->snes->openBus; +} + +static void cart_writeLorom(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val) { + if(((bank >= 0x70 && bank < 0x7e) || bank > 0xf0) && adr < 0x8000 && cart->ramSize > 0) { + // banks 70-7e and f0-ff, adr 0000-7fff + cart->ram[(((bank & 0xf) << 15) | adr) & (cart->ramSize - 1)] = val; + } +} + +static uint8_t cart_readHirom(Cart* cart, uint8_t bank, uint16_t adr) { + bank &= 0x7f; + if(bank < 0x40 && adr >= 0x6000 && adr < 0x8000 && cart->ramSize > 0) { + // banks 00-3f and 80-bf, adr 6000-7fff + return cart->ram[(((bank & 0x3f) << 13) | (adr & 0x1fff)) & (cart->ramSize - 1)]; + } + if(adr >= 0x8000 || bank >= 0x40) { + // adr 8000-ffff in all banks or all addresses in banks 40-7f and c0-ff + return cart->rom[(((bank & 0x3f) << 16) | adr) & (cart->romSize - 1)]; + } + assert(0); + return cart->snes->openBus; +} + +static void cart_writeHirom(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val) { + bank &= 0x7f; + if(bank < 0x40 && adr >= 0x6000 && adr < 0x8000 && cart->ramSize > 0) { + // banks 00-3f and 80-bf, adr 6000-7fff + cart->ram[(((bank & 0x3f) << 13) | (adr & 0x1fff)) & (cart->ramSize - 1)] = val; + } +} diff --git a/src/snes/cart.h b/src/snes/cart.h new file mode 100644 index 0000000..5c9985f --- /dev/null +++ b/src/snes/cart.h @@ -0,0 +1,34 @@ + +#ifndef CART_H +#define CART_H + +#include +#include +#include +#include +#include + +typedef struct Cart Cart; + +#include "snes.h" + +struct Cart { + Snes* snes; + uint8_t type; + + uint8_t* rom; + uint32_t romSize; + uint8_t* ram; + uint32_t ramSize; +}; + +// TODO: how to handle reset & load? (especially where to init ram) + +Cart* cart_init(Snes* snes); +void cart_free(Cart* cart); +void cart_reset(Cart* cart); // will reset special chips etc, general reading is set up in load +void cart_load(Cart* cart, int type, uint8_t* rom, int romSize, int ramSize); // TODO: figure out how to handle (battery, cart-chips etc) +uint8_t cart_read(Cart* cart, uint8_t bank, uint16_t adr); +void cart_write(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val); +void cart_saveload(Cart *cart, SaveLoadFunc *func, void *ctx); +#endif diff --git a/src/snes/cpu.c b/src/snes/cpu.c new file mode 100644 index 0000000..cfd5ffd --- /dev/null +++ b/src/snes/cpu.c @@ -0,0 +1,2356 @@ + +#include +#include +#include +#include +#include +#include +#include +#include "cpu.h" +#include "snes.h" + +static const int cyclesPerOpcode[256] = { + 7, 6, 7, 4, 5, 3, 5, 6, 3, 2, 2, 4, 6, 4, 6, 5, + 2, 5, 5, 7, 5, 4, 6, 6, 2, 4, 2, 2, 6, 4, 7, 5, + 6, 6, 8, 4, 3, 3, 5, 6, 4, 2, 2, 5, 4, 4, 6, 5, + 2, 5, 5, 7, 4, 4, 6, 6, 2, 4, 2, 2, 4, 4, 7, 5, + 6, 6, 2, 4, 7, 3, 5, 6, 3, 2, 2, 3, 3, 4, 6, 5, + 2, 5, 5, 7, 7, 4, 6, 6, 2, 4, 3, 2, 4, 4, 7, 5, + 6, 6, 6, 4, 3, 3, 5, 6, 4, 2, 2, 6, 5, 4, 6, 5, + 2, 5, 5, 7, 4, 4, 6, 6, 2, 4, 4, 2, 6, 4, 7, 5, + 3, 6, 4, 4, 3, 3, 3, 6, 2, 2, 2, 3, 4, 4, 4, 5, + 2, 6, 5, 7, 4, 4, 4, 6, 2, 5, 2, 2, 4, 5, 5, 5, + 2, 6, 2, 4, 3, 3, 3, 6, 2, 2, 2, 4, 4, 4, 4, 5, + 2, 5, 5, 7, 4, 4, 4, 6, 2, 4, 2, 2, 4, 4, 4, 5, + 2, 6, 3, 4, 3, 3, 5, 6, 2, 2, 2, 3, 4, 4, 6, 5, + 2, 5, 5, 7, 6, 4, 6, 6, 2, 4, 3, 3, 6, 4, 7, 5, + 2, 6, 3, 4, 3, 3, 5, 6, 2, 2, 2, 3, 4, 4, 6, 5, + 2, 5, 5, 7, 5, 4, 6, 6, 2, 4, 4, 2, 8, 4, 7, 5 +}; + +static uint8_t cpu_read(Cpu* cpu, uint32_t adr); +static void cpu_write(Cpu* cpu, uint32_t adr, uint8_t val); +static uint8_t cpu_readOpcode(Cpu* cpu); +static uint16_t cpu_readOpcodeWord(Cpu* cpu); +static void cpu_setZN(Cpu* cpu, uint16_t value, bool byte); +static void cpu_doBranch(Cpu* cpu, uint8_t value, bool check); +static uint8_t cpu_pullByte(Cpu* cpu); +static void cpu_pushByte(Cpu* cpu, uint8_t value); +static uint16_t cpu_pullWord(Cpu* cpu); +static void cpu_pushWord(Cpu* cpu, uint16_t value); +static uint16_t cpu_readWord(Cpu* cpu, uint32_t adrl, uint32_t adrh); +static void cpu_writeWord(Cpu* cpu, uint32_t adrl, uint32_t adrh, uint16_t value, bool reversed); +static void cpu_doInterrupt(Cpu* cpu, bool irq); +static void cpu_doOpcode(Cpu* cpu, uint8_t opcode); + +// addressing modes and opcode functions not declared, only used after defintions + +static uint8_t cpu_read(Cpu* cpu, uint32_t adr) { + // assume mem is a pointer to a Snes + return snes_cpuRead((Snes*) cpu->mem, adr); +} + +static void cpu_write(Cpu* cpu, uint32_t adr, uint8_t val) { + // assume mem is a pointer to a Snes + snes_cpuWrite((Snes*) cpu->mem, adr, val); +} + +Cpu* cpu_init(void* mem, int memType) { + Cpu* cpu = malloc(sizeof(Cpu)); + cpu->mem = mem; + cpu->memType = memType; + return cpu; +} + +void cpu_free(Cpu* cpu) { + free(cpu); +} + +void cpu_reset(Cpu* cpu) { + cpu->a = 0; + cpu->x = 0; + cpu->y = 0; + cpu->sp = 0x100; + cpu->pc = cpu_read(cpu, 0xfffc) | (cpu_read(cpu, 0xfffd) << 8); + cpu->dp = 0; + cpu->k = 0; + cpu->db = 0; + cpu->c = false; + cpu->z = false; + cpu->v = false; + cpu->n = false; + cpu->i = true; + cpu->d = false; + cpu->xf = true; + cpu->mf = true; + cpu->e = true; + cpu->irqWanted = false; + cpu->nmiWanted = false; + cpu->waiting = false; + cpu->stopped = false; + cpu->cyclesUsed = 0; +} + +void cpu_saveload(Cpu *cpu, SaveLoadFunc *func, void *ctx) { + func(ctx, &cpu->a, offsetof(Cpu, cyclesUsed) - offsetof(Cpu, a)); + cpu->spBreakpoint = 0x0; +} + +int cpu_runOpcode(Cpu* cpu) { + cpu->cyclesUsed = 0; + if(cpu->stopped) return 1; + + // not stopped or waiting, execute a opcode or go to interrupt + if((!cpu->i && cpu->irqWanted) || cpu->nmiWanted) { + cpu->cyclesUsed = 7; // interrupt: at least 7 cycles + if(cpu->nmiWanted) { + cpu->nmiWanted = false; + cpu_doInterrupt(cpu, false); + } else { + // must be irq + cpu_doInterrupt(cpu, true); + } + } + uint8_t opcode = cpu_readOpcode(cpu); + cpu->cyclesUsed = cyclesPerOpcode[opcode]; + cpu_doOpcode(cpu, opcode); + return cpu->cyclesUsed; +} + +static uint8_t cpu_readOpcode(Cpu* cpu) { + return cpu_read(cpu, (cpu->k << 16) | cpu->pc++); +} + +static uint16_t cpu_readOpcodeWord(Cpu* cpu) { + uint8_t low = cpu_readOpcode(cpu); + return low | (cpu_readOpcode(cpu) << 8); +} + +uint8_t cpu_getFlags(Cpu* cpu) { + uint8_t val = cpu->n << 7; + val |= cpu->v << 6; + val |= cpu->mf << 5; + val |= cpu->xf << 4; + val |= cpu->d << 3; + val |= cpu->i << 2; + val |= cpu->z << 1; + val |= cpu->c; + return val; +} + +void cpu_setFlags(Cpu* cpu, uint8_t val) { + cpu->n = val & 0x80; + cpu->v = val & 0x40; + cpu->mf = val & 0x20; + cpu->xf = val & 0x10; + cpu->d = val & 8; + cpu->i = val & 4; + cpu->z = val & 2; + cpu->c = val & 1; + if(cpu->e) { + cpu->mf = true; + cpu->xf = true; + cpu->sp = (cpu->sp & 0xff) | 0x100; + } + if(cpu->xf) { + cpu->x &= 0xff; + cpu->y &= 0xff; + } +} + +static void cpu_setZN(Cpu* cpu, uint16_t value, bool byte) { + if(byte) { + cpu->z = (value & 0xff) == 0; + cpu->n = value & 0x80; + } else { + cpu->z = value == 0; + cpu->n = value & 0x8000; + } +} + +static void cpu_doBranch(Cpu* cpu, uint8_t value, bool check) { + if(check) { + cpu->cyclesUsed++; // taken branch: 1 extra cycle + cpu->pc += (int8_t) value; + } +} + +static uint8_t cpu_pullByte(Cpu* cpu) { + cpu->sp++; + if(cpu->e) cpu->sp = (cpu->sp & 0xff) | 0x100; + return cpu_read(cpu, cpu->sp); +} + +static void cpu_pushByte(Cpu* cpu, uint8_t value) { + cpu_write(cpu, cpu->sp, value); + cpu->sp--; + if(cpu->e) cpu->sp = (cpu->sp & 0xff) | 0x100; +} + +static uint16_t cpu_pullWord(Cpu* cpu) { + uint8_t value = cpu_pullByte(cpu); + return value | (cpu_pullByte(cpu) << 8); +} + +static void cpu_pushWord(Cpu* cpu, uint16_t value) { + cpu_pushByte(cpu, value >> 8); + cpu_pushByte(cpu, value & 0xff); +} + +static uint16_t cpu_readWord(Cpu* cpu, uint32_t adrl, uint32_t adrh) { + uint8_t value = cpu_read(cpu, adrl); + return value | (cpu_read(cpu, adrh) << 8); +} + +static void cpu_writeWord(Cpu* cpu, uint32_t adrl, uint32_t adrh, uint16_t value, bool reversed) { + if(reversed) { + cpu_write(cpu, adrh, value >> 8); + cpu_write(cpu, adrl, value & 0xff); + } else { + cpu_write(cpu, adrl, value & 0xff); + cpu_write(cpu, adrh, value >> 8); + } +} + +static void cpu_doInterrupt(Cpu* cpu, bool irq) { + cpu_pushByte(cpu, cpu->k); + cpu_pushWord(cpu, cpu->pc); + cpu_pushByte(cpu, cpu_getFlags(cpu)); + cpu->cyclesUsed++; // native mode: 1 extra cycle + cpu->i = true; + cpu->d = false; + cpu->k = 0; + if(irq) { + cpu->pc = cpu_readWord(cpu, 0xffee, 0xffef); + } else { + // nmi + cpu->pc = cpu_readWord(cpu, 0xffea, 0xffeb); + } +} + +// addressing modes + +static uint32_t cpu_adrImm(Cpu* cpu, uint32_t* low, bool xFlag) { + if((xFlag && cpu->xf) || (!xFlag && cpu->mf)) { + *low = (cpu->k << 16) | cpu->pc++; + return 0; + } else { + *low = (cpu->k << 16) | cpu->pc++; + return (cpu->k << 16) | cpu->pc++; + } +} + +static uint32_t cpu_adrDp(Cpu* cpu, uint32_t* low) { + uint8_t adr = cpu_readOpcode(cpu); + if(cpu->dp & 0xff) cpu->cyclesUsed++; // dpr not 0: 1 extra cycle + *low = (cpu->dp + adr) & 0xffff; + return (cpu->dp + adr + 1) & 0xffff; +} + +static uint32_t cpu_adrDpx(Cpu* cpu, uint32_t* low) { + uint8_t adr = cpu_readOpcode(cpu); + if(cpu->dp & 0xff) cpu->cyclesUsed++; // dpr not 0: 1 extra cycle + *low = (cpu->dp + adr + cpu->x) & 0xffff; + return (cpu->dp + adr + cpu->x + 1) & 0xffff; +} + +static uint32_t cpu_adrDpy(Cpu* cpu, uint32_t* low) { + uint8_t adr = cpu_readOpcode(cpu); + if(cpu->dp & 0xff) cpu->cyclesUsed++; // dpr not 0: 1 extra cycle + *low = (cpu->dp + adr + cpu->y) & 0xffff; + return (cpu->dp + adr + cpu->y + 1) & 0xffff; +} + +static uint32_t cpu_adrIdp(Cpu* cpu, uint32_t* low) { + uint8_t adr = cpu_readOpcode(cpu); + if(cpu->dp & 0xff) cpu->cyclesUsed++; // dpr not 0: 1 extra cycle + uint16_t pointer = cpu_readWord(cpu, (cpu->dp + adr) & 0xffff, (cpu->dp + adr + 1) & 0xffff); + *low = (cpu->db << 16) + pointer; + return ((cpu->db << 16) + pointer + 1) & 0xffffff; +} + +static uint32_t cpu_adrIdx(Cpu* cpu, uint32_t* low) { + uint8_t adr = cpu_readOpcode(cpu); + if(cpu->dp & 0xff) cpu->cyclesUsed++; // dpr not 0: 1 extra cycle + uint16_t pointer = cpu_readWord(cpu, (cpu->dp + adr + cpu->x) & 0xffff, (cpu->dp + adr + cpu->x + 1) & 0xffff); + *low = (cpu->db << 16) + pointer; + return ((cpu->db << 16) + pointer + 1) & 0xffffff; +} + +static uint32_t cpu_adrIdy(Cpu* cpu, uint32_t* low, bool write) { + uint8_t adr = cpu_readOpcode(cpu); + if(cpu->dp & 0xff) cpu->cyclesUsed++; // dpr not 0: 1 extra cycle + uint16_t pointer = cpu_readWord(cpu, (cpu->dp + adr) & 0xffff, (cpu->dp + adr + 1) & 0xffff); + if(write && (!cpu->xf || ((pointer >> 8) != ((pointer + cpu->y) >> 8)))) cpu->cyclesUsed++; + // x = 0 or page crossed, with writing opcode: 1 extra cycle + *low = ((cpu->db << 16) + pointer + cpu->y) & 0xffffff; + return ((cpu->db << 16) + pointer + cpu->y + 1) & 0xffffff; +} + +static uint32_t cpu_adrIdl(Cpu* cpu, uint32_t* low) { + uint8_t adr = cpu_readOpcode(cpu); + if(cpu->dp & 0xff) cpu->cyclesUsed++; // dpr not 0: 1 extra cycle + uint32_t pointer = cpu_readWord(cpu, (cpu->dp + adr) & 0xffff, (cpu->dp + adr + 1) & 0xffff); + pointer |= cpu_read(cpu, (cpu->dp + adr + 2) & 0xffff) << 16; + *low = pointer; + return (pointer + 1) & 0xffffff; +} + +static uint32_t cpu_adrIly(Cpu* cpu, uint32_t* low) { + uint8_t adr = cpu_readOpcode(cpu); + if(cpu->dp & 0xff) cpu->cyclesUsed++; // dpr not 0: 1 extra cycle + uint32_t pointer = cpu_readWord(cpu, (cpu->dp + adr) & 0xffff, (cpu->dp + adr + 1) & 0xffff); + pointer |= cpu_read(cpu, (cpu->dp + adr + 2) & 0xffff) << 16; + *low = (pointer + cpu->y) & 0xffffff; + return (pointer + cpu->y + 1) & 0xffffff; +} + +static uint32_t cpu_adrSr(Cpu* cpu, uint32_t* low) { + uint8_t adr = cpu_readOpcode(cpu); + *low = (cpu->sp + adr) & 0xffff; + return (cpu->sp + adr + 1) & 0xffff; +} + +static uint32_t cpu_adrIsy(Cpu* cpu, uint32_t* low) { + uint8_t adr = cpu_readOpcode(cpu); + uint16_t pointer = cpu_readWord(cpu, (cpu->sp + adr) & 0xffff, (cpu->sp + adr + 1) & 0xffff); + *low = ((cpu->db << 16) + pointer + cpu->y) & 0xffffff; + return ((cpu->db << 16) + pointer + cpu->y + 1) & 0xffffff; +} + +static uint32_t cpu_adrAbs(Cpu* cpu, uint32_t* low) { + uint16_t adr = cpu_readOpcodeWord(cpu); + *low = (cpu->db << 16) + adr; + return ((cpu->db << 16) + adr + 1) & 0xffffff; +} + +static uint32_t cpu_adrAbx(Cpu* cpu, uint32_t* low, bool write) { + uint16_t adr = cpu_readOpcodeWord(cpu); + if(write && (!cpu->xf || ((adr >> 8) != ((adr + cpu->x) >> 8)))) cpu->cyclesUsed++; + // x = 0 or page crossed, with writing opcode: 1 extra cycle + *low = ((cpu->db << 16) + adr + cpu->x) & 0xffffff; + return ((cpu->db << 16) + adr + cpu->x + 1) & 0xffffff; +} + +static uint32_t cpu_adrAby(Cpu* cpu, uint32_t* low, bool write) { + uint16_t adr = cpu_readOpcodeWord(cpu); + if(write && (!cpu->xf || ((adr >> 8) != ((adr + cpu->y) >> 8)))) cpu->cyclesUsed++; + // x = 0 or page crossed, with writing opcode: 1 extra cycle + *low = ((cpu->db << 16) + adr + cpu->y) & 0xffffff; + return ((cpu->db << 16) + adr + cpu->y + 1) & 0xffffff; +} + +static uint32_t cpu_adrAbl(Cpu* cpu, uint32_t* low) { + uint32_t adr = cpu_readOpcodeWord(cpu); + adr |= cpu_readOpcode(cpu) << 16; + *low = adr; + return (adr + 1) & 0xffffff; +} + +static uint32_t cpu_adrAlx(Cpu* cpu, uint32_t* low) { + uint32_t adr = cpu_readOpcodeWord(cpu); + adr |= cpu_readOpcode(cpu) << 16; + *low = (adr + cpu->x) & 0xffffff; + return (adr + cpu->x + 1) & 0xffffff; +} + +static uint16_t cpu_adrIax(Cpu* cpu) { + uint16_t adr = cpu_readOpcodeWord(cpu); + return cpu_readWord(cpu, (cpu->k << 16) | ((adr + cpu->x) & 0xffff), (cpu->k << 16) | ((adr + cpu->x + 1) & 0xffff)); +} + +// opcode functions + +static void cpu_and(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low); + cpu->a = (cpu->a & 0xff00) | ((cpu->a & value) & 0xff); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + uint16_t value = cpu_readWord(cpu, low, high); + cpu->a &= value; + } + cpu_setZN(cpu, cpu->a, cpu->mf); +} + +static void cpu_ora(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low); + cpu->a = (cpu->a & 0xff00) | ((cpu->a | value) & 0xff); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + uint16_t value = cpu_readWord(cpu, low, high); + cpu->a |= value; + } + cpu_setZN(cpu, cpu->a, cpu->mf); +} + +static void cpu_eor(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low); + cpu->a = (cpu->a & 0xff00) | ((cpu->a ^ value) & 0xff); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + uint16_t value = cpu_readWord(cpu, low, high); + cpu->a ^= value; + } + cpu_setZN(cpu, cpu->a, cpu->mf); +} + +static void cpu_adc(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low); + int result = 0; + if(cpu->d) { + result = (cpu->a & 0xf) + (value & 0xf) + cpu->c; + if(result > 0x9) result = ((result + 0x6) & 0xf) + 0x10; + result = (cpu->a & 0xf0) + (value & 0xf0) + result; + } else { + result = (cpu->a & 0xff) + value + cpu->c; + } + cpu->v = (cpu->a & 0x80) == (value & 0x80) && (value & 0x80) != (result & 0x80); + if(cpu->d && result > 0x9f) result += 0x60; + cpu->c = result > 0xff; + cpu->a = (cpu->a & 0xff00) | (result & 0xff); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + uint16_t value = cpu_readWord(cpu, low, high); + int result = 0; + if(cpu->d) { + result = (cpu->a & 0xf) + (value & 0xf) + cpu->c; + if(result > 0x9) result = ((result + 0x6) & 0xf) + 0x10; + result = (cpu->a & 0xf0) + (value & 0xf0) + result; + if(result > 0x9f) result = ((result + 0x60) & 0xff) + 0x100; + result = (cpu->a & 0xf00) + (value & 0xf00) + result; + if(result > 0x9ff) result = ((result + 0x600) & 0xfff) + 0x1000; + result = (cpu->a & 0xf000) + (value & 0xf000) + result; + } else { + result = cpu->a + value + cpu->c; + } + cpu->v = (cpu->a & 0x8000) == (value & 0x8000) && (value & 0x8000) != (result & 0x8000); + if(cpu->d && result > 0x9fff) result += 0x6000; + cpu->c = result > 0xffff; + cpu->a = result; + } + cpu_setZN(cpu, cpu->a, cpu->mf); +} + +static void cpu_sbc(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low) ^ 0xff; + int result = 0; + if(cpu->d) { + result = (cpu->a & 0xf) + (value & 0xf) + cpu->c; + if(result < 0x10) result = (result - 0x6) & ((result - 0x6 < 0) ? 0xf : 0x1f); + result = (cpu->a & 0xf0) + (value & 0xf0) + result; + } else { + result = (cpu->a & 0xff) + value + cpu->c; + } + cpu->v = (cpu->a & 0x80) == (value & 0x80) && (value & 0x80) != (result & 0x80); + if(cpu->d && result < 0x100) result -= 0x60; + cpu->c = result > 0xff; + cpu->a = (cpu->a & 0xff00) | (result & 0xff); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + uint16_t value = cpu_readWord(cpu, low, high) ^ 0xffff; + int result = 0; + if(cpu->d) { + result = (cpu->a & 0xf) + (value & 0xf) + cpu->c; + if(result < 0x10) result = (result - 0x6) & ((result - 0x6 < 0) ? 0xf : 0x1f); + result = (cpu->a & 0xf0) + (value & 0xf0) + result; + if(result < 0x100) result = (result - 0x60) & ((result - 0x60 < 0) ? 0xff : 0x1ff); + result = (cpu->a & 0xf00) + (value & 0xf00) + result; + if(result < 0x1000) result = (result - 0x600) & ((result - 0x600 < 0) ? 0xfff : 0x1fff); + result = (cpu->a & 0xf000) + (value & 0xf000) + result; + } else { + result = cpu->a + value + cpu->c; + } + cpu->v = (cpu->a & 0x8000) == (value & 0x8000) && (value & 0x8000) != (result & 0x8000); + if(cpu->d && result < 0x10000) result -= 0x6000; + cpu->c = result > 0xffff; + cpu->a = result; + } + cpu_setZN(cpu, cpu->a, cpu->mf); +} + +static void cpu_cmp(Cpu* cpu, uint32_t low, uint32_t high) { + int result = 0; + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low) ^ 0xff; + result = (cpu->a & 0xff) + value + 1; + cpu->c = result > 0xff; + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + uint16_t value = cpu_readWord(cpu, low, high) ^ 0xffff; + result = cpu->a + value + 1; + cpu->c = result > 0xffff; + } + cpu_setZN(cpu, result, cpu->mf); +} + +static void cpu_cpx(Cpu* cpu, uint32_t low, uint32_t high) { + int result = 0; + if(cpu->xf) { + uint8_t value = cpu_read(cpu, low) ^ 0xff; + result = (cpu->x & 0xff) + value + 1; + cpu->c = result > 0xff; + } else { + cpu->cyclesUsed++; // x = 0: 1 extra cycle + uint16_t value = cpu_readWord(cpu, low, high) ^ 0xffff; + result = cpu->x + value + 1; + cpu->c = result > 0xffff; + } + cpu_setZN(cpu, result, cpu->xf); +} + +static void cpu_cpy(Cpu* cpu, uint32_t low, uint32_t high) { + int result = 0; + if(cpu->xf) { + uint8_t value = cpu_read(cpu, low) ^ 0xff; + result = (cpu->y & 0xff) + value + 1; + cpu->c = result > 0xff; + } else { + cpu->cyclesUsed++; // x = 0: 1 extra cycle + uint16_t value = cpu_readWord(cpu, low, high) ^ 0xffff; + result = cpu->y + value + 1; + cpu->c = result > 0xffff; + } + cpu_setZN(cpu, result, cpu->xf); +} + +static void cpu_bit(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low); + uint8_t result = (cpu->a & 0xff) & value; + cpu->z = result == 0; + cpu->n = value & 0x80; + cpu->v = value & 0x40; + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + uint16_t value = cpu_readWord(cpu, low, high); + uint16_t result = cpu->a & value; + cpu->z = result == 0; + cpu->n = value & 0x8000; + cpu->v = value & 0x4000; + } +} + +static void cpu_lda(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + cpu->a = (cpu->a & 0xff00) | cpu_read(cpu, low); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + cpu->a = cpu_readWord(cpu, low, high); + } + cpu_setZN(cpu, cpu->a, cpu->mf); +} + +static void cpu_ldx(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->xf) { + cpu->x = cpu_read(cpu, low); + } else { + cpu->cyclesUsed++; // x = 0: 1 extra cycle + cpu->x = cpu_readWord(cpu, low, high); + } + cpu_setZN(cpu, cpu->x, cpu->xf); +} + +static void cpu_ldy(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->xf) { + cpu->y = cpu_read(cpu, low); + } else { + cpu->cyclesUsed++; // x = 0: 1 extra cycle + cpu->y = cpu_readWord(cpu, low, high); + } + cpu_setZN(cpu, cpu->y, cpu->xf); +} + +static void cpu_sta(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + cpu_write(cpu, low, (uint8_t)cpu->a); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + cpu_writeWord(cpu, low, high, cpu->a, false); + } +} + +static void cpu_stx(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->xf) { + cpu_write(cpu, low, (uint8_t)cpu->x); + } else { + cpu->cyclesUsed++; // x = 0: 1 extra cycle + cpu_writeWord(cpu, low, high, cpu->x, false); + } +} + +static void cpu_sty(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->xf) { + cpu_write(cpu, low, (uint8_t)cpu->y); + } else { + cpu->cyclesUsed++; // x = 0: 1 extra cycle + cpu_writeWord(cpu, low, high, cpu->y, false); + } +} + +static void cpu_stz(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + cpu_write(cpu, low, 0); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + cpu_writeWord(cpu, low, high, 0, false); + } +} + +static void cpu_ror(Cpu* cpu, uint32_t low, uint32_t high) { + bool carry = false; + int result = 0; + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low); + carry = value & 1; + result = (value >> 1) | (cpu->c << 7); + cpu_write(cpu, low, result); + } else { + cpu->cyclesUsed += 2; // m = 0: 2 extra cycles + uint16_t value = cpu_readWord(cpu, low, high); + carry = value & 1; + result = (value >> 1) | (cpu->c << 15); + cpu_writeWord(cpu, low, high, result, true); + } + cpu_setZN(cpu, result, cpu->mf); + cpu->c = carry; +} + +static void cpu_rol(Cpu* cpu, uint32_t low, uint32_t high) { + int result = 0; + if(cpu->mf) { + result = (cpu_read(cpu, low) << 1) | cpu->c; + cpu->c = result & 0x100; + cpu_write(cpu, low, result); + } else { + cpu->cyclesUsed += 2; // m = 0: 2 extra cycles + result = (cpu_readWord(cpu, low, high) << 1) | cpu->c; + cpu->c = result & 0x10000; + cpu_writeWord(cpu, low, high, result, true); + } + cpu_setZN(cpu, result, cpu->mf); +} + +static void cpu_lsr(Cpu* cpu, uint32_t low, uint32_t high) { + int result = 0; + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low); + cpu->c = value & 1; + result = value >> 1; + cpu_write(cpu, low, result); + } else { + cpu->cyclesUsed += 2; // m = 0: 2 extra cycles + uint16_t value = cpu_readWord(cpu, low, high); + cpu->c = value & 1; + result = value >> 1; + cpu_writeWord(cpu, low, high, result, true); + } + cpu_setZN(cpu, result, cpu->mf); +} + +static void cpu_asl(Cpu* cpu, uint32_t low, uint32_t high) { + int result = 0; + if(cpu->mf) { + result = cpu_read(cpu, low) << 1; + cpu->c = result & 0x100; + cpu_write(cpu, low, result); + } else { + cpu->cyclesUsed += 2; // m = 0: 2 extra cycles + result = cpu_readWord(cpu, low, high) << 1; + cpu->c = result & 0x10000; + cpu_writeWord(cpu, low, high, result, true); + } + cpu_setZN(cpu, result, cpu->mf); +} + +static void cpu_inc(Cpu* cpu, uint32_t low, uint32_t high) { + int result = 0; + if(cpu->mf) { + result = cpu_read(cpu, low) + 1; + cpu_write(cpu, low, result); + } else { + cpu->cyclesUsed += 2; // m = 0: 2 extra cycles + result = cpu_readWord(cpu, low, high) + 1; + cpu_writeWord(cpu, low, high, result, true); + } + cpu_setZN(cpu, result, cpu->mf); +} + +static void cpu_dec(Cpu* cpu, uint32_t low, uint32_t high) { + int result = 0; + if(cpu->mf) { + result = cpu_read(cpu, low) - 1; + cpu_write(cpu, low, result); + } else { + cpu->cyclesUsed += 2; // m = 0: 2 extra cycles + result = cpu_readWord(cpu, low, high) - 1; + cpu_writeWord(cpu, low, high, result, true); + } + cpu_setZN(cpu, result, cpu->mf); +} + +static void cpu_tsb(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low); + cpu->z = ((cpu->a & 0xff) & value) == 0; + cpu_write(cpu, low, value | (cpu->a & 0xff)); + } else { + cpu->cyclesUsed += 2; // m = 0: 2 extra cycles + uint16_t value = cpu_readWord(cpu, low, high); + cpu->z = (cpu->a & value) == 0; + cpu_writeWord(cpu, low, high, value | cpu->a, true); + } +} + +static void cpu_trb(Cpu* cpu, uint32_t low, uint32_t high) { + if(cpu->mf) { + uint8_t value = cpu_read(cpu, low); + cpu->z = ((cpu->a & 0xff) & value) == 0; + cpu_write(cpu, low, value & ~(cpu->a & 0xff)); + } else { + cpu->cyclesUsed += 2; // m = 0: 2 extra cycles + uint16_t value = cpu_readWord(cpu, low, high); + cpu->z = (cpu->a & value) == 0; + cpu_writeWord(cpu, low, high, value & ~cpu->a, true); + } +} + + +int CpuOpcodeHook(uint32_t addr); + +uint32_t pc_hist[8], pc_hist_ctr; + +uint32_t pc_bp = 0x828A55; + +static void cpu_doOpcode(Cpu* cpu, uint8_t opcode) { + pc_hist[pc_hist_ctr] = cpu->k << 16 | cpu->pc; + pc_hist_ctr = (pc_hist_ctr + 1) & 7; + if (cpu->pc == 0x910b) { + opcode += 0; + } + if (((cpu->k << 16) | cpu->pc - 1) == pc_bp) { + opcode += 0; + } +restart: + switch(opcode) { + case 0x00: { // brk imp + uint32_t addr = (cpu->k << 16) | cpu->pc | 0x800000; + switch (opcode = CpuOpcodeHook(addr - 1)) { + case 0: + break; + case 1: // rts + cpu->pc = cpu_pullWord(cpu) + 1; + break; + case 2: // rtl + cpu->pc = cpu_pullWord(cpu) + 1; + cpu->k = cpu_pullByte(cpu); + break; + case 0xe5: + case 0xed: cpu->c = 1; goto restart; + case 0x65: + case 0x6d: + case 0x69: + case 0x7d: cpu->c = 0; goto restart; + default: +// printf("Unk op 0x%x!\n", opcode); + goto restart; + } + break; + } + case 0x01: { // ora idx + uint32_t low = 0; + uint32_t high = cpu_adrIdx(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x02: { // cop imm(s) + cpu_readOpcode(cpu); + cpu_pushByte(cpu, cpu->k); + cpu_pushWord(cpu, cpu->pc); + cpu_pushByte(cpu, cpu_getFlags(cpu)); + cpu->cyclesUsed++; // native mode: 1 extra cycle + cpu->i = true; + cpu->d = false; + cpu->k = 0; + cpu->pc = cpu_readWord(cpu, 0xffe4, 0xffe5); + break; + } + case 0x03: { // ora sr + uint32_t low = 0; + uint32_t high = cpu_adrSr(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x04: { // tsb dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_tsb(cpu, low, high); + break; + } + case 0x05: { // ora dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x06: { // asl dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_asl(cpu, low, high); + break; + } + case 0x07: { // ora idl + uint32_t low = 0; + uint32_t high = cpu_adrIdl(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x08: { // php imp + cpu_pushByte(cpu, cpu_getFlags(cpu)); + break; + } + case 0x09: { // ora imm(m) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, false); + cpu_ora(cpu, low, high); + break; + } + case 0x0a: { // asla imp + if(cpu->mf) { + cpu->c = cpu->a & 0x80; + cpu->a = (cpu->a & 0xff00) | ((cpu->a << 1) & 0xff); + } else { + cpu->c = cpu->a & 0x8000; + cpu->a <<= 1; + } + cpu_setZN(cpu, cpu->a, cpu->mf); + break; + } + case 0x0b: { // phd imp + cpu_pushWord(cpu, cpu->dp); + break; + } + case 0x0c: { // tsb abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_tsb(cpu, low, high); + break; + } + case 0x0d: { // ora abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x0e: { // asl abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_asl(cpu, low, high); + break; + } + case 0x0f: { // ora abl + uint32_t low = 0; + uint32_t high = cpu_adrAbl(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x10: { // bpl rel + cpu_doBranch(cpu, cpu_readOpcode(cpu), !cpu->n); + break; + } + case 0x11: { // ora idy(r) + uint32_t low = 0; + uint32_t high = cpu_adrIdy(cpu, &low, false); + cpu_ora(cpu, low, high); + break; + } + case 0x12: { // ora idp + uint32_t low = 0; + uint32_t high = cpu_adrIdp(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x13: { // ora isy + uint32_t low = 0; + uint32_t high = cpu_adrIsy(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x14: { // trb dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_trb(cpu, low, high); + break; + } + case 0x15: { // ora dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x16: { // asl dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_asl(cpu, low, high); + break; + } + case 0x17: { // ora ily + uint32_t low = 0; + uint32_t high = cpu_adrIly(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x18: { // clc imp + cpu->c = false; + break; + } + case 0x19: { // ora aby(r) + uint32_t low = 0; + uint32_t high = cpu_adrAby(cpu, &low, false); + cpu_ora(cpu, low, high); + break; + } + case 0x1a: { // inca imp + if(cpu->mf) { + cpu->a = (cpu->a & 0xff00) | ((cpu->a + 1) & 0xff); + } else { + cpu->a++; + } + cpu_setZN(cpu, cpu->a, cpu->mf); + break; + } + case 0x1b: { // tcs imp + cpu->sp = cpu->a; + break; + } + case 0x1c: { // trb abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_trb(cpu, low, high); + break; + } + case 0x1d: { // ora abx(r) + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, false); + cpu_ora(cpu, low, high); + break; + } + case 0x1e: { // asl abx + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, true); + cpu_asl(cpu, low, high); + break; + } + case 0x1f: { // ora alx + uint32_t low = 0; + uint32_t high = cpu_adrAlx(cpu, &low); + cpu_ora(cpu, low, high); + break; + } + case 0x20: { // jsr abs + uint16_t value = cpu_readOpcodeWord(cpu); + cpu_pushWord(cpu, cpu->pc - 1); + cpu->pc = value; + break; + } + case 0x21: { // and idx + uint32_t low = 0; + uint32_t high = cpu_adrIdx(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x22: { // jsl abl + uint16_t value = cpu_readOpcodeWord(cpu); + uint8_t newK = cpu_readOpcode(cpu); + cpu_pushByte(cpu, cpu->k); + cpu_pushWord(cpu, cpu->pc - 1); + cpu->pc = value; + cpu->k = newK; + break; + } + case 0x23: { // and sr + uint32_t low = 0; + uint32_t high = cpu_adrSr(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x24: { // bit dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_bit(cpu, low, high); + break; + } + case 0x25: { // and dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x26: { // rol dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_rol(cpu, low, high); + break; + } + case 0x27: { // and idl + uint32_t low = 0; + uint32_t high = cpu_adrIdl(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x28: { // plp imp + cpu_setFlags(cpu, cpu_pullByte(cpu)); + break; + } + case 0x29: { // and imm(m) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, false); + cpu_and(cpu, low, high); + break; + } + case 0x2a: { // rola imp + int result = (cpu->a << 1) | cpu->c; + if(cpu->mf) { + cpu->c = result & 0x100; + cpu->a = (cpu->a & 0xff00) | (result & 0xff); + } else { + cpu->c = result & 0x10000; + cpu->a = result; + } + cpu_setZN(cpu, cpu->a, cpu->mf); + break; + } + case 0x2b: { // pld imp + cpu->dp = cpu_pullWord(cpu); + cpu_setZN(cpu, cpu->dp, false); + break; + } + case 0x2c: { // bit abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_bit(cpu, low, high); + break; + } + case 0x2d: { // and abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x2e: { // rol abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_rol(cpu, low, high); + break; + } + case 0x2f: { // and abl + uint32_t low = 0; + uint32_t high = cpu_adrAbl(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x30: { // bmi rel + cpu_doBranch(cpu, cpu_readOpcode(cpu), cpu->n); + break; + } + case 0x31: { // and idy(r) + uint32_t low = 0; + uint32_t high = cpu_adrIdy(cpu, &low, false); + cpu_and(cpu, low, high); + break; + } + case 0x32: { // and idp + uint32_t low = 0; + uint32_t high = cpu_adrIdp(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x33: { // and isy + uint32_t low = 0; + uint32_t high = cpu_adrIsy(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x34: { // bit dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_bit(cpu, low, high); + break; + } + case 0x35: { // and dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x36: { // rol dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_rol(cpu, low, high); + break; + } + case 0x37: { // and ily + uint32_t low = 0; + uint32_t high = cpu_adrIly(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x38: { // sec imp + cpu->c = true; + break; + } + case 0x39: { // and aby(r) + uint32_t low = 0; + uint32_t high = cpu_adrAby(cpu, &low, false); + cpu_and(cpu, low, high); + break; + } + case 0x3a: { // deca imp + if(cpu->mf) { + cpu->a = (cpu->a & 0xff00) | ((cpu->a - 1) & 0xff); + } else { + cpu->a--; + } + cpu_setZN(cpu, cpu->a, cpu->mf); + break; + } + case 0x3b: { // tsc imp + cpu->a = cpu->sp; + cpu_setZN(cpu, cpu->a, false); + break; + } + case 0x3c: { // bit abx(r) + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, false); + cpu_bit(cpu, low, high); + break; + } + case 0x3d: { // and abx(r) + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, false); + cpu_and(cpu, low, high); + break; + } + case 0x3e: { // rol abx + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, true); + cpu_rol(cpu, low, high); + break; + } + case 0x3f: { // and alx + uint32_t low = 0; + uint32_t high = cpu_adrAlx(cpu, &low); + cpu_and(cpu, low, high); + break; + } + case 0x40: { // rti imp + cpu_setFlags(cpu, cpu_pullByte(cpu)); + cpu->cyclesUsed++; // native mode: 1 extra cycle + cpu->pc = cpu_pullWord(cpu); + cpu->k = cpu_pullByte(cpu); + break; + } + case 0x41: { // eor idx + uint32_t low = 0; + uint32_t high = cpu_adrIdx(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x42: { // wdm imm(s) + cpu_readOpcode(cpu); + break; + } + case 0x43: { // eor sr + uint32_t low = 0; + uint32_t high = cpu_adrSr(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x44: { // mvp bm + uint8_t dest = cpu_readOpcode(cpu); + uint8_t src = cpu_readOpcode(cpu); + cpu->db = dest; + cpu_write(cpu, (dest << 16) | cpu->y, cpu_read(cpu, (src << 16) | cpu->x)); + cpu->a--; + cpu->x--; + cpu->y--; + if(cpu->a != 0xffff) { + cpu->pc -= 3; + } + if(cpu->xf) { + cpu->x &= 0xff; + cpu->y &= 0xff; + } + break; + } + case 0x45: { // eor dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x46: { // lsr dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_lsr(cpu, low, high); + break; + } + case 0x47: { // eor idl + uint32_t low = 0; + uint32_t high = cpu_adrIdl(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x48: { // pha imp + if(cpu->mf) { + cpu_pushByte(cpu, (uint8_t)cpu->a); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + cpu_pushWord(cpu, cpu->a); + } + break; + } + case 0x49: { // eor imm(m) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, false); + cpu_eor(cpu, low, high); + break; + } + case 0x4a: { // lsra imp + cpu->c = cpu->a & 1; + if(cpu->mf) { + cpu->a = (cpu->a & 0xff00) | ((cpu->a >> 1) & 0x7f); + } else { + cpu->a >>= 1; + } + cpu_setZN(cpu, cpu->a, cpu->mf); + break; + } + case 0x4b: { // phk imp + cpu_pushByte(cpu, cpu->k); + break; + } + case 0x4c: { // jmp abs + cpu->pc = cpu_readOpcodeWord(cpu); + break; + } + case 0x4d: { // eor abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x4e: { // lsr abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_lsr(cpu, low, high); + break; + } + case 0x4f: { // eor abl + uint32_t low = 0; + uint32_t high = cpu_adrAbl(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x50: { // bvc rel + cpu_doBranch(cpu, cpu_readOpcode(cpu), !cpu->v); + break; + } + case 0x51: { // eor idy(r) + uint32_t low = 0; + uint32_t high = cpu_adrIdy(cpu, &low, false); + cpu_eor(cpu, low, high); + break; + } + case 0x52: { // eor idp + uint32_t low = 0; + uint32_t high = cpu_adrIdp(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x53: { // eor isy + uint32_t low = 0; + uint32_t high = cpu_adrIsy(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x54: { // mvn bm + uint8_t dest = cpu_readOpcode(cpu); + uint8_t src = cpu_readOpcode(cpu); + cpu->db = dest; + cpu_write(cpu, (dest << 16) | cpu->y, cpu_read(cpu, (src << 16) | cpu->x)); + cpu->a--; + cpu->x++; + cpu->y++; + if(cpu->a != 0xffff) { + cpu->pc -= 3; + } + if(cpu->xf) { + cpu->x &= 0xff; + cpu->y &= 0xff; + } + break; + } + case 0x55: { // eor dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x56: { // lsr dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_lsr(cpu, low, high); + break; + } + case 0x57: { // eor ily + uint32_t low = 0; + uint32_t high = cpu_adrIly(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x58: { // cli imp + cpu->i = false; + break; + } + case 0x59: { // eor aby(r) + uint32_t low = 0; + uint32_t high = cpu_adrAby(cpu, &low, false); + cpu_eor(cpu, low, high); + break; + } + case 0x5a: { // phy imp + if(cpu->xf) { + cpu_pushByte(cpu, (uint8_t)cpu->y); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + cpu_pushWord(cpu, cpu->y); + } + break; + } + case 0x5b: { // tcd imp + cpu->dp = cpu->a; + cpu_setZN(cpu, cpu->dp, false); + break; + } + case 0x5c: { // jml abl + uint16_t value = cpu_readOpcodeWord(cpu); + cpu->k = cpu_readOpcode(cpu); + cpu->pc = value; + break; + } + case 0x5d: { // eor abx(r) + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, false); + cpu_eor(cpu, low, high); + break; + } + case 0x5e: { // lsr abx + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, true); + cpu_lsr(cpu, low, high); + break; + } + case 0x5f: { // eor alx + uint32_t low = 0; + uint32_t high = cpu_adrAlx(cpu, &low); + cpu_eor(cpu, low, high); + break; + } + case 0x60: { // rts imp + if (cpu->sp >= cpu->spBreakpoint && cpu->spBreakpoint) { + int delta = cpu->sp - cpu->spBreakpoint; + assert(delta == 0 || delta == 2); + cpu->spBreakpoint = 0; + if (HookedFunctionRts(delta == 2)) + return; + } + cpu->pc = cpu_pullWord(cpu) + 1; + break; + } + case 0x61: { // adc idx + uint32_t low = 0; + uint32_t high = cpu_adrIdx(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x62: { // per rll + uint16_t value = cpu_readOpcodeWord(cpu); + cpu_pushWord(cpu, cpu->pc + (int16_t) value); + break; + } + case 0x63: { // adc sr + uint32_t low = 0; + uint32_t high = cpu_adrSr(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x64: { // stz dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_stz(cpu, low, high); + break; + } + case 0x65: { // adc dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x66: { // ror dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_ror(cpu, low, high); + break; + } + case 0x67: { // adc idl + uint32_t low = 0; + uint32_t high = cpu_adrIdl(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x68: { // pla imp + if(cpu->mf) { + cpu->a = (cpu->a & 0xff00) | cpu_pullByte(cpu); + } else { + cpu->cyclesUsed++; // 16-bit m: 1 extra cycle + cpu->a = cpu_pullWord(cpu); + } + cpu_setZN(cpu, cpu->a, cpu->mf); + break; + } + case 0x69: { // adc imm(m) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, false); + cpu_adc(cpu, low, high); + break; + } + case 0x6a: { // rora imp + bool carry = cpu->a & 1; + if(cpu->mf) { + cpu->a = (cpu->a & 0xff00) | ((cpu->a >> 1) & 0x7f) | (cpu->c << 7); + } else { + cpu->a = (cpu->a >> 1) | (cpu->c << 15); + } + cpu->c = carry; + cpu_setZN(cpu, cpu->a, cpu->mf); + break; + } + case 0x6b: { // rtl imp + if (cpu->sp >= cpu->spBreakpoint && cpu->spBreakpoint) { + assert(cpu->sp == cpu->spBreakpoint); + cpu->spBreakpoint = 0; + if (HookedFunctionRts(0)) + return; + } + + cpu->pc = cpu_pullWord(cpu) + 1; + cpu->k = cpu_pullByte(cpu); + break; + } + case 0x6c: { // jmp ind + uint16_t adr = cpu_readOpcodeWord(cpu); + cpu->pc = cpu_readWord(cpu, adr, (adr + 1) & 0xffff); + break; + } + case 0x6d: { // adc abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x6e: { // ror abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_ror(cpu, low, high); + break; + } + case 0x6f: { // adc abl + uint32_t low = 0; + uint32_t high = cpu_adrAbl(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x70: { // bvs rel + cpu_doBranch(cpu, cpu_readOpcode(cpu), cpu->v); + break; + } + case 0x71: { // adc idy(r) + uint32_t low = 0; + uint32_t high = cpu_adrIdy(cpu, &low, false); + cpu_adc(cpu, low, high); + break; + } + case 0x72: { // adc idp + uint32_t low = 0; + uint32_t high = cpu_adrIdp(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x73: { // adc isy + uint32_t low = 0; + uint32_t high = cpu_adrIsy(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x74: { // stz dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_stz(cpu, low, high); + break; + } + case 0x75: { // adc dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x76: { // ror dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_ror(cpu, low, high); + break; + } + case 0x77: { // adc ily + uint32_t low = 0; + uint32_t high = cpu_adrIly(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x78: { // sei imp + cpu->i = true; + break; + } + case 0x79: { // adc aby(r) + uint32_t low = 0; + uint32_t high = cpu_adrAby(cpu, &low, false); + cpu_adc(cpu, low, high); + break; + } + case 0x7a: { // ply imp + if(cpu->xf) { + cpu->y = cpu_pullByte(cpu); + } else { + cpu->cyclesUsed++; // 16-bit x: 1 extra cycle + cpu->y = cpu_pullWord(cpu); + } + cpu_setZN(cpu, cpu->y, cpu->xf); + break; + } + case 0x7b: { // tdc imp + cpu->a = cpu->dp; + cpu_setZN(cpu, cpu->a, false); + break; + } + case 0x7c: { // jmp iax + cpu->pc = cpu_adrIax(cpu); + break; + } + case 0x7d: { // adc abx(r) + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, false); + cpu_adc(cpu, low, high); + break; + } + case 0x7e: { // ror abx + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, true); + cpu_ror(cpu, low, high); + break; + } + case 0x7f: { // adc alx + uint32_t low = 0; + uint32_t high = cpu_adrAlx(cpu, &low); + cpu_adc(cpu, low, high); + break; + } + case 0x80: { // bra rel + cpu->pc += (int8_t) cpu_readOpcode(cpu); + break; + } + case 0x81: { // sta idx + uint32_t low = 0; + uint32_t high = cpu_adrIdx(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0x82: { // brl rll + cpu->pc += (int16_t) cpu_readOpcodeWord(cpu); + break; + } + case 0x83: { // sta sr + uint32_t low = 0; + uint32_t high = cpu_adrSr(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0x84: { // sty dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_sty(cpu, low, high); + break; + } + case 0x85: { // sta dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0x86: { // stx dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_stx(cpu, low, high); + break; + } + case 0x87: { // sta idl + uint32_t low = 0; + uint32_t high = cpu_adrIdl(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0x88: { // dey imp + if(cpu->xf) { + cpu->y = (cpu->y - 1) & 0xff; + } else { + cpu->y--; + } + cpu_setZN(cpu, cpu->y, cpu->xf); + break; + } + case 0x89: { // biti imm(m) + if(cpu->mf) { + uint8_t result = (cpu->a & 0xff) & cpu_readOpcode(cpu); + cpu->z = result == 0; + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + uint16_t result = cpu->a & cpu_readOpcodeWord(cpu); + cpu->z = result == 0; + } + break; + } + case 0x8a: { // txa imp + if(cpu->mf) { + cpu->a = (cpu->a & 0xff00) | (cpu->x & 0xff); + } else { + cpu->a = cpu->x; + } + cpu_setZN(cpu, cpu->a, cpu->mf); + break; + } + case 0x8b: { // phb imp + cpu_pushByte(cpu, cpu->db); + break; + } + case 0x8c: { // sty abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_sty(cpu, low, high); + break; + } + case 0x8d: { // sta abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0x8e: { // stx abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_stx(cpu, low, high); + break; + } + case 0x8f: { // sta abl + uint32_t low = 0; + uint32_t high = cpu_adrAbl(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0x90: { // bcc rel + cpu_doBranch(cpu, cpu_readOpcode(cpu), !cpu->c); + break; + } + case 0x91: { // sta idy + uint32_t low = 0; + uint32_t high = cpu_adrIdy(cpu, &low, true); + cpu_sta(cpu, low, high); + break; + } + case 0x92: { // sta idp + uint32_t low = 0; + uint32_t high = cpu_adrIdp(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0x93: { // sta isy + uint32_t low = 0; + uint32_t high = cpu_adrIsy(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0x94: { // sty dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_sty(cpu, low, high); + break; + } + case 0x95: { // sta dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0x96: { // stx dpy + uint32_t low = 0; + uint32_t high = cpu_adrDpy(cpu, &low); + cpu_stx(cpu, low, high); + break; + } + case 0x97: { // sta ily + uint32_t low = 0; + uint32_t high = cpu_adrIly(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0x98: { // tya imp + if(cpu->mf) { + cpu->a = (cpu->a & 0xff00) | (cpu->y & 0xff); + } else { + cpu->a = cpu->y; + } + cpu_setZN(cpu, cpu->a, cpu->mf); + break; + } + case 0x99: { // sta aby + uint32_t low = 0; + uint32_t high = cpu_adrAby(cpu, &low, true); + cpu_sta(cpu, low, high); + break; + } + case 0x9a: { // txs imp + cpu->sp = cpu->x; + break; + } + case 0x9b: { // txy imp + if(cpu->xf) { + cpu->y = cpu->x & 0xff; + } else { + cpu->y = cpu->x; + } + cpu_setZN(cpu, cpu->y, cpu->xf); + break; + } + case 0x9c: { // stz abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_stz(cpu, low, high); + break; + } + case 0x9d: { // sta abx + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, true); + cpu_sta(cpu, low, high); + break; + } + case 0x9e: { // stz abx + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, true); + cpu_stz(cpu, low, high); + break; + } + case 0x9f: { // sta alx + uint32_t low = 0; + uint32_t high = cpu_adrAlx(cpu, &low); + cpu_sta(cpu, low, high); + break; + } + case 0xa0: { // ldy imm(x) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, true); + cpu_ldy(cpu, low, high); + break; + } + case 0xa1: { // lda idx + uint32_t low = 0; + uint32_t high = cpu_adrIdx(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xa2: { // ldx imm(x) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, true); + cpu_ldx(cpu, low, high); + break; + } + case 0xa3: { // lda sr + uint32_t low = 0; + uint32_t high = cpu_adrSr(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xa4: { // ldy dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_ldy(cpu, low, high); + break; + } + case 0xa5: { // lda dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xa6: { // ldx dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_ldx(cpu, low, high); + break; + } + case 0xa7: { // lda idl + uint32_t low = 0; + uint32_t high = cpu_adrIdl(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xa8: { // tay imp + if(cpu->xf) { + cpu->y = cpu->a & 0xff; + } else { + cpu->y = cpu->a; + } + cpu_setZN(cpu, cpu->y, cpu->xf); + break; + } + case 0xa9: { // lda imm(m) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, false); + cpu_lda(cpu, low, high); + break; + } + case 0xaa: { // tax imp + if(cpu->xf) { + cpu->x = cpu->a & 0xff; + } else { + cpu->x = cpu->a; + } + cpu_setZN(cpu, cpu->x, cpu->xf); + break; + } + case 0xab: { // plb imp + cpu->db = cpu_pullByte(cpu); + cpu_setZN(cpu, cpu->db, true); + break; + } + case 0xac: { // ldy abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_ldy(cpu, low, high); + break; + } + case 0xad: { // lda abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xae: { // ldx abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_ldx(cpu, low, high); + break; + } + case 0xaf: { // lda abl + uint32_t low = 0; + uint32_t high = cpu_adrAbl(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xb0: { // bcs rel + cpu_doBranch(cpu, cpu_readOpcode(cpu), cpu->c); + break; + } + case 0xb1: { // lda idy(r) + uint32_t low = 0; + uint32_t high = cpu_adrIdy(cpu, &low, false); + cpu_lda(cpu, low, high); + break; + } + case 0xb2: { // lda idp + uint32_t low = 0; + uint32_t high = cpu_adrIdp(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xb3: { // lda isy + uint32_t low = 0; + uint32_t high = cpu_adrIsy(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xb4: { // ldy dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_ldy(cpu, low, high); + break; + } + case 0xb5: { // lda dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xb6: { // ldx dpy + uint32_t low = 0; + uint32_t high = cpu_adrDpy(cpu, &low); + cpu_ldx(cpu, low, high); + break; + } + case 0xb7: { // lda ily + uint32_t low = 0; + uint32_t high = cpu_adrIly(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xb8: { // clv imp + cpu->v = false; + break; + } + case 0xb9: { // lda aby(r) + uint32_t low = 0; + uint32_t high = cpu_adrAby(cpu, &low, false); + cpu_lda(cpu, low, high); + break; + } + case 0xba: { // tsx imp + if(cpu->xf) { + cpu->x = cpu->sp & 0xff; + } else { + cpu->x = cpu->sp; + } + cpu_setZN(cpu, cpu->x, cpu->xf); + break; + } + case 0xbb: { // tyx imp + if(cpu->xf) { + cpu->x = cpu->y & 0xff; + } else { + cpu->x = cpu->y; + } + cpu_setZN(cpu, cpu->x, cpu->xf); + break; + } + case 0xbc: { // ldy abx(r) + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, false); + cpu_ldy(cpu, low, high); + break; + } + case 0xbd: { // lda abx(r) + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, false); + cpu_lda(cpu, low, high); + break; + } + case 0xbe: { // ldx aby(r) + uint32_t low = 0; + uint32_t high = cpu_adrAby(cpu, &low, false); + cpu_ldx(cpu, low, high); + break; + } + case 0xbf: { // lda alx + uint32_t low = 0; + uint32_t high = cpu_adrAlx(cpu, &low); + cpu_lda(cpu, low, high); + break; + } + case 0xc0: { // cpy imm(x) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, true); + cpu_cpy(cpu, low, high); + break; + } + case 0xc1: { // cmp idx + uint32_t low = 0; + uint32_t high = cpu_adrIdx(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xc2: { // rep imm(s) + cpu_setFlags(cpu, cpu_getFlags(cpu) & ~cpu_readOpcode(cpu)); + break; + } + case 0xc3: { // cmp sr + uint32_t low = 0; + uint32_t high = cpu_adrSr(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xc4: { // cpy dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_cpy(cpu, low, high); + break; + } + case 0xc5: { // cmp dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xc6: { // dec dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_dec(cpu, low, high); + break; + } + case 0xc7: { // cmp idl + uint32_t low = 0; + uint32_t high = cpu_adrIdl(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xc8: { // iny imp + if(cpu->xf) { + cpu->y = (cpu->y + 1) & 0xff; + } else { + cpu->y++; + } + cpu_setZN(cpu, cpu->y, cpu->xf); + break; + } + case 0xc9: { // cmp imm(m) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, false); + cpu_cmp(cpu, low, high); + break; + } + case 0xca: { // dex imp + if(cpu->xf) { + cpu->x = (cpu->x - 1) & 0xff; + } else { + cpu->x--; + } + cpu_setZN(cpu, cpu->x, cpu->xf); + break; + } + case 0xcb: { // wai imp + assert(0); + break; + } + case 0xcc: { // cpy abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_cpy(cpu, low, high); + break; + } + case 0xcd: { // cmp abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xce: { // dec abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_dec(cpu, low, high); + break; + } + case 0xcf: { // cmp abl + uint32_t low = 0; + uint32_t high = cpu_adrAbl(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xd0: { // bne rel + cpu_doBranch(cpu, cpu_readOpcode(cpu), !cpu->z); + break; + } + case 0xd1: { // cmp idy(r) + uint32_t low = 0; + uint32_t high = cpu_adrIdy(cpu, &low, false); + cpu_cmp(cpu, low, high); + break; + } + case 0xd2: { // cmp idp + uint32_t low = 0; + uint32_t high = cpu_adrIdp(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xd3: { // cmp isy + uint32_t low = 0; + uint32_t high = cpu_adrIsy(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xd4: { // pei dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_pushWord(cpu, cpu_readWord(cpu, low, high)); + break; + } + case 0xd5: { // cmp dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xd6: { // dec dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_dec(cpu, low, high); + break; + } + case 0xd7: { // cmp ily + uint32_t low = 0; + uint32_t high = cpu_adrIly(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xd8: { // cld imp + cpu->d = false; + break; + } + case 0xd9: { // cmp aby(r) + uint32_t low = 0; + uint32_t high = cpu_adrAby(cpu, &low, false); + cpu_cmp(cpu, low, high); + break; + } + case 0xda: { // phx imp + if(cpu->xf) { + cpu_pushByte(cpu, (uint8_t)cpu->x); + } else { + cpu->cyclesUsed++; // m = 0: 1 extra cycle + cpu_pushWord(cpu, cpu->x); + } + break; + } + case 0xdb: { // stp imp + cpu->stopped = true; + break; + } + case 0xdc: { // jml ial + uint16_t adr = cpu_readOpcodeWord(cpu); + cpu->pc = cpu_readWord(cpu, adr, (adr + 1) & 0xffff); + cpu->k = cpu_read(cpu, (adr + 2) & 0xffff); + break; + } + case 0xdd: { // cmp abx(r) + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, false); + cpu_cmp(cpu, low, high); + break; + } + case 0xde: { // dec abx + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, true); + cpu_dec(cpu, low, high); + break; + } + case 0xdf: { // cmp alx + uint32_t low = 0; + uint32_t high = cpu_adrAlx(cpu, &low); + cpu_cmp(cpu, low, high); + break; + } + case 0xe0: { // cpx imm(x) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, true); + cpu_cpx(cpu, low, high); + break; + } + case 0xe1: { // sbc idx + uint32_t low = 0; + uint32_t high = cpu_adrIdx(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + case 0xe2: { // sep imm(s) + cpu_setFlags(cpu, cpu_getFlags(cpu) | cpu_readOpcode(cpu)); + break; + } + case 0xe3: { // sbc sr + uint32_t low = 0; + uint32_t high = cpu_adrSr(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + case 0xe4: { // cpx dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_cpx(cpu, low, high); + break; + } + case 0xe5: { // sbc dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + case 0xe6: { // inc dp + uint32_t low = 0; + uint32_t high = cpu_adrDp(cpu, &low); + cpu_inc(cpu, low, high); + break; + } + case 0xe7: { // sbc idl + uint32_t low = 0; + uint32_t high = cpu_adrIdl(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + case 0xe8: { // inx imp + if(cpu->xf) { + cpu->x = (cpu->x + 1) & 0xff; + } else { + cpu->x++; + } + cpu_setZN(cpu, cpu->x, cpu->xf); + break; + } + case 0xe9: { // sbc imm(m) + uint32_t low = 0; + uint32_t high = cpu_adrImm(cpu, &low, false); + cpu_sbc(cpu, low, high); + break; + } + case 0xea: { // nop imp + // no operation + break; + } + case 0xeb: { // xba imp + uint8_t low = cpu->a & 0xff; + uint8_t high = cpu->a >> 8; + cpu->a = (low << 8) | high; + cpu_setZN(cpu, high, true); + break; + } + case 0xec: { // cpx abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_cpx(cpu, low, high); + break; + } + case 0xed: { // sbc abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + case 0xee: { // inc abs + uint32_t low = 0; + uint32_t high = cpu_adrAbs(cpu, &low); + cpu_inc(cpu, low, high); + break; + } + case 0xef: { // sbc abl + uint32_t low = 0; + uint32_t high = cpu_adrAbl(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + case 0xf0: { // beq rel + cpu_doBranch(cpu, cpu_readOpcode(cpu), cpu->z); + break; + } + case 0xf1: { // sbc idy(r) + uint32_t low = 0; + uint32_t high = cpu_adrIdy(cpu, &low, false); + cpu_sbc(cpu, low, high); + break; + } + case 0xf2: { // sbc idp + uint32_t low = 0; + uint32_t high = cpu_adrIdp(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + case 0xf3: { // sbc isy + uint32_t low = 0; + uint32_t high = cpu_adrIsy(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + case 0xf4: { // pea imm(l) + uint16_t w = cpu_readOpcodeWord(cpu); + if (w == 0xC2AE) + cpu->y = 0; + cpu_pushWord(cpu, w); + + break; + } + case 0xf5: { // sbc dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + case 0xf6: { // inc dpx + uint32_t low = 0; + uint32_t high = cpu_adrDpx(cpu, &low); + cpu_inc(cpu, low, high); + break; + } + case 0xf7: { // sbc ily + uint32_t low = 0; + uint32_t high = cpu_adrIly(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + case 0xf8: { // sed imp + cpu->d = true; + break; + } + case 0xf9: { // sbc aby(r) + uint32_t low = 0; + uint32_t high = cpu_adrAby(cpu, &low, false); + cpu_sbc(cpu, low, high); + break; + } + case 0xfa: { // plx imp + if(cpu->xf) { + cpu->x = cpu_pullByte(cpu); + } else { + cpu->cyclesUsed++; // 16-bit x: 1 extra cycle + cpu->x = cpu_pullWord(cpu); + } + cpu_setZN(cpu, cpu->x, cpu->xf); + break; + } + case 0xfb: { // xce imp + bool temp = cpu->c; + cpu->c = cpu->e; + cpu->e = temp; + cpu_setFlags(cpu, cpu_getFlags(cpu)); // updates x and m flags, clears upper half of x and y if needed + break; + } + case 0xfc: { // jsr iax + uint16_t value = cpu_adrIax(cpu); + cpu_pushWord(cpu, cpu->pc - 1); + cpu->pc = value; + break; + } + case 0xfd: { // sbc abx(r) + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, false); + cpu_sbc(cpu, low, high); + break; + } + case 0xfe: { // inc abx + uint32_t low = 0; + uint32_t high = cpu_adrAbx(cpu, &low, true); + cpu_inc(cpu, low, high); + break; + } + case 0xff: { // sbc alx + uint32_t low = 0; + uint32_t high = cpu_adrAlx(cpu, &low); + cpu_sbc(cpu, low, high); + break; + } + } +} \ No newline at end of file diff --git a/src/snes/cpu.h b/src/snes/cpu.h new file mode 100644 index 0000000..47225c2 --- /dev/null +++ b/src/snes/cpu.h @@ -0,0 +1,59 @@ + +#ifndef CPU_H +#define CPU_H + +#include +#include +#include +#include +#include +#include "saveload.h" + +typedef struct Cpu Cpu; + +struct Cpu { + // reference to memory handler, for reading//writing + void* mem; + uint8_t memType; // used to define which type mem is + // registers + uint16_t a; + uint16_t x; + uint16_t y; + uint16_t sp; + uint16_t pc; + uint16_t dp; // direct page (D) + uint8_t k; // program bank (PB) + uint8_t db; // data bank (B) + // flags + bool c; + bool z; + bool v; + bool n; + bool i; + bool d; + bool xf; + bool mf; + bool e; + // interrupts + bool irqWanted; + bool nmiWanted; + // power state (WAI/STP) + bool waiting; + bool stopped; + // internal use + uint8_t cyclesUsed; // indicates how many cycles an opcode used + uint16_t spBreakpoint; + bool in_emu; +}; + +extern struct Cpu *g_cpu; +bool HookedFunctionRts(int is_long); + +Cpu* cpu_init(void* mem, int memType); +void cpu_free(Cpu* cpu); +void cpu_reset(Cpu* cpu); +int cpu_runOpcode(Cpu* cpu); +uint8_t cpu_getFlags(Cpu *cpu); +void cpu_setFlags(Cpu *cpu, uint8_t val); +void cpu_saveload(Cpu *cpu, SaveLoadFunc *func, void *ctx); +#endif diff --git a/src/snes/dma.c b/src/snes/dma.c new file mode 100644 index 0000000..efe14a0 --- /dev/null +++ b/src/snes/dma.c @@ -0,0 +1,332 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include "dma.h" +#include "snes.h" + +static const int bAdrOffsets[8][4] = { + {0, 0, 0, 0}, + {0, 1, 0, 1}, + {0, 0, 0, 0}, + {0, 0, 1, 1}, + {0, 1, 2, 3}, + {0, 1, 0, 1}, + {0, 0, 0, 0}, + {0, 0, 1, 1} +}; + +static const int transferLength[8] = { + 1, 2, 2, 4, 4, 4, 2, 4 +}; + +static void dma_transferByte(Dma* dma, uint16_t aAdr, uint8_t aBank, uint8_t bAdr, bool fromB); + +Dma* dma_init(Snes* snes) { + Dma* dma = malloc(sizeof(Dma)); + dma->snes = snes; + return dma; +} + +void dma_free(Dma* dma) { + free(dma); +} + +void dma_reset(Dma* dma) { + for(int i = 0; i < 8; i++) { + dma->channel[i].bAdr = 0xff; + dma->channel[i].aAdr = 0xffff; + dma->channel[i].aBank = 0xff; + dma->channel[i].size = 0xffff; + dma->channel[i].indBank = 0xff; + dma->channel[i].tableAdr = 0xffff; + dma->channel[i].repCount = 0xff; + dma->channel[i].unusedByte = 0xff; + dma->channel[i].dmaActive = false; + dma->channel[i].hdmaActive = false; + dma->channel[i].mode = 7; + dma->channel[i].fixed = true; + dma->channel[i].decrement = true; + dma->channel[i].indirect = true; + dma->channel[i].fromB = true; + dma->channel[i].unusedBit = true; + dma->channel[i].doTransfer = false; + dma->channel[i].terminated = false; + dma->channel[i].offIndex = 0; + } + dma->hdmaTimer = 0; + dma->dmaTimer = 0; + dma->dmaBusy = false; +} + +void dma_saveload(Dma *dma, SaveLoadFunc *func, void *ctx) { + func(ctx, &dma->channel, sizeof(Dma) - offsetof(Dma, channel)); +} + +uint8_t dma_read(Dma* dma, uint16_t adr) { + uint8_t c = (adr & 0x70) >> 4; + switch(adr & 0xf) { + case 0x0: { + uint8_t val = dma->channel[c].mode; + val |= dma->channel[c].fixed << 3; + val |= dma->channel[c].decrement << 4; + val |= dma->channel[c].unusedBit << 5; + val |= dma->channel[c].indirect << 6; + val |= dma->channel[c].fromB << 7; + return val; + } + case 0x1: { + return dma->channel[c].bAdr; + } + case 0x2: { + return dma->channel[c].aAdr & 0xff; + } + case 0x3: { + return dma->channel[c].aAdr >> 8; + } + case 0x4: { + return dma->channel[c].aBank; + } + case 0x5: { + return dma->channel[c].size & 0xff; + } + case 0x6: { + return dma->channel[c].size >> 8; + } + case 0x7: { + return dma->channel[c].indBank; + } + case 0x8: { + return dma->channel[c].tableAdr & 0xff; + } + case 0x9: { + return dma->channel[c].tableAdr >> 8; + } + case 0xa: { + return dma->channel[c].repCount; + } + case 0xb: + case 0xf: { + return dma->channel[c].unusedByte; + } + default: { + assert(0); + return dma->snes->openBus; + } + } +} + +void dma_write(Dma* dma, uint16_t adr, uint8_t val) { + uint8_t c = (adr & 0x70) >> 4; + switch(adr & 0xf) { + case 0x0: { + dma->channel[c].mode = val & 0x7; + dma->channel[c].fixed = val & 0x8; + dma->channel[c].decrement = val & 0x10; + dma->channel[c].unusedBit = val & 0x20; + dma->channel[c].indirect = val & 0x40; + dma->channel[c].fromB = val & 0x80; + break; + } + case 0x1: { + dma->channel[c].bAdr = val; + break; + } + case 0x2: { + dma->channel[c].aAdr = (dma->channel[c].aAdr & 0xff00) | val; + break; + } + case 0x3: { + dma->channel[c].aAdr = (dma->channel[c].aAdr & 0xff) | (val << 8); + break; + } + case 0x4: { + dma->channel[c].aBank = val; + break; + } + case 0x5: { + dma->channel[c].size = (dma->channel[c].size & 0xff00) | val; + break; + } + case 0x6: { + dma->channel[c].size = (dma->channel[c].size & 0xff) | (val << 8); + break; + } + case 0x7: { + dma->channel[c].indBank = val; + break; + } + case 0x8: { + dma->channel[c].tableAdr = (dma->channel[c].tableAdr & 0xff00) | val; + break; + } + case 0x9: { + dma->channel[c].tableAdr = (dma->channel[c].tableAdr & 0xff) | (val << 8); + break; + } + case 0xa: { + dma->channel[c].repCount = val; + break; + } + case 0xb: + case 0xf: { + dma->channel[c].unusedByte = val; + break; + } + default: { + break; + } + } +} + +void dma_doDma(Dma* dma) { + if(dma->dmaTimer > 0) { + dma->dmaTimer -= 2; + return; + } + // figure out first channel that is active + int i = 0; + for(i = 0; i < 8; i++) { + if(dma->channel[i].dmaActive) { + break; + } + } + if(i == 8) { + // no active channels + dma->dmaBusy = false; + return; + } + // do channel i + dma_transferByte( + dma, dma->channel[i].aAdr, dma->channel[i].aBank, + dma->channel[i].bAdr + bAdrOffsets[dma->channel[i].mode][dma->channel[i].offIndex++], dma->channel[i].fromB + ); + dma->channel[i].offIndex &= 3; + dma->dmaTimer += 6; // 8 cycles for each byte taken, -2 for this cycle + if(!dma->channel[i].fixed) { + dma->channel[i].aAdr += dma->channel[i].decrement ? -1 : 1; + } + dma->channel[i].size--; + if(dma->channel[i].size == 0) { + dma->channel[i].offIndex = 0; // reset offset index + dma->channel[i].dmaActive = false; + dma->dmaTimer += 8; // 8 cycle overhead per channel + } +} + +void dma_initHdma(Dma* dma) { + dma->hdmaTimer = 0; + bool hdmaHappened = false; + for(int i = 0; i < 8; i++) { + if(dma->channel[i].hdmaActive) { + hdmaHappened = true; + // terminate any dma + dma->channel[i].dmaActive = false; + dma->channel[i].offIndex = 0; + // load address, repCount, and indirect address if needed + dma->channel[i].tableAdr = dma->channel[i].aAdr; + dma->channel[i].repCount = snes_read(dma->snes, (dma->channel[i].aBank << 16) | dma->channel[i].tableAdr++); + dma->hdmaTimer += 8; // 8 cycle overhead for each active channel + if(dma->channel[i].indirect) { + dma->channel[i].size = snes_read(dma->snes, (dma->channel[i].aBank << 16) | dma->channel[i].tableAdr++); + dma->channel[i].size |= snes_read(dma->snes, (dma->channel[i].aBank << 16) | dma->channel[i].tableAdr++) << 8; + dma->hdmaTimer += 16; // another 16 cycles for indirect (total 24) + } + dma->channel[i].doTransfer = true; + } else { + dma->channel[i].doTransfer = false; + } + dma->channel[i].terminated = false; + } + if(hdmaHappened) dma->hdmaTimer += 16; // 18 cycles overhead, -2 for this cycle +} + +void dma_doHdma(Dma* dma) { + dma->hdmaTimer = 0; + bool hdmaHappened = false; + for(int i = 0; i < 8; i++) { + if(dma->channel[i].hdmaActive && !dma->channel[i].terminated) { +// printf("DMA %d: 0x%x\n", i, dma->channel[i].bAdr); + hdmaHappened = true; + // terminate any dma + dma->channel[i].dmaActive = false; + dma->channel[i].offIndex = 0; + // do the hdma + dma->hdmaTimer += 8; // 8 cycles overhead for each active channel + + + if(dma->channel[i].doTransfer) { + for(int j = 0; j < transferLength[dma->channel[i].mode]; j++) { + dma->hdmaTimer += 8; // 8 cycles for each byte transferred + if(dma->channel[i].indirect) { + dma_transferByte( + dma, dma->channel[i].size++, dma->channel[i].indBank, + dma->channel[i].bAdr + bAdrOffsets[dma->channel[i].mode][j], dma->channel[i].fromB + ); + } else { + dma_transferByte( + dma, dma->channel[i].tableAdr++, dma->channel[i].aBank, + dma->channel[i].bAdr + bAdrOffsets[dma->channel[i].mode][j], dma->channel[i].fromB + ); + } + } + } + dma->channel[i].repCount--; + dma->channel[i].doTransfer = dma->channel[i].repCount & 0x80; + if((dma->channel[i].repCount & 0x7f) == 0) { + dma->channel[i].repCount = snes_read(dma->snes, (dma->channel[i].aBank << 16) | dma->channel[i].tableAdr++); + if(dma->channel[i].indirect) { + // TODO: oddness with not fetching high byte if last active channel and reCount is 0 + dma->channel[i].size = snes_read(dma->snes, (dma->channel[i].aBank << 16) | dma->channel[i].tableAdr++); + dma->channel[i].size |= snes_read(dma->snes, (dma->channel[i].aBank << 16) | dma->channel[i].tableAdr++) << 8; + dma->hdmaTimer += 16; // 16 cycles for new indirect address + } + if(dma->channel[i].repCount == 0) dma->channel[i].terminated = true; + dma->channel[i].doTransfer = true; + } + } + } + if(hdmaHappened) dma->hdmaTimer += 16; // 18 cycles overhead, -2 for this cycle +} + +static void dma_transferByte(Dma* dma, uint16_t aAdr, uint8_t aBank, uint8_t bAdr, bool fromB) { + // TODO: invalid writes: + // accesing b-bus via a-bus gives open bus, + // $2180-$2183 while accessing ram via a-bus open busses $2180-$2183 + // cannot access $4300-$437f (dma regs), or $420b / $420c + if(fromB) { + snes_write(dma->snes, (aBank << 16) | aAdr, snes_readBBus(dma->snes, bAdr)); + } else { + snes_writeBBus(dma->snes, bAdr, snes_read(dma->snes, (aBank << 16) | aAdr)); + } +} + +bool dma_cycle(Dma* dma) { + if(dma->hdmaTimer > 0) { + dma->hdmaTimer -= 2; + return true; + } else if(dma->dmaBusy) { + dma_doDma(dma); + return true; + } + return false; +} + +void dma_startDma(Dma* dma, uint8_t val, bool hdma) { + for(int i = 0; i < 8; i++) { + if(hdma) { + dma->channel[i].hdmaActive = val & (1 << i); + } else { + dma->channel[i].dmaActive = val & (1 << i); + } + } + if(!hdma) { + dma->dmaBusy = val; + dma->dmaTimer += dma->dmaBusy ? 16 : 0; // 12-24 cycle overhead for entire dma transfer + } +} diff --git a/src/snes/dma.h b/src/snes/dma.h new file mode 100644 index 0000000..0facfa3 --- /dev/null +++ b/src/snes/dma.h @@ -0,0 +1,57 @@ + +#ifndef DMA_H +#define DMA_H + +#include +#include +#include +#include +#include + +typedef struct Dma Dma; + +#include "snes.h" + +typedef struct DmaChannel { + uint8_t bAdr; + uint16_t aAdr; + uint8_t aBank; + uint16_t size; // also indirect hdma adr + uint8_t indBank; // hdma + uint16_t tableAdr; // hdma + uint8_t repCount; // hdma + uint8_t unusedByte; + bool dmaActive; + bool hdmaActive; + uint8_t mode; + bool fixed; + bool decrement; + bool indirect; // hdma + bool fromB; + bool unusedBit; + bool doTransfer; // hdma + bool terminated; // hdma + uint8_t offIndex; +} DmaChannel; + +struct Dma { + Snes* snes; + DmaChannel channel[8]; + uint16_t hdmaTimer; + uint32_t dmaTimer; + bool dmaBusy; +}; + +Dma* dma_init(Snes* snes); +void dma_free(Dma* dma); +void dma_reset(Dma* dma); +uint8_t dma_read(Dma* dma, uint16_t adr); // 43x0-43xf +void dma_write(Dma* dma, uint16_t adr, uint8_t val); // 43x0-43xf +void dma_doDma(Dma* dma); +void dma_initHdma(Dma* dma); +void dma_doHdma(Dma* dma); +bool dma_cycle(Dma* dma); +void dma_startDma(Dma* dma, uint8_t val, bool hdma); +void dma_saveload(Dma *dma, SaveLoadFunc *func, void *ctx); + +#endif diff --git a/src/snes/dsp.c b/src/snes/dsp.c new file mode 100644 index 0000000..8ce1882 --- /dev/null +++ b/src/snes/dsp.c @@ -0,0 +1,578 @@ + +#include +#include +#include +#include +#include +#include + +#include "dsp.h" +#include "apu.h" + +#define MY_CHANGES 1 + +static const int rateValues[32] = { + 0, 2048, 1536, 1280, 1024, 768, 640, 512, + 384, 320, 256, 192, 160, 128, 96, 80, + 64, 48, 40, 32, 24, 20, 16, 12, + 10, 8, 6, 5, 4, 3, 2, 1 +}; + +static const uint16_t gaussValues[512] = { + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x002, 0x002, 0x002, 0x002, 0x002, + 0x002, 0x002, 0x003, 0x003, 0x003, 0x003, 0x003, 0x004, 0x004, 0x004, 0x004, 0x004, 0x005, 0x005, 0x005, 0x005, + 0x006, 0x006, 0x006, 0x006, 0x007, 0x007, 0x007, 0x008, 0x008, 0x008, 0x009, 0x009, 0x009, 0x00A, 0x00A, 0x00A, + 0x00B, 0x00B, 0x00B, 0x00C, 0x00C, 0x00D, 0x00D, 0x00E, 0x00E, 0x00F, 0x00F, 0x00F, 0x010, 0x010, 0x011, 0x011, + 0x012, 0x013, 0x013, 0x014, 0x014, 0x015, 0x015, 0x016, 0x017, 0x017, 0x018, 0x018, 0x019, 0x01A, 0x01B, 0x01B, + 0x01C, 0x01D, 0x01D, 0x01E, 0x01F, 0x020, 0x020, 0x021, 0x022, 0x023, 0x024, 0x024, 0x025, 0x026, 0x027, 0x028, + 0x029, 0x02A, 0x02B, 0x02C, 0x02D, 0x02E, 0x02F, 0x030, 0x031, 0x032, 0x033, 0x034, 0x035, 0x036, 0x037, 0x038, + 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x040, 0x041, 0x042, 0x043, 0x045, 0x046, 0x047, 0x049, 0x04A, 0x04C, 0x04D, + 0x04E, 0x050, 0x051, 0x053, 0x054, 0x056, 0x057, 0x059, 0x05A, 0x05C, 0x05E, 0x05F, 0x061, 0x063, 0x064, 0x066, + 0x068, 0x06A, 0x06B, 0x06D, 0x06F, 0x071, 0x073, 0x075, 0x076, 0x078, 0x07A, 0x07C, 0x07E, 0x080, 0x082, 0x084, + 0x086, 0x089, 0x08B, 0x08D, 0x08F, 0x091, 0x093, 0x096, 0x098, 0x09A, 0x09C, 0x09F, 0x0A1, 0x0A3, 0x0A6, 0x0A8, + 0x0AB, 0x0AD, 0x0AF, 0x0B2, 0x0B4, 0x0B7, 0x0BA, 0x0BC, 0x0BF, 0x0C1, 0x0C4, 0x0C7, 0x0C9, 0x0CC, 0x0CF, 0x0D2, + 0x0D4, 0x0D7, 0x0DA, 0x0DD, 0x0E0, 0x0E3, 0x0E6, 0x0E9, 0x0EC, 0x0EF, 0x0F2, 0x0F5, 0x0F8, 0x0FB, 0x0FE, 0x101, + 0x104, 0x107, 0x10B, 0x10E, 0x111, 0x114, 0x118, 0x11B, 0x11E, 0x122, 0x125, 0x129, 0x12C, 0x130, 0x133, 0x137, + 0x13A, 0x13E, 0x141, 0x145, 0x148, 0x14C, 0x150, 0x153, 0x157, 0x15B, 0x15F, 0x162, 0x166, 0x16A, 0x16E, 0x172, + 0x176, 0x17A, 0x17D, 0x181, 0x185, 0x189, 0x18D, 0x191, 0x195, 0x19A, 0x19E, 0x1A2, 0x1A6, 0x1AA, 0x1AE, 0x1B2, + 0x1B7, 0x1BB, 0x1BF, 0x1C3, 0x1C8, 0x1CC, 0x1D0, 0x1D5, 0x1D9, 0x1DD, 0x1E2, 0x1E6, 0x1EB, 0x1EF, 0x1F3, 0x1F8, + 0x1FC, 0x201, 0x205, 0x20A, 0x20F, 0x213, 0x218, 0x21C, 0x221, 0x226, 0x22A, 0x22F, 0x233, 0x238, 0x23D, 0x241, + 0x246, 0x24B, 0x250, 0x254, 0x259, 0x25E, 0x263, 0x267, 0x26C, 0x271, 0x276, 0x27B, 0x280, 0x284, 0x289, 0x28E, + 0x293, 0x298, 0x29D, 0x2A2, 0x2A6, 0x2AB, 0x2B0, 0x2B5, 0x2BA, 0x2BF, 0x2C4, 0x2C9, 0x2CE, 0x2D3, 0x2D8, 0x2DC, + 0x2E1, 0x2E6, 0x2EB, 0x2F0, 0x2F5, 0x2FA, 0x2FF, 0x304, 0x309, 0x30E, 0x313, 0x318, 0x31D, 0x322, 0x326, 0x32B, + 0x330, 0x335, 0x33A, 0x33F, 0x344, 0x349, 0x34E, 0x353, 0x357, 0x35C, 0x361, 0x366, 0x36B, 0x370, 0x374, 0x379, + 0x37E, 0x383, 0x388, 0x38C, 0x391, 0x396, 0x39B, 0x39F, 0x3A4, 0x3A9, 0x3AD, 0x3B2, 0x3B7, 0x3BB, 0x3C0, 0x3C5, + 0x3C9, 0x3CE, 0x3D2, 0x3D7, 0x3DC, 0x3E0, 0x3E5, 0x3E9, 0x3ED, 0x3F2, 0x3F6, 0x3FB, 0x3FF, 0x403, 0x408, 0x40C, + 0x410, 0x415, 0x419, 0x41D, 0x421, 0x425, 0x42A, 0x42E, 0x432, 0x436, 0x43A, 0x43E, 0x442, 0x446, 0x44A, 0x44E, + 0x452, 0x455, 0x459, 0x45D, 0x461, 0x465, 0x468, 0x46C, 0x470, 0x473, 0x477, 0x47A, 0x47E, 0x481, 0x485, 0x488, + 0x48C, 0x48F, 0x492, 0x496, 0x499, 0x49C, 0x49F, 0x4A2, 0x4A6, 0x4A9, 0x4AC, 0x4AF, 0x4B2, 0x4B5, 0x4B7, 0x4BA, + 0x4BD, 0x4C0, 0x4C3, 0x4C5, 0x4C8, 0x4CB, 0x4CD, 0x4D0, 0x4D2, 0x4D5, 0x4D7, 0x4D9, 0x4DC, 0x4DE, 0x4E0, 0x4E3, + 0x4E5, 0x4E7, 0x4E9, 0x4EB, 0x4ED, 0x4EF, 0x4F1, 0x4F3, 0x4F5, 0x4F6, 0x4F8, 0x4FA, 0x4FB, 0x4FD, 0x4FF, 0x500, + 0x502, 0x503, 0x504, 0x506, 0x507, 0x508, 0x50A, 0x50B, 0x50C, 0x50D, 0x50E, 0x50F, 0x510, 0x511, 0x511, 0x512, + 0x513, 0x514, 0x514, 0x515, 0x516, 0x516, 0x517, 0x517, 0x517, 0x518, 0x518, 0x518, 0x518, 0x518, 0x519, 0x519 +}; + +static void dsp_cycleChannel(Dsp* dsp, int ch); +static void dsp_handleEcho(Dsp* dsp, int* outputL, int* outputR); +static void dsp_handleGain(Dsp* dsp, int ch); +static void dsp_decodeBrr(Dsp* dsp, int ch); +static int16_t dsp_getSample(Dsp* dsp, int ch, int sampleNum, int offset); +static void dsp_handleNoise(Dsp* dsp); + +Dsp* dsp_init(uint8_t *ram) { + Dsp* dsp = malloc(sizeof(Dsp)); + dsp->apu_ram = ram; + return dsp; +} + +void dsp_free(Dsp* dsp) { + free(dsp); +} + +void dsp_reset(Dsp* dsp) { + memset(dsp->ram, 0, sizeof(dsp->ram)); + dsp->ram[0x7c] = 0xff; // set ENDx + for(int i = 0; i < 8; i++) { + dsp->channel[i].pitch = 0; + dsp->channel[i].pitchCounter = 0; + dsp->channel[i].pitchModulation = false; + memset(dsp->channel[i].decodeBuffer, 0, sizeof(dsp->channel[i].decodeBuffer)); + dsp->channel[i].srcn = 0; + dsp->channel[i].decodeOffset = 0; + dsp->channel[i].previousFlags = 0; + dsp->channel[i].old = 0; + dsp->channel[i].older = 0; + dsp->channel[i].useNoise = false; + memset(dsp->channel[i].adsrRates, 0, sizeof(dsp->channel[i].adsrRates)); + dsp->channel[i].rateCounter = 0; + dsp->channel[i].adsrState = 0; + dsp->channel[i].sustainLevel = 0; + dsp->channel[i].useGain = false; + dsp->channel[i].gainMode = 0; + dsp->channel[i].directGain = false; + dsp->channel[i].gainValue = 0; + dsp->channel[i].gain = 0; + dsp->channel[i].keyOn = false; + dsp->channel[i].keyOff = false; + dsp->channel[i].sampleOut = 0; + dsp->channel[i].volumeL = 0; + dsp->channel[i].volumeR = 0; + dsp->channel[i].echoEnable = false; + } + dsp->dirPage = 0; + dsp->evenCycle = false; + dsp->mute = true; + dsp->reset = true; + dsp->masterVolumeL = 0; + dsp->masterVolumeR = 0; + dsp->noiseSample = -0x4000; + dsp->noiseRate = 0; + dsp->noiseCounter = 0; + dsp->echoWrites = false; + dsp->echoVolumeL = 0; + dsp->echoVolumeR = 0; + dsp->feedbackVolume = 0; + dsp->echoBufferAdr = 0; + dsp->echoDelay = 1; + dsp->echoRemain = 1; + dsp->echoBufferIndex = 0; + dsp->firBufferIndex = 0; + memset(dsp->firValues, 0, sizeof(dsp->firValues)); + memset(dsp->firBufferL, 0, sizeof(dsp->firBufferL)); + memset(dsp->firBufferR, 0, sizeof(dsp->firBufferR)); + memset(dsp->sampleBuffer, 0, sizeof(dsp->sampleBuffer)); + dsp->sampleOffset = 0; +} + +void dsp_saveload(Dsp *dsp, SaveLoadFunc *func, void *ctx) { + func(ctx, &dsp->ram, sizeof(Dsp) - offsetof(Dsp, ram)); +} + +void dsp_cycle(Dsp* dsp) { + int totalL = 0; + int totalR = 0; + for(int i = 0; i < 8; i++) { + dsp_cycleChannel(dsp, i); + totalL += (dsp->channel[i].sampleOut * dsp->channel[i].volumeL) >> 6; + totalR += (dsp->channel[i].sampleOut * dsp->channel[i].volumeR) >> 6; + totalL = totalL < -0x8000 ? -0x8000 : (totalL > 0x7fff ? 0x7fff : totalL); // clamp 16-bit + totalR = totalR < -0x8000 ? -0x8000 : (totalR > 0x7fff ? 0x7fff : totalR); // clamp 16-bit + } + totalL = (totalL * dsp->masterVolumeL) >> 7; + totalR = (totalR * dsp->masterVolumeR) >> 7; + totalL = totalL < -0x8000 ? -0x8000 : (totalL > 0x7fff ? 0x7fff : totalL); // clamp 16-bit + totalR = totalR < -0x8000 ? -0x8000 : (totalR > 0x7fff ? 0x7fff : totalR); // clamp 16-bit + dsp_handleEcho(dsp, &totalL, &totalR); + if(dsp->mute) { + totalL = 0; + totalR = 0; + } + dsp_handleNoise(dsp); + // put it in the samplebuffer + if (dsp->sampleOffset < 534) { + dsp->sampleBuffer[dsp->sampleOffset * 2] = totalL; + dsp->sampleBuffer[dsp->sampleOffset * 2 + 1] = totalR; + // prevent sampleOffset from going above 534-1 (out of sampleBuffer bounds) + dsp->sampleOffset++; + } + dsp->evenCycle = !dsp->evenCycle; +} + +static void dsp_handleEcho(Dsp* dsp, int* outputL, int* outputR) { + // get value out of ram + uint16_t adr = dsp->echoBufferAdr + dsp->echoBufferIndex * 4; + dsp->firBufferL[dsp->firBufferIndex] = ( + dsp->apu_ram[adr] + (dsp->apu_ram[(adr + 1) & 0xffff] << 8) + ); + dsp->firBufferL[dsp->firBufferIndex] >>= 1; + dsp->firBufferR[dsp->firBufferIndex] = ( + dsp->apu_ram[(adr + 2) & 0xffff] + (dsp->apu_ram[(adr + 3) & 0xffff] << 8) + ); + dsp->firBufferR[dsp->firBufferIndex] >>= 1; + // calculate FIR-sum + int sumL = 0, sumR = 0; + for(int i = 0; i < 8; i++) { + sumL += (dsp->firBufferL[(dsp->firBufferIndex + i + 1) & 0x7] * dsp->firValues[i]) >> 6; + sumR += (dsp->firBufferR[(dsp->firBufferIndex + i + 1) & 0x7] * dsp->firValues[i]) >> 6; + if(i == 6) { + // clip to 16-bit before last addition + sumL = ((int16_t) (sumL & 0xffff)); // clip 16-bit + sumR = ((int16_t) (sumR & 0xffff)); // clip 16-bit + } + } + sumL = sumL < -0x8000 ? -0x8000 : (sumL > 0x7fff ? 0x7fff : sumL); // clamp 16-bit + sumR = sumR < -0x8000 ? -0x8000 : (sumR > 0x7fff ? 0x7fff : sumR); // clamp 16-bit + // modify output with sum + int outL = *outputL + ((sumL * dsp->echoVolumeL) >> 7); + int outR = *outputR + ((sumR * dsp->echoVolumeR) >> 7); + *outputL = outL < -0x8000 ? -0x8000 : (outL > 0x7fff ? 0x7fff : outL); // clamp 16-bit + *outputR = outR < -0x8000 ? -0x8000 : (outR > 0x7fff ? 0x7fff : outR); // clamp 16-bit + // get echo input + int inL = 0, inR = 0; + for(int i = 0; i < 8; i++) { + if(dsp->channel[i].echoEnable) { + inL += (dsp->channel[i].sampleOut * dsp->channel[i].volumeL) >> 6; + inR += (dsp->channel[i].sampleOut * dsp->channel[i].volumeR) >> 6; + inL = inL < -0x8000 ? -0x8000 : (inL > 0x7fff ? 0x7fff : inL); // clamp 16-bit + inR = inR < -0x8000 ? -0x8000 : (inR > 0x7fff ? 0x7fff : inR); // clamp 16-bit + } + } + // write this to ram + inL += (sumL * dsp->feedbackVolume) >> 7; + inR += (sumR * dsp->feedbackVolume) >> 7; + inL = inL < -0x8000 ? -0x8000 : (inL > 0x7fff ? 0x7fff : inL); // clamp 16-bit + inR = inR < -0x8000 ? -0x8000 : (inR > 0x7fff ? 0x7fff : inR); // clamp 16-bit + inL &= 0xfffe; + inR &= 0xfffe; + if(dsp->echoWrites) { + dsp->apu_ram[adr] = inL & 0xff; + dsp->apu_ram[(adr + 1) & 0xffff] = inL >> 8; + dsp->apu_ram[(adr + 2) & 0xffff] = inR & 0xff; + dsp->apu_ram[(adr + 3) & 0xffff] = inR >> 8; + } + // handle indexes + dsp->firBufferIndex++; + dsp->firBufferIndex &= 7; + dsp->echoBufferIndex++; + dsp->echoRemain--; + if(dsp->echoRemain == 0) { + dsp->echoRemain = dsp->echoDelay; + dsp->echoBufferIndex = 0; + } +} + +static void dsp_cycleChannel(Dsp* dsp, int ch) { + // handle pitch counter + uint16_t pitch = dsp->channel[ch].pitch; + if(ch > 0 && dsp->channel[ch].pitchModulation) { + int factor = (dsp->channel[ch - 1].sampleOut >> 4) + 0x400; + pitch = (pitch * factor) >> 10; + if(pitch > 0x3fff) pitch = 0x3fff; + } + int newCounter = dsp->channel[ch].pitchCounter + pitch; + if(newCounter > 0xffff) { + // next sample + dsp_decodeBrr(dsp, ch); + } + dsp->channel[ch].pitchCounter = newCounter; + int16_t sample = 0; + if(dsp->channel[ch].useNoise) { + sample = dsp->noiseSample; + } else { + sample = dsp_getSample(dsp, ch, dsp->channel[ch].pitchCounter >> 12, (dsp->channel[ch].pitchCounter >> 4) & 0xff); + } +#if !MY_CHANGES + if(dsp->evenCycle) { + // handle keyon/off (every other cycle) + if(dsp->channel[ch].keyOff) { + // go to release + dsp->channel[ch].adsrState = 4; + } else if(dsp->channel[ch].keyOn) { + dsp->channel[ch].keyOn = false; + // restart current sample + dsp->channel[ch].previousFlags = 0; + uint16_t samplePointer = dsp->dirPage + 4 * dsp->channel[ch].srcn; + dsp->channel[ch].decodeOffset = dsp->apu_ram[samplePointer]; + dsp->channel[ch].decodeOffset |= dsp->apu_ram[(samplePointer + 1) & 0xffff] << 8; + memset(dsp->channel[ch].decodeBuffer, 0, sizeof(dsp->channel[ch].decodeBuffer)); + dsp->channel[ch].gain = 0; + dsp->channel[ch].adsrState = dsp->channel[ch].useGain ? 3 : 0; + } + } +#endif + // handle reset + if(dsp->reset) { + dsp->channel[ch].adsrState = 4; + dsp->channel[ch].gain = 0; + } + // handle envelope/adsr + bool doingDirectGain = dsp->channel[ch].adsrState != 4 && dsp->channel[ch].useGain && dsp->channel[ch].directGain; + uint16_t rate = dsp->channel[ch].adsrState == 4 ? 0 : dsp->channel[ch].adsrRates[dsp->channel[ch].adsrState]; + if(dsp->channel[ch].adsrState != 4 && !doingDirectGain && rate != 0) { + dsp->channel[ch].rateCounter++; + } + if(dsp->channel[ch].adsrState == 4 || (!doingDirectGain && dsp->channel[ch].rateCounter >= rate && rate != 0)) { + if(dsp->channel[ch].adsrState != 4) dsp->channel[ch].rateCounter = 0; + dsp_handleGain(dsp, ch); + } + if(doingDirectGain) dsp->channel[ch].gain = dsp->channel[ch].gainValue; + // set outputs + dsp->ram[(ch << 4) | 8] = dsp->channel[ch].gain >> 4; + sample = (sample * dsp->channel[ch].gain) >> 11; + dsp->ram[(ch << 4) | 9] = sample >> 7; + dsp->channel[ch].sampleOut = sample; +} + +static void dsp_handleGain(Dsp* dsp, int ch) { + switch(dsp->channel[ch].adsrState) { + case 0: { // attack + uint16_t rate = dsp->channel[ch].adsrRates[dsp->channel[ch].adsrState]; + dsp->channel[ch].gain += rate == 1 ? 1024 : 32; + if(dsp->channel[ch].gain >= 0x7e0) dsp->channel[ch].adsrState = 1; + if(dsp->channel[ch].gain > 0x7ff) dsp->channel[ch].gain = 0x7ff; + break; + } + case 1: { // decay + dsp->channel[ch].gain -= ((dsp->channel[ch].gain - 1) >> 8) + 1; + if(dsp->channel[ch].gain < dsp->channel[ch].sustainLevel) dsp->channel[ch].adsrState = 2; + break; + } + case 2: { // sustain + dsp->channel[ch].gain -= ((dsp->channel[ch].gain - 1) >> 8) + 1; + break; + } + case 3: { // gain + switch(dsp->channel[ch].gainMode) { + case 0: { // linear decrease + dsp->channel[ch].gain -= 32; + // decreasing below 0 will underflow to above 0x7ff + if(dsp->channel[ch].gain > 0x7ff) dsp->channel[ch].gain = 0; + break; + } + case 1: { // exponential decrease + dsp->channel[ch].gain -= ((dsp->channel[ch].gain - 1) >> 8) + 1; + break; + } + case 2: { // linear increase + dsp->channel[ch].gain += 32; + if(dsp->channel[ch].gain > 0x7ff) dsp->channel[ch].gain = 0x7ff; + break; + } + case 3: { // bent increase + dsp->channel[ch].gain += dsp->channel[ch].gain < 0x600 ? 32 : 8; + if(dsp->channel[ch].gain > 0x7ff) dsp->channel[ch].gain = 0x7ff; + break; + } + } + break; + } + case 4: { // release + dsp->channel[ch].gain -= 8; + // decreasing below 0 will underflow to above 0x7ff + if(dsp->channel[ch].gain > 0x7ff) dsp->channel[ch].gain = 0; + break; + } + } +} + +static int16_t dsp_getSample(Dsp* dsp, int ch, int sampleNum, int offset) { + int16_t news = dsp->channel[ch].decodeBuffer[sampleNum + 3]; + int16_t olds = dsp->channel[ch].decodeBuffer[sampleNum + 2]; + int16_t olders = dsp->channel[ch].decodeBuffer[sampleNum + 1]; + int16_t oldests = dsp->channel[ch].decodeBuffer[sampleNum]; + int out = (gaussValues[0xff - offset] * oldests) >> 10; + out += (gaussValues[0x1ff - offset] * olders) >> 10; + out += (gaussValues[0x100 + offset] * olds) >> 10; + out = ((int16_t) (out & 0xffff)); // clip 16-bit + out += (gaussValues[offset] * news) >> 10; + out = out < -0x8000 ? -0x8000 : (out > 0x7fff ? 0x7fff : out); // clamp 16-bit + return out >> 1; +} + +static void dsp_decodeBrr(Dsp* dsp, int ch) { + // copy last 3 samples (16-18) to first 3 for interpolation + dsp->channel[ch].decodeBuffer[0] = dsp->channel[ch].decodeBuffer[16]; + dsp->channel[ch].decodeBuffer[1] = dsp->channel[ch].decodeBuffer[17]; + dsp->channel[ch].decodeBuffer[2] = dsp->channel[ch].decodeBuffer[18]; + // handle flags from previous block + if(dsp->channel[ch].previousFlags == 1 || dsp->channel[ch].previousFlags == 3) { + // loop sample + uint16_t samplePointer = dsp->dirPage + 4 * dsp->channel[ch].srcn; + dsp->channel[ch].decodeOffset = dsp->apu_ram[(samplePointer + 2) & 0xffff]; + dsp->channel[ch].decodeOffset |= (dsp->apu_ram[(samplePointer + 3) & 0xffff]) << 8; + if(dsp->channel[ch].previousFlags == 1) { + // also release and clear gain + dsp->channel[ch].adsrState = 4; + dsp->channel[ch].gain = 0; + } + dsp->ram[0x7c] |= 1 << ch; // set ENDx + } + uint8_t header = dsp->apu_ram[dsp->channel[ch].decodeOffset++]; + int shift = header >> 4; + int filter = (header & 0xc) >> 2; + dsp->channel[ch].previousFlags = header & 0x3; + uint8_t curByte = 0; + int old = dsp->channel[ch].old; + int older = dsp->channel[ch].older; + for(int i = 0; i < 16; i++) { + int s = 0; + if(i & 1) { + s = curByte & 0xf; + } else { + curByte = dsp->apu_ram[dsp->channel[ch].decodeOffset++]; + s = curByte >> 4; + } + if(s > 7) s -= 16; + if(shift <= 0xc) { + s = (s << shift) >> 1; + } else { + s = (s >> 3) << 12; + } + switch(filter) { + case 1: s += old + (-old >> 4); break; + case 2: s += 2 * old + ((3 * -old) >> 5) - older + (older >> 4); break; + case 3: s += 2 * old + ((13 * -old) >> 6) - older + ((3 * older) >> 4); break; + } + s = s < -0x8000 ? -0x8000 : (s > 0x7fff ? 0x7fff : s); // clamp 16-bit + s = ((int16_t) ((s & 0x7fff) << 1)) >> 1; // clip 15-bit + older = old; + old = s; + dsp->channel[ch].decodeBuffer[i + 3] = s; + } + dsp->channel[ch].older = older; + dsp->channel[ch].old = old; +} + +static void dsp_handleNoise(Dsp* dsp) { + if(dsp->noiseRate != 0) { + dsp->noiseCounter++; + } + if(dsp->noiseCounter >= dsp->noiseRate && dsp->noiseRate != 0) { + int bit = (dsp->noiseSample & 1) ^ ((dsp->noiseSample >> 1) & 1); + dsp->noiseSample = ((dsp->noiseSample >> 1) & 0x3fff) | (bit << 14); + dsp->noiseSample = ((int16_t) ((dsp->noiseSample & 0x7fff) << 1)) >> 1; + dsp->noiseCounter = 0; + } +} + +uint8_t dsp_read(Dsp* dsp, uint8_t adr) { + return dsp->ram[adr]; +} + +void dsp_write(Dsp* dsp, uint8_t adr, uint8_t val) { + int ch = adr >> 4; + switch(adr) { + case 0x00: case 0x10: case 0x20: case 0x30: case 0x40: case 0x50: case 0x60: case 0x70: { + dsp->channel[ch].volumeL = val; + break; + } + case 0x01: case 0x11: case 0x21: case 0x31: case 0x41: case 0x51: case 0x61: case 0x71: { + dsp->channel[ch].volumeR = val; + break; + } + case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52: case 0x62: case 0x72: { + dsp->channel[ch].pitch = (dsp->channel[ch].pitch & 0x3f00) | val; + break; + } + case 0x03: case 0x13: case 0x23: case 0x33: case 0x43: case 0x53: case 0x63: case 0x73: { + dsp->channel[ch].pitch = ((dsp->channel[ch].pitch & 0x00ff) | (val << 8)) & 0x3fff; + break; + } + case 0x04: case 0x14: case 0x24: case 0x34: case 0x44: case 0x54: case 0x64: case 0x74: { + dsp->channel[ch].srcn = val; + break; + } + case 0x05: case 0x15: case 0x25: case 0x35: case 0x45: case 0x55: case 0x65: case 0x75: { + dsp->channel[ch].adsrRates[0] = rateValues[(val & 0xf) * 2 + 1]; + dsp->channel[ch].adsrRates[1] = rateValues[((val & 0x70) >> 4) * 2 + 16]; + dsp->channel[ch].useGain = (val & 0x80) == 0; + break; + } + case 0x06: case 0x16: case 0x26: case 0x36: case 0x46: case 0x56: case 0x66: case 0x76: { + dsp->channel[ch].adsrRates[2] = rateValues[val & 0x1f]; + dsp->channel[ch].sustainLevel = (((val & 0xe0) >> 5) + 1) * 0x100; + break; + } + case 0x07: case 0x17: case 0x27: case 0x37: case 0x47: case 0x57: case 0x67: case 0x77: { + dsp->channel[ch].directGain = (val & 0x80) == 0; + if(val & 0x80) { + dsp->channel[ch].gainMode = (val & 0x60) >> 5; + dsp->channel[ch].adsrRates[3] = rateValues[val & 0x1f]; + } else { + dsp->channel[ch].gainValue = (val & 0x7f) * 16; + } + break; + } + case 0x0c: { + dsp->masterVolumeL = val; + break; + } + case 0x1c: { + dsp->masterVolumeR = val; + break; + } + case 0x2c: { + dsp->echoVolumeL = val; + break; + } + case 0x3c: { + dsp->echoVolumeR = val; + break; + } + case 0x4c: { + for(int ch = 0; ch < 8; ch++) { + dsp->channel[ch].keyOn = val & (1 << ch); +#if MY_CHANGES + if (dsp->channel[ch].keyOn) { + dsp->channel[ch].keyOn = false; + // restart current sample + dsp->channel[ch].previousFlags = 0; + uint16_t samplePointer = dsp->dirPage + 4 * dsp->channel[ch].srcn; + dsp->channel[ch].decodeOffset = dsp->apu_ram[samplePointer]; + dsp->channel[ch].decodeOffset |= dsp->apu_ram[(samplePointer + 1) & 0xffff] << 8; + memset(dsp->channel[ch].decodeBuffer, 0, sizeof(dsp->channel[ch].decodeBuffer)); + dsp->channel[ch].gain = 0; + dsp->channel[ch].adsrState = dsp->channel[ch].useGain ? 3 : 0; + } +#endif + } + break; + } + case 0x5c: { + for(int ch = 0; ch < 8; ch++) { + dsp->channel[ch].keyOff = val & (1 << ch); +#if MY_CHANGES + if (dsp->channel[ch].keyOff) { + // go to release + dsp->channel[ch].adsrState = 4; + } +#endif + } + break; + } + case 0x6c: { + dsp->reset = val & 0x80; + dsp->mute = val & 0x40; + dsp->echoWrites = (val & 0x20) == 0; + dsp->noiseRate = rateValues[val & 0x1f]; + break; + } + case 0x7c: { + val = 0; // any write clears ENDx + break; + } + case 0x0d: { + dsp->feedbackVolume = val; + break; + } + case 0x2d: { + for(int i = 0; i < 8; i++) { + dsp->channel[i].pitchModulation = val & (1 << i); + } + break; + } + case 0x3d: { + for(int i = 0; i < 8; i++) { + dsp->channel[i].useNoise = val & (1 << i); + } + break; + } + case 0x4d: { + for(int i = 0; i < 8; i++) { + dsp->channel[i].echoEnable = val & (1 << i); + } + break; + } + case 0x5d: { + dsp->dirPage = val << 8; + break; + } + case 0x6d: { + dsp->echoBufferAdr = val << 8; + break; + } + case 0x7d: { + dsp->echoDelay = (val & 0xf) * 512; // 2048-byte steps, stereo sample is 4 bytes + if(dsp->echoDelay == 0) dsp->echoDelay = 1; + break; + } + case 0x0f: case 0x1f: case 0x2f: case 0x3f: case 0x4f: case 0x5f: case 0x6f: case 0x7f: { + dsp->firValues[ch] = val; + break; + } + } + dsp->ram[adr] = val; +} + +void dsp_getSamples(Dsp* dsp, int16_t* sampleData, int samplesPerFrame) { + // resample from 534 samples per frame to wanted value + double adder = 534.0 / samplesPerFrame; + double location = 0.0; + for(int i = 0; i < samplesPerFrame; i++) { + sampleData[i * 2] = dsp->sampleBuffer[((int) location) * 2]; + sampleData[i * 2 + 1] = dsp->sampleBuffer[((int) location) * 2 + 1]; + location += adder; + } + dsp->sampleOffset = 0; +} diff --git a/src/snes/dsp.h b/src/snes/dsp.h new file mode 100644 index 0000000..8b695f7 --- /dev/null +++ b/src/snes/dsp.h @@ -0,0 +1,99 @@ + +#ifndef DSP_H +#define DSP_H + +#include +#include +#include +#include +#include +#include "saveload.h" + +typedef struct Dsp Dsp; + +typedef struct Apu Apu; + +typedef struct DspChannel { + // pitch + uint16_t pitch; + uint16_t pitchCounter; + bool pitchModulation; + // brr decoding + int16_t decodeBuffer[19]; // 16 samples per brr-block, +3 for interpolation + uint8_t srcn; + uint16_t decodeOffset; + uint8_t previousFlags; // from last sample + int16_t old; + int16_t older; + bool useNoise; + // adsr, envelope, gain + uint16_t adsrRates[4]; // attack, decay, sustain, gain + uint16_t rateCounter; + uint8_t adsrState; // 0: attack, 1: decay, 2: sustain, 3: gain, 4: release + uint16_t sustainLevel; + bool useGain; + uint8_t gainMode; + bool directGain; + uint16_t gainValue; // for direct gain + uint16_t gain; + // keyon/off + bool keyOn; + bool keyOff; + // output + int16_t sampleOut; // final sample, to be multiplied by channel volume + int8_t volumeL; + int8_t volumeR; + bool echoEnable; +} DspChannel; + +struct Dsp { + uint8_t *apu_ram; + // mirror ram + uint8_t ram[0x80]; + // 8 channels + DspChannel channel[8]; + // overarching + uint16_t dirPage; + bool evenCycle; + bool mute; + bool reset; + int8_t masterVolumeL; + int8_t masterVolumeR; + // noise + int16_t noiseSample; + uint16_t noiseRate; + uint16_t noiseCounter; + // echo + bool echoWrites; + int8_t echoVolumeL; + int8_t echoVolumeR; + int8_t feedbackVolume; + uint16_t echoBufferAdr; + uint16_t echoDelay; + uint16_t echoRemain; + uint16_t echoBufferIndex; + uint8_t firBufferIndex; + int8_t firValues[8]; + int16_t firBufferL[8]; + int16_t firBufferR[8]; + // sample buffer (1 frame at 32040 Hz: 534 samples, *2 for stereo) + int16_t sampleBuffer[534 * 2]; + uint16_t sampleOffset; // current offset in samplebuffer +}; + +typedef struct DspRegWriteHistory { + uint32_t count; + uint8_t addr[256]; + uint8_t val[256]; +} DspRegWriteHistory; + +Dsp *dsp_init(uint8_t *ram); +void dsp_free(Dsp* dsp); +void dsp_reset(Dsp* dsp); +void dsp_cycle(Dsp* dsp); +uint8_t dsp_read(Dsp* dsp, uint8_t adr); +void dsp_write(Dsp* dsp, uint8_t adr, uint8_t val); +void dsp_getSamples(Dsp* dsp, int16_t* sampleData, int samplesPerFrame); +void dsp_saveload(Dsp *dsp, SaveLoadFunc *func, void *ctx); + +#endif diff --git a/src/snes/dsp_regs.h b/src/snes/dsp_regs.h new file mode 100644 index 0000000..03f73d2 --- /dev/null +++ b/src/snes/dsp_regs.h @@ -0,0 +1,109 @@ +#ifndef DSP_REGS_H +#define DSP_REGS_H + +enum DspReg { + V0VOLL = 0x00, + V0VOLR = 0x01, + V0PITCHL = 0x02, + V0PITCHH = 0x03, + V0SRCN = 0x04, + V0ADSR1 = 0x05, + V0ADSR2 = 0x06, + V0GAIN = 0x07, + V0ENVX = 0x08, + V0OUTX = 0x09, + MVOLL = 0x0C, + EFB = 0x0D, + FIR0 = 0x0F, + V1VOLL = 0x10, + V1VOLR = 0x11, + V1PL = 0x12, + V1PH = 0x13, + V1SRCN = 0x14, + V1ADSR1 = 0x15, + V1ADSR2 = 0x16, + V1GAIN = 0x17, + V1ENVX = 0x18, + V1OUTX = 0x19, + MVOLR = 0x1C, + FIR1 = 0x1F, + V2VOLL = 0x20, + V2VOLR = 0x21, + V2PL = 0x22, + V2PH = 0x23, + V2SRCN = 0x24, + V2ADSR1 = 0x25, + V2ADSR2 = 0x26, + V2GAIN = 0x27, + V2ENVX = 0x28, + V2OUTX = 0x29, + EVOLL = 0x2C, + PMON = 0x2D, + FIR2 = 0x2F, + V3VOLL = 0x30, + V3VOLR = 0x31, + V3PL = 0x32, + V3PH = 0x33, + V3SRCN = 0x34, + V3ADSR1 = 0x35, + V3ADSR2 = 0x36, + V3GAIN = 0x37, + V3ENVX = 0x38, + V3OUTX = 0x39, + EVOLR = 0x3C, + NON = 0x3D, + FIR3 = 0x3F, + V4VOLL = 0x40, + V4VOLR = 0x41, + V4PL = 0x42, + V4PH = 0x43, + V4SRCN = 0x44, + V4ADSR1 = 0x45, + V4ADSR2 = 0x46, + V4GAIN = 0x47, + V4ENVX = 0x48, + V4OUTX = 0x49, + KON = 0x4C, + EON = 0x4D, + FIR4 = 0x4F, + V5VOLL = 0x50, + V5VOLR = 0x51, + V5PL = 0x52, + V5PH = 0x53, + V5SRCN = 0x54, + V5ADSR1 = 0x55, + V5ADSR2 = 0x56, + V5GAIN = 0x57, + V5ENVX = 0x58, + V5OUTX = 0x59, + KOF = 0x5C, + DIR = 0x5D, + FIR5 = 0x5F, + V6VOLL = 0x60, + V6VOLR = 0x61, + V6PL = 0x62, + V6PH = 0x63, + V6SRCN = 0x64, + V6ADSR1 = 0x65, + V6ADSR2 = 0x66, + V6GAIN = 0x67, + V6ENVX = 0x68, + V6OUTX = 0x69, + FLG = 0x6C, + ESA = 0x6D, + FIR6 = 0x6F, + V7VOLL = 0x70, + V7VOLR = 0x71, + V7PL = 0x72, + V7PH = 0x73, + V7SRCN = 0x74, + V7ADSR1 = 0x75, + V7ADSR2 = 0x76, + V7GAIN = 0x77, + V7ENVX = 0x78, + V7OUTX = 0x79, + ENDX = 0x7C, + EDL = 0x7D, + FIR7 = 0x7F, +}; +#endif // DSP_REGS_H \ No newline at end of file diff --git a/src/snes/input.c b/src/snes/input.c new file mode 100644 index 0000000..2327be3 --- /dev/null +++ b/src/snes/input.c @@ -0,0 +1,26 @@ + +#include +#include +#include +#include +#include + +#include "input.h" +#include "snes.h" + +Input* input_init(Snes* snes) { + Input* input = malloc(sizeof(Input)); + input->snes = snes; + // TODO: handle (where?) + input->type = 1; + input->currentState = 0; + return input; +} + +void input_free(Input* input) { + free(input); +} + +void input_reset(Input* input) { +} + diff --git a/src/snes/input.h b/src/snes/input.h new file mode 100644 index 0000000..be45fed --- /dev/null +++ b/src/snes/input.h @@ -0,0 +1,26 @@ + +#ifndef INPUT_H +#define INPUT_H + +#include +#include +#include +#include +#include + +typedef struct Input Input; + +#include "snes.h" + +struct Input { + Snes* snes; + uint8_t type; + // for controller + uint16_t currentState; // actual state +}; + +Input* input_init(Snes* snes); +void input_free(Input* input); +void input_reset(Input* input); + +#endif diff --git a/src/snes/ppu.c b/src/snes/ppu.c new file mode 100644 index 0000000..95e5088 --- /dev/null +++ b/src/snes/ppu.c @@ -0,0 +1,1619 @@ + +#include +#include +#include +#include +#include +#include + +#include "ppu.h" +#include "snes.h" +#include "../types.h" +typedef uint64_t uint64; +typedef uint32_t uint32; +typedef uint32_t uint; +typedef uint16_t uint16; +typedef int16_t int16; +typedef uint8_t uint8; + +extern bool g_new_ppu; +static void PpuDrawWholeLine(Ppu *ppu, uint y); + +// array for layer definitions per mode: +// 0-7: mode 0-7; 8: mode 1 + l3prio; 9: mode 7 + extbg + +// 0-3; layers 1-4; 4: sprites; 5: nonexistent +static const int layersPerMode[10][12] = { + {4, 0, 1, 4, 0, 1, 4, 2, 3, 4, 2, 3}, + {4, 0, 1, 4, 0, 1, 4, 2, 4, 2, 5, 5}, + {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, + {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, + {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, + {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, + {4, 0, 4, 4, 0, 4, 5, 5, 5, 5, 5, 5}, + {4, 4, 4, 0, 4, 5, 5, 5, 5, 5, 5, 5}, + {2, 4, 0, 1, 4, 0, 1, 4, 4, 2, 5, 5}, + {4, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5, 5} +}; + +static const int prioritysPerMode[10][12] = { + {3, 1, 1, 2, 0, 0, 1, 1, 1, 0, 0, 0}, + {3, 1, 1, 2, 0, 0, 1, 1, 0, 0, 5, 5}, + {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, + {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, + {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, + {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, + {3, 1, 2, 1, 0, 0, 5, 5, 5, 5, 5, 5}, + {3, 2, 1, 0, 0, 5, 5, 5, 5, 5, 5, 5}, + {1, 3, 1, 1, 2, 0, 0, 1, 0, 0, 5, 5}, + {3, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5, 5} +}; + +static const int layerCountPerMode[10] = { + 12, 10, 8, 8, 8, 8, 6, 5, 10, 7 +}; + +static const int bitDepthsPerMode[10][4] = { + {2, 2, 2, 2}, + {4, 4, 2, 5}, + {4, 4, 5, 5}, + {8, 4, 5, 5}, + {8, 2, 5, 5}, + {4, 2, 5, 5}, + {4, 5, 5, 5}, + {8, 5, 5, 5}, + {4, 4, 2, 5}, + {8, 7, 5, 5} +}; + +static const int spriteSizes[8][2] = { + {8, 16}, {8, 32}, {8, 64}, {16, 32}, + {16, 64}, {32, 64}, {16, 32}, {16, 32} +}; + +static void ppu_handlePixel(Ppu* ppu, int x, int y); +static int ppu_getPixel(Ppu* ppu, int x, int y, bool sub, int* r, int* g, int* b); +static uint16_t ppu_getOffsetValue(Ppu* ppu, int col, int row); +static int ppu_getPixelForBgLayer(Ppu* ppu, int x, int y, int layer, bool priority); +static void ppu_handleOPT(Ppu* ppu, int layer, int* lx, int* ly); +static void ppu_calculateMode7Starts(Ppu* ppu, int y); +static int ppu_getPixelForMode7(Ppu* ppu, int x, int layer, bool priority); +static bool ppu_getWindowState(Ppu* ppu, int layer, int x); +static bool ppu_evaluateSprites(Ppu* ppu, int line); +static uint16_t ppu_getVramRemap(Ppu* ppu); +#define SPRITE_PRIO_TO_PRIO(prio, level6) (((prio) * 4 + 2) * 16 + 4 + (level6 ? 2 : 0)) +#define SPRITE_PRIO_TO_PRIO_HI(prio) ((prio) * 4 + 2) + + +#define IS_SCREEN_ENABLED(ppu, sub, layer) (ppu->screenEnabled[sub] & (1 << layer)) +#define IS_SCREEN_WINDOWED(ppu, sub, layer) (ppu->screenWindowed[sub] & (1 << layer)) +#define IS_MOSAIC_ENABLED(ppu, layer) ((ppu->mosaicEnabled & (1 << layer))) +#define GET_WINDOW_FLAGS(ppu, layer) (ppu->windowsel >> (layer * 4)) +enum { + kWindow1Inversed = 1, + kWindow1Enabled = 2, + kWindow2Inversed = 4, + kWindow2Enabled = 8, +}; + +Ppu* ppu_init(Snes* snes) { + Ppu* ppu = malloc(sizeof(Ppu)); + ppu->snes = snes; + return ppu; +} + +void ppu_free(Ppu* ppu) { + free(ppu); +} + +void ppu_copy(Ppu *ppu, Ppu *ppu_src) { + Snes *snes = ppu->snes; + size_t pitch = ppu->renderPitch; + uint8_t *renderBuffer = ppu->renderBuffer; + memcpy(ppu, ppu_src, sizeof(*ppu)); + ppu->renderBuffer = renderBuffer; + ppu->renderPitch = (uint32_t)pitch; + ppu->snes = snes; +} + +void ppu_reset(Ppu* ppu) { + { + Snes *snes = ppu->snes; + size_t pitch = ppu->renderPitch; + uint8_t *renderBuffer = ppu->renderBuffer; + memset(ppu, 0, sizeof(*ppu)); + ppu->renderBuffer = renderBuffer; + ppu->renderPitch = (uint32_t)pitch; + ppu->snes = snes; + } + ppu->vramPointer = 0; + ppu->vramIncrementOnHigh = false; + ppu->vramIncrement = 1; + ppu->vramRemapMode = 0; + ppu->vramReadBuffer = 0; + memset(ppu->cgram, 0, sizeof(ppu->cgram)); + ppu->cgramPointer = 0; + ppu->cgramSecondWrite = false; + ppu->cgramBuffer = 0; + memset(ppu->oam, 0, sizeof(ppu->oam)); + memset(ppu->highOam, 0, sizeof(ppu->highOam)); + ppu->oamAdr = 0; + ppu->oamAdrWritten = 0; + ppu->oamInHigh = false; + ppu->oamInHighWritten = false; + ppu->oamSecondWrite = false; + ppu->oamBuffer = 0; + ppu->objPriority = false; + ppu->objTileAdr1 = 0; + ppu->objTileAdr2 = 0; + ppu->objSize = 0; + ppu->timeOver = false; + ppu->rangeOver = false; + ppu->objInterlace = false; + for(int i = 0; i < 4; i++) { + ppu->bgLayer[i].hScroll = 0; + ppu->bgLayer[i].vScroll = 0; + ppu->bgLayer[i].tilemapWider = false; + ppu->bgLayer[i].tilemapHigher = false; + ppu->bgLayer[i].tilemapAdr = 0; + ppu->bgLayer[i].tileAdr = 0; + ppu->bgLayer[i].bigTiles = false; + ppu->bgLayer[i].mosaicEnabled = false; + } + ppu->scrollPrev = 0; + ppu->scrollPrev2 = 0; + ppu->mosaicSize = 1; + ppu->mosaicStartLine = 1; + for(int i = 0; i < 5; i++) { + ppu->layer[i].mainScreenEnabled = false; + ppu->layer[i].subScreenEnabled = false; + ppu->layer[i].mainScreenWindowed = false; + ppu->layer[i].subScreenWindowed = false; + } + memset(ppu->m7matrix, 0, sizeof(ppu->m7matrix)); + ppu->m7prev = 0; + ppu->m7largeField = false; + ppu->m7charFill = false; + ppu->m7xFlip = false; + ppu->m7yFlip = false; + ppu->m7extBg = false; + ppu->m7startX = 0; + ppu->m7startY = 0; + for(int i = 0; i < 6; i++) { + ppu->windowLayer[i].window1enabled = false; + ppu->windowLayer[i].window2enabled = false; + ppu->windowLayer[i].window1inversed = false; + ppu->windowLayer[i].window2inversed = false; + ppu->windowLayer[i].maskLogic = 0; + } + ppu->window1left = 0; + ppu->window1right = 0; + ppu->window2left = 0; + ppu->window2right = 0; + ppu->clipMode = 0; + ppu->preventMathMode = 0; + ppu->addSubscreen = false; + ppu->subtractColor = false; + ppu->halfColor = false; + memset(ppu->mathEnabled, 0, sizeof(ppu->mathEnabled)); + ppu->fixedColorR = 0; + ppu->fixedColorG = 0; + ppu->fixedColorB = 0; + ppu->forcedBlank = true; + ppu->brightness = 0; + ppu->mode = 0; + ppu->bg3priority = false; + ppu->evenFrame = false; + ppu->pseudoHires = false; + ppu->overscan = false; + ppu->frameOverscan = false; + ppu->interlace = false; + ppu->frameInterlace = false; + ppu->directColor = false; + ppu->hCount = 0; + ppu->vCount = 0; + ppu->hCountSecond = false; + ppu->vCountSecond = false; + ppu->countersLatched = false; + ppu->ppu1openBus = 0; + ppu->ppu2openBus = 0; +} + +void ppu_saveload(Ppu *ppu, SaveLoadFunc *func, void *ctx) { + func(ctx, &ppu->vram, offsetof(Ppu, pixelbuffer_placeholder) - offsetof(Ppu, vram)); +} + +void PpuBeginDrawing(Ppu *ppu, uint8_t *pixels, size_t pitch, uint32_t render_flags) { + ppu->renderPitch = (uint)pitch; + ppu->renderBuffer = pixels; +} + +bool ppu_checkOverscan(Ppu* ppu) { + // called at (0,225) + ppu->frameOverscan = ppu->overscan; // set if we have a overscan-frame + return ppu->frameOverscan; +} + +void ppu_handleVblank(Ppu* ppu) { + // called either right after ppu_checkOverscan at (0,225), or at (0,240) + if(!ppu->forcedBlank) { + ppu->oamAdr = ppu->oamAdrWritten; + ppu->oamInHigh = ppu->oamInHighWritten; + ppu->oamSecondWrite = false; + } + ppu->frameInterlace = ppu->interlace; // set if we have a interlaced frame +} + +static inline void ClearBackdrop(PpuPixelPrioBufs *buf) { + for (size_t i = 0; i != arraysize(buf->data); i += 4) + *(uint64*)&buf->data[i] = 0x0500050005000500; +} + +void ppu_runLine(Ppu* ppu, int line) { + if(line == 0) { + // pre-render line + // TODO: this now happens halfway into the first line + ppu->mosaicStartLine = 1; + ppu->rangeOver = false; + ppu->timeOver = false; + ppu->evenFrame = !ppu->evenFrame; + } else { + // Cache the brightness computation + if (ppu->brightness != ppu->lastBrightnessMult) { + uint8_t ppu_brightness = ppu->brightness; + ppu->lastBrightnessMult = ppu_brightness; + for (int i = 0; i < 32; i++) + ppu->brightnessMultHalf[i * 2] = ppu->brightnessMultHalf[i * 2 + 1] = ppu->brightnessMult[i] = + ((i << 3) | (i >> 2)) * ppu_brightness / 15; + // Store 31 extra entries to remove the need for clamping to 31. + memset(&ppu->brightnessMult[32], ppu->brightnessMult[31], 31); + } + + // evaluate sprites + ClearBackdrop(&ppu->objBuffer); + ppu->lineHasSprites = !ppu->forcedBlank && ppu_evaluateSprites(ppu, line - 1); + + if (g_new_ppu) { + PpuDrawWholeLine(ppu, line); + } else { + // actual line + if (ppu->mode == 7) ppu_calculateMode7Starts(ppu, line); + for (int x = 0; x < 256; x++) { + ppu_handlePixel(ppu, x, line); + } + } + } +} + +typedef struct PpuWindows { + int16 edges[6]; + uint8 nr; + uint8 bits; +} PpuWindows; + +static void PpuWindows_Clear(PpuWindows *win, Ppu *ppu, uint layer) { + win->edges[0] = -(layer != 2 ? ppu->extraLeftCur : 0); + win->edges[1] = 256 + (layer != 2 ? ppu->extraRightCur : 0); + win->nr = 1; + win->bits = 0; +} + +static void PpuWindows_Calc(PpuWindows *win, Ppu *ppu, uint layer) { + // Evaluate which spans to render based on the window settings. + // There are at most 5 windows. + // Algorithm from Snes9x + uint32 winflags = GET_WINDOW_FLAGS(ppu, layer); + uint nr = 1; + int window_right = 256 + (layer != 2 ? ppu->extraRightCur : 0); + win->edges[0] = - (layer != 2 ? ppu->extraLeftCur : 0); + win->edges[1] = window_right; + uint i, j; + int t; + bool w1_ena = (winflags & kWindow1Enabled) && ppu->window1left <= ppu->window1right; + if (w1_ena) { + if (ppu->window1left > win->edges[0]) { + win->edges[nr] = ppu->window1left; + win->edges[++nr] = window_right; + } + if (ppu->window1right + 1 < window_right) { + win->edges[nr] = ppu->window1right + 1; + win->edges[++nr] = window_right; + } + } + bool w2_ena = (winflags & kWindow2Enabled) && ppu->window2left <= ppu->window2right; + if (w2_ena) { + for (i = 0; i <= nr && (t = ppu->window2left) != win->edges[i]; i++) { + if (t < win->edges[i]) { + for (j = nr++; j >= i; j--) + win->edges[j + 1] = win->edges[j]; + win->edges[i] = t; + break; + } + } + for (; i <= nr && (t = ppu->window2right + 1) != win->edges[i]; i++) { + if (t < win->edges[i]) { + for (j = nr++; j >= i; j--) + win->edges[j + 1] = win->edges[j]; + win->edges[i] = t; + break; + } + } + } + win->nr = nr; + // get a bitmap of how regions map to windows + uint8 w1_bits = 0, w2_bits = 0; + if (w1_ena) { + for (i = 0; win->edges[i] != ppu->window1left; i++); + for (j = i; win->edges[j] != ppu->window1right + 1; j++); + w1_bits = ((1 << (j - i)) - 1) << i; + } + if ((winflags & (kWindow1Enabled | kWindow1Inversed)) == (kWindow1Enabled | kWindow1Inversed)) + w1_bits = ~w1_bits; + if (w2_ena) { + for (i = 0; win->edges[i] != ppu->window2left; i++); + for (j = i; win->edges[j] != ppu->window2right + 1; j++); + w2_bits = ((1 << (j - i)) - 1) << i; + } + if ((winflags & (kWindow2Enabled | kWindow2Inversed)) == (kWindow2Enabled | kWindow2Inversed)) + w2_bits = ~w2_bits; + win->bits = w1_bits | w2_bits; +} + +// Draw a whole line of a 4bpp background layer into bgBuffers +static void PpuDrawBackground_4bpp(Ppu *ppu, uint y, bool sub, uint layer, PpuZbufType zhi, PpuZbufType zlo) { +#define DO_PIXEL(i) do { \ + pixel = (bits >> i) & 1 | (bits >> (7 + i)) & 2 | (bits >> (14 + i)) & 4 | (bits >> (21 + i)) & 8; \ + if ((bits & (0x01010101 << i)) && z > dstz[i]) dstz[i] = z + pixel; } while (0) +#define DO_PIXEL_HFLIP(i) do { \ + pixel = (bits >> (7 - i)) & 1 | (bits >> (14 - i)) & 2 | (bits >> (21 - i)) & 4 | (bits >> (28 - i)) & 8; \ + if ((bits & (0x80808080 >> i)) && z > dstz[i]) dstz[i] = z + pixel; } while (0) +#define READ_BITS(ta, tile) (addr = &ppu->vram[((ta) + (tile) * 16) & 0x7fff], addr[0] | addr[8] << 16) + enum { kPaletteShift = 6 }; + if (!IS_SCREEN_ENABLED(ppu, sub, layer)) + return; // layer is completely hidden + PpuWindows win; + IS_SCREEN_WINDOWED(ppu, sub, layer) ? PpuWindows_Calc(&win, ppu, layer) : PpuWindows_Clear(&win, ppu, layer); + BgLayer *bglayer = &ppu->bgLayer[layer]; + y += bglayer->vScroll; + int sc_offs = bglayer->tilemapAdr + (((y >> 3) & 0x1f) << 5); + if ((y & 0x100) && bglayer->tilemapHigher) + sc_offs += bglayer->tilemapWider ? 0x800 : 0x400; + const uint16 *tps[2] = { + &ppu->vram[sc_offs & 0x7fff], + &ppu->vram[sc_offs + (bglayer->tilemapWider ? 0x400 : 0) & 0x7fff] + }; + int tileadr = ppu->bgLayer[layer].tileAdr, pixel; + int tileadr1 = tileadr + 7 - (y & 0x7), tileadr0 = tileadr + (y & 0x7); + const uint16 *addr; + for (size_t windex = 0; windex < win.nr; windex++) { + if (win.bits & (1 << windex)) + continue; // layer is disabled for this window part + uint x = win.edges[windex] + bglayer->hScroll; + uint w = win.edges[windex + 1] - win.edges[windex]; + PpuZbufType *dstz = ppu->bgBuffers[sub].data + win.edges[windex] + kPpuExtraLeftRight; + const uint16 *tp = tps[x >> 8 & 1] + ((x >> 3) & 0x1f); + const uint16 *tp_last = tps[x >> 8 & 1] + 31; + const uint16 *tp_next = tps[(x >> 8 & 1) ^ 1]; +#define NEXT_TP() if (tp != tp_last) tp += 1; else tp = tp_next, tp_next = tp_last - 31, tp_last = tp + 31; + // Handle clipped pixels on left side + if (x & 7) { + int curw = IntMin(8 - (x & 7), w); + w -= curw; + uint32 tile = *tp; + NEXT_TP(); + int ta = (tile & 0x8000) ? tileadr1 : tileadr0; + PpuZbufType z = (tile & 0x2000) ? zhi : zlo; + uint32 bits = READ_BITS(ta, tile & 0x3ff); + if (bits) { + z += ((tile & 0x1c00) >> kPaletteShift); + if (tile & 0x4000) { + bits >>= (x & 7), x += curw; + do DO_PIXEL(0); while (bits >>= 1, dstz++, --curw); + } else { + bits <<= (x & 7), x += curw; + do DO_PIXEL_HFLIP(0); while (bits <<= 1, dstz++, --curw); + } + } else { + dstz += curw; + } + } + // Handle full tiles in the middle + while (w >= 8) { + uint32 tile = *tp; + NEXT_TP(); + int ta = (tile & 0x8000) ? tileadr1 : tileadr0; + PpuZbufType z = (tile & 0x2000) ? zhi : zlo; + uint32 bits = READ_BITS(ta, tile & 0x3ff); + if (bits) { + z += ((tile & 0x1c00) >> kPaletteShift); + if (tile & 0x4000) { + DO_PIXEL(0); DO_PIXEL(1); DO_PIXEL(2); DO_PIXEL(3); + DO_PIXEL(4); DO_PIXEL(5); DO_PIXEL(6); DO_PIXEL(7); + } else { + DO_PIXEL_HFLIP(0); DO_PIXEL_HFLIP(1); DO_PIXEL_HFLIP(2); DO_PIXEL_HFLIP(3); + DO_PIXEL_HFLIP(4); DO_PIXEL_HFLIP(5); DO_PIXEL_HFLIP(6); DO_PIXEL_HFLIP(7); + } + } + dstz += 8, w -= 8; + } + // Handle remaining clipped part + if (w) { + uint32 tile = *tp; + int ta = (tile & 0x8000) ? tileadr1 : tileadr0; + PpuZbufType z = (tile & 0x2000) ? zhi : zlo; + uint32 bits = READ_BITS(ta, tile & 0x3ff); + if (bits) { + z += ((tile & 0x1c00) >> kPaletteShift); + if (tile & 0x4000) { + do DO_PIXEL(0); while (bits >>= 1, dstz++, --w); + } else { + do DO_PIXEL_HFLIP(0); while (bits <<= 1, dstz++, --w); + } + } + } + } +#undef READ_BITS +#undef DO_PIXEL +#undef DO_PIXEL_HFLIP +} + +// Draw a whole line of a 2bpp background layer into bgBuffers +static void PpuDrawBackground_2bpp(Ppu *ppu, uint y, bool sub, uint layer, PpuZbufType zhi, PpuZbufType zlo) { +#define DO_PIXEL(i) do { \ + pixel = (bits >> i) & 1 | (bits >> (7 + i)) & 2; \ + if (pixel && z > dstz[i]) dstz[i] = z + pixel; } while (0) +#define DO_PIXEL_HFLIP(i) do { \ + pixel = (bits >> (7 - i)) & 1 | (bits >> (14 - i)) & 2; \ + if (pixel && z > dstz[i]) dstz[i] = z + pixel; } while (0) +#define READ_BITS(ta, tile) (addr = &ppu->vram[(ta) + (tile) * 8 & 0x7fff], addr[0]) + enum { kPaletteShift = 8 }; + if (!IS_SCREEN_ENABLED(ppu, sub, layer)) + return; // layer is completely hidden + PpuWindows win; + IS_SCREEN_WINDOWED(ppu, sub, layer) ? PpuWindows_Calc(&win, ppu, layer) : PpuWindows_Clear(&win, ppu, layer); + BgLayer *bglayer = &ppu->bgLayer[layer]; + y += bglayer->vScroll; + int sc_offs = bglayer->tilemapAdr + (((y >> 3) & 0x1f) << 5); + if ((y & 0x100) && bglayer->tilemapHigher) + sc_offs += bglayer->tilemapWider ? 0x800 : 0x400; + const uint16 *tps[2] = { + &ppu->vram[sc_offs & 0x7fff], + &ppu->vram[sc_offs + (bglayer->tilemapWider ? 0x400 : 0) & 0x7fff] + }; + int tileadr = ppu->bgLayer[layer].tileAdr, pixel; + int tileadr1 = tileadr + 7 - (y & 0x7), tileadr0 = tileadr + (y & 0x7); + + const uint16 *addr; + for (size_t windex = 0; windex < win.nr; windex++) { + if (win.bits & (1 << windex)) + continue; // layer is disabled for this window part + uint x = win.edges[windex] + bglayer->hScroll; + uint w = win.edges[windex + 1] - win.edges[windex]; + PpuZbufType *dstz = ppu->bgBuffers[sub].data + win.edges[windex] + kPpuExtraLeftRight; + const uint16 *tp = tps[x >> 8 & 1] + ((x >> 3) & 0x1f); + const uint16 *tp_last = tps[x >> 8 & 1] + 31; + const uint16 *tp_next = tps[(x >> 8 & 1) ^ 1]; + +#define NEXT_TP() if (tp != tp_last) tp += 1; else tp = tp_next, tp_next = tp_last - 31, tp_last = tp + 31; + // Handle clipped pixels on left side + if (x & 7) { + int curw = IntMin(8 - (x & 7), w); + w -= curw; + uint32 tile = *tp; + NEXT_TP(); + int ta = (tile & 0x8000) ? tileadr1 : tileadr0; + PpuZbufType z = (tile & 0x2000) ? zhi : zlo; + uint32 bits = READ_BITS(ta, tile & 0x3ff); + if (bits) { + z += ((tile & 0x1c00) >> kPaletteShift); + if (tile & 0x4000) { + bits >>= (x & 7), x += curw; + do DO_PIXEL(0); while (bits >>= 1, dstz++, --curw); + } else { + bits <<= (x & 7), x += curw; + do DO_PIXEL_HFLIP(0); while (bits <<= 1, dstz++, --curw); + } + } else { + dstz += curw; + } + } + // Handle full tiles in the middle + while (w >= 8) { + uint32 tile = *tp; + NEXT_TP(); + int ta = (tile & 0x8000) ? tileadr1 : tileadr0; + PpuZbufType z = (tile & 0x2000) ? zhi : zlo; + uint32 bits = READ_BITS(ta, tile & 0x3ff); + if (bits) { + z += ((tile & 0x1c00) >> kPaletteShift); + if (tile & 0x4000) { + DO_PIXEL(0); DO_PIXEL(1); DO_PIXEL(2); DO_PIXEL(3); + DO_PIXEL(4); DO_PIXEL(5); DO_PIXEL(6); DO_PIXEL(7); + } else { + DO_PIXEL_HFLIP(0); DO_PIXEL_HFLIP(1); DO_PIXEL_HFLIP(2); DO_PIXEL_HFLIP(3); + DO_PIXEL_HFLIP(4); DO_PIXEL_HFLIP(5); DO_PIXEL_HFLIP(6); DO_PIXEL_HFLIP(7); + } + } + dstz += 8, w -= 8; + } + // Handle remaining clipped part + if (w) { + uint32 tile = *tp; + int ta = (tile & 0x8000) ? tileadr1 : tileadr0; + PpuZbufType z = (tile & 0x2000) ? zhi : zlo; + uint32 bits = READ_BITS(ta, tile & 0x3ff); + if (bits) { + z += ((tile & 0x1c00) >> kPaletteShift); + if (tile & 0x4000) { + do DO_PIXEL(0); while (bits >>= 1, dstz++, --w); + } else { + do DO_PIXEL_HFLIP(0); while (bits <<= 1, dstz++, --w); + } + } + } + } +#undef NEXT_TP +#undef READ_BITS +#undef DO_PIXEL +#undef DO_PIXEL_HFLIP +} + +// Assumes it's drawn on an empty backdrop +static void PpuDrawBackground_mode7(Ppu *ppu, uint y, bool sub, PpuZbufType z) { + int layer = 0; + if (!IS_SCREEN_ENABLED(ppu, sub, layer)) + return; // layer is completely hidden + PpuWindows win; + IS_SCREEN_WINDOWED(ppu, sub, layer) ? PpuWindows_Calc(&win, ppu, layer) : PpuWindows_Clear(&win, ppu, layer); + + // expand 13-bit values to signed values + int hScroll = ((int16_t)(ppu->m7matrix[6] << 3)) >> 3; + int vScroll = ((int16_t)(ppu->m7matrix[7] << 3)) >> 3; + int xCenter = ((int16_t)(ppu->m7matrix[4] << 3)) >> 3; + int yCenter = ((int16_t)(ppu->m7matrix[5] << 3)) >> 3; + int clippedH = hScroll - xCenter; + int clippedV = vScroll - yCenter; + clippedH = (clippedH & 0x2000) ? (clippedH | ~1023) : (clippedH & 1023); + clippedV = (clippedV & 0x2000) ? (clippedV | ~1023) : (clippedV & 1023); + bool mosaic_enabled = IS_MOSAIC_ENABLED(ppu, 0); + if (mosaic_enabled) + y = ppu->mosaicModulo[y]; + uint32 ry = ppu->m7yFlip ? 255 - y : y; + uint32 m7startX = (ppu->m7matrix[0] * clippedH & ~63) + (ppu->m7matrix[1] * ry & ~63) + + (ppu->m7matrix[1] * clippedV & ~63) + (xCenter << 8); + uint32 m7startY = (ppu->m7matrix[2] * clippedH & ~63) + (ppu->m7matrix[3] * ry & ~63) + + (ppu->m7matrix[3] * clippedV & ~63) + (yCenter << 8); + for (size_t windex = 0; windex < win.nr; windex++) { + if (win.bits & (1 << windex)) + continue; // layer is disabled for this window part + int x = win.edges[windex], x2 = win.edges[windex + 1], tile; + PpuZbufType *dstz = ppu->bgBuffers[sub].data + x + kPpuExtraLeftRight; + PpuZbufType *dstz_end = ppu->bgBuffers[sub].data + x2 + kPpuExtraLeftRight; + uint32 rx = ppu->m7xFlip ? 255 - x : x; + uint32 xpos = m7startX + ppu->m7matrix[0] * rx; + uint32 ypos = m7startY + ppu->m7matrix[2] * rx; + uint32 dx = ppu->m7xFlip ? -ppu->m7matrix[0] : ppu->m7matrix[0]; + uint32 dy = ppu->m7xFlip ? -ppu->m7matrix[2] : ppu->m7matrix[2]; + uint32 outside_value = ppu->m7largeField ? 0x3ffff : 0xffffffff; + bool char_fill = ppu->m7charFill; + if (mosaic_enabled) { + int w = ppu->mosaicSize - (x - ppu->mosaicModulo[x]); + do { + w = IntMin(w, dstz_end - dstz); + if ((uint32)(xpos | ypos) > outside_value) { + if (!char_fill) + continue; + tile = 0; + } else { + tile = ppu->vram[(ypos >> 11 & 0x7f) * 128 + (xpos >> 11 & 0x7f)] & 0xff; + } + uint8 pixel = ppu->vram[tile * 64 + (ypos >> 8 & 7) * 8 + (xpos >> 8 & 7)] >> 8; + if (pixel) { + int i = 0; + do dstz[i] = pixel + z; while (++i != w); + } + } while (xpos += dx * w, ypos += dy * w, dstz += w, w = ppu->mosaicSize, dstz_end - dstz != 0); + } else { + do { + if ((uint32)(xpos | ypos) > outside_value) { + if (!char_fill) + continue; + tile = 0; + } else { + tile = ppu->vram[(ypos >> 11 & 0x7f) * 128 + (xpos >> 11 & 0x7f)] & 0xff; + } + uint8 pixel = ppu->vram[tile * 64 + (ypos >> 8 & 7) * 8 + (xpos >> 8 & 7)] >> 8; + if (pixel) + dstz[0] = pixel + z; + } while (xpos += dx, ypos += dy, ++dstz != dstz_end); + } + } +} + + +static void PpuDrawSprites(Ppu *ppu, uint y, uint sub, bool clear_backdrop) { + int layer = 4; + if (!IS_SCREEN_ENABLED(ppu, sub, layer)) + return; // layer is completely hidden + PpuWindows win; + IS_SCREEN_WINDOWED(ppu, sub, layer) ? PpuWindows_Calc(&win, ppu, layer) : PpuWindows_Clear(&win, ppu, layer); + for (size_t windex = 0; windex < win.nr; windex++) { + if (win.bits & (1 << windex)) + continue; // layer is disabled for this window part + int left = win.edges[windex]; + int width = win.edges[windex + 1] - left; + PpuZbufType *src = ppu->objBuffer.data + left + kPpuExtraLeftRight; + PpuZbufType *dst = ppu->bgBuffers[sub].data + left + kPpuExtraLeftRight; + if (clear_backdrop) { + memcpy(dst, src, width * sizeof(uint16)); + } else { + do { + if (src[0] > dst[0]) + dst[0] = src[0]; + } while (src++, dst++, --width); + } + } +} + +static void PpuDrawBackgrounds(Ppu *ppu, int y, bool sub) { + // Top 4 bits contain the prio level, and bottom 4 bits the layer type. + // SPRITE_PRIO_TO_PRIO can be used to convert from obj prio to this prio. + // 15: BG3 tiles with priority 1 if bit 3 of $2105 is set + // 14: Sprites with priority 3 (4 * sprite_prio + 2) + // 12: BG1 tiles with priority 1 + // 11: BG2 tiles with priority 1 + // 10: Sprites with priority 2 (4 * sprite_prio + 2) + // 8: BG1 tiles with priority 0 + // 7: BG2 tiles with priority 0 + // 6: Sprites with priority 1 (4 * sprite_prio + 2) + // 3: BG3 tiles with priority 1 if bit 3 of $2105 is clear + // 2: Sprites with priority 0 (4 * sprite_prio + 2) + // 1: BG3 tiles with priority 0 + // 0: backdrop + + if (ppu->mode == 1) { + if (ppu->lineHasSprites) + PpuDrawSprites(ppu, y, sub, true); + + if (IS_MOSAIC_ENABLED(ppu, 0)) + assert(0); + else + PpuDrawBackground_4bpp(ppu, y, sub, 0, 0xc000, 0x8000); + + if (IS_MOSAIC_ENABLED(ppu, 1)) + assert(0); + else + PpuDrawBackground_4bpp(ppu, y, sub, 1, 0xb100, 0x7100); + + if (IS_MOSAIC_ENABLED(ppu, 2)) + assert(0); + else + PpuDrawBackground_2bpp(ppu, y, sub, 2, 0xf200, 0x1200); + } else { + // mode 7 + PpuDrawBackground_mode7(ppu, y, sub, 0x5000); + if (ppu->lineHasSprites) + PpuDrawSprites(ppu, y, sub, false); + } +} + +static NOINLINE void PpuDrawWholeLine(Ppu *ppu, uint y) { + if (ppu->forcedBlank) { + uint8 *dst = &ppu->renderBuffer[(y - 1) * ppu->renderPitch]; + size_t n = sizeof(uint32) * (256 + ppu->extraLeftRight * 2); + memset(dst, 0, n); + return; + } + + // Default background is backdrop + ClearBackdrop(&ppu->bgBuffers[0]); + + // Render main screen + PpuDrawBackgrounds(ppu, y, false); + + // The 6:th bit is automatically zero, math is never applied to the first half of the sprites. + uint32 math_enabled = 0; + for(int i = 0; i < 6; i++) + math_enabled |= ppu->mathEnabled[i] << i; + + // Render also the subscreen? + bool rendered_subscreen = false; + if (ppu->preventMathMode != 3 && ppu->addSubscreen && math_enabled) { + ClearBackdrop(&ppu->bgBuffers[1]); + if (ppu->screenEnabled[1] != 0) { + PpuDrawBackgrounds(ppu, y, true); + rendered_subscreen = true; + } + } + + // Color window affects the drawing mode in each region + PpuWindows cwin; + PpuWindows_Calc(&cwin, ppu, 5); + static const uint8 kCwBitsMod[8] = { + 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0xff, 0x00, + }; + uint32 cw_clip_math = ((cwin.bits & kCwBitsMod[ppu->clipMode]) ^ kCwBitsMod[ppu->clipMode + 4]) | + ((cwin.bits & kCwBitsMod[ppu->preventMathMode]) ^ kCwBitsMod[ppu->preventMathMode + 4]) << 8; + + uint32 *dst = (uint32*)&ppu->renderBuffer[(y - 1) * ppu->renderPitch], *dst_org = dst; + + dst += (ppu->extraLeftRight - ppu->extraLeftCur); + + uint32 windex = 0; + do { + uint32 left = cwin.edges[windex] + kPpuExtraLeftRight, right = cwin.edges[windex + 1] + kPpuExtraLeftRight; + // If clip is set, then zero out the rgb values from the main screen. + uint32 clip_color_mask = (cw_clip_math & 1) ? 0x1f : 0; + uint32 math_enabled_cur = (cw_clip_math & 0x100) ? math_enabled : 0; + uint32 fixed_color = ppu->fixedColorR | ppu->fixedColorG << 5 | ppu->fixedColorB << 10; + if (math_enabled_cur == 0 || fixed_color == 0 && !ppu->halfColor && !rendered_subscreen) { + // Math is disabled (or has no effect), so can avoid the per-pixel maths check + uint32 i = left; + do { + uint32 color = ppu->cgram[ppu->bgBuffers[0].data[i] & 0xff]; + dst[0] = ppu->brightnessMult[color & clip_color_mask] << 16 | + ppu->brightnessMult[(color >> 5) & clip_color_mask] << 8 | + ppu->brightnessMult[(color >> 10) & clip_color_mask]; + } while (dst++, ++i < right); + } else { + uint8 *half_color_map = ppu->halfColor ? ppu->brightnessMultHalf : ppu->brightnessMult; + // Store this in locals + math_enabled_cur |= ppu->addSubscreen << 8 | ppu->subtractColor << 9; + // Need to check for each pixel whether to use math or not based on the main screen layer. + uint32 i = left; + do { + uint32 color = ppu->cgram[ppu->bgBuffers[0].data[i] & 0xff], color2; + uint8 main_layer = (ppu->bgBuffers[0].data[i] >> 8) & 0xf; + uint32 r = color & clip_color_mask; + uint32 g = (color >> 5) & clip_color_mask; + uint32 b = (color >> 10) & clip_color_mask; + uint8 *color_map = ppu->brightnessMult; + if (math_enabled_cur & (1 << main_layer)) { + if (math_enabled_cur & 0x100) { // addSubscreen ? + if ((ppu->bgBuffers[1].data[i] & 0xff) != 0) + color2 = ppu->cgram[ppu->bgBuffers[1].data[i] & 0xff], color_map = half_color_map; + else // Don't halve if ppu->addSubscreen && backdrop + color2 = fixed_color; + } else { + color2 = fixed_color, color_map = half_color_map; + } + uint32 r2 = (color2 & 0x1f), g2 = ((color2 >> 5) & 0x1f), b2 = ((color2 >> 10) & 0x1f); + if (math_enabled_cur & 0x200) { // subtractColor? + r = (r >= r2) ? r - r2 : 0; + g = (g >= g2) ? g - g2 : 0; + b = (b >= b2) ? b - b2 : 0; + } else { + r += r2; + g += g2; + b += b2; + } + } + dst[0] = color_map[b] | color_map[g] << 8 | color_map[r] << 16; + } while (dst++, ++i < right); + } + } while (cw_clip_math >>= 1, ++windex < cwin.nr); + +} + + +static void ppu_handlePixel(Ppu* ppu, int x, int y) { + int r = 0, r2 = 0; + int g = 0, g2 = 0; + int b = 0, b2 = 0; + if(!ppu->forcedBlank) { + int mainLayer = ppu_getPixel(ppu, x, y, false, &r, &g, &b); + bool colorWindowState = ppu_getWindowState(ppu, 5, x); + if( + ppu->clipMode == 3 || + (ppu->clipMode == 2 && colorWindowState) || + (ppu->clipMode == 1 && !colorWindowState) + ) { + r = 0; + g = 0; + b = 0; + } + int secondLayer = 5; // backdrop + bool mathEnabled = mainLayer < 6 && ppu->mathEnabled[mainLayer] && !( + ppu->preventMathMode == 3 || + (ppu->preventMathMode == 2 && colorWindowState) || + (ppu->preventMathMode == 1 && !colorWindowState) + ); + if((mathEnabled && ppu->addSubscreen) || ppu->pseudoHires || ppu->mode == 5 || ppu->mode == 6) { + secondLayer = ppu_getPixel(ppu, x, y, true, &r2, &g2, &b2); + } + // TODO: subscreen pixels can be clipped to black as well + // TODO: math for subscreen pixels (add/sub sub to main) + if(mathEnabled) { + if(ppu->subtractColor) { + r -= (ppu->addSubscreen && secondLayer != 5) ? r2 : ppu->fixedColorR; + g -= (ppu->addSubscreen && secondLayer != 5) ? g2 : ppu->fixedColorG; + b -= (ppu->addSubscreen && secondLayer != 5) ? b2 : ppu->fixedColorB; + } else { + r += (ppu->addSubscreen && secondLayer != 5) ? r2 : ppu->fixedColorR; + g += (ppu->addSubscreen && secondLayer != 5) ? g2 : ppu->fixedColorG; + b += (ppu->addSubscreen && secondLayer != 5) ? b2 : ppu->fixedColorB; + } + if(ppu->halfColor && (secondLayer != 5 || !ppu->addSubscreen)) { + r >>= 1; + g >>= 1; + b >>= 1; + } + if(r > 31) r = 31; + if(g > 31) g = 31; + if(b > 31) b = 31; + if(r < 0) r = 0; + if(g < 0) g = 0; + if(b < 0) b = 0; + } + if(!(ppu->pseudoHires || ppu->mode == 5 || ppu->mode == 6)) { + r2 = r; g2 = g; b2 = b; + } + } + int row = y - 1; + uint8 *pixelBuffer = (uint8*) &ppu->renderBuffer[row * ppu->renderPitch + (x + ppu->extraLeftRight) * 4]; + pixelBuffer[0] = ((b << 3) | (b >> 2)) * ppu->brightness / 15; + pixelBuffer[1] = ((g << 3) | (g >> 2)) * ppu->brightness / 15; + pixelBuffer[2] = ((r << 3) | (r >> 2)) * ppu->brightness / 15; + pixelBuffer[3] = 0; +} + +static int ppu_getPixel(Ppu* ppu, int x, int y, bool sub, int* r, int* g, int* b) { + // figure out which color is on this location on main- or subscreen, sets it in r, g, b + // returns which layer it is: 0-3 for bg layer, 4 or 6 for sprites (depending on palette), 5 for backdrop + int actMode = ppu->mode == 1 && ppu->bg3priority ? 8 : ppu->mode; + actMode = ppu->mode == 7 && ppu->m7extBg ? 9 : actMode; + int layer = 5; + int pixel = 0; + for(int i = 0; i < layerCountPerMode[actMode]; i++) { + int curLayer = layersPerMode[actMode][i]; + int curPriority = prioritysPerMode[actMode][i]; + bool layerActive = false; + if(!sub) { + layerActive = ppu->layer[curLayer].mainScreenEnabled && ( + !ppu->layer[curLayer].mainScreenWindowed || !ppu_getWindowState(ppu, curLayer, x) + ); + } else { + layerActive = ppu->layer[curLayer].subScreenEnabled && ( + !ppu->layer[curLayer].subScreenWindowed || !ppu_getWindowState(ppu, curLayer, x) + ); + } + if(layerActive) { + if(curLayer < 4) { + // bg layer + int lx = x; + int ly = y; + if(ppu->bgLayer[curLayer].mosaicEnabled && ppu->mosaicSize > 1) { + lx -= lx % ppu->mosaicSize; + ly -= (ly - ppu->mosaicStartLine) % ppu->mosaicSize; + } + if(ppu->mode == 7) { + pixel = ppu_getPixelForMode7(ppu, lx, curLayer, curPriority); + } else { + lx += ppu->bgLayer[curLayer].hScroll; + if(ppu->mode == 5 || ppu->mode == 6) { + lx *= 2; + lx += (sub || ppu->bgLayer[curLayer].mosaicEnabled) ? 0 : 1; + if(ppu->interlace) { + ly *= 2; + ly += (ppu->evenFrame || ppu->bgLayer[curLayer].mosaicEnabled) ? 0 : 1; + } + } + ly += ppu->bgLayer[curLayer].vScroll; + if(ppu->mode == 2 || ppu->mode == 4 || ppu->mode == 6) { + ppu_handleOPT(ppu, curLayer, &lx, &ly); + } + pixel = ppu_getPixelForBgLayer( + ppu, lx & 0x3ff, ly & 0x3ff, + curLayer, curPriority + ); + } + } else { + // get a pixel from the sprite buffer + pixel = 0; + if ((ppu->objBuffer.data[x + kPpuExtraLeftRight] >> 12) == SPRITE_PRIO_TO_PRIO_HI(curPriority)) + pixel = ppu->objBuffer.data[x + kPpuExtraLeftRight] & 0xff; + } + } + if(pixel > 0) { + layer = curLayer; + break; + } + } + if(ppu->directColor && layer < 4 && bitDepthsPerMode[actMode][layer] == 8) { + *r = ((pixel & 0x7) << 2) | ((pixel & 0x100) >> 7); + *g = ((pixel & 0x38) >> 1) | ((pixel & 0x200) >> 8); + *b = ((pixel & 0xc0) >> 3) | ((pixel & 0x400) >> 8); + } else { + uint16_t color = ppu->cgram[pixel & 0xff]; + *r = color & 0x1f; + *g = (color >> 5) & 0x1f; + *b = (color >> 10) & 0x1f; + } + if(layer == 4 && pixel < 0xc0) layer = 6; // sprites with palette color < 0xc0 + return layer; +} + +static void ppu_handleOPT(Ppu* ppu, int layer, int* lx, int* ly) { + int x = *lx; + int y = *ly; + int column = 0; + if(ppu->mode == 6) { + column = ((x - (x & 0xf)) - ((ppu->bgLayer[layer].hScroll * 2) & 0xfff0)) >> 4; + } else { + column = ((x - (x & 0x7)) - (ppu->bgLayer[layer].hScroll & 0xfff8)) >> 3; + } + if(column > 0) { + // fetch offset values from layer 3 tilemap + int valid = layer == 0 ? 0x2000 : 0x4000; + uint16_t hOffset = ppu_getOffsetValue(ppu, column - 1, 0); + uint16_t vOffset = 0; + if(ppu->mode == 4) { + if(hOffset & 0x8000) { + vOffset = hOffset; + hOffset = 0; + } + } else { + vOffset = ppu_getOffsetValue(ppu, column - 1, 1); + } + if(ppu->mode == 6) { + // TODO: not sure if correct + if(hOffset & valid) *lx = (((hOffset & 0x3f8) + (column * 8)) * 2) | (x & 0xf); + } else { + if(hOffset & valid) *lx = ((hOffset & 0x3f8) + (column * 8)) | (x & 0x7); + } + // TODO: not sure if correct for interlace + if(vOffset & valid) *ly = (vOffset & 0x3ff) + (y - ppu->bgLayer[layer].vScroll); + } +} + +static uint16_t ppu_getOffsetValue(Ppu* ppu, int col, int row) { + int x = col * 8 + ppu->bgLayer[2].hScroll; + int y = row * 8 + ppu->bgLayer[2].vScroll; + int tileBits = ppu->bgLayer[2].bigTiles ? 4 : 3; + int tileHighBit = ppu->bgLayer[2].bigTiles ? 0x200 : 0x100; + uint16_t tilemapAdr = ppu->bgLayer[2].tilemapAdr + (((y >> tileBits) & 0x1f) << 5 | ((x >> tileBits) & 0x1f)); + if((x & tileHighBit) && ppu->bgLayer[2].tilemapWider) tilemapAdr += 0x400; + if((y & tileHighBit) && ppu->bgLayer[2].tilemapHigher) tilemapAdr += ppu->bgLayer[2].tilemapWider ? 0x800 : 0x400; + return ppu->vram[tilemapAdr & 0x7fff]; +} + +static int ppu_getPixelForBgLayer(Ppu* ppu, int x, int y, int layer, bool priority) { + // figure out address of tilemap word and read it + bool wideTiles = ppu->bgLayer[layer].bigTiles || ppu->mode == 5 || ppu->mode == 6; + int tileBitsX = wideTiles ? 4 : 3; + int tileHighBitX = wideTiles ? 0x200 : 0x100; + int tileBitsY = ppu->bgLayer[layer].bigTiles ? 4 : 3; + int tileHighBitY = ppu->bgLayer[layer].bigTiles ? 0x200 : 0x100; + uint16_t tilemapAdr = ppu->bgLayer[layer].tilemapAdr + (((y >> tileBitsY) & 0x1f) << 5 | ((x >> tileBitsX) & 0x1f)); + if((x & tileHighBitX) && ppu->bgLayer[layer].tilemapWider) tilemapAdr += 0x400; + if((y & tileHighBitY) && ppu->bgLayer[layer].tilemapHigher) tilemapAdr += ppu->bgLayer[layer].tilemapWider ? 0x800 : 0x400; + uint16_t tile = ppu->vram[tilemapAdr & 0x7fff]; + // check priority, get palette + if(((bool) (tile & 0x2000)) != priority) return 0; // wrong priority + int paletteNum = (tile & 0x1c00) >> 10; + // figure out position within tile + int row = (tile & 0x8000) ? 7 - (y & 0x7) : (y & 0x7); + int col = (tile & 0x4000) ? (x & 0x7) : 7 - (x & 0x7); + int tileNum = tile & 0x3ff; + if(wideTiles) { + // if unflipped right half of tile, or flipped left half of tile + if(((bool) (x & 8)) ^ ((bool) (tile & 0x4000))) tileNum += 1; + } + if(ppu->bgLayer[layer].bigTiles) { + // if unflipped bottom half of tile, or flipped upper half of tile + if(((bool) (y & 8)) ^ ((bool) (tile & 0x8000))) tileNum += 0x10; + } + // read tiledata, ajust palette for mode 0 + int bitDepth = bitDepthsPerMode[ppu->mode][layer]; + if(ppu->mode == 0) paletteNum += 8 * layer; + // plane 1 (always) + int paletteSize = 4; + uint16_t plane1 = ppu->vram[(ppu->bgLayer[layer].tileAdr + ((tileNum & 0x3ff) * 4 * bitDepth) + row) & 0x7fff]; + int pixel = (plane1 >> col) & 1; + pixel |= ((plane1 >> (8 + col)) & 1) << 1; + // plane 2 (for 4bpp, 8bpp) + if(bitDepth > 2) { + paletteSize = 16; + uint16_t plane2 = ppu->vram[(ppu->bgLayer[layer].tileAdr + ((tileNum & 0x3ff) * 4 * bitDepth) + 8 + row) & 0x7fff]; + pixel |= ((plane2 >> col) & 1) << 2; + pixel |= ((plane2 >> (8 + col)) & 1) << 3; + } + // plane 3 & 4 (for 8bpp) + if(bitDepth > 4) { + paletteSize = 256; + uint16_t plane3 = ppu->vram[(ppu->bgLayer[layer].tileAdr + ((tileNum & 0x3ff) * 4 * bitDepth) + 16 + row) & 0x7fff]; + pixel |= ((plane3 >> col) & 1) << 4; + pixel |= ((plane3 >> (8 + col)) & 1) << 5; + uint16_t plane4 = ppu->vram[(ppu->bgLayer[layer].tileAdr + ((tileNum & 0x3ff) * 4 * bitDepth) + 24 + row) & 0x7fff]; + pixel |= ((plane4 >> col) & 1) << 6; + pixel |= ((plane4 >> (8 + col)) & 1) << 7; + } + // return cgram index, or 0 if transparent, palette number in bits 10-8 for 8-color layers + return pixel == 0 ? 0 : paletteSize * paletteNum + pixel; +} + +static void ppu_calculateMode7Starts(Ppu* ppu, int y) { + // expand 13-bit values to signed values + int hScroll = ((int16_t) (ppu->m7matrix[6] << 3)) >> 3; + int vScroll = ((int16_t) (ppu->m7matrix[7] << 3)) >> 3; + int xCenter = ((int16_t) (ppu->m7matrix[4] << 3)) >> 3; + int yCenter = ((int16_t) (ppu->m7matrix[5] << 3)) >> 3; + // do calculation + int clippedH = hScroll - xCenter; + int clippedV = vScroll - yCenter; + clippedH = (clippedH & 0x2000) ? (clippedH | ~1023) : (clippedH & 1023); + clippedV = (clippedV & 0x2000) ? (clippedV | ~1023) : (clippedV & 1023); + if(ppu->bgLayer[0].mosaicEnabled && ppu->mosaicSize > 1) { + y -= (y - ppu->mosaicStartLine) % ppu->mosaicSize; + } + uint8_t ry = ppu->m7yFlip ? 255 - y : y; + ppu->m7startX = ( + ((ppu->m7matrix[0] * clippedH) & ~63) + + ((ppu->m7matrix[1] * ry) & ~63) + + ((ppu->m7matrix[1] * clippedV) & ~63) + + (xCenter << 8) + ); + ppu->m7startY = ( + ((ppu->m7matrix[2] * clippedH) & ~63) + + ((ppu->m7matrix[3] * ry) & ~63) + + ((ppu->m7matrix[3] * clippedV) & ~63) + + (yCenter << 8) + ); +} + +static int ppu_getPixelForMode7(Ppu* ppu, int x, int layer, bool priority) { + uint8_t rx = ppu->m7xFlip ? 255 - x : x; + int xPos = (ppu->m7startX + ppu->m7matrix[0] * rx) >> 8; + int yPos = (ppu->m7startY + ppu->m7matrix[2] * rx) >> 8; + bool outsideMap = xPos < 0 || xPos >= 1024 || yPos < 0 || yPos >= 1024; + xPos &= 0x3ff; + yPos &= 0x3ff; + if(!ppu->m7largeField) outsideMap = false; + uint8_t tile = outsideMap ? 0 : ppu->vram[(yPos >> 3) * 128 + (xPos >> 3)] & 0xff; + uint8_t pixel = outsideMap && !ppu->m7charFill ? 0 : ppu->vram[tile * 64 + (yPos & 7) * 8 + (xPos & 7)] >> 8; + if(layer == 1) { + if(((bool) (pixel & 0x80)) != priority) return 0; + return pixel & 0x7f; + } + return pixel; +} + +static bool ppu_getWindowState(Ppu* ppu, int layer, int x) { + if(!ppu->windowLayer[layer].window1enabled && !ppu->windowLayer[layer].window2enabled) { + return false; + } + if(ppu->windowLayer[layer].window1enabled && !ppu->windowLayer[layer].window2enabled) { + bool test = x >= ppu->window1left && x <= ppu->window1right; + return ppu->windowLayer[layer].window1inversed ? !test : test; + } + if(!ppu->windowLayer[layer].window1enabled && ppu->windowLayer[layer].window2enabled) { + bool test = x >= ppu->window2left && x <= ppu->window2right; + return ppu->windowLayer[layer].window2inversed ? !test : test; + } + bool test1 = x >= ppu->window1left && x <= ppu->window1right; + bool test2 = x >= ppu->window2left && x <= ppu->window2right; + if(ppu->windowLayer[layer].window1inversed) test1 = !test1; + if(ppu->windowLayer[layer].window2inversed) test2 = !test2; + switch(ppu->windowLayer[layer].maskLogic) { + case 0: return test1 || test2; + case 1: return test1 && test2; + case 2: return test1 != test2; + case 3: return test1 == test2; + } + return false; +} + +static bool ppu_evaluateSprites(Ppu* ppu, int line) { + // TODO: iterate over oam normally to determine in-range sprites, + // then iterate those in-range sprites in reverse for tile-fetching + // TODO: rectangular sprites, wierdness with sprites at -256 + uint8_t index = ppu->objPriority ? (ppu->oamAdr & 0xfe) : 0; + int spritesFound = 0; + int tilesFound = 0; + for(int i = 0; i < 128; i++) { + uint8_t y = ppu->oam[index] >> 8; + // check if the sprite is on this line and get the sprite size + uint8_t row = line - y; + int spriteSize = spriteSizes[ppu->objSize][(ppu->highOam[index >> 3] >> ((index & 7) + 1)) & 1]; + int spriteHeight = ppu->objInterlace ? spriteSize / 2 : spriteSize; + if(row < spriteHeight) { + // in y-range, get the x location, using the high bit as well + int x = ppu->oam[index] & 0xff; + x |= ((ppu->highOam[index >> 3] >> (index & 7)) & 1) << 8; + if(x > 255) x -= 512; + // if in x-range + if(x > -spriteSize) { + // break if we found 32 sprites already + spritesFound++; + if(spritesFound > 32) { + ppu->rangeOver = true; + break; + } + // update row according to obj-interlace + if(ppu->objInterlace) row = row * 2 + (ppu->evenFrame ? 0 : 1); + // get some data for the sprite and y-flip row if needed + int oam1 = ppu->oam[index + 1]; + int tile = oam1 & 0xff; + int objAdr = (oam1 & 0x100) ? ppu->objTileAdr2 : ppu->objTileAdr1; + int palette = (oam1 & 0xe00) >> 9; + bool hFlipped = oam1 & 0x4000; + if(oam1 & 0x8000) row = spriteSize - 1 - row; + // fetch all tiles in x-range + int paletteBase = 0x80 + 16 * ((oam1 & 0xe00) >> 9); + int prio = SPRITE_PRIO_TO_PRIO((oam1 & 0x3000) >> 12, (oam1 & 0x800) == 0); + PpuZbufType z = paletteBase + (prio << 8); + + for(int col = 0; col < spriteSize; col += 8) { + if(col + x > -8 && col + x < 256) { + // break if we found 34 8*1 slivers already + tilesFound++; + if(tilesFound > 34) { + ppu->timeOver = true; + break; + } + // figure out which tile this uses, looping within 16x16 pages, and get it's data + int usedCol = oam1 & 0x4000 ? spriteSize - 1 - col : col; + int usedTile = ((((oam1 & 0xff) >> 4) + (row >> 3)) << 4) | (((oam1 & 0xf) + (usedCol >> 3)) & 0xf); + uint16 *addr = &ppu->vram[(objAdr + usedTile * 16 + (row & 0x7)) & 0x7fff]; + uint32 plane = addr[0] | addr[8] << 16; + // go over each pixel + int px_left = IntMax(-(col + x + kPpuExtraLeftRight), 0); + int px_right = IntMin(256 + kPpuExtraLeftRight - (col + x), 8); + PpuZbufType *dst = ppu->objBuffer.data + col + x + px_left + kPpuExtraLeftRight; + + for (int px = px_left; px < px_right; px++, dst++) { + int shift = oam1 & 0x4000 ? px : 7 - px; + uint32 bits = plane >> shift; + int pixel = (bits >> 0) & 1 | (bits >> 7) & 2 | (bits >> 14) & 4 | (bits >> 21) & 8; + // draw it in the buffer if there is a pixel here, and the buffer there is still empty + if (pixel != 0 && (dst[0] & 0xff) == 0) + dst[0] = z + pixel; + } + + } + } + if(tilesFound > 34) break; // break out of sprite-loop if max tiles found + } + } + index += 2; + } + return tilesFound != 0; +} + +static uint16_t ppu_getVramRemap(Ppu* ppu) { + uint16_t adr = ppu->vramPointer; + switch(ppu->vramRemapMode) { + case 0: return adr; + case 1: return (adr & 0xff00) | ((adr & 0xe0) >> 5) | ((adr & 0x1f) << 3); + case 2: return (adr & 0xfe00) | ((adr & 0x1c0) >> 6) | ((adr & 0x3f) << 3); + case 3: return (adr & 0xfc00) | ((adr & 0x380) >> 7) | ((adr & 0x7f) << 3); + } + return adr; +} + +uint8_t ppu_read(Ppu* ppu, uint8_t adr) { + switch(adr) { + case 0x04: case 0x14: case 0x24: + case 0x05: case 0x15: case 0x25: + case 0x06: case 0x16: case 0x26: + case 0x08: case 0x18: case 0x28: + case 0x09: case 0x19: case 0x29: + case 0x0a: case 0x1a: case 0x2a: { + return ppu->ppu1openBus; + } + case 0x34: + case 0x35: + case 0x36: { + int result = ppu->m7matrix[0] * (ppu->m7matrix[1] >> 8); + ppu->ppu1openBus = (result >> (8 * (adr - 0x34))) & 0xff; + return ppu->ppu1openBus; + } + case 0x37: { + // TODO: only when ppulatch is set + ppu->hCount = ppu->snes->hPos / 4; + ppu->vCount = ppu->snes->vPos; + ppu->countersLatched = true; + return ppu->snes->openBus; + } + case 0x38: { + uint8_t ret = 0; + if(ppu->oamInHigh) { + ret = ppu->highOam[((ppu->oamAdr & 0xf) << 1) | ppu->oamSecondWrite]; + if(ppu->oamSecondWrite) { + ppu->oamAdr++; + if(ppu->oamAdr == 0) ppu->oamInHigh = false; + } + } else { + if(!ppu->oamSecondWrite) { + ret = ppu->oam[ppu->oamAdr] & 0xff; + } else { + ret = ppu->oam[ppu->oamAdr++] >> 8; + if(ppu->oamAdr == 0) ppu->oamInHigh = true; + } + } + ppu->oamSecondWrite = !ppu->oamSecondWrite; + ppu->ppu1openBus = ret; + return ret; + } + case 0x39: { + uint16_t val = ppu->vramReadBuffer; + if(!ppu->vramIncrementOnHigh) { + ppu->vramReadBuffer = ppu->vram[ppu_getVramRemap(ppu) & 0x7fff]; + ppu->vramPointer += ppu->vramIncrement; + } + ppu->ppu1openBus = val & 0xff; + return val & 0xff; + } + case 0x3a: { + uint16_t val = ppu->vramReadBuffer; + if(ppu->vramIncrementOnHigh) { + ppu->vramReadBuffer = ppu->vram[ppu_getVramRemap(ppu) & 0x7fff]; + ppu->vramPointer += ppu->vramIncrement; + } + ppu->ppu1openBus = val >> 8; + return val >> 8; + } + case 0x3b: { + uint8_t ret = 0; + if(!ppu->cgramSecondWrite) { + ret = ppu->cgram[ppu->cgramPointer] & 0xff; + } else { + ret = ((ppu->cgram[ppu->cgramPointer++] >> 8) & 0x7f) | (ppu->ppu2openBus & 0x80); + } + ppu->cgramSecondWrite = !ppu->cgramSecondWrite; + ppu->ppu2openBus = ret; + return ret; + } + case 0x3c: { + uint8_t val = 0; + if(ppu->hCountSecond) { + val = ((ppu->hCount >> 8) & 1) | (ppu->ppu2openBus & 0xfe); + } else { + val = ppu->hCount & 0xff; + } + ppu->hCountSecond = !ppu->hCountSecond; + ppu->ppu2openBus = val; + return val; + } + case 0x3d: { + uint8_t val = 0; + if(ppu->vCountSecond) { + val = ((ppu->vCount >> 8) & 1) | (ppu->ppu2openBus & 0xfe); + } else { + val = ppu->vCount & 0xff; + } + ppu->vCountSecond = !ppu->vCountSecond; + ppu->ppu2openBus = val; + return val; + } + case 0x3e: { + uint8_t val = 0x1; // ppu1 version (4 bit) + val |= ppu->ppu1openBus & 0x10; + val |= ppu->rangeOver << 6; + val |= ppu->timeOver << 7; + ppu->ppu1openBus = val; + return val; + } + case 0x3f: { + uint8_t val = 0x3; // ppu2 version (4 bit), bit 4: ntsc/pal + val |= ppu->ppu2openBus & 0x20; + val |= ppu->countersLatched << 6; + val |= ppu->evenFrame << 7; + ppu->countersLatched = false; // TODO: only when ppulatch is set + ppu->hCountSecond = false; + ppu->vCountSecond = false; + ppu->ppu2openBus = val; + return val; + } + default: { + return ppu->snes->openBus; + } + } +} + +void ppu_write(Ppu* ppu, uint8_t adr, uint8_t val) { +// if (adr != 24 && adr != 25) +// printf("ppu_write(%d, %d)\n", adr, val); + switch(adr) { + case 0x00: { + // TODO: oam address reset when written on first line of vblank, (and when forced blank is disabled?) + ppu->brightness = val & 0xf; + ppu->forcedBlank = val & 0x80; + break; + } + case 0x01: { + ppu->objSize = val >> 5; + ppu->objTileAdr1 = (val & 7) << 13; + ppu->objTileAdr2 = ppu->objTileAdr1 + (((val & 0x18) + 8) << 9); + break; + } + case 0x02: { + ppu->oamAdr = val; + ppu->oamAdrWritten = ppu->oamAdr; + ppu->oamInHigh = ppu->oamInHighWritten; + ppu->oamSecondWrite = false; + break; + } + case 0x03: { + ppu->objPriority = val & 0x80; + ppu->oamInHigh = val & 1; + ppu->oamInHighWritten = ppu->oamInHigh; + ppu->oamAdr = ppu->oamAdrWritten; + ppu->oamSecondWrite = false; + break; + } + case 0x04: { + if(ppu->oamInHigh) { + ppu->highOam[((ppu->oamAdr & 0xf) << 1) | ppu->oamSecondWrite] = val; + if(ppu->oamSecondWrite) { + ppu->oamAdr++; + if(ppu->oamAdr == 0) ppu->oamInHigh = false; + } + } else { + if(!ppu->oamSecondWrite) { + ppu->oamBuffer = val; + } else { + ppu->oam[ppu->oamAdr++] = (val << 8) | ppu->oamBuffer; + if(ppu->oamAdr == 0) ppu->oamInHigh = true; + } + } + ppu->oamSecondWrite = !ppu->oamSecondWrite; + break; + } + case 0x05: { + ppu->mode = val & 0x7; + ppu->bg3priority = val & 0x8; + ppu->bgLayer[0].bigTiles = val & 0x10; + ppu->bgLayer[1].bigTiles = val & 0x20; + ppu->bgLayer[2].bigTiles = val & 0x40; + ppu->bgLayer[3].bigTiles = val & 0x80; + break; + } + case 0x06: { + // TODO: mosaic line reset specifics + ppu->bgLayer[0].mosaicEnabled = val & 0x1; + ppu->bgLayer[1].mosaicEnabled = val & 0x2; + ppu->bgLayer[2].mosaicEnabled = val & 0x4; + ppu->bgLayer[3].mosaicEnabled = val & 0x8; + ppu->mosaicSize = (val >> 4) + 1; + ppu->mosaicStartLine = 0;// ppu->snes->vPos; + break; + } + case 0x07: + case 0x08: + case 0x09: + case 0x0a: { + ppu->bgLayer[adr - 7].tilemapWider = val & 0x1; + ppu->bgLayer[adr - 7].tilemapHigher = val & 0x2; + ppu->bgLayer[adr - 7].tilemapAdr = (val & 0xfc) << 8; + break; + } + case 0x0b: { + ppu->bgLayer[0].tileAdr = (val & 0xf) << 12; + ppu->bgLayer[1].tileAdr = (val & 0xf0) << 8; + break; + } + case 0x0c: { + ppu->bgLayer[2].tileAdr = (val & 0xf) << 12; + ppu->bgLayer[3].tileAdr = (val & 0xf0) << 8; + break; + } + case 0x0d: { + ppu->m7matrix[6] = ((val << 8) | ppu->m7prev) & 0x1fff; + ppu->m7prev = val; + // fallthrough to normal layer BG-HOFS + } + case 0x0f: + case 0x11: + case 0x13: { + ppu->bgLayer[(adr - 0xd) / 2].hScroll = ((val << 8) | (ppu->scrollPrev & 0xf8) | (ppu->scrollPrev2 & 0x7)) & 0x3ff; + ppu->scrollPrev = val; + ppu->scrollPrev2 = val; + break; + } + case 0x0e: { + ppu->m7matrix[7] = ((val << 8) | ppu->m7prev) & 0x1fff; + ppu->m7prev = val; + // fallthrough to normal layer BG-VOFS + } + case 0x10: + case 0x12: + case 0x14: { + ppu->bgLayer[(adr - 0xe) / 2].vScroll = ((val << 8) | ppu->scrollPrev) & 0x3ff; + ppu->scrollPrev = val; + break; + } + case 0x15: { + if((val & 3) == 0) { + ppu->vramIncrement = 1; + } else if((val & 3) == 1) { + ppu->vramIncrement = 32; + } else { + ppu->vramIncrement = 128; + } + ppu->vramRemapMode = (val & 0xc) >> 2; + ppu->vramIncrementOnHigh = val & 0x80; + break; + } + case 0x16: { + ppu->vramPointer = (ppu->vramPointer & 0xff00) | val; + ppu->vramReadBuffer = ppu->vram[ppu_getVramRemap(ppu) & 0x7fff]; + break; + } + case 0x17: { + ppu->vramPointer = (ppu->vramPointer & 0x00ff) | (val << 8); + ppu->vramReadBuffer = ppu->vram[ppu_getVramRemap(ppu) & 0x7fff]; + break; + } + case 0x18: { + // TODO: vram access during rendering (also cgram and oam) + uint16_t vramAdr = ppu_getVramRemap(ppu); + ppu->vram[vramAdr & 0x7fff] = (ppu->vram[vramAdr & 0x7fff] & 0xff00) | val; + if(!ppu->vramIncrementOnHigh) ppu->vramPointer += ppu->vramIncrement; + break; + } + case 0x19: { + uint16_t vramAdr = ppu_getVramRemap(ppu); + ppu->vram[vramAdr & 0x7fff] = (ppu->vram[vramAdr & 0x7fff] & 0x00ff) | (val << 8); + if(ppu->vramIncrementOnHigh) ppu->vramPointer += ppu->vramIncrement; + break; + } + case 0x1a: { + ppu->m7largeField = val & 0x80; + ppu->m7charFill = val & 0x40; + ppu->m7yFlip = val & 0x2; + ppu->m7xFlip = val & 0x1; + break; + } + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: { + ppu->m7matrix[adr - 0x1b] = (val << 8) | ppu->m7prev; + ppu->m7prev = val; + break; + } + case 0x1f: + case 0x20: { + ppu->m7matrix[adr - 0x1b] = ((val << 8) | ppu->m7prev) & 0x1fff; + ppu->m7prev = val; + break; + } + case 0x21: { + ppu->cgramPointer = val; + ppu->cgramSecondWrite = false; + break; + } + case 0x22: { + if(!ppu->cgramSecondWrite) { + ppu->cgramBuffer = val; + } else { + ppu->cgram[ppu->cgramPointer++] = (val << 8) | ppu->cgramBuffer; + } + ppu->cgramSecondWrite = !ppu->cgramSecondWrite; + break; + } + case 0x23: + case 0x24: + case 0x25: { + + if (adr == 0x23) + ppu->windowsel = (ppu->windowsel & ~0xff) | val; + else if (adr == 0x24) + ppu->windowsel = (ppu->windowsel & ~0xff00) | (val << 8); + else if (adr == 0x25) + ppu->windowsel = (ppu->windowsel & ~0xff0000) | (val << 16); + + ppu->windowLayer[(adr - 0x23) * 2].window1inversed = val & 0x1; + ppu->windowLayer[(adr - 0x23) * 2].window1enabled = val & 0x2; + ppu->windowLayer[(adr - 0x23) * 2].window2inversed = val & 0x4; + ppu->windowLayer[(adr - 0x23) * 2].window2enabled = val & 0x8; + ppu->windowLayer[(adr - 0x23) * 2 + 1].window1inversed = val & 0x10; + ppu->windowLayer[(adr - 0x23) * 2 + 1].window1enabled = val & 0x20; + ppu->windowLayer[(adr - 0x23) * 2 + 1].window2inversed = val & 0x40; + ppu->windowLayer[(adr - 0x23) * 2 + 1].window2enabled = val & 0x80; + break; + } + case 0x26: { + ppu->window1left = val; + break; + } + case 0x27: { + ppu->window1right = val; + break; + } + case 0x28: { + ppu->window2left = val; + break; + } + case 0x29: { + ppu->window2right = val; + break; + } + case 0x2a: { + ppu->windowLayer[0].maskLogic = val & 0x3; + ppu->windowLayer[1].maskLogic = (val >> 2) & 0x3; + ppu->windowLayer[2].maskLogic = (val >> 4) & 0x3; + ppu->windowLayer[3].maskLogic = (val >> 6) & 0x3; + break; + } + case 0x2b: { + ppu->windowLayer[4].maskLogic = val & 0x3; + ppu->windowLayer[5].maskLogic = (val >> 2) & 0x3; + break; + } + case 0x2c: { + ppu->screenEnabled[0] = val; + ppu->layer[0].mainScreenEnabled = val & 0x1; + ppu->layer[1].mainScreenEnabled = val & 0x2; + ppu->layer[2].mainScreenEnabled = val & 0x4; + ppu->layer[3].mainScreenEnabled = val & 0x8; + ppu->layer[4].mainScreenEnabled = val & 0x10; + break; + } + case 0x2d: { + ppu->screenEnabled[1] = val; + ppu->layer[0].subScreenEnabled = val & 0x1; + ppu->layer[1].subScreenEnabled = val & 0x2; + ppu->layer[2].subScreenEnabled = val & 0x4; + ppu->layer[3].subScreenEnabled = val & 0x8; + ppu->layer[4].subScreenEnabled = val & 0x10; + break; + } + case 0x2e: { + ppu->screenWindowed[0] = val; + ppu->layer[0].mainScreenWindowed = val & 0x1; + ppu->layer[1].mainScreenWindowed = val & 0x2; + ppu->layer[2].mainScreenWindowed = val & 0x4; + ppu->layer[3].mainScreenWindowed = val & 0x8; + ppu->layer[4].mainScreenWindowed = val & 0x10; + break; + } + case 0x2f: { + ppu->screenWindowed[1] = val; + ppu->layer[0].subScreenWindowed = val & 0x1; + ppu->layer[1].subScreenWindowed = val & 0x2; + ppu->layer[2].subScreenWindowed = val & 0x4; + ppu->layer[3].subScreenWindowed = val & 0x8; + ppu->layer[4].subScreenWindowed = val & 0x10; + break; + } + case 0x30: { + ppu->directColor = val & 0x1; + ppu->addSubscreen = val & 0x2; + ppu->preventMathMode = (val & 0x30) >> 4; + ppu->clipMode = (val & 0xc0) >> 6; + break; + } + case 0x31: { + ppu->subtractColor = val & 0x80; + ppu->halfColor = val & 0x40; + for(int i = 0; i < 6; i++) { + ppu->mathEnabled[i] = val & (1 << i); + } + break; + } + case 0x32: { + if(val & 0x80) ppu->fixedColorB = val & 0x1f; + if(val & 0x40) ppu->fixedColorG = val & 0x1f; + if(val & 0x20) ppu->fixedColorR = val & 0x1f; + break; + } + case 0x33: { + ppu->interlace = val & 0x1; + ppu->objInterlace = val & 0x2; + ppu->overscan = val & 0x4; + ppu->pseudoHires = val & 0x8; + ppu->m7extBg = val & 0x40; + break; + } + default: { + break; + } + } +} + +int PpuGetCurrentRenderScale(Ppu *ppu, uint32_t render_flags) { + return 1; +} diff --git a/src/snes/ppu.h b/src/snes/ppu.h new file mode 100644 index 0000000..703db86 --- /dev/null +++ b/src/snes/ppu.h @@ -0,0 +1,187 @@ +#ifndef PPU_H +#define PPU_H + +#include +#include +#include +#include +#include + +typedef struct Ppu Ppu; + +#include "snes.h" + +typedef struct BgLayer { + uint16_t hScroll; + uint16_t vScroll; + bool tilemapWider; + bool tilemapHigher; + uint16_t tilemapAdr; + uint16_t tileAdr; + bool bigTiles; + bool mosaicEnabled; +} BgLayer; + +enum { + kPpuXPixels = 256, + kPpuExtraLeftRight = 0, +}; + +typedef uint16_t PpuZbufType; + +typedef struct PpuPixelPrioBufs { + // This holds the prio in the upper 8 bits and the color in the lower 8 bits. + PpuZbufType data[kPpuXPixels]; +} PpuPixelPrioBufs; + +enum { + kPpuRenderFlags_NewRenderer = 1, + // Render mode7 upsampled by 4x4 + kPpuRenderFlags_4x4Mode7 = 2, + // Use 240 height instead of 224 + kPpuRenderFlags_Height240 = 4, + // Disable sprite render limits + kPpuRenderFlags_NoSpriteLimits = 8, +}; + + + +typedef struct Layer { + bool mainScreenEnabled; + bool subScreenEnabled; + bool mainScreenWindowed; + bool subScreenWindowed; +} Layer; + +typedef struct WindowLayer { + bool window1enabled; + bool window2enabled; + bool window1inversed; + bool window2inversed; + uint8_t maskLogic; +} WindowLayer; + +struct Ppu { + Snes* snes; + // vram access + uint16_t vram[0x8000]; + uint16_t vramPointer; + bool vramIncrementOnHigh; + uint16_t vramIncrement; + uint8_t vramRemapMode; + uint16_t vramReadBuffer; + // cgram access + uint16_t cgram[0x100]; + uint8_t cgramPointer; + bool cgramSecondWrite; + uint8_t cgramBuffer; + // oam access + uint16_t oam[0x100]; + uint8_t highOam[0x20]; + uint8_t oamAdr; + uint8_t oamAdrWritten; + bool oamInHigh; + bool oamInHighWritten; + bool oamSecondWrite; + uint8_t oamBuffer; + // object/sprites + bool objPriority; + uint16_t objTileAdr1; + uint16_t objTileAdr2; + uint8_t objSize; + uint8_t objPixelBufferXX[256]; // line buffers + uint8_t objPriorityBufferXX[256]; + bool timeOver; + bool rangeOver; + bool objInterlace; + // background layers + BgLayer bgLayer[4]; + uint8_t scrollPrev; + uint8_t scrollPrev2; + uint8_t mosaicSize; + uint8_t mosaicStartLine; + // layers + Layer layer[5]; + // mode 7 + int16_t m7matrix[8]; // a, b, c, d, x, y, h, v + uint8_t m7prev; + bool m7largeField; + bool m7charFill; + bool m7xFlip; + bool m7yFlip; + bool m7extBg; + // mode 7 internal + int32_t m7startX; + int32_t m7startY; + // windows + WindowLayer windowLayer[6]; + uint8_t window1left; + uint8_t window1right; + uint8_t window2left; + uint8_t window2right; + // color math + uint8_t clipMode; + uint8_t preventMathMode; + bool addSubscreen; + bool subtractColor; + bool halfColor; + bool mathEnabled[6]; + uint8_t fixedColorR; + uint8_t fixedColorG; + uint8_t fixedColorB; + // settings + bool forcedBlank; + uint8_t brightness; + uint8_t mode; + bool bg3priority; + bool evenFrame; + bool pseudoHires; + bool overscan; + bool frameOverscan; // if we are overscanning this frame (determined at 0,225) + bool interlace; + bool frameInterlace; // if we are interlacing this frame (determined at start vblank) + bool directColor; + // latching + uint16_t hCount; + uint16_t vCount; + bool hCountSecond; + bool vCountSecond; + bool countersLatched; + uint8_t ppu1openBus; + uint8_t ppu2openBus; + // pixel buffer (xbgr) + // times 2 for even and odd frame + uint8_t pixelbuffer_placeholder; + + uint32_t windowsel; + uint8_t extraLeftCur, extraRightCur, extraLeftRight; + uint8_t screenEnabled[2]; + uint8_t screenWindowed[2]; + uint8_t mosaicEnabled; + uint8_t lastBrightnessMult; + bool lineHasSprites; + PpuPixelPrioBufs bgBuffers[2]; + PpuPixelPrioBufs objBuffer; + uint32_t renderPitch; + uint8_t *renderBuffer; + uint8_t brightnessMult[32 + 31]; + uint8_t brightnessMultHalf[32 * 2]; + uint8_t mosaicModulo[kPpuXPixels]; + +}; + +Ppu* ppu_init(Snes* snes); +void ppu_free(Ppu* ppu); +void ppu_copy(Ppu *ppu, Ppu *ppu_src); +void ppu_reset(Ppu* ppu); +bool ppu_checkOverscan(Ppu* ppu); +void ppu_handleVblank(Ppu* ppu); +void ppu_runLine(Ppu* ppu, int line); +uint8_t ppu_read(Ppu* ppu, uint8_t adr); +void ppu_write(Ppu* ppu, uint8_t adr, uint8_t val); +void ppu_saveload(Ppu *ppu, SaveLoadFunc *func, void *ctx); +void PpuBeginDrawing(Ppu *ppu, uint8_t *pixels, size_t pitch, uint32_t render_flags); + +int PpuGetCurrentRenderScale(Ppu *ppu, uint32_t render_flags); + +#endif diff --git a/src/snes/saveload.h b/src/snes/saveload.h new file mode 100644 index 0000000..6704713 --- /dev/null +++ b/src/snes/saveload.h @@ -0,0 +1,5 @@ +#pragma once + +typedef void SaveLoadFunc(void *ctx, void *data, size_t data_size); + +#define SL(x) func(ctx, &x, sizeof(x)) \ No newline at end of file diff --git a/src/snes/snes.c b/src/snes/snes.c new file mode 100644 index 0000000..6d4dc63 --- /dev/null +++ b/src/snes/snes.c @@ -0,0 +1,458 @@ + +#include +#include +#include +#include +#include +#include +#include +#include "snes.h" +#include "cpu.h" +#include "apu.h" +#include "dma.h" +#include "ppu.h" +#include "cart.h" +#include "input.h" +#include "../tracing.h" + +extern bool g_is_turbo; +int snes_frame_counter; +static const double apuCyclesPerMaster = (32040 * 32) / (1364 * 262 * 60.0); +extern uint8_t g_ram[0x20000]; + +extern void RtlApuWrite(uint32_t adr, uint8_t val); + +static uint8_t snes_readReg(Snes* snes, uint16_t adr); +static void snes_writeReg(Snes* snes, uint16_t adr, uint8_t val); + +Snes* snes_init(uint8_t *ram) { + Snes* snes = malloc(sizeof(Snes)); + snes->ram = ram; + snes->debug_cycles = false; + snes->debug_apu_cycles = false; + snes->runningWhichVersion = 0; + + snes->cpu = cpu_init(snes, 0); + snes->apu = apu_init(); + snes->dma = dma_init(snes); + snes->my_ppu = ppu_init(snes); + snes->snes_ppu = ppu_init(snes); + snes->ppu = snes->snes_ppu; + snes->cart = cart_init(snes); + snes->input1 = input_init(snes); + snes->input2 = input_init(snes); + return snes; +} + +void snes_free(Snes* snes) { + cpu_free(snes->cpu); + apu_free(snes->apu); + dma_free(snes->dma); + ppu_free(snes->ppu); + cart_free(snes->cart); + input_free(snes->input1); + input_free(snes->input2); + free(snes); +} + +void snes_saveload(Snes *snes, SaveLoadFunc *func, void *ctx) { + cpu_saveload(snes->cpu, func, ctx); + apu_saveload(snes->apu, func, ctx); + dma_saveload(snes->dma, func, ctx); + ppu_saveload(snes->ppu, func, ctx); + cart_saveload(snes->cart, func, ctx); + + func(ctx, &snes->hPos, offsetof(Snes, openBus) + 1 - offsetof(Snes, hPos)); + func(ctx, snes->ram, 0x20000); + func(ctx, &snes->ramAdr, 4); + + snes->runningWhichVersion = 0; +} + +void snes_reset(Snes* snes, bool hard) { + cart_reset(snes->cart); // reset cart first, because resetting cpu will read from it (reset vector) + cpu_reset(snes->cpu); + apu_reset(snes->apu); + dma_reset(snes->dma); + ppu_reset(snes->my_ppu); + ppu_reset(snes->snes_ppu); + input_reset(snes->input1); + input_reset(snes->input2); + if (hard) + memset(snes->ram, 0, 0x20000); + snes->ramAdr = 0; + snes->hPos = 0; + snes->vPos = 0; + snes->frames = 0; + snes->cpuCyclesLeft = 52; // 5 reads (8) + 2 IntOp (6) + snes->cpuMemOps = 0; + snes->apuCatchupCycles = 0.0; + snes->hIrqEnabled = false; + snes->vIrqEnabled = false; + snes->nmiEnabled = false; + snes->hTimer = 0x1ff; + snes->vTimer = 0x1ff; + snes->inNmi = false; + snes->inIrq = false; + snes->inVblank = false; + memset(snes->portAutoReadX, 0, sizeof(snes->portAutoReadX)); + snes->autoJoyRead = false; + snes->autoJoyTimer = 0; + snes->ppuLatch = false; + snes->multiplyA = 0xff; + snes->multiplyResult = 0xfe01; + snes->divideA = 0xffff; + snes->divideResult = 0x101; + snes->fastMem = false; + snes->openBus = 0; +} + +void snes_handle_pos_stuff(Snes *snes) { + // handle positional stuff + // TODO: better timing? (especially Hpos) + if (snes->hPos == 0) { + // end of hblank, do most vPos-tests + bool startingVblank = false; + if (snes->vPos == 0) { + // end of vblank + snes->inVblank = false; + snes->inNmi = false; + dma_initHdma(snes->dma); + } else if (snes->vPos == 225) { + // ask the ppu if we start vblank now or at vPos 240 (overscan) + startingVblank = !ppu_checkOverscan(snes->ppu); + } else if (snes->vPos == 240) { + // if we are not yet in vblank, we had an overscan frame, set startingVblank + if (!snes->inVblank) startingVblank = true; + } + if (startingVblank) { + // if we are starting vblank + ppu_handleVblank(snes->ppu); + snes->inVblank = true; + snes->inNmi = true; + if (snes->nmiEnabled) { + snes->cpu->nmiWanted = true; // request NMI on CPU + } + if (snes->autoJoyRead) { + // TODO: this starts a little after start of vblank + snes->autoJoyTimer = 0; + } + } + } else if (snes->hPos == 512) { + // render the line halfway of the screen for better compatibility + if (!snes->inVblank && !snes->disableRender) + ppu_runLine(snes->ppu, snes->vPos); + } else if (snes->hPos == 1024) { + // start of hblank + if (!snes->inVblank) + dma_doHdma(snes->dma); + } + // handle autoJoyRead-timer + //if (snes->autoJoyTimer > 0) snes->autoJoyTimer -= 2; + // increment position + // TODO: exact frame timing (line 240 on odd frame is 4 cycles shorter, + // even frames in interlace is 1 extra line) + snes->hPos += 2; + if (snes->hPos == 1364) { + snes->hPos = 0; + snes->vPos++; + if (snes->vPos == 262) { + snes->vPos = 0; + snes->frames++; +// snes_catchupApu(snes); // catch up the apu at the end of the frame + } + } +} + +#define IS_ADR(x) (x == 0xfffff ) + +void snes_catchupApu(Snes* snes) { + if (snes->apuCatchupCycles > 10000) + snes->apuCatchupCycles = 10000; + + int catchupCycles = (int) snes->apuCatchupCycles; + + for(int i = 0; i < catchupCycles; i++) { + apu_cycle(snes->apu); + } + snes->apuCatchupCycles -= (double) catchupCycles; +} + +uint8_t snes_readBBus(Snes* snes, uint8_t adr) { + if(adr < 0x40) { + return ppu_read(snes->ppu, adr); + } + if(adr < 0x80) { + assert(0); + snes->apuCatchupCycles = 32; + snes_catchupApu(snes); // catch up the apu before reading + return snes->apu->outPorts[adr & 0x3]; + } + if(adr == 0x80) { + uint8_t ret = snes->ram[snes->ramAdr++]; + snes->ramAdr &= 0x1ffff; + return ret; + } + + assert(0); + return snes->openBus; +} + + +#define is_uploading_apu (*(uint16_t*)(g_ram+0x617)) + +void snes_writeBBus(Snes* snes, uint8_t adr, uint8_t val) { + if(adr < 0x40) { + ppu_write(snes->ppu, adr, val); + return; + } + if(adr < 0x80) { + RtlApuWrite(0x2100 + adr, val); + return; + } + switch(adr) { + case 0x80: { + snes->ram[snes->ramAdr++] = val; + snes->ramAdr &= 0x1ffff; + break; + } + case 0x81: { + snes->ramAdr = (snes->ramAdr & 0x1ff00) | val; + break; + } + case 0x82: { + snes->ramAdr = (snes->ramAdr & 0x100ff) | (val << 8); + break; + } + case 0x83: { + snes->ramAdr = (snes->ramAdr & 0x0ffff) | ((val & 1) << 16); + break; + } + } +} + +static uint16_t SwapInputBits(uint16_t x) { + uint16_t r = 0; + for (int i = 0; i < 16; i++, x >>= 1) + r = r * 2 + (x & 1); + return r; +} + +static uint8_t snes_readReg(Snes* snes, uint16_t adr) { + switch(adr) { + case 0x4210: { + uint8_t val = 0x2; // CPU version (4 bit) + val |= snes->inNmi << 7; + + return val | (snes->openBus & 0x70); + } + case 0x4211: { + uint8_t val = snes->inIrq << 7; + snes->inIrq = false; + snes->cpu->irqWanted = false; + return val | (snes->openBus & 0x7f); + } + case 0x4212: { + uint8_t val = (snes->autoJoyTimer > 0); + val |= (snes->hPos >= 1024) << 6; + val |= snes->inVblank << 7; + return val | (snes->openBus & 0x3e); + } + case 0x4213: + return snes->ppuLatch << 7; // IO-port + case 0x4214: + return snes->divideResult & 0xff; + case 0x4215: + return snes->divideResult >> 8; + case 0x4216: + return snes->multiplyResult & 0xff; + case 0x4217: + return snes->multiplyResult >> 8; + case 0x4218: + return SwapInputBits(snes->input1->currentState) & 0xff; + case 0x4219: + return SwapInputBits(snes->input1->currentState) >> 8; + case 0x421a: + case 0x421c: + case 0x421e: + case 0x421b: + case 0x421d: + case 0x421f: + return 0; + + default: { + return snes->openBus; + } + } +} + +static void snes_writeReg(Snes* snes, uint16_t adr, uint8_t val) { + switch(adr) { + case 0x4200: { + snes->autoJoyRead = val & 0x1; + if(!snes->autoJoyRead) snes->autoJoyTimer = 0; + snes->hIrqEnabled = val & 0x10; + snes->vIrqEnabled = val & 0x20; + snes->nmiEnabled = val & 0x80; + if(!snes->hIrqEnabled && !snes->vIrqEnabled) { + snes->inIrq = false; + snes->cpu->irqWanted = false; + } + // TODO: enabling nmi during vblank with inNmi still set generates nmi + // enabling virq (and not h) on the vPos that vTimer is at generates irq (?) + break; + } + case 0x4201: { + if(!(val & 0x80) && snes->ppuLatch) { + // latch the ppu + ppu_read(snes->ppu, 0x37); + } + snes->ppuLatch = val & 0x80; + break; + } + case 0x4202: { + snes->multiplyA = val; + break; + } + case 0x4203: { + snes->multiplyResult = snes->multiplyA * val; + break; + } + case 0x4204: { + snes->divideA = (snes->divideA & 0xff00) | val; + break; + } + case 0x4205: { + snes->divideA = (snes->divideA & 0x00ff) | (val << 8); + break; + } + case 0x4206: { + if(val == 0) { + snes->divideResult = 0xffff; + snes->multiplyResult = snes->divideA; + } else { + snes->divideResult = snes->divideA / val; + snes->multiplyResult = snes->divideA % val; + } + break; + } + case 0x4207: { + snes->hTimer = (snes->hTimer & 0x100) | val; + break; + } + case 0x4208: { + snes->hTimer = (snes->hTimer & 0x0ff) | ((val & 1) << 8); + break; + } + case 0x4209: { + snes->vTimer = (snes->vTimer & 0x100) | val; + break; + } + case 0x420a: { + snes->vTimer = (snes->vTimer & 0x0ff) | ((val & 1) << 8); + break; + } + case 0x420b: { + if (val == 2) { + uint32_t t = snes->dma->channel[1].aBank << 16 | snes->dma->channel[1].aAdr; + int data = snes_read(snes, t) | snes_read(snes, t + 1) << 8; + + if (0)printf("DMA: 0x%x -> 0x%x (ppu 0x%x), 0x%x bytes, data 0x%x\n", + t, snes->dma->channel[1].bAdr, + snes->ppu->vramPointer, snes->dma->channel[1].size, data); + } + dma_startDma(snes->dma, val, false); + while (dma_cycle(snes->dma)) {} + break; + } + case 0x420c: { + dma_startDma(snes->dma, val, true); + break; + } + case 0x420d: { + snes->fastMem = val & 0x1; + break; + } + default: { + break; + } + } +} + +uint8_t snes_read(Snes* snes, uint32_t adr) { + uint8_t bank = adr >> 16; + adr &= 0xffff; + if(bank == 0x7e || bank == 0x7f) { + return snes->ram[((bank & 1) << 16) | adr]; // ram + } + if(bank < 0x40 || (bank >= 0x80 && bank < 0xc0)) { + if(adr < 0x2000) { + return snes->ram[adr]; // ram mirror + } + if(adr >= 0x2100 && adr < 0x2200) { + return snes_readBBus(snes, adr & 0xff); // B-bus + } + if (adr == 0x4016 || adr == 0x4017) { + assert(0); + } + if(adr >= 0x4200 && adr < 0x4220 || adr >= 0x4218 && adr < 0x4220) { + return snes_readReg(snes, adr); // internal registers + } + if(adr >= 0x4300 && adr < 0x4380) { + return dma_read(snes->dma, adr); // dma registers + } + } + // read from cart + return cart_read(snes->cart, bank, adr); +} + +void LogWrite(Snes *snes, uint32_t adr, uint8_t val) { + printf("@%d: Write to 0x%x = 0x%.2x: 0x%x: 0x%x: x = 0x%x, y = 0x%x, c = %d\n", + snes_frame_counter, adr, val, snes->cpu->k << 16 | snes->cpu->pc, + snes->ram[0x12] | snes->ram[0x13] << 8, snes->cpu->x, snes->cpu->y, snes->cpu->c); +} + +void snes_write(Snes* snes, uint32_t adr, uint8_t val) { + uint8_t bank = adr >> 16; + adr &= 0xffff; + if(bank == 0x7e || bank == 0x7f) { + uint32_t addr = ((bank & 1) << 16) | adr; + snes->ram[addr] = val; // ram + if (IS_ADR(addr)) { + LogWrite(snes, adr, val); + } + } + if(bank < 0x40 || (bank >= 0x80 && bank < 0xc0)) { + if(adr < 0x2000) { + snes->ram[adr] = val; // ram mirror + if (IS_ADR(adr)) { + LogWrite(snes, adr, val); + } + } + if(adr >= 0x2100 && adr < 0x2200) { + snes_writeBBus(snes, adr & 0xff, val); // B-bus + } + if(adr >= 0x4200 && adr < 0x4220) { + snes_writeReg(snes, adr, val); // internal registers + } + if(adr >= 0x4300 && adr < 0x4380) { + dma_write(snes->dma, adr, val); // dma registers + } + } + // write to cart + cart_write(snes->cart, bank, adr, val); +} + + +uint8_t snes_cpuRead(Snes* snes, uint32_t adr) { + snes->cpuMemOps++; + snes->cpuCyclesLeft += 8; + return snes_read(snes, adr); +} + +void snes_cpuWrite(Snes* snes, uint32_t adr, uint8_t val) { + snes->cpuMemOps++; + snes->cpuCyclesLeft += 8; + snes_write(snes, adr, val); +} + diff --git a/src/snes/snes.h b/src/snes/snes.h new file mode 100644 index 0000000..2728206 --- /dev/null +++ b/src/snes/snes.h @@ -0,0 +1,95 @@ + +#ifndef SNES_H +#define SNES_H + +#include +#include +#include +#include +#include + +typedef struct Snes Snes; + +#include "cpu.h" +#include "apu.h" +#include "dma.h" +#include "ppu.h" +#include "cart.h" +#include "input.h" +#include "saveload.h" + +struct Snes { + Cpu* cpu; + Apu* apu; + Ppu* ppu, *snes_ppu, *my_ppu; + Dma* dma; + Cart* cart; + // input + bool debug_cycles; + bool debug_apu_cycles; + bool disableRender; + uint8_t runningWhichVersion; + Input* input1; + Input* input2; + // ram + uint8_t *ram; + uint32_t ramAdr; + // frame timing + uint16_t hPos; + uint16_t vPos; + uint32_t frames; + // cpu handling + uint8_t cpuCyclesLeft; + uint8_t cpuMemOps; + double apuCatchupCycles; + // nmi / irq + bool hIrqEnabled; + bool vIrqEnabled; + bool nmiEnabled; + uint16_t hTimer; + uint16_t vTimer; + bool inNmi; + bool inIrq; + bool inVblank; + // joypad handling + uint16_t portAutoReadX[4]; // as read by auto-joypad read + bool autoJoyRead; + uint16_t autoJoyTimer; // times how long until reading is done + bool ppuLatch; + // multiplication/division + uint8_t multiplyA; + uint16_t multiplyResult; + uint16_t divideA; + uint16_t divideResult; + // misc + bool fastMem; + uint8_t openBus; +}; + +Snes* snes_init(uint8_t *ram); +void snes_free(Snes* snes); +void snes_reset(Snes* snes, bool hard); +void snes_runFrame(Snes* snes); +// used by dma, cpu +uint8_t snes_readBBus(Snes* snes, uint8_t adr); +void snes_writeBBus(Snes* snes, uint8_t adr, uint8_t val); +uint8_t snes_read(Snes* snes, uint32_t adr); +void snes_write(Snes* snes, uint32_t adr, uint8_t val); +uint8_t snes_cpuRead(Snes* snes, uint32_t adr); +void snes_cpuWrite(Snes* snes, uint32_t adr, uint8_t val); +// debugging +void snes_debugCycle(Snes* snes, bool* cpuNext, bool* spcNext); + +void snes_handle_pos_stuff(Snes *snes); + +// snes_other.c functions: + +bool snes_loadRom(Snes* snes, const uint8_t* data, int length); +void snes_setPixels(Snes* snes, uint8_t* pixelData); +void snes_setSamples(Snes* snes, int16_t* sampleData, int samplesPerFrame); +void snes_saveload(Snes *snes, SaveLoadFunc *func, void *ctx); +uint8_t snes_readBBusOrg(Snes *snes, uint8_t adr); +void snes_catchupApu(Snes *snes); + +extern int snes_frame_counter; +#endif diff --git a/src/snes/snes_other.c b/src/snes/snes_other.c new file mode 100644 index 0000000..49f06f6 --- /dev/null +++ b/src/snes/snes_other.c @@ -0,0 +1,204 @@ + +#include +#include +#include +#include +#include + +#include "snes.h" +#include "cart.h" +#include "ppu.h" +#include "dsp.h" + +typedef struct CartHeader { + // normal header + uint8_t headerVersion; // 1, 2, 3 + char name[22]; // $ffc0-$ffd4 (max 21 bytes + \0), $ffd4=$00: header V2 + uint8_t speed; // $ffd5.7-4 (always 2 or 3) + uint8_t type; // $ffd5.3-0 + uint8_t coprocessor; // $ffd6.7-4 + uint8_t chips; // $ffd6.3-0 + uint32_t romSize; // $ffd7 (0x400 << x) + uint32_t ramSize; // $ffd8 (0x400 << x) + uint8_t region; // $ffd9 (also NTSC/PAL) + uint8_t maker; // $ffda ($33: header V3) + uint8_t version; // $ffdb + uint16_t checksumComplement; // $ffdc,$ffdd + uint16_t checksum; // $ffde,$ffdf + // v2/v3 (v2 only exCoprocessor) + char makerCode[3]; // $ffb0,$ffb1: (2 chars + \0) + char gameCode[5]; // $ffb2-$ffb5: (4 chars + \0) + uint32_t flashSize; // $ffbc (0x400 << x) + uint32_t exRamSize; // $ffbd (0x400 << x) (used for GSU?) + uint8_t specialVersion; // $ffbe + uint8_t exCoprocessor; // $ffbf (if coprocessor = $f) + // calculated stuff + int16_t score; // score for header, to see which mapping is most likely + bool pal; // if this is a rom for PAL regions instead of NTSC + uint8_t cartType; // calculated type +} CartHeader; + +static void readHeader(const uint8_t* data, int length, int location, CartHeader* header); + +bool snes_loadRom(Snes* snes, const uint8_t* data, int length) { + // if smaller than smallest possible, don't load + if(length < 0x8000) { + printf("Failed to load rom: rom to small (%d bytes)\n", length); + return false; + } + // check headers + CartHeader headers[4]; + memset(headers, 0, sizeof(headers)); + for(int i = 0; i < 4; i++) { + headers[i].score = -50; + } + if(length >= 0x8000) readHeader(data, length, 0x7fc0, &headers[0]); + if(length >= 0x8200) readHeader(data, length, 0x81c0, &headers[1]); + if(length >= 0x10000) readHeader(data, length, 0xffc0, &headers[2]); + if(length >= 0x10200) readHeader(data, length, 0x101c0, &headers[3]); + // see which it is + int max = 0; + int used = 0; + for(int i = 0; i < 4; i++) { + if(headers[i].score > max) { + max = headers[i].score; + used = i; + } + } + if(used & 1) { + // odd-numbered ones are for headered roms + data += 0x200; // move pointer past header + length -= 0x200; // and subtract from size + } + // check if we can load it + if(headers[used].cartType > 2) { + printf("Failed to load rom: unsupported type (%d)\n", headers[used].cartType); + return false; + } + // expand to a power of 2 + int newLength = 0x8000; + while(true) { + if(length <= newLength) { + break; + } + newLength *= 2; + } + uint8_t* newData = malloc(newLength); + memcpy(newData, data, length); + int test = 1; + while(length != newLength) { + if(length & test) { + memcpy(newData + length, newData + length - test, test); + length += test; + } + test *= 2; + } + // load it + printf("Loaded %s rom\n\"%s\"\n", headers[used].cartType == 2 ? "HiROM" : "LoROM", headers[used].name); + cart_load( + snes->cart, headers[used].cartType, + newData, newLength, headers[used].chips > 0 ? headers[used].ramSize : 0 + ); + snes_reset(snes, true); // reset after loading + free(newData); + return true; +} + +void snes_setSamples(Snes* snes, int16_t* sampleData, int samplesPerFrame) { + // size is 2 (int16) * 2 (stereo) * samplesPerFrame + // sets samples in the sampleData + dsp_getSamples(snes->apu->dsp, sampleData, samplesPerFrame); +} + +static void readHeader(const uint8_t* data, int length, int location, CartHeader* header) { + // read name, TODO: non-ASCII names? + for(int i = 0; i < 21; i++) { + uint8_t ch = data[location + i]; + if(ch >= 0x20 && ch < 0x7f) { + header->name[i] = ch; + } else { + header->name[i] = '.'; + } + } + header->name[21] = 0; + // read rest + header->speed = data[location + 0x15] >> 4; + header->type = data[location + 0x15] & 0xf; + header->coprocessor = data[location + 0x16] >> 4; + header->chips = data[location + 0x16] & 0xf; + header->romSize = 0x400 << data[location + 0x17]; + header->ramSize = 0x400 << data[location + 0x18]; + header->region = data[location + 0x19]; + header->maker = data[location + 0x1a]; + header->version = data[location + 0x1b]; + header->checksumComplement = (data[location + 0x1d] << 8) + data[location + 0x1c]; + header->checksum = (data[location + 0x1f] << 8) + data[location + 0x1e]; + // read v3 and/or v2 + header->headerVersion = 1; + if(header->maker == 0x33) { + header->headerVersion = 3; + // maker code + for(int i = 0; i < 2; i++) { + uint8_t ch = data[location - 0x10 + i]; + if(ch >= 0x20 && ch < 0x7f) { + header->makerCode[i] = ch; + } else { + header->makerCode[i] = '.'; + } + } + header->makerCode[2] = 0; + // game code + for(int i = 0; i < 4; i++) { + uint8_t ch = data[location - 0xe + i]; + if(ch >= 0x20 && ch < 0x7f) { + header->gameCode[i] = ch; + } else { + header->gameCode[i] = '.'; + } + } + header->gameCode[4] = 0; + header->flashSize = 0x400 << data[location - 4]; + header->exRamSize = 0x400 << data[location - 3]; + header->specialVersion = data[location - 2]; + header->exCoprocessor = data[location - 1]; + } else if(data[location + 0x14] == 0) { + header->headerVersion = 2; + header->exCoprocessor = data[location - 1]; + } + // get region + header->pal = (header->region >= 0x2 && header->region <= 0xc) || header->region == 0x11; + header->cartType = location < 0x9000 ? 1 : 2; + // get score + // TODO: check name, maker/game-codes (if V3) for ASCII, more vectors, + // more first opcode, rom-sizes (matches?), type (matches header location?) + int score = 0; + score += (header->speed == 2 || header->speed == 3) ? 5 : -4; + score += (header->type <= 3 || header->type == 5) ? 5 : -2; + score += (header->coprocessor <= 5 || header->coprocessor >= 0xe) ? 5 : -2; + score += (header->chips <= 6 || header->chips == 9 || header->chips == 0xa) ? 5 : -2; + score += (header->region <= 0x14) ? 5 : -2; + score += (header->checksum + header->checksumComplement == 0xffff) ? 8 : -6; + uint16_t resetVector = data[location + 0x3c] | (data[location + 0x3d] << 8); + score += (resetVector >= 0x8000) ? 8 : -20; + // check first opcode after reset + int opcodeLoc = location + 0x40 - 0x8000 + (resetVector & 0x7fff); + uint8_t opcode = 0xff; + if(opcodeLoc < length) { + opcode = data[opcodeLoc]; + } else { + score -= 14; + } + if(opcode == 0x78 || opcode == 0x18) { + // sei, clc (for clc:xce) + score += 6; + } + if(opcode == 0x4c || opcode == 0x5c || opcode == 0x9c) { + // jmp abs, jml abl, stz abs + score += 3; + } + if(opcode == 0x00 || opcode == 0xff || opcode == 0xdb) { + // brk, sbc alx, stp + score -= 6; + } + header->score = score; +} diff --git a/src/snes/spc.c b/src/snes/spc.c new file mode 100644 index 0000000..5fe8f67 --- /dev/null +++ b/src/snes/spc.c @@ -0,0 +1,1527 @@ + +#include +#include +#include +#include +#include +#include + +#include "spc.h" +#include "apu.h" + +static const int cyclesPerOpcode[256] = { + 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8, + 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 4, 6, + 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 5, 4, + 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 3, 8, + 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 6, 6, + 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 4, 5, 2, 2, 4, 3, + 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 5, 5, + 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 6, + 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 2, 4, 5, + 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 12,5, + 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 2, 4, 4, + 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 4, + 2, 8, 4, 5, 4, 5, 4, 7, 2, 5, 6, 4, 5, 2, 4, 9, + 2, 8, 4, 5, 5, 6, 6, 7, 4, 5, 5, 5, 2, 2, 6, 3, + 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3, + 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3 +}; + +static uint8_t spc_read(Spc* spc, uint16_t adr); +static void spc_write(Spc* spc, uint16_t adr, uint8_t val); +static uint8_t spc_readOpcode(Spc* spc); +static uint16_t spc_readOpcodeWord(Spc* spc); +static uint8_t spc_getFlags(Spc* spc); +static void spc_setFlags(Spc* spc, uint8_t value); +static void spc_setZN(Spc* spc, uint8_t value); +static void spc_doBranch(Spc* spc, uint8_t value, bool check); +static uint8_t spc_pullByte(Spc* spc); +static void spc_pushByte(Spc* spc, uint8_t value); +static uint16_t spc_pullWord(Spc* spc); +static void spc_pushWord(Spc* spc, uint16_t value); +static uint16_t spc_readWord(Spc* spc, uint16_t adrl, uint16_t adrh); +static void spc_writeWord(Spc* spc, uint16_t adrl, uint16_t adrh, uint16_t value); +static void spc_doOpcode(Spc* spc, uint8_t opcode); + +// addressing modes and opcode functions not declared, only used after defintions + +static uint8_t spc_read(Spc* spc, uint16_t adr) { + return apu_cpuRead(spc->apu, adr); +} + +static void spc_write(Spc* spc, uint16_t adr, uint8_t val) { + apu_cpuWrite(spc->apu, adr, val); +} + +Spc* spc_init(Apu* apu) { + Spc* spc = malloc(sizeof(Spc)); + spc->apu = apu; + return spc; +} + +void spc_free(Spc* spc) { + free(spc); +} + +void spc_reset(Spc* spc) { + spc->a = 0; + spc->x = 0; + spc->y = 0; + spc->sp = 0; + spc->pc = spc_read(spc, 0xfffe) | (spc_read(spc, 0xffff) << 8); + spc->c = false; + spc->z = false; + spc->v = false; + spc->n = false; + spc->i = false; + spc->h = false; + spc->p = false; + spc->b = false; + spc->stopped = false; + spc->cyclesUsed = 0; +} + +void spc_saveload(Spc *spc, SaveLoadFunc *func, void *ctx) { + func(ctx, &spc->a, offsetof(Spc, cyclesUsed) - offsetof(Spc, a)); +} + +int spc_runOpcode(Spc* spc) { + spc->cyclesUsed = 0; + if(spc->stopped) return 1; + uint8_t opcode = spc_readOpcode(spc); + spc->cyclesUsed = cyclesPerOpcode[opcode]; + spc_doOpcode(spc, opcode); + return spc->cyclesUsed; +} + +static uint8_t spc_readOpcode(Spc* spc) { + return spc_read(spc, spc->pc++); +} + +static uint16_t spc_readOpcodeWord(Spc* spc) { + uint8_t low = spc_readOpcode(spc); + return low | (spc_readOpcode(spc) << 8); +} + +static uint8_t spc_getFlags(Spc* spc) { + uint8_t val = spc->n << 7; + val |= spc->v << 6; + val |= spc->p << 5; + val |= spc->b << 4; + val |= spc->h << 3; + val |= spc->i << 2; + val |= spc->z << 1; + val |= spc->c; + return val; +} + +static void spc_setFlags(Spc* spc, uint8_t val) { + spc->n = val & 0x80; + spc->v = val & 0x40; + spc->p = val & 0x20; + spc->b = val & 0x10; + spc->h = val & 8; + spc->i = val & 4; + spc->z = val & 2; + spc->c = val & 1; +} + +static void spc_setZN(Spc* spc, uint8_t value) { + spc->z = value == 0; + spc->n = value & 0x80; +} + +static void spc_doBranch(Spc* spc, uint8_t value, bool check) { + if(check) { + spc->cyclesUsed += 2; // taken branch: 2 extra cycles + spc->pc += (int8_t) value; + } +} + +static uint8_t spc_pullByte(Spc* spc) { + spc->sp++; + return spc_read(spc, 0x100 | spc->sp); +} + +static void spc_pushByte(Spc* spc, uint8_t value) { + spc_write(spc, 0x100 | spc->sp, value); + spc->sp--; +} + +static uint16_t spc_pullWord(Spc* spc) { + uint8_t value = spc_pullByte(spc); + return value | (spc_pullByte(spc) << 8); +} + +static void spc_pushWord(Spc* spc, uint16_t value) { + spc_pushByte(spc, value >> 8); + spc_pushByte(spc, value & 0xff); +} + +static uint16_t spc_readWord(Spc* spc, uint16_t adrl, uint16_t adrh) { + uint8_t value = spc_read(spc, adrl); + return value | (spc_read(spc, adrh) << 8); +} + +static void spc_writeWord(Spc* spc, uint16_t adrl, uint16_t adrh, uint16_t value) { + spc_write(spc, adrl, value & 0xff); + spc_write(spc, adrh, value >> 8); +} + +// adressing modes + +static uint16_t spc_adrDp(Spc* spc) { + return spc_readOpcode(spc) | (spc->p << 8); +} + +static uint16_t spc_adrAbs(Spc* spc) { + return spc_readOpcodeWord(spc); +} + +static uint16_t spc_adrInd(Spc* spc) { + return spc->x | (spc->p << 8); +} + +static uint16_t spc_adrIdx(Spc* spc) { + uint8_t pointer = spc_readOpcode(spc); + return spc_readWord(spc, ((pointer + spc->x) & 0xff) | (spc->p << 8), ((pointer + spc->x + 1) & 0xff) | (spc->p << 8)); +} + +static uint16_t spc_adrImm(Spc* spc) { + return spc->pc++; +} + +static uint16_t spc_adrDpx(Spc* spc) { + return ((spc_readOpcode(spc) + spc->x) & 0xff) | (spc->p << 8); +} + +static uint16_t spc_adrDpy(Spc* spc) { + return ((spc_readOpcode(spc) + spc->y) & 0xff) | (spc->p << 8); +} + +static uint16_t spc_adrAbx(Spc* spc) { + return (spc_readOpcodeWord(spc) + spc->x) & 0xffff; +} + +static uint16_t spc_adrAby(Spc* spc) { + return (spc_readOpcodeWord(spc) + spc->y) & 0xffff; +} + +static uint16_t spc_adrIdy(Spc* spc) { + uint8_t pointer = spc_readOpcode(spc); + uint16_t adr = spc_readWord(spc, pointer | (spc->p << 8), ((pointer + 1) & 0xff) | (spc->p << 8)); + return (adr + spc->y) & 0xffff; +} + +static uint16_t spc_adrDpDp(Spc* spc, uint16_t* src) { + *src = spc_readOpcode(spc) | (spc->p << 8); + return spc_readOpcode(spc) | (spc->p << 8); +} + +static uint16_t spc_adrDpImm(Spc* spc, uint16_t* src) { + *src = spc->pc++; + return spc_readOpcode(spc) | (spc->p << 8); +} + +static uint16_t spc_adrIndInd(Spc* spc, uint16_t* src) { + *src = spc->y | (spc->p << 8); + return spc->x | (spc->p << 8); +} + +static uint8_t spc_adrAbsBit(Spc* spc, uint16_t* adr) { + uint16_t adrBit = spc_readOpcodeWord(spc); + *adr = adrBit & 0x1fff; + return adrBit >> 13; +} + +static uint16_t spc_adrDpWord(Spc* spc, uint16_t* low) { + uint8_t adr = spc_readOpcode(spc); + *low = adr | (spc->p << 8); + return ((adr + 1) & 0xff) | (spc->p << 8); +} + +static uint16_t spc_adrIndP(Spc* spc) { + return spc->x++ | (spc->p << 8); +} + +// opcode functions + +static void spc_and(Spc* spc, uint16_t adr) { + spc->a &= spc_read(spc, adr); + spc_setZN(spc, spc->a); +} + +static void spc_andm(Spc* spc, uint16_t dst, uint16_t src) { + uint8_t value = spc_read(spc, src); + uint8_t result = spc_read(spc, dst) & value; + spc_write(spc, dst, result); + spc_setZN(spc, result); +} + +static void spc_or(Spc* spc, uint16_t adr) { + spc->a |= spc_read(spc, adr); + spc_setZN(spc, spc->a); +} + +static void spc_orm(Spc* spc, uint16_t dst, uint16_t src) { + uint8_t value = spc_read(spc, src); + uint8_t result = spc_read(spc, dst) | value; + spc_write(spc, dst, result); + spc_setZN(spc, result); +} + +static void spc_eor(Spc* spc, uint16_t adr) { + spc->a ^= spc_read(spc, adr); + spc_setZN(spc, spc->a); +} + +static void spc_eorm(Spc* spc, uint16_t dst, uint16_t src) { + uint8_t value = spc_read(spc, src); + uint8_t result = spc_read(spc, dst) ^ value; + spc_write(spc, dst, result); + spc_setZN(spc, result); +} + +static void spc_adc(Spc* spc, uint16_t adr) { + uint8_t value = spc_read(spc, adr); + int result = spc->a + value + spc->c; + spc->v = (spc->a & 0x80) == (value & 0x80) && (value & 0x80) != (result & 0x80); + spc->h = ((spc->a & 0xf) + (value & 0xf) + spc->c) > 0xf; + spc->c = result > 0xff; + spc->a = result; + spc_setZN(spc, spc->a); +} + +static void spc_adcm(Spc* spc, uint16_t dst, uint16_t src) { + uint8_t value = spc_read(spc, src); + uint8_t applyOn = spc_read(spc, dst); + int result = applyOn + value + spc->c; + spc->v = (applyOn & 0x80) == (value & 0x80) && (value & 0x80) != (result & 0x80); + spc->h = ((applyOn & 0xf) + (value & 0xf) + spc->c) > 0xf; + spc->c = result > 0xff; + spc_write(spc, dst, result); + spc_setZN(spc, result); +} + +static void spc_sbc(Spc* spc, uint16_t adr) { + uint8_t value = spc_read(spc, adr) ^ 0xff; + int result = spc->a + value + spc->c; + spc->v = (spc->a & 0x80) == (value & 0x80) && (value & 0x80) != (result & 0x80); + spc->h = ((spc->a & 0xf) + (value & 0xf) + spc->c) > 0xf; + spc->c = result > 0xff; + spc->a = result; + spc_setZN(spc, spc->a); +} + +static void spc_sbcm(Spc* spc, uint16_t dst, uint16_t src) { + uint8_t value = spc_read(spc, src) ^ 0xff; + uint8_t applyOn = spc_read(spc, dst); + int result = applyOn + value + spc->c; + spc->v = (applyOn & 0x80) == (value & 0x80) && (value & 0x80) != (result & 0x80); + spc->h = ((applyOn & 0xf) + (value & 0xf) + spc->c) > 0xf; + spc->c = result > 0xff; + spc_write(spc, dst, result); + spc_setZN(spc, result); +} + +static void spc_cmp(Spc* spc, uint16_t adr) { + uint8_t value = spc_read(spc, adr) ^ 0xff; + int result = spc->a + value + 1; + spc->c = result > 0xff; + spc_setZN(spc, result); +} + +static void spc_cmpx(Spc* spc, uint16_t adr) { + uint8_t value = spc_read(spc, adr) ^ 0xff; + int result = spc->x + value + 1; + spc->c = result > 0xff; + spc_setZN(spc, result); +} + +static void spc_cmpy(Spc* spc, uint16_t adr) { + uint8_t value = spc_read(spc, adr) ^ 0xff; + int result = spc->y + value + 1; + spc->c = result > 0xff; + spc_setZN(spc, result); +} + +static void spc_cmpm(Spc* spc, uint16_t dst, uint16_t src) { + uint8_t value = spc_read(spc, src) ^ 0xff; + int result = spc_read(spc, dst) + value + 1; + spc->c = result > 0xff; + spc_setZN(spc, result); +} + +static void spc_mov(Spc* spc, uint16_t adr) { + spc->a = spc_read(spc, adr); + spc_setZN(spc, spc->a); +} + +static void spc_movx(Spc* spc, uint16_t adr) { + spc->x = spc_read(spc, adr); + spc_setZN(spc, spc->x); +} + +static void spc_movy(Spc* spc, uint16_t adr) { + spc->y = spc_read(spc, adr); + spc_setZN(spc, spc->y); +} + +static void spc_movs(Spc* spc, uint16_t adr) { + spc_read(spc, adr); + spc_write(spc, adr, spc->a); +} + +static void spc_movsx(Spc* spc, uint16_t adr) { + spc_read(spc, adr); + spc_write(spc, adr, spc->x); +} + +static void spc_movsy(Spc* spc, uint16_t adr) { + spc_read(spc, adr); + spc_write(spc, adr, spc->y); +} + +static void spc_asl(Spc* spc, uint16_t adr) { + uint8_t val = spc_read(spc, adr); + spc->c = val & 0x80; + val <<= 1; + spc_write(spc, adr, val); + spc_setZN(spc, val); +} + +static void spc_lsr(Spc* spc, uint16_t adr) { + uint8_t val = spc_read(spc, adr); + spc->c = val & 1; + val >>= 1; + spc_write(spc, adr, val); + spc_setZN(spc, val); +} + +static void spc_rol(Spc* spc, uint16_t adr) { + uint8_t val = spc_read(spc, adr); + bool newC = val & 0x80; + val = (val << 1) | spc->c; + spc->c = newC; + spc_write(spc, adr, val); + spc_setZN(spc, val); +} + +static void spc_ror(Spc* spc, uint16_t adr) { + uint8_t val = spc_read(spc, adr); + bool newC = val & 1; + val = (val >> 1) | (spc->c << 7); + spc->c = newC; + spc_write(spc, adr, val); + spc_setZN(spc, val); +} + +static void spc_inc(Spc* spc, uint16_t adr) { + uint8_t val = spc_read(spc, adr) + 1; + spc_write(spc, adr, val); + spc_setZN(spc, val); +} + +static void spc_dec(Spc* spc, uint16_t adr) { + uint8_t val = spc_read(spc, adr) - 1; + spc_write(spc, adr, val); + spc_setZN(spc, val); +} + +static void spc_doOpcode(Spc* spc, uint8_t opcode) { + switch(opcode) { + case 0x00: { // nop imp + // no operation + break; + } + case 0x01: + case 0x11: + case 0x21: + case 0x31: + case 0x41: + case 0x51: + case 0x61: + case 0x71: + case 0x81: + case 0x91: + case 0xa1: + case 0xb1: + case 0xc1: + case 0xd1: + case 0xe1: + case 0xf1: { // tcall imp + spc_pushWord(spc, spc->pc); + uint16_t adr = 0xffde - (2 * (opcode >> 4)); + spc->pc = spc_readWord(spc, adr, adr + 1); + break; + } + case 0x02: + case 0x22: + case 0x42: + case 0x62: + case 0x82: + case 0xa2: + case 0xc2: + case 0xe2: { // set1 dp + uint16_t adr = spc_adrDp(spc); + spc_write(spc, adr, spc_read(spc, adr) | (1 << (opcode >> 5))); + break; + } + case 0x12: + case 0x32: + case 0x52: + case 0x72: + case 0x92: + case 0xb2: + case 0xd2: + case 0xf2: { // clr1 dp + uint16_t adr = spc_adrDp(spc); + spc_write(spc, adr, spc_read(spc, adr) & ~(1 << (opcode >> 5))); + break; + } + case 0x03: + case 0x23: + case 0x43: + case 0x63: + case 0x83: + case 0xa3: + case 0xc3: + case 0xe3: { // bbs dp, rel + uint8_t val = spc_read(spc, spc_adrDp(spc)); + spc_doBranch(spc, spc_readOpcode(spc), val & (1 << (opcode >> 5))); + break; + } + case 0x13: + case 0x33: + case 0x53: + case 0x73: + case 0x93: + case 0xb3: + case 0xd3: + case 0xf3: { // bbc dp, rel + uint8_t val = spc_read(spc, spc_adrDp(spc)); + spc_doBranch(spc, spc_readOpcode(spc), (val & (1 << (opcode >> 5))) == 0); + break; + } + case 0x04: { // or dp + spc_or(spc, spc_adrDp(spc)); + break; + } + case 0x05: { // or abs + spc_or(spc, spc_adrAbs(spc)); + break; + } + case 0x06: { // or ind + spc_or(spc, spc_adrInd(spc)); + break; + } + case 0x07: { // or idx + spc_or(spc, spc_adrIdx(spc)); + break; + } + case 0x08: { // or imm + spc_or(spc, spc_adrImm(spc)); + break; + } + case 0x09: { // orm dp, dp + uint16_t src = 0; + uint16_t dst = spc_adrDpDp(spc, &src); + spc_orm(spc, dst, src); + break; + } + case 0x0a: { // or1 abs.bit + uint16_t adr = 0; + uint8_t bit = spc_adrAbsBit(spc, &adr); + spc->c = spc->c | ((spc_read(spc, adr) >> bit) & 1); + break; + } + case 0x0b: { // asl dp + spc_asl(spc, spc_adrDp(spc)); + break; + } + case 0x0c: { // asl abs + spc_asl(spc, spc_adrAbs(spc)); + break; + } + case 0x0d: { // pushp imp + spc_pushByte(spc, spc_getFlags(spc)); + break; + } + case 0x0e: { // tset1 abs + uint16_t adr = spc_adrAbs(spc); + uint8_t val = spc_read(spc, adr); + uint8_t result = spc->a + (val ^ 0xff) + 1; + spc_setZN(spc, result); + spc_write(spc, adr, val | spc->a); + break; + } + case 0x0f: { // brk imp + spc_pushWord(spc, spc->pc); + spc_pushByte(spc, spc_getFlags(spc)); + spc->i = false; + spc->b = true; + spc->pc = spc_readWord(spc, 0xffde, 0xffdf); + break; + } + case 0x10: { // bpl rel + spc_doBranch(spc, spc_readOpcode(spc), !spc->n); + break; + } + case 0x14: { // or dpx + spc_or(spc, spc_adrDpx(spc)); + break; + } + case 0x15: { // or abx + spc_or(spc, spc_adrAbx(spc)); + break; + } + case 0x16: { // or aby + spc_or(spc, spc_adrAby(spc)); + break; + } + case 0x17: { // or idy + spc_or(spc, spc_adrIdy(spc)); + break; + } + case 0x18: { // orm dp, imm + uint16_t src = 0; + uint16_t dst = spc_adrDpImm(spc, &src); + spc_orm(spc, dst, src); + break; + } + case 0x19: { // orm ind, ind + uint16_t src = 0; + uint16_t dst = spc_adrIndInd(spc, &src); + spc_orm(spc, dst, src); + break; + } + case 0x1a: { // decw dp + uint16_t low = 0; + uint16_t high = spc_adrDpWord(spc, &low); + uint16_t value = spc_readWord(spc, low, high) - 1; + spc->z = value == 0; + spc->n = value & 0x8000; + spc_writeWord(spc, low, high, value); + break; + } + case 0x1b: { // asl dpx + spc_asl(spc, spc_adrDpx(spc)); + break; + } + case 0x1c: { // asla imp + spc->c = spc->a & 0x80; + spc->a <<= 1; + spc_setZN(spc, spc->a); + break; + } + case 0x1d: { // decx imp + spc->x--; + spc_setZN(spc, spc->x); + break; + } + case 0x1e: { // cmpx abs + spc_cmpx(spc, spc_adrAbs(spc)); + break; + } + case 0x1f: { // jmp iax + uint16_t pointer = spc_readOpcodeWord(spc); + spc->pc = spc_readWord(spc, (pointer + spc->x) & 0xffff, (pointer + spc->x + 1) & 0xffff); + break; + } + case 0x20: { // clrp imp + spc->p = false; + break; + } + case 0x24: { // and dp + spc_and(spc, spc_adrDp(spc)); + break; + } + case 0x25: { // and abs + spc_and(spc, spc_adrAbs(spc)); + break; + } + case 0x26: { // and ind + spc_and(spc, spc_adrInd(spc)); + break; + } + case 0x27: { // and idx + spc_and(spc, spc_adrIdx(spc)); + break; + } + case 0x28: { // and imm + spc_and(spc, spc_adrImm(spc)); + break; + } + case 0x29: { // andm dp, dp + uint16_t src = 0; + uint16_t dst = spc_adrDpDp(spc, &src); + spc_andm(spc, dst, src); + break; + } + case 0x2a: { // or1n abs.bit + uint16_t adr = 0; + uint8_t bit = spc_adrAbsBit(spc, &adr); + spc->c = spc->c | (~(spc_read(spc, adr) >> bit) & 1); + break; + } + case 0x2b: { // rol dp + spc_rol(spc, spc_adrDp(spc)); + break; + } + case 0x2c: { // rol abs + spc_rol(spc, spc_adrAbs(spc)); + break; + } + case 0x2d: { // pusha imp + spc_pushByte(spc, spc->a); + break; + } + case 0x2e: { // cbne dp, rel + uint8_t val = spc_read(spc, spc_adrDp(spc)) ^ 0xff; + uint8_t result = spc->a + val + 1; + spc_doBranch(spc, spc_readOpcode(spc), result != 0); + break; + } + case 0x2f: { // bra rel + spc->pc += (int8_t) spc_readOpcode(spc); + break; + } + case 0x30: { // bmi rel + spc_doBranch(spc, spc_readOpcode(spc), spc->n); + break; + } + case 0x34: { // and dpx + spc_and(spc, spc_adrDpx(spc)); + break; + } + case 0x35: { // and abx + spc_and(spc, spc_adrAbx(spc)); + break; + } + case 0x36: { // and aby + spc_and(spc, spc_adrAby(spc)); + break; + } + case 0x37: { // and idy + spc_and(spc, spc_adrIdy(spc)); + break; + } + case 0x38: { // andm dp, imm + uint16_t src = 0; + uint16_t dst = spc_adrDpImm(spc, &src); + spc_andm(spc, dst, src); + break; + } + case 0x39: { // andm ind, ind + uint16_t src = 0; + uint16_t dst = spc_adrIndInd(spc, &src); + spc_andm(spc, dst, src); + break; + } + case 0x3a: { // incw dp + uint16_t low = 0; + uint16_t high = spc_adrDpWord(spc, &low); + uint16_t value = spc_readWord(spc, low, high) + 1; + spc->z = value == 0; + spc->n = value & 0x8000; + spc_writeWord(spc, low, high, value); + break; + } + case 0x3b: { // rol dpx + spc_rol(spc, spc_adrDpx(spc)); + break; + } + case 0x3c: { // rola imp + bool newC = spc->a & 0x80; + spc->a = (spc->a << 1) | spc->c; + spc->c = newC; + spc_setZN(spc, spc->a); + break; + } + case 0x3d: { // incx imp + spc->x++; + spc_setZN(spc, spc->x); + break; + } + case 0x3e: { // cmpx dp + spc_cmpx(spc, spc_adrDp(spc)); + break; + } + case 0x3f: { // call abs + uint16_t dst = spc_readOpcodeWord(spc); + spc_pushWord(spc, spc->pc); + spc->pc = dst; + break; + } + case 0x40: { // setp imp + spc->p = true; + break; + } + case 0x44: { // eor dp + spc_eor(spc, spc_adrDp(spc)); + break; + } + case 0x45: { // eor abs + spc_eor(spc, spc_adrAbs(spc)); + break; + } + case 0x46: { // eor ind + spc_eor(spc, spc_adrInd(spc)); + break; + } + case 0x47: { // eor idx + spc_eor(spc, spc_adrIdx(spc)); + break; + } + case 0x48: { // eor imm + spc_eor(spc, spc_adrImm(spc)); + break; + } + case 0x49: { // eorm dp, dp + uint16_t src = 0; + uint16_t dst = spc_adrDpDp(spc, &src); + spc_eorm(spc, dst, src); + break; + } + case 0x4a: { // and1 abs.bit + uint16_t adr = 0; + uint8_t bit = spc_adrAbsBit(spc, &adr); + spc->c = spc->c & ((spc_read(spc, adr) >> bit) & 1); + break; + } + case 0x4b: { // lsr dp + spc_lsr(spc, spc_adrDp(spc)); + break; + } + case 0x4c: { // lsr abs + spc_lsr(spc, spc_adrAbs(spc)); + break; + } + case 0x4d: { // pushx imp + spc_pushByte(spc, spc->x); + break; + } + case 0x4e: { // tclr1 abs + uint16_t adr = spc_adrAbs(spc); + uint8_t val = spc_read(spc, adr); + uint8_t result = spc->a + (val ^ 0xff) + 1; + spc_setZN(spc, result); + spc_write(spc, adr, val & ~spc->a); + break; + } + case 0x4f: { // pcall dp + uint8_t dst = spc_readOpcode(spc); + spc_pushWord(spc, spc->pc); + spc->pc = 0xff00 | dst; + break; + } + case 0x50: { // bvc rel + spc_doBranch(spc, spc_readOpcode(spc), !spc->v); + break; + } + case 0x54: { // eor dpx + spc_eor(spc, spc_adrDpx(spc)); + break; + } + case 0x55: { // eor abx + spc_eor(spc, spc_adrAbx(spc)); + break; + } + case 0x56: { // eor aby + spc_eor(spc, spc_adrAby(spc)); + break; + } + case 0x57: { // eor idy + spc_eor(spc, spc_adrIdy(spc)); + break; + } + case 0x58: { // eorm dp, imm + uint16_t src = 0; + uint16_t dst = spc_adrDpImm(spc, &src); + spc_eorm(spc, dst, src); + break; + } + case 0x59: { // eorm ind, ind + uint16_t src = 0; + uint16_t dst = spc_adrIndInd(spc, &src); + spc_eorm(spc, dst, src); + break; + } + case 0x5a: { // cmpw dp + uint16_t low = 0; + uint16_t high = spc_adrDpWord(spc, &low); + uint16_t value = spc_readWord(spc, low, high) ^ 0xffff; + uint16_t ya = spc->a | (spc->y << 8); + int result = ya + value + 1; + spc->c = result > 0xffff; + spc->z = (result & 0xffff) == 0; + spc->n = result & 0x8000; + break; + } + case 0x5b: { // lsr dpx + spc_lsr(spc, spc_adrDpx(spc)); + break; + } + case 0x5c: { // lsra imp + spc->c = spc->a & 1; + spc->a >>= 1; + spc_setZN(spc, spc->a); + break; + } + case 0x5d: { // movxa imp + spc->x = spc->a; + spc_setZN(spc, spc->x); + break; + } + case 0x5e: { // cmpy abs + spc_cmpy(spc, spc_adrAbs(spc)); + break; + } + case 0x5f: { // jmp abs + spc->pc = spc_readOpcodeWord(spc); + break; + } + case 0x60: { // clrc imp + spc->c = false; + break; + } + case 0x64: { // cmp dp + spc_cmp(spc, spc_adrDp(spc)); + break; + } + case 0x65: { // cmp abs + spc_cmp(spc, spc_adrAbs(spc)); + break; + } + case 0x66: { // cmp ind + spc_cmp(spc, spc_adrInd(spc)); + break; + } + case 0x67: { // cmp idx + spc_cmp(spc, spc_adrIdx(spc)); + break; + } + case 0x68: { // cmp imm + spc_cmp(spc, spc_adrImm(spc)); + break; + } + case 0x69: { // cmpm dp, dp + uint16_t src = 0; + uint16_t dst = spc_adrDpDp(spc, &src); + spc_cmpm(spc, dst, src); + break; + } + case 0x6a: { // and1n abs.bit + uint16_t adr = 0; + uint8_t bit = spc_adrAbsBit(spc, &adr); + spc->c = spc->c & (~(spc_read(spc, adr) >> bit) & 1); + break; + } + case 0x6b: { // ror dp + spc_ror(spc, spc_adrDp(spc)); + break; + } + case 0x6c: { // ror abs + spc_ror(spc, spc_adrAbs(spc)); + break; + } + case 0x6d: { // pushy imp + spc_pushByte(spc, spc->y); + break; + } + case 0x6e: { // dbnz dp, rel + uint16_t adr = spc_adrDp(spc); + uint8_t result = spc_read(spc, adr) - 1; + spc_write(spc, adr, result); + spc_doBranch(spc, spc_readOpcode(spc), result != 0); + break; + } + case 0x6f: { // ret imp + spc->pc = spc_pullWord(spc); + break; + } + case 0x70: { // bvs rel + spc_doBranch(spc, spc_readOpcode(spc), spc->v); + break; + } + case 0x74: { // cmp dpx + spc_cmp(spc, spc_adrDpx(spc)); + break; + } + case 0x75: { // cmp abx + spc_cmp(spc, spc_adrAbx(spc)); + break; + } + case 0x76: { // cmp aby + spc_cmp(spc, spc_adrAby(spc)); + break; + } + case 0x77: { // cmp idy + spc_cmp(spc, spc_adrIdy(spc)); + break; + } + case 0x78: { // cmpm dp, imm + uint16_t src = 0; + uint16_t dst = spc_adrDpImm(spc, &src); + spc_cmpm(spc, dst, src); + break; + } + case 0x79: { // cmpm ind, ind + uint16_t src = 0; + uint16_t dst = spc_adrIndInd(spc, &src); + spc_cmpm(spc, dst, src); + break; + } + case 0x7a: { // addw dp + uint16_t low = 0; + uint16_t high = spc_adrDpWord(spc, &low); + uint16_t value = spc_readWord(spc, low, high); + uint16_t ya = spc->a | (spc->y << 8); + int result = ya + value; + spc->v = (ya & 0x8000) == (value & 0x8000) && (value & 0x8000) != (result & 0x8000); + spc->h = ((ya & 0xfff) + (value & 0xfff) + 1) > 0xfff; + spc->c = result > 0xffff; + spc->z = (result & 0xffff) == 0; + spc->n = result & 0x8000; + spc->a = result & 0xff; + spc->y = result >> 8; + break; + } + case 0x7b: { // ror dpx + spc_ror(spc, spc_adrDpx(spc)); + break; + } + case 0x7c: { // rora imp + bool newC = spc->a & 1; + spc->a = (spc->a >> 1) | (spc->c << 7); + spc->c = newC; + spc_setZN(spc, spc->a); + break; + } + case 0x7d: { // movax imp + spc->a = spc->x; + spc_setZN(spc, spc->a); + break; + } + case 0x7e: { // cmpy dp + spc_cmpy(spc, spc_adrDp(spc)); + break; + } + case 0x7f: { // reti imp + spc_setFlags(spc, spc_pullByte(spc)); + spc->pc = spc_pullWord(spc); + break; + } + case 0x80: { // setc imp + spc->c = true; + break; + } + case 0x84: { // adc dp + spc_adc(spc, spc_adrDp(spc)); + break; + } + case 0x85: { // adc abs + spc_adc(spc, spc_adrAbs(spc)); + break; + } + case 0x86: { // adc ind + spc_adc(spc, spc_adrInd(spc)); + break; + } + case 0x87: { // adc idx + spc_adc(spc, spc_adrIdx(spc)); + break; + } + case 0x88: { // adc imm + spc_adc(spc, spc_adrImm(spc)); + break; + } + case 0x89: { // adcm dp, dp + uint16_t src = 0; + uint16_t dst = spc_adrDpDp(spc, &src); + spc_adcm(spc, dst, src); + break; + } + case 0x8a: { // eor1 abs.bit + uint16_t adr = 0; + uint8_t bit = spc_adrAbsBit(spc, &adr); + spc->c = spc->c ^ ((spc_read(spc, adr) >> bit) & 1); + break; + } + case 0x8b: { // dec dp + spc_dec(spc, spc_adrDp(spc)); + break; + } + case 0x8c: { // dec abs + spc_dec(spc, spc_adrAbs(spc)); + break; + } + case 0x8d: { // movy imm + spc_movy(spc, spc_adrImm(spc)); + break; + } + case 0x8e: { // popp imp + spc_setFlags(spc, spc_pullByte(spc)); + break; + } + case 0x8f: { // movm dp, imm + uint16_t src = 0; + uint16_t dst = spc_adrDpImm(spc, &src); + uint8_t val = spc_read(spc, src); + spc_read(spc, dst); + spc_write(spc, dst, val); + break; + } + case 0x90: { // bcc rel + spc_doBranch(spc, spc_readOpcode(spc), !spc->c); + break; + } + case 0x94: { // adc dpx + spc_adc(spc, spc_adrDpx(spc)); + break; + } + case 0x95: { // adc abx + spc_adc(spc, spc_adrAbx(spc)); + break; + } + case 0x96: { // adc aby + spc_adc(spc, spc_adrAby(spc)); + break; + } + case 0x97: { // adc idy + spc_adc(spc, spc_adrIdy(spc)); + break; + } + case 0x98: { // adcm dp, imm + uint16_t src = 0; + uint16_t dst = spc_adrDpImm(spc, &src); + spc_adcm(spc, dst, src); + break; + } + case 0x99: { // adcm ind, ind + uint16_t src = 0; + uint16_t dst = spc_adrIndInd(spc, &src); + spc_adcm(spc, dst, src); + break; + } + case 0x9a: { // subw dp + uint16_t low = 0; + uint16_t high = spc_adrDpWord(spc, &low); + uint16_t value = spc_readWord(spc, low, high) ^ 0xffff; + uint16_t ya = spc->a | (spc->y << 8); + int result = ya + value + 1; + spc->v = (ya & 0x8000) == (value & 0x8000) && (value & 0x8000) != (result & 0x8000); + spc->h = ((ya & 0xfff) + (value & 0xfff) + 1) > 0xfff; + spc->c = result > 0xffff; + spc->z = (result & 0xffff) == 0; + spc->n = result & 0x8000; + spc->a = result & 0xff; + spc->y = result >> 8; + break; + } + case 0x9b: { // dec dpx + spc_dec(spc, spc_adrDpx(spc)); + break; + } + case 0x9c: { // deca imp + spc->a--; + spc_setZN(spc, spc->a); + break; + } + case 0x9d: { // movxp imp + spc->x = spc->sp; + spc_setZN(spc, spc->x); + break; + } + case 0x9e: { // div imp + // TODO: proper division algorithm + uint16_t value = spc->a | (spc->y << 8); + int result = 0xffff; + int mod = spc->a; + if(spc->x != 0) { + result = value / spc->x; + mod = value % spc->x; + } + spc->v = result > 0xff; + spc->h = (spc->x & 0xf) <= (spc->y & 0xf); + spc->a = result; + spc->y = mod; + spc_setZN(spc, spc->a); + break; + } + case 0x9f: { // xcn imp + spc->a = (spc->a >> 4) | (spc->a << 4); + spc_setZN(spc, spc->a); + break; + } + case 0xa0: { // ei imp + spc->i = true; + break; + } + case 0xa4: { // sbc dp + spc_sbc(spc, spc_adrDp(spc)); + break; + } + case 0xa5: { // sbc abs + spc_sbc(spc, spc_adrAbs(spc)); + break; + } + case 0xa6: { // sbc ind + spc_sbc(spc, spc_adrInd(spc)); + break; + } + case 0xa7: { // sbc idx + spc_sbc(spc, spc_adrIdx(spc)); + break; + } + case 0xa8: { // sbc imm + spc_sbc(spc, spc_adrImm(spc)); + break; + } + case 0xa9: { // sbcm dp, dp + uint16_t src = 0; + uint16_t dst = spc_adrDpDp(spc, &src); + spc_sbcm(spc, dst, src); + break; + } + case 0xaa: { // mov1 abs.bit + uint16_t adr = 0; + uint8_t bit = spc_adrAbsBit(spc, &adr); + spc->c = (spc_read(spc, adr) >> bit) & 1; + break; + } + case 0xab: { // inc dp + spc_inc(spc, spc_adrDp(spc)); + break; + } + case 0xac: { // inc abs + spc_inc(spc, spc_adrAbs(spc)); + break; + } + case 0xad: { // cmpy imm + spc_cmpy(spc, spc_adrImm(spc)); + break; + } + case 0xae: { // popa imp + spc->a = spc_pullByte(spc); + break; + } + case 0xaf: { // movs ind+ + uint16_t adr = spc_adrIndP(spc); + spc_write(spc, adr, spc->a); + break; + } + case 0xb0: { // bcs rel + spc_doBranch(spc, spc_readOpcode(spc), spc->c); + break; + } + case 0xb4: { // sbc dpx + spc_sbc(spc, spc_adrDpx(spc)); + break; + } + case 0xb5: { // sbc abx + spc_sbc(spc, spc_adrAbx(spc)); + break; + } + case 0xb6: { // sbc aby + spc_sbc(spc, spc_adrAby(spc)); + break; + } + case 0xb7: { // sbc idy + spc_sbc(spc, spc_adrIdy(spc)); + break; + } + case 0xb8: { // sbcm dp, imm + uint16_t src = 0; + uint16_t dst = spc_adrDpImm(spc, &src); + spc_sbcm(spc, dst, src); + break; + } + case 0xb9: { // sbcm ind, ind + uint16_t src = 0; + uint16_t dst = spc_adrIndInd(spc, &src); + spc_sbcm(spc, dst, src); + break; + } + case 0xba: { // movw dp + uint16_t low = 0; + uint16_t high = spc_adrDpWord(spc, &low); + uint16_t val = spc_readWord(spc, low, high); + spc->a = val & 0xff; + spc->y = val >> 8; + spc->z = val == 0; + spc->n = val & 0x8000; + break; + } + case 0xbb: { // inc dpx + spc_inc(spc, spc_adrDpx(spc)); + break; + } + case 0xbc: { // inca imp + spc->a++; + spc_setZN(spc, spc->a); + break; + } + case 0xbd: { // movpx imp + spc->sp = spc->x; + break; + } + case 0xbe: { // das imp + if(spc->a > 0x99 || !spc->c) { + spc->a -= 0x60; + spc->c = false; + } + if((spc->a & 0xf) > 9 || !spc->h) { + spc->a -= 6; + } + spc_setZN(spc, spc->a); + break; + } + case 0xbf: { // mov ind+ + uint16_t adr = spc_adrIndP(spc); + spc->a = spc_read(spc, adr); + spc_setZN(spc, spc->a); + break; + } + case 0xc0: { // di imp + spc->i = false; + break; + } + case 0xc4: { // movs dp + spc_movs(spc, spc_adrDp(spc)); + break; + } + case 0xc5: { // movs abs + spc_movs(spc, spc_adrAbs(spc)); + break; + } + case 0xc6: { // movs ind + spc_movs(spc, spc_adrInd(spc)); + break; + } + case 0xc7: { // movs idx + spc_movs(spc, spc_adrIdx(spc)); + break; + } + case 0xc8: { // cmpx imm + spc_cmpx(spc, spc_adrImm(spc)); + break; + } + case 0xc9: { // movsx abs + spc_movsx(spc, spc_adrAbs(spc)); + break; + } + case 0xca: { // mov1s abs.bit + uint16_t adr = 0; + uint8_t bit = spc_adrAbsBit(spc, &adr); + uint8_t result = (spc_read(spc, adr) & (~(1 << bit))) | (spc->c << bit); + spc_write(spc, adr, result); + break; + } + case 0xcb: { // movsy dp + spc_movsy(spc, spc_adrDp(spc)); + break; + } + case 0xcc: { // movsy abs + spc_movsy(spc, spc_adrAbs(spc)); + break; + } + case 0xcd: { // movx imm + spc_movx(spc, spc_adrImm(spc)); + break; + } + case 0xce: { // popx imp + spc->x = spc_pullByte(spc); + break; + } + case 0xcf: { // mul imp + uint16_t result = spc->a * spc->y; + spc->a = result & 0xff; + spc->y = result >> 8; + spc_setZN(spc, spc->y); + break; + } + case 0xd0: { // bne rel + spc_doBranch(spc, spc_readOpcode(spc), !spc->z); + break; + } + case 0xd4: { // movs dpx + spc_movs(spc, spc_adrDpx(spc)); + break; + } + case 0xd5: { // movs abx + spc_movs(spc, spc_adrAbx(spc)); + break; + } + case 0xd6: { // movs aby + spc_movs(spc, spc_adrAby(spc)); + break; + } + case 0xd7: { // movs idy + spc_movs(spc, spc_adrIdy(spc)); + break; + } + case 0xd8: { // movsx dp + spc_movsx(spc, spc_adrDp(spc)); + break; + } + case 0xd9: { // movsx dpy + spc_movsx(spc, spc_adrDpy(spc)); + break; + } + case 0xda: { // movws dp + uint16_t low = 0; + uint16_t high = spc_adrDpWord(spc, &low); + spc_read(spc, low); + spc_write(spc, low, spc->a); + spc_write(spc, high, spc->y); + break; + } + case 0xdb: { // movsy dpx + spc_movsy(spc, spc_adrDpx(spc)); + break; + } + case 0xdc: { // decy imp + spc->y--; + spc_setZN(spc, spc->y); + break; + } + case 0xdd: { // movay imp + spc->a = spc->y; + spc_setZN(spc, spc->a); + break; + } + case 0xde: { // cbne dpx, rel + uint8_t val = spc_read(spc, spc_adrDpx(spc)) ^ 0xff; + uint8_t result = spc->a + val + 1; + spc_doBranch(spc, spc_readOpcode(spc), result != 0); + break; + } + case 0xdf: { // daa imp + if(spc->a > 0x99 || spc->c) { + spc->a += 0x60; + spc->c = true; + } + if((spc->a & 0xf) > 9 || spc->h) { + spc->a += 6; + } + spc_setZN(spc, spc->a); + break; + } + case 0xe0: { // clrv imp + spc->v = false; + spc->h = false; + break; + } + case 0xe4: { // mov dp + spc_mov(spc, spc_adrDp(spc)); + break; + } + case 0xe5: { // mov abs + spc_mov(spc, spc_adrAbs(spc)); + break; + } + case 0xe6: { // mov ind + spc_mov(spc, spc_adrInd(spc)); + break; + } + case 0xe7: { // mov idx + spc_mov(spc, spc_adrIdx(spc)); + break; + } + case 0xe8: { // mov imm + spc_mov(spc, spc_adrImm(spc)); + break; + } + case 0xe9: { // movx abs + spc_movx(spc, spc_adrAbs(spc)); + break; + } + case 0xea: { // not1 abs.bit + uint16_t adr = 0; + uint8_t bit = spc_adrAbsBit(spc, &adr); + uint8_t result = spc_read(spc, adr) ^ (1 << bit); + spc_write(spc, adr, result); + break; + } + case 0xeb: { // movy dp + spc_movy(spc, spc_adrDp(spc)); + break; + } + case 0xec: { // movy abs + spc_movy(spc, spc_adrAbs(spc)); + break; + } + case 0xed: { // notc imp + spc->c = !spc->c; + break; + } + case 0xee: { // popy imp + spc->y = spc_pullByte(spc); + break; + } + case 0xef: { // sleep imp + spc->stopped = true; // no interrupts, so sleeping stops as well + break; + } + case 0xf0: { // beq rel + spc_doBranch(spc, spc_readOpcode(spc), spc->z); + break; + } + case 0xf4: { // mov dpx + spc_mov(spc, spc_adrDpx(spc)); + break; + } + case 0xf5: { // mov abx + spc_mov(spc, spc_adrAbx(spc)); + break; + } + case 0xf6: { // mov aby + spc_mov(spc, spc_adrAby(spc)); + break; + } + case 0xf7: { // mov idy + spc_mov(spc, spc_adrIdy(spc)); + break; + } + case 0xf8: { // movx dp + spc_movx(spc, spc_adrDp(spc)); + break; + } + case 0xf9: { // movx dpy + spc_movx(spc, spc_adrDpy(spc)); + break; + } + case 0xfa: { // movm dp, dp + uint16_t src = 0; + uint16_t dst = spc_adrDpDp(spc, &src); + uint8_t val = spc_read(spc, src); + spc_write(spc, dst, val); + break; + } + case 0xfb: { // movy dpx + spc_movy(spc, spc_adrDpx(spc)); + break; + } + case 0xfc: { // incy imp + spc->y++; + spc_setZN(spc, spc->y); + break; + } + case 0xfd: { // movya imp + spc->y = spc->a; + spc_setZN(spc, spc->y); + break; + } + case 0xfe: { // dbnzy rel + spc->y--; + spc_doBranch(spc, spc_readOpcode(spc), spc->y != 0); + break; + } + case 0xff: { // stop imp + spc->stopped = true; + break; + } + } +} diff --git a/src/snes/spc.h b/src/snes/spc.h new file mode 100644 index 0000000..46d7c5e --- /dev/null +++ b/src/snes/spc.h @@ -0,0 +1,44 @@ +#ifndef SPC_H +#define SPC_H + +#include +#include +#include +#include +#include + +typedef struct Spc Spc; + +#include "apu.h" +#include "saveload.h" + +struct Spc { + Apu* apu; + // registers + uint8_t a; + uint8_t x; + uint8_t y; + uint8_t sp; + uint16_t pc; + // flags + bool c; + bool z; + bool v; + bool n; + bool i; + bool h; + bool p; + bool b; + // stopping + bool stopped; + // internal use + uint8_t cyclesUsed; // indicates how many cycles an opcode used +}; + +Spc* spc_init(Apu* apu); +void spc_free(Spc* spc); +void spc_reset(Spc* spc); +int spc_runOpcode(Spc* spc); +void spc_saveload(Spc *spc, SaveLoadFunc *func, void *ctx); + +#endif diff --git a/src/spc_player.c b/src/spc_player.c new file mode 100644 index 0000000..e0121ec --- /dev/null +++ b/src/spc_player.c @@ -0,0 +1,1788 @@ +#include "spc_player.h" + +#include +#include +#include +#include +#include "types.h" +#include "snes/spc.h" +#include "snes/dsp_regs.h" +#include "tracing.h" + +void Sfx1_HandleCmdFromSnes(SpcPlayer *p); +void Sfx2_HandleCmdFromSnes(SpcPlayer *p); +void Sfx3_HandleCmdFromSnes(SpcPlayer *p); +void Sfx1_Process(SpcPlayer *p); +void Sfx2_Process(SpcPlayer *p); +void Sfx3_Process(SpcPlayer *p); + +typedef struct MemMap { + uint16 off, org_off; +} MemMap; + +typedef struct MemMapSized { + uint16 off, org_off, size; +} MemMapSized; +static const MemMap kChannel_Maps[] = { +{offsetof(Channel, pattern_order_ptr_for_chan), 0x8030}, +{offsetof(Channel, note_ticks_left), 0x70}, +{offsetof(Channel, note_keyoff_ticks_left), 0x71}, +{offsetof(Channel, subroutine_num_loops), 0x80}, +{offsetof(Channel, volume_fade_ticks), 0x90}, +{offsetof(Channel, pan_num_ticks), 0x91}, +{offsetof(Channel, pitch_slide_length), 0xa0}, +{offsetof(Channel, pitch_slide_delay_left), 0xa1}, +{offsetof(Channel, vibrato_hold_count), 0xb0}, +{offsetof(Channel, vib_depth), 0xb1}, +{offsetof(Channel, tremolo_hold_count), 0xc0}, +{offsetof(Channel, tremolo_depth), 0xc1}, +{offsetof(Channel, vibrato_change_count), 0x100}, +{offsetof(Channel, note_length), 0x200}, +{offsetof(Channel, note_gate_off_fixedpt), 0x201}, +{offsetof(Channel, channel_volume_master), 0x210}, +{offsetof(Channel, instrument_id), 0x211}, +{offsetof(Channel, instrument_pitch_base), 0x8220}, +{offsetof(Channel, saved_pattern_ptr), 0x8230}, +{offsetof(Channel, pattern_start_ptr), 0x8240}, +{offsetof(Channel, pitch_envelope_num_ticks), 0x280}, +{offsetof(Channel, pitch_envelope_delay), 0x281}, +{offsetof(Channel, pitch_envelope_direction), 0x290}, +{offsetof(Channel, pitch_envelope_slide_value), 0x291}, +{offsetof(Channel, vibrato_count), 0x2a0}, +{offsetof(Channel, vibrato_rate), 0x2a1}, +{offsetof(Channel, vibrato_delay_ticks), 0x2b0}, +{offsetof(Channel, vibrato_fade_num_ticks), 0x2b1}, +{offsetof(Channel, vibrato_fade_add_per_tick), 0x2c0}, +{offsetof(Channel, vibrato_depth_target), 0x2c1}, +{offsetof(Channel, tremolo_count), 0x2d0}, +{offsetof(Channel, tremolo_rate), 0x2d1}, +{offsetof(Channel, tremolo_delay_ticks), 0x2e0}, +{offsetof(Channel, channel_transposition), 0x2f0}, +{offsetof(Channel, channel_volume), 0x8300}, +{offsetof(Channel, volume_fade_addpertick), 0x8310}, +{offsetof(Channel, volume_fade_target), 0x320}, +{offsetof(Channel, final_volume), 0x321}, +{offsetof(Channel, pan_value), 0x8330}, +{offsetof(Channel, pan_add_per_tick), 0x8340}, +{offsetof(Channel, pan_target_value), 0x350}, +{offsetof(Channel, pan_flag_with_phase_invert), 0x351}, +{offsetof(Channel, pitch), 0x8360}, +{offsetof(Channel, pitch_add_per_tick), 0x8370}, +{offsetof(Channel, pitch_target), 0x380}, +{offsetof(Channel, fine_tune), 0x381}, +{offsetof(Channel, cutk), 0x400}, +}; +#pragma warning (disable: 4267) +static const MemMapSized kSpcPlayer_Maps[] = { +{offsetof(SpcPlayer, input_ports), 0x0, 4}, +{offsetof(SpcPlayer, port_to_snes), 0x4, 4}, +{offsetof(SpcPlayer, last_value_from_snes), 0x8, 4}, +{offsetof(SpcPlayer, counter_sf0c), 0xc, 2}, +{offsetof(SpcPlayer, always_zero), 0xe, 2}, +{offsetof(SpcPlayer, temp_accum), 0x10, 2}, +{offsetof(SpcPlayer, ttt), 0x12, 1}, +{offsetof(SpcPlayer, did_affect_volumepitch_flag), 0x13, 1}, +{offsetof(SpcPlayer, addr0), 0x14, 2}, +{offsetof(SpcPlayer, addr1), 0x16, 2}, +{offsetof(SpcPlayer, lfsr_value), 0x18, 2}, +{offsetof(SpcPlayer, is_chan_on), 0x1a, 1}, +{offsetof(SpcPlayer, fast_forward), 0x1b, 1}, +{offsetof(SpcPlayer, timer_cycles), 0x1c, 1}, +{offsetof(SpcPlayer, word_20), 0x20, 2}, +{offsetof(SpcPlayer, sfx1.cur_ptr), 0x22, 2}, +{offsetof(SpcPlayer, sfx1.chan_voice_bitset_ptr), 0x24, 2}, +{offsetof(SpcPlayer, sfx1.chan_voice_mask_ptr), 0x26, 2}, +{offsetof(SpcPlayer, sfx1.chan_voice_index_ptr), 0x28, 2}, +{offsetof(SpcPlayer, sfx_chans_1[0].ptr), 0x2a, 2}, +{offsetof(SpcPlayer, sfx_chans_1[1].ptr), 0x2c, 2}, +{offsetof(SpcPlayer, sfx_chans_1[2].ptr), 0x2e, 2}, +{offsetof(SpcPlayer, music_ptr_toplevel), 0x40, 2}, +{offsetof(SpcPlayer, block_count), 0x42, 1}, +{offsetof(SpcPlayer, sfx_timer_accum), 0x43, 1}, +{offsetof(SpcPlayer, chn), 0x44, 1}, +{offsetof(SpcPlayer, key_ON), 0x45, 1}, +{offsetof(SpcPlayer, key_OFF), 0x46, 1}, +{offsetof(SpcPlayer, cur_chan_bit), 0x47, 1}, +{offsetof(SpcPlayer, reg_FLG), 0x48, 1}, +{offsetof(SpcPlayer, reg_NON), 0x49, 1}, +{offsetof(SpcPlayer, reg_EON), 0x4a, 1}, +{offsetof(SpcPlayer, echo_stored_time), 0x4c, 1}, +{offsetof(SpcPlayer, echo_parameter_EDL), 0x4d, 1}, +{offsetof(SpcPlayer, reg_EFB), 0x4e, 1}, +{offsetof(SpcPlayer, global_transposition), 0x50, 1}, +{offsetof(SpcPlayer, main_tempo_accum), 0x51, 1}, +{offsetof(SpcPlayer, tempo), 0x52, 2}, +{offsetof(SpcPlayer, tempo_fade_num_ticks), 0x54, 1}, +{offsetof(SpcPlayer, tempo_fade_final), 0x55, 1}, +{offsetof(SpcPlayer, tempo_fade_add), 0x56, 2}, +{offsetof(SpcPlayer, master_volume), 0x58, 2}, +{offsetof(SpcPlayer, master_volume_fade_ticks), 0x5a, 1}, +{offsetof(SpcPlayer, master_volume_fade_target), 0x5b, 1}, +{offsetof(SpcPlayer, master_volume_fade_add_per_tick), 0x5c, 2}, +{offsetof(SpcPlayer, vol_dirty), 0x5e, 1}, +{offsetof(SpcPlayer, percussion_base_id), 0x5f, 1}, +{offsetof(SpcPlayer, echo_volume_left), 0x60, 2}, +{offsetof(SpcPlayer, echo_volume_right), 0x62, 2}, +{offsetof(SpcPlayer, echo_volume_fade_add_left), 0x64, 2}, +{offsetof(SpcPlayer, echo_volume_fade_add_right), 0x66, 2}, +{offsetof(SpcPlayer, echo_volume_fade_ticks), 0x68, 1}, +{offsetof(SpcPlayer, echo_volume_fade_target_left), 0x69, 1}, +{offsetof(SpcPlayer, echo_volume_fade_target_right), 0x6a, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].ptr), 0xd0, 2}, +{offsetof(SpcPlayer, p_echoBuffer), 0xd2, 2}, +{offsetof(SpcPlayer, sfx2.cur_ptr), 0xd4, 2}, +{offsetof(SpcPlayer, sfx2.chan_voice_bitset_ptr), 0xd6, 2}, +{offsetof(SpcPlayer, sfx2.chan_voice_mask_ptr), 0xd8, 2}, +{offsetof(SpcPlayer, sfx2.chan_voice_index_ptr), 0xda, 2}, +{offsetof(SpcPlayer, sfx_chans_2[0].ptr), 0xdc, 2}, +{offsetof(SpcPlayer, sfx_chans_2[1].ptr), 0xde, 2}, +{offsetof(SpcPlayer, sfx3.cur_ptr), 0xe0, 2}, +{offsetof(SpcPlayer, sfx3.chan_voice_bitset_ptr), 0xe2, 2}, +{offsetof(SpcPlayer, sfx3.chan_voice_mask_ptr), 0xe4, 2}, +{offsetof(SpcPlayer, sfx3.chan_voice_index_ptr), 0xe6, 2}, +{offsetof(SpcPlayer, sfx_chans_3[0].ptr), 0xe8, 2}, +{offsetof(SpcPlayer, sfx_chans_3[1].ptr), 0xea, 2}, +{offsetof(SpcPlayer, memset_ptr), 0xee, 2}, +{offsetof(SpcPlayer, memset_ctr), 0x390, 1}, +{offsetof(SpcPlayer, sfx1.cur_sound), 0x392, 1}, +{offsetof(SpcPlayer, sfx1.cur_sound_index), 0x393, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].ptr_idx), 0x394, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].ptr_idx), 0x395, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].ptr_idx), 0x396, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].ptr_idx), 0x397, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].instr_timer), 0x398, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].instr_timer), 0x399, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].instr_timer), 0x39a, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].instr_timer), 0x39b, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].disable), 0x39c, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].disable), 0x39d, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].disable), 0x39e, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].disable), 0x39f, 1}, +{offsetof(SpcPlayer, sfx1.chan_idx), 0x3a0, 1}, +{offsetof(SpcPlayer, sfx1.voices_to_setup), 0x3a1, 1}, +{offsetof(SpcPlayer, sfx1.voice_index), 0x3a2, 1}, +{offsetof(SpcPlayer, sfx1.voices_remaining), 0x3a3, 1}, +{offsetof(SpcPlayer, sfx1.init_flag), 0x3a4, 1}, +{offsetof(SpcPlayer, sfx1.voice_id), 0x3a5, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].voice_bitset), 0x3a6, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].voice_bitset), 0x3a7, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].voice_bitset), 0x3a8, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].voice_bitset), 0x3a9, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].channel_mask), 0x3aa, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].channel_mask), 0x3ab, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].channel_mask), 0x3ac, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].channel_mask), 0x3ad, 1}, +{offsetof(SpcPlayer, sfx1.chan_idx_x2), 0x3ae, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].voice_index), 0x3af, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].voice_index), 0x3b0, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].voice_index), 0x3b1, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].voice_index), 0x3b2, 1}, +{offsetof(SpcPlayer, sfx1.enabled_voices), 0x3b3, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].voice_index_mult8), 0x3b4, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].voice_index_mult8), 0x3b5, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].voice_index_mult8), 0x3b6, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].voice_index_mult8), 0x3b7, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].volume), 0x3b8, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].phase_invert), 0x3b9, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].volume), 0x3ba, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].phase_invert), 0x3bb, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].volume), 0x3bc, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].phase_invert), 0x3bd, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].volume), 0x3be, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].phase_invert), 0x3bf, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].release_flag), 0x3c0, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].release_timer), 0x3c1, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].release_flag), 0x3c2, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].release_timer), 0x3c3, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].release_flag), 0x3c4, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].release_timer), 0x3c5, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].release_flag), 0x3c6, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].release_timer), 0x3c7, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].repeat_ctr), 0x3c8, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].repeat_ctr), 0x3c9, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].repeat_ctr), 0x3ca, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].repeat_ctr), 0x3cb, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].repeat_pt), 0x3cc, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].repeat_pt), 0x3cd, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].repeat_pt), 0x3ce, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].repeat_pt), 0x3cf, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].adsr_settings), 0x3d0, 2}, +{offsetof(SpcPlayer, sfx_chans_1[1].adsr_settings), 0x3d2, 2}, +{offsetof(SpcPlayer, sfx_chans_1[2].adsr_settings), 0x3d4, 2}, +{offsetof(SpcPlayer, sfx_chans_1[3].adsr_settings), 0x3d6, 2}, +{offsetof(SpcPlayer, sfx_chans_1[0].update_adsr), 0x3d8, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].update_adsr), 0x3d9, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].update_adsr), 0x3da, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].update_adsr), 0x3db, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].note), 0x3dc, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].subnote), 0x3dd, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].subnote_delta), 0x3de, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].target_note), 0x3df, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].enable_pitch_slide), 0x3e0, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].legato), 0x3e1, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].enable_pitch_slide_legato), 0x3e2, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].note), 0x3e3, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].subnote), 0x3e4, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].subnote_delta), 0x3e5, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].target_note), 0x3e6, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].enable_pitch_slide), 0x3e7, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].legato), 0x3e8, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].enable_pitch_slide_legato), 0x3e9, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].note), 0x3ea, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].subnote), 0x3eb, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].subnote_delta), 0x3ec, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].target_note), 0x3ed, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].enable_pitch_slide), 0x3ee, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].legato), 0x3ef, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].enable_pitch_slide_legato), 0x3f0, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].note), 0x3f1, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].subnote), 0x3f2, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].subnote_delta), 0x3f3, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].target_note), 0x3f4, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].enable_pitch_slide), 0x3f5, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].legato), 0x3f6, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].enable_pitch_slide_legato), 0x3f7, 1}, +{offsetof(SpcPlayer, sfx2.cur_sound), 0x3f8, 1}, +{offsetof(SpcPlayer, sfx2.cur_sound_index), 0x3f9, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].ptr_idx), 0x3fa, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].ptr_idx), 0x3fb, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].instr_timer), 0x3fc, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].instr_timer), 0x3fd, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].disable), 0x3fe, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].disable), 0x3ff, 1}, +{offsetof(SpcPlayer, sfx2.chan_idx), 0x440, 1}, +{offsetof(SpcPlayer, sfx2.voices_to_setup), 0x441, 1}, +{offsetof(SpcPlayer, sfx2.voice_index), 0x442, 1}, +{offsetof(SpcPlayer, sfx2.voices_remaining), 0x443, 1}, +{offsetof(SpcPlayer, sfx2.init_flag), 0x444, 1}, +{offsetof(SpcPlayer, sfx2.voice_id), 0x445, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].voice_bitset), 0x446, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].voice_bitset), 0x447, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].channel_mask), 0x448, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].channel_mask), 0x449, 1}, +{offsetof(SpcPlayer, sfx2.chan_idx_x2), 0x44a, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].voice_index), 0x44b, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].voice_index), 0x44c, 1}, +{offsetof(SpcPlayer, sfx2.enabled_voices), 0x44d, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].voice_index_mult8), 0x44e, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].voice_index_mult8), 0x44f, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].volume), 0x450, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].phase_invert), 0x451, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].volume), 0x452, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].phase_invert), 0x453, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].release_flag), 0x454, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].release_timer), 0x455, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].release_flag), 0x456, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].release_timer), 0x457, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].repeat_ctr), 0x458, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].repeat_ctr), 0x459, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].repeat_pt), 0x45a, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].repeat_pt), 0x45b, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].adsr_settings), 0x45c, 2}, +{offsetof(SpcPlayer, sfx_chans_2[1].adsr_settings), 0x45e, 2}, +{offsetof(SpcPlayer, sfx_chans_2[0].update_adsr), 0x460, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].update_adsr), 0x461, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].note), 0x462, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].subnote), 0x463, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].subnote_delta), 0x464, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].target_note), 0x465, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].enable_pitch_slide), 0x466, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].legato), 0x467, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].enable_pitch_slide_legato), 0x468, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].note), 0x469, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].subnote), 0x46a, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].subnote_delta), 0x46b, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].target_note), 0x46c, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].enable_pitch_slide), 0x46d, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].legato), 0x46e, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].enable_pitch_slide_legato), 0x46f, 1}, +{offsetof(SpcPlayer, sfx3.cur_sound), 0x470, 1}, +{offsetof(SpcPlayer, sfx3.cur_sound_index), 0x471, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].ptr_idx), 0x472, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].ptr_idx), 0x473, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].instr_timer), 0x474, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].instr_timer), 0x475, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].disable), 0x476, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].disable), 0x477, 1}, +{offsetof(SpcPlayer, sfx3.chan_idx), 0x478, 1}, +{offsetof(SpcPlayer, sfx3.voices_to_setup), 0x479, 1}, +{offsetof(SpcPlayer, sfx3.voice_index), 0x47a, 1}, +{offsetof(SpcPlayer, sfx3.voices_remaining), 0x47b, 1}, +{offsetof(SpcPlayer, sfx3.init_flag), 0x47c, 1}, +{offsetof(SpcPlayer, sfx3.voice_id), 0x47d, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].voice_bitset), 0x47e, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].voice_bitset), 0x47f, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].channel_mask), 0x480, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].channel_mask), 0x481, 1}, +{offsetof(SpcPlayer, sfx3.chan_idx_x2), 0x482, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].voice_index), 0x483, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].voice_index), 0x484, 1}, +{offsetof(SpcPlayer, sfx3.enabled_voices), 0x485, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].voice_index_mult8), 0x486, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].voice_index_mult8), 0x487, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].volume), 0x488, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].phase_invert), 0x489, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].volume), 0x48a, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].phase_invert), 0x48b, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].release_flag), 0x48c, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].release_timer), 0x48d, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].release_flag), 0x48e, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].release_timer), 0x48f, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].repeat_ctr), 0x490, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].repeat_ctr), 0x491, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].repeat_pt), 0x492, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].repeat_pt), 0x493, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].adsr_settings), 0x494, 2}, +{offsetof(SpcPlayer, sfx_chans_3[1].adsr_settings), 0x496, 2}, +{offsetof(SpcPlayer, sfx_chans_3[0].update_adsr), 0x498, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].update_adsr), 0x499, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].note), 0x49a, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].subnote), 0x49b, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].subnote_delta), 0x49c, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].target_note), 0x49d, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].enable_pitch_slide), 0x49e, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].legato), 0x49f, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].enable_pitch_slide_legato), 0x4a0, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].note), 0x4a1, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].subnote), 0x4a2, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].subnote_delta), 0x4a3, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].target_note), 0x4a4, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].enable_pitch_slide), 0x4a5, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].legato), 0x4a6, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].enable_pitch_slide_legato), 0x4a7, 1}, +{offsetof(SpcPlayer, disable_sfx2), 0x4a9, 1}, +{offsetof(SpcPlayer, byte_4B1), 0x4b1, 1}, +{offsetof(SpcPlayer, sfx3.some_value), 0x4ba, 1}, +{offsetof(SpcPlayer, sfx1.priority), 0x4bb, 1}, +{offsetof(SpcPlayer, sfx2.priority), 0x4bc, 1}, +{offsetof(SpcPlayer, sfx3.priority), 0x4bd, 1}, +{offsetof(SpcPlayer, last_written_edl), 0x4be, 1 }, + + +}; + +static void PlayNote(SpcPlayer *p, Channel *c, uint8 note); + +static void Dsp_Write(SpcPlayer *p, uint8_t reg, uint8 value) { + DspRegWriteHistory *hist = p->reg_write_history; + if (hist) { + if (hist->count < 256) { + if (hist->count == 9 && reg == 0x5d) { + reg += 0; + } + hist->addr[hist->count] = reg; + hist->val[hist->count] = value; + hist->count++; + } + } + if (p->dsp) + dsp_write(p->dsp, reg, value); +} + +static void Not_Implemented(void) { + assert(0); + printf("Not Implemented\n"); +} + +static uint16 SpcDivHelper(int a, uint8 b) { + int org_a = a; + if (a & 0x100) + a = -a; + int q = b ? (a & 0xff) / b : 0xff; + int r = b ? (a & 0xff) % b : (a & 0xff); + int t = (q << 8) + (b ? ((r << 8) / b & 0xff) : 0xff); + return (org_a & 0x100) ? -t : t; +} + +static void SetupEchoParameter_EDL(SpcPlayer *p, uint8 a) { + p->echo_parameter_EDL = a; + if (a != p->last_written_edl) { + a = (p->last_written_edl & 0xf) ^ 0xff; + if (p->echo_stored_time & 0x80) + a += p->echo_stored_time; + p->echo_stored_time = a; + + Dsp_Write(p, EON, 0); + Dsp_Write(p, EFB, 0); + Dsp_Write(p, EVOLR, 0); + Dsp_Write(p, EVOLL, 0); + Dsp_Write(p, FLG, p->reg_FLG | 0x20); + + p->last_written_edl = p->echo_parameter_EDL; + Dsp_Write(p, EDL, p->echo_parameter_EDL); + } + Dsp_Write(p, ESA, (p->echo_parameter_EDL * 8 ^ 0xff) + 0x16); +} + +static void WriteVolumeToDsp(SpcPlayer *p, Channel *c, uint16 volume) { + static const uint8 kVolumeTable[22] = {0, 1, 3, 7, 13, 21, 30, 41, 52, 66, 81, 94, 103, 110, 115, 119, 122, 124, 125, 126, 127, 127}; + if (p->is_chan_on & p->cur_chan_bit) + return; + for (int i = 0; i < 2; i++) { + int j = volume >> 8; + uint8 t; + if (j >= 21) { + // Undefined behavior + t = p->ram[j + 0x1E1D] + ((p->ram[j + 0x1E1D + 1] - p->ram[j + 0x1E1D]) * (uint8)volume >> 8); + } else { + t = kVolumeTable[j] + ((kVolumeTable[j + 1] - kVolumeTable[j]) * (uint8)volume >> 8); + } + + + t = t * c->final_volume >> 8; + if ((c->pan_flag_with_phase_invert << i) & 0x80) + t = -t; + Dsp_Write(p, V0VOLL + i + c->index * 16, t); + volume = 0x1400 - volume; + } +} + +static void WritePitchInner(SpcPlayer *p, Channel *c, uint16 pitch) { + static const uint16 kBaseNoteFreqs[13] = {2143, 2270, 2405, 2548, 2700, 2860, 3030, 3211, 3402, 3604, 3818, 4045, 4286}; + uint8 pp = (pitch >> 8) & 0x7f; + uint8 q = pp / 12, r = pp % 12; + uint16 t = kBaseNoteFreqs[r] + ((uint8)(kBaseNoteFreqs[r + 1] - kBaseNoteFreqs[r]) * (uint8)pitch >> 8); + t *= 2; + while (q != 6) + t >>= 1, q++; + + t = c->instrument_pitch_base * t >> 8; + if (!(p->cur_chan_bit & p->is_chan_on)) { + uint8 reg = c->index * 16; + Dsp_Write(p, reg + V0PITCHL, t & 0xff); + Dsp_Write(p, reg + V0PITCHH, t >> 8); + } +} + +static void WritePitch(SpcPlayer *p, Channel *c, uint16 pitch) { + if ((pitch >> 8) >= 0x34) { + pitch += (pitch >> 8) - 0x34; + } else if ((pitch >> 8) < 0x13) { + pitch += (uint8)(((pitch >> 8) - 0x13) * 2) - 256; + } + WritePitchInner(p, c, pitch); +} + +static void Music_ResetChan(SpcPlayer *p) { + Channel *c = &p->channel[7]; + p->cur_chan_bit = 0x80; + do { + HIBYTE(c->channel_volume) = 0xff; + c->pan_flag_with_phase_invert = 10; + c->pan_value = 10 << 8; + c->instrument_id = 0; + c->fine_tune = 0; + c->channel_transposition = 0; + c->pitch_envelope_num_ticks = 0; + c->cutk = 0; + c->vib_depth = 0; + c->tremolo_depth = 0; + } while (c--, p->cur_chan_bit >>= 1); + p->master_volume_fade_ticks = 0; + p->echo_volume_fade_ticks = 0; + p->tempo_fade_num_ticks = 0; + p->global_transposition = 0; + p->block_count = 0; + p->percussion_base_id = 0; + HIBYTE(p->master_volume) = 0xc0; + HIBYTE(p->tempo) = 0x20; +} + +static void Channel_SetInstrument_NoSetId(SpcPlayer *p, Channel *c, uint8 instrument) { + if (instrument & 0x80) + instrument = instrument + 54 + p->percussion_base_id; + const uint8 *ip = p->ram + instrument * 6 + 0x6c00; + if (p->is_chan_on & p->cur_chan_bit) + return; + uint8 reg = c->index * 16; + if (ip[0] & 0x80) { + // noise + p->reg_FLG = (p->reg_FLG & 0x20) | ip[0] & 0x1f; + p->reg_NON |= p->cur_chan_bit; + Dsp_Write(p, reg + V0SRCN, 0); + } else { + Dsp_Write(p, reg + V0SRCN, ip[0]); + } + Dsp_Write(p, reg + V0ADSR1, ip[1]); + Dsp_Write(p, reg + V0ADSR2, ip[2]); + Dsp_Write(p, reg + V0GAIN, ip[3]); + c->instrument_pitch_base = ip[4] << 8 | ip[5]; +} + +static void Channel_SetInstrument(SpcPlayer *p, Channel *c, uint8 instrument) { + c->instrument_id = instrument; + Channel_SetInstrument_NoSetId(p, c, instrument); +} + +static void ComputePitchAdd(Channel *c, uint8 pitch) { + c->pitch_target = pitch & 0x7f; + c->pitch_add_per_tick = SpcDivHelper(c->pitch_target - (c->pitch >> 8), c->pitch_slide_length); +} + +static void PitchSlideToNote_Check(SpcPlayer *p, Channel *c) { + if (c->pitch_slide_length || p->ram[c->pattern_order_ptr_for_chan] != 0xf9) + return; + c->pattern_order_ptr_for_chan++; + c->pitch_slide_delay_left = p->ram[c->pattern_order_ptr_for_chan++]; + c->pitch_slide_length = p->ram[c->pattern_order_ptr_for_chan++]; + ComputePitchAdd(c, p->ram[c->pattern_order_ptr_for_chan++] + p->global_transposition + c->channel_transposition); +} + +static const uint8 kEffectByteLength[31] = { + 1, 1, 2, 3, 0, 1, 2, 1, 2, 1, 1, 3, 0, 1, 2, 3, 1, 3, 3, 0, 1, 3, 0, 3, 3, 3, 1, 2, 0, 0, 0}; + +static void HandleEffect(SpcPlayer *p, Channel *c, uint8 effect) { + uint8 arg = kEffectByteLength[effect - 0xe0] ? p->ram[c->pattern_order_ptr_for_chan++] : 0; + + switch (effect) { + case 0xe0: + Channel_SetInstrument(p, c, arg); + break; + case 0xe1: + c->pan_flag_with_phase_invert = arg; + c->pan_value = (arg & 0x1f) << 8; + break; + case 0xe2: + c->pan_num_ticks = arg; + c->pan_target_value = p->ram[c->pattern_order_ptr_for_chan++]; + c->pan_add_per_tick = SpcDivHelper(c->pan_target_value - (c->pan_value >> 8), arg); + break; + case 0xe3: // vibrato on + c->vibrato_delay_ticks = arg; + c->vibrato_rate = p->ram[c->pattern_order_ptr_for_chan++]; + c->vibrato_depth_target = c->vib_depth = p->ram[c->pattern_order_ptr_for_chan++]; + c->vibrato_fade_num_ticks = 0; + break; + case 0xe4: // vibrato off + c->vibrato_depth_target = c->vib_depth = 0; + c->vibrato_fade_num_ticks = 0; + break; + case 0xe5: + p->master_volume = arg << 8; + break; + case 0xe6: + p->master_volume_fade_ticks = arg; + p->master_volume_fade_target = p->ram[c->pattern_order_ptr_for_chan++]; + p->master_volume_fade_add_per_tick = SpcDivHelper(p->master_volume_fade_target - (p->master_volume >> 8), arg); + break; + case 0xe7: + p->tempo = arg << 8; + break; + case 0xe8: + p->tempo_fade_num_ticks = arg; + p->tempo_fade_final = p->ram[c->pattern_order_ptr_for_chan++]; + p->tempo_fade_add = SpcDivHelper(p->tempo_fade_final - (p->tempo >> 8), arg); + break; + case 0xe9: + p->global_transposition = arg; + break; + case 0xea: + c->channel_transposition = arg; + break; + case 0xeb: + c->tremolo_delay_ticks = arg; + c->tremolo_rate = p->ram[c->pattern_order_ptr_for_chan++]; + c->tremolo_depth = p->ram[c->pattern_order_ptr_for_chan++]; + break; + case 0xec: + c->tremolo_depth = 0; + break; + case 0xed: + c->channel_volume = arg << 8; + break; + case 0xee: + c->volume_fade_ticks = arg; + c->volume_fade_target = p->ram[c->pattern_order_ptr_for_chan++]; + c->volume_fade_addpertick = SpcDivHelper(c->volume_fade_target - (c->channel_volume >> 8), arg); + break; + case 0xef: + c->pattern_start_ptr = p->ram[c->pattern_order_ptr_for_chan++] << 8 | arg; + c->subroutine_num_loops = p->ram[c->pattern_order_ptr_for_chan++]; + c->saved_pattern_ptr = c->pattern_order_ptr_for_chan; + c->pattern_order_ptr_for_chan = c->pattern_start_ptr; + break; + case 0xf0: + c->vibrato_fade_num_ticks = arg; + c->vibrato_fade_add_per_tick = arg ? c->vib_depth / arg : 0xff; + break; + case 0xf1: // note pitch envelope to + case 0xf2: + c->pitch_envelope_direction = (effect == 0xf1); + c->pitch_envelope_delay = arg; + c->pitch_envelope_num_ticks = p->ram[c->pattern_order_ptr_for_chan++]; + c->pitch_envelope_slide_value = p->ram[c->pattern_order_ptr_for_chan++]; + break; + case 0xf3: + c->pitch_envelope_num_ticks = 0; + break; + case 0xf4: + c->fine_tune = arg; + break; + case 0xf5: + p->reg_EON = arg; + p->echo_volume_left = p->ram[c->pattern_order_ptr_for_chan++] << 8; + p->echo_volume_right = p->ram[c->pattern_order_ptr_for_chan++] << 8; + p->reg_FLG &= ~0x20; + break; + case 0xf6: // echo off + p->echo_volume_left = 0; + p->echo_volume_right = 0; + p->reg_FLG |= 0x20; + break; + case 0xf7: { + static const int8_t kEchoFirParameters[] = { + 127, 0, 0, 0, 0, 0, 0, 0, + 88, -65, -37, -16, -2, 7, 12, 12, + 12, 33, 43, 43, 19, -2, -13, -7, + 52, 51, 0, -39, -27, 1, -4, -21, + }; + SetupEchoParameter_EDL(p, arg); + p->reg_EFB = p->ram[c->pattern_order_ptr_for_chan++]; + const int8_t *ep = kEchoFirParameters + p->ram[c->pattern_order_ptr_for_chan++] * 8; + for (int i = 0; i < 8; i++) + Dsp_Write(p, FIR0 + i * 16, *ep++); + break; + } + case 0xf8: + p->echo_volume_fade_ticks = arg; + p->echo_volume_fade_target_left = p->ram[c->pattern_order_ptr_for_chan++]; + p->echo_volume_fade_target_right = p->ram[c->pattern_order_ptr_for_chan++]; + p->echo_volume_fade_add_left = SpcDivHelper(p->echo_volume_fade_target_left - (p->echo_volume_left >> 8), arg); + p->echo_volume_fade_add_right = SpcDivHelper(p->echo_volume_fade_target_right - (p->echo_volume_right >> 8), arg); + break; + case 0xf9: + c->pitch_slide_delay_left = arg; + c->pitch_slide_length = p->ram[c->pattern_order_ptr_for_chan++]; + ComputePitchAdd(c, p->ram[c->pattern_order_ptr_for_chan++] + p->global_transposition + c->channel_transposition); + break; + case 0xfa: + p->percussion_base_id = arg; + break; + case 0xfb: + c->pattern_order_ptr_for_chan++; + break; + case 0xfc: + c->cutk = arg + 1; + break; + case 0xfd: + p->fast_forward = arg + 1; + p->key_OFF |= ~p->is_chan_on; + break; + case 0xfe: + p->fast_forward = arg; + p->key_OFF |= ~p->is_chan_on; + break; + default: + Not_Implemented(); + } +} + +static bool WantWriteKof(SpcPlayer *p, Channel *c) { + int loops = c->subroutine_num_loops; + int ptr = c->pattern_order_ptr_for_chan; + + for (;;) { + uint8 cmd = p->ram[ptr++]; + if (cmd == 0) { + if (loops == 0) + return true; + ptr = (--loops == 0) ? c->saved_pattern_ptr : c->pattern_start_ptr; + } else { + while (!(cmd & 0x80)) + cmd = p->ram[ptr++]; + if (cmd == 0xc8) + return false; + if (cmd == 0xef) { + ptr = p->ram[ptr + 0] | p->ram[ptr + 1] << 8; + } else if (cmd >= 0xe0) { + ptr += kEffectByteLength[cmd - 0xe0]; + } else { + return true; + } + } + } +} + +void CalcFinalVolume(SpcPlayer *p, Channel *c, uint8 vol) { + int t = (p->master_volume >> 8) * vol >> 8; + t = t * c->channel_volume_master >> 8; + t = t * (c->channel_volume >> 8) >> 8; + c->final_volume = t * t >> 8; +} + +static void CalcTremolo(SpcPlayer *p, Channel *c, uint8 a) { + if (a & 0x80) + a = (a * 2) ^ 0xff; + else + a = (a * 2); + a = a * c->tremolo_depth >> 8; + CalcFinalVolume(p, c, a ^ 0xff); +} + +static void HandleTremolo(SpcPlayer *p, Channel *c) { + p->did_affect_volumepitch_flag |= 0x80; + CalcTremolo(p, c, (c->tremolo_rate * p->main_tempo_accum >> 8)); +} + +static void CalcVibratoAddPitch(SpcPlayer *p, Channel *c, uint16 pitch, uint8 value) { + int t = value << 2; + t ^= (t & 0x100) ? 0xff : 0; + int r = (c->vib_depth >= 0xf1) ? + (uint8)t * (c->vib_depth & 0xf) : + (uint8)t * c->vib_depth >> 8; + WritePitch(p, c, pitch + (value & 0x80 ? -r : r)); +} + +static void HandlePanAndSweep(SpcPlayer *p, Channel *c) { + p->did_affect_volumepitch_flag = 0; + if (c->tremolo_depth && c->tremolo_hold_count == c->tremolo_delay_ticks) { + HandleTremolo(p, c); + } + + uint16 volume = c->pan_value; + + if (c->pan_num_ticks) { + p->did_affect_volumepitch_flag = 0x80; + volume += p->main_tempo_accum * (int16_t)c->pan_add_per_tick / 256; + } + + if (p->did_affect_volumepitch_flag) + WriteVolumeToDsp(p, c, volume); + + p->did_affect_volumepitch_flag = 0; + uint16 pitch = c->pitch; + if (c->pitch_slide_length && !c->pitch_slide_delay_left) { + p->did_affect_volumepitch_flag |= 0x80; + pitch += p->main_tempo_accum * (int16_t)c->pitch_add_per_tick / 256; + } + + if (c->vib_depth && c->vibrato_delay_ticks == c->vibrato_hold_count) { + CalcVibratoAddPitch(p, c, pitch, (p->main_tempo_accum * c->vibrato_rate >> 8) + c->vibrato_count); + return; + } + + if (p->did_affect_volumepitch_flag) + WritePitch(p, c, pitch); +} + +static void HandleNoteTick(SpcPlayer *p, Channel *c) { + if (c->note_keyoff_ticks_left != 0 && (--c->note_keyoff_ticks_left == 0 || c->note_ticks_left == 2)) { + if (WantWriteKof(p, c) && !(p->cur_chan_bit & p->is_chan_on)) + Dsp_Write(p, KOF, p->cur_chan_bit); + } + + p->did_affect_volumepitch_flag = 0; + if (c->pitch_slide_length) { + if (c->pitch_slide_delay_left) { + c->pitch_slide_delay_left--; + } else { + p->did_affect_volumepitch_flag = 0x80; + + if (--c->pitch_slide_length == 0) { + c->pitch = c->pitch_target << 8 | c->fine_tune; + } else { + c->pitch += c->pitch_add_per_tick; + } + } + } + + uint16 pitch = c->pitch; + + if (c->vib_depth) { + if (c->vibrato_delay_ticks == c->vibrato_hold_count) { + if (c->vibrato_change_count == c->vibrato_fade_num_ticks) { + c->vib_depth = c->vibrato_depth_target; + } else { + c->vib_depth = (c->vibrato_change_count++ == 0 ? 0 : c->vib_depth) + c->vibrato_fade_add_per_tick; + } + c->vibrato_count += c->vibrato_rate; + CalcVibratoAddPitch(p, c, pitch, c->vibrato_count); + return; + } + c->vibrato_hold_count++; + } + + if (p->did_affect_volumepitch_flag) + WritePitch(p, c, pitch); +} + +static void Chan_HandleTick(SpcPlayer *p, Channel *c) { + if (c->volume_fade_ticks) { + if (--c->volume_fade_ticks == 0) { + c->channel_volume = c->volume_fade_target << 8; + } else { + c->channel_volume += c->volume_fade_addpertick; + } + p->vol_dirty |= p->cur_chan_bit; + } + if (c->tremolo_depth) { + if (c->tremolo_delay_ticks == c->tremolo_hold_count) { + p->vol_dirty |= p->cur_chan_bit; + if (c->tremolo_count & 0x80 && c->tremolo_depth == 0xff) { + c->tremolo_count = 0x80; + } else { + c->tremolo_count += c->tremolo_rate; + } + CalcTremolo(p, c, c->tremolo_count); + } else { + c->tremolo_hold_count++; + CalcFinalVolume(p, c, 0xff); + } + } else { + CalcFinalVolume(p, c, 0xff); + } + + if (c->pan_num_ticks) { + if (--c->pan_num_ticks == 0) + c->pan_value = c->pan_target_value << 8; + else + c->pan_value += c->pan_add_per_tick; + p->vol_dirty |= p->cur_chan_bit; + } + + if (p->vol_dirty & p->cur_chan_bit) + WriteVolumeToDsp(p, c, c->pan_value); +} + +static void Music_HandleCmdFromSnes(SpcPlayer *p) { + Channel *c; + int t; + uint8 a = p->input_ports[0]; + p->input_ports[0] = 255; + + if (a == 0xf0) { // 0xf0 - pausemusic + p->key_OFF |= ~p->is_chan_on; + } else { + if (a != 0xf1 && a != 255) start_playing_sound: { + p->port_to_snes[0] = a; + p->music_ptr_toplevel = WORD(p->ram[0x5820 + (a - 1) * 2]); + p->counter_sf0c = 2; + p->key_OFF |= ~p->is_chan_on; + return; + } + if (p->port_to_snes[0] == 0) + return; + if (p->counter_sf0c == 0) + goto label_a; + if (--p->counter_sf0c != 0) { + Music_ResetChan(p); + return; + } + for (;;) next_phrase: { + t = WORD(p->ram[p->music_ptr_toplevel]); + p->music_ptr_toplevel += 2; + if ((t >> 8) != 0) + break; + if (t == 0) { + a = 0; + goto start_playing_sound; + } + if (t == 0x80) { + p->fast_forward = 0x80; + } else if (t == 0x81) { + p->fast_forward = 0; + } else { + if (sign8(--p->block_count)) + p->block_count = t; + t = WORD(p->ram[p->music_ptr_toplevel]); + p->music_ptr_toplevel += 2; + if (p->block_count != 0) + p->music_ptr_toplevel = t; + } + } + for (int i = 0; i < 8; i++) + p->channel[i].pattern_order_ptr_for_chan = WORD(p->ram[t]), t += 2; + + c = p->channel, p->cur_chan_bit = 1; + do { + if (HIBYTE(c->pattern_order_ptr_for_chan) && c->instrument_id == 0) + Channel_SetInstrument(p, c, 0); + c->subroutine_num_loops = 0; + c->volume_fade_ticks = 0; + c->pan_num_ticks = 0; + c->note_ticks_left = 1; + } while (c++, p->cur_chan_bit <<= 1); +label_a: + p->vol_dirty = 0; + c = p->channel, p->cur_chan_bit = 1; + do { + if (!HIBYTE(c->pattern_order_ptr_for_chan)) + continue; + if (!--c->note_ticks_left) { + for (;;) { + uint8 cmd = p->ram[c->pattern_order_ptr_for_chan++]; + if (cmd == 0) { + if (!c->subroutine_num_loops) + goto next_phrase; + c->pattern_order_ptr_for_chan = (--c->subroutine_num_loops == 0) ? c->saved_pattern_ptr : c->pattern_start_ptr; + continue; + } + if (!(cmd & 0x80)) { + static const uint8 kNoteVol[16] = { 25, 50, 76, 101, 114, 127, 140, 152, 165, 178, 191, 203, 216, 229, 242, 252 }; + static const uint8 kNoteGateOffPct[8] = { 50, 101, 127, 152, 178, 203, 229, 252 }; + c->note_length = cmd; + cmd = p->ram[c->pattern_order_ptr_for_chan++]; + if (!(cmd & 0x80)) { + c->note_gate_off_fixedpt = kNoteGateOffPct[cmd >> 4 & 7]; + c->channel_volume_master = kNoteVol[cmd & 0xf]; + cmd = p->ram[c->pattern_order_ptr_for_chan++]; + } + } + if (cmd >= 0xe0) { + HandleEffect(p, c, cmd); + continue; + } + if ((c->cutk | p->fast_forward) == 0) + PlayNote(p, c, cmd); + c->note_ticks_left = c->note_length; + t = c->note_ticks_left * c->note_gate_off_fixedpt >> 8; + c->note_keyoff_ticks_left = (t != 0) ? t : 1; + PitchSlideToNote_Check(p, c); + break; + } + } else if (!p->fast_forward) { + HandleNoteTick(p, c); + PitchSlideToNote_Check(p, c); + } + } while (c++, p->cur_chan_bit <<= 1); + if (p->tempo_fade_num_ticks) + p->tempo = (--p->tempo_fade_num_ticks == 0) ? p->tempo_fade_final << 8 : p->tempo + p->tempo_fade_add; + if (p->echo_volume_fade_ticks) { + p->echo_volume_left += p->echo_volume_fade_add_left; + p->echo_volume_right += p->echo_volume_fade_add_right; + if (--p->echo_volume_fade_ticks == 0) { + p->echo_volume_left = p->echo_volume_fade_target_left << 8; + p->echo_volume_right = p->echo_volume_fade_target_right << 8; + } + } + if (p->master_volume_fade_ticks) { + p->master_volume = (--p->master_volume_fade_ticks == 0) ? p->master_volume_fade_target << 8 : p->master_volume + p->master_volume_fade_add_per_tick; + p->vol_dirty = 0xff; + } + c = p->channel, p->cur_chan_bit = 1; + do { + if (HIBYTE(c->pattern_order_ptr_for_chan)) + Chan_HandleTick(p, c); + } while (c++, p->cur_chan_bit <<= 1); + } +} + +static void PlayNote(SpcPlayer *p, Channel *c, uint8 note) { + if (note >= 0xca) { + Channel_SetInstrument(p, c, note); + note = 0xa4; + } + +// if (c->index == 0) { +// if (note == 0xc8) { +// printf("-+-\n"); +// } else if (note == 0xc9) { +// printf("---\n"); +// } +// } + + if (note >= 0xc8 || p->is_chan_on & p->cur_chan_bit) + return; + + //static const char *const kNoteNames[] = { "C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-" }; + //if (c->index==0) + // printf("%s%d\n", kNoteNames[(note & 0x7f) % 12], (note & 0x7f) / 12 + 1); + + c->pitch = ((note & 0x7f) + p->global_transposition + c->channel_transposition) << 8 | c->fine_tune; + c->vibrato_count = c->vibrato_fade_num_ticks << 7; + c->vibrato_hold_count = 0; + c->vibrato_change_count = 0; + c->tremolo_count = 0; + c->tremolo_hold_count = 0; + p->vol_dirty |= p->cur_chan_bit; + p->key_ON |= p->cur_chan_bit; + c->pitch_slide_length = c->pitch_envelope_num_ticks; + if (c->pitch_slide_length) { + c->pitch_slide_delay_left = c->pitch_envelope_delay; + if (!c->pitch_envelope_direction) + c->pitch -= c->pitch_envelope_slide_value << 8; + ComputePitchAdd(c, (c->pitch >> 8) + c->pitch_envelope_slide_value); + } + WritePitch(p, c, c->pitch); +} + +static void Spc_Loop_Part1(SpcPlayer *p) { + Dsp_Write(p, KOF, p->key_OFF); + Dsp_Write(p, PMON, 0); + Dsp_Write(p, NON, p->reg_NON); + Dsp_Write(p, KOF, 0); + Dsp_Write(p, KON, p->key_ON); + if (!(p->echo_stored_time & 0x80)) { + Dsp_Write(p, FLG, p->reg_FLG); + if (p->echo_stored_time == p->echo_parameter_EDL) { + Dsp_Write(p, EON, p->reg_EON); + Dsp_Write(p, EFB, p->reg_EFB); + Dsp_Write(p, EVOLR, p->echo_volume_right >> 8); + Dsp_Write(p, EVOLL, p->echo_volume_left >> 8); + } + } + p->key_OFF = p->key_ON = 0; +} + +static void Spc_Loop_Part2(SpcPlayer *p, uint8 ticks) { + int t = p->sfx_timer_accum + (uint8)(ticks * 0x20); + p->sfx_timer_accum = t; + if (t >= 0x100) { + Sfx1_HandleCmdFromSnes(p); + Sfx2_HandleCmdFromSnes(p); + Sfx3_HandleCmdFromSnes(p); + + if (p->echo_stored_time != p->echo_parameter_EDL) + p->echo_stored_time++; + } + + t = p->main_tempo_accum + (uint8)(ticks * HIBYTE(p->tempo)); + p->main_tempo_accum = t; + if (t >= 256) { + do { + Music_HandleCmdFromSnes(p); + } while (p->fast_forward); + } else if (p->port_to_snes[0]) { + Channel *c = p->channel; + for (p->cur_chan_bit = 1; p->cur_chan_bit != 0; p->cur_chan_bit <<= 1, c++) { + if (HIBYTE(c->pattern_order_ptr_for_chan)) + HandlePanAndSweep(p, c); + } + } +} + +static void Vector_Reset_Spc(SpcPlayer *p) { + dsp_reset(p->dsp); + + memset(&p->ram[0x500], 0, 0x1000); + memset(&p->ram[0x20], 0, 0xf); + memset(&p->ram[0xd0], 0, 0x1f); + + memset(&p->ram[0x391], 0, 0x6f); + memset(&p->ram[0x440], 0, 0x7f); + + SpcPlayer_CopyVariablesFromRam(p); + +// memset(&p->new_value_from_snes, 0, sizeof(SpcPlayer) - offsetof(SpcPlayer, new_value_from_snes)); + + for (int i = 0; i < 8; i++) + p->channel[i].index = i; + SetupEchoParameter_EDL(p, 1); + p->reg_FLG |= 0x20; + Dsp_Write(p, MVOLL, 0x60); + Dsp_Write(p, MVOLR, 0x60); + Dsp_Write(p, DIR, 0x6d); + HIBYTE(p->tempo) = 16; + p->timer_cycles = 0; +} + +void Sfx_Chan_Reset(SpcPlayer *p, SfxRegs *sr, SfxChan *s) { + s->disable = 0xff; + s->update_adsr = 0; + sr->enabled_voices &= s->channel_mask; + p->is_chan_on &= s->channel_mask; + p->cur_chan_bit |= s->voice_bitset; + p->key_OFF |= s->voice_bitset; + Channel *c = &p->channel[s->voice_index >> 1]; + Channel_SetInstrument_NoSetId(p, c, c->instrument_id); + c->final_volume = s->volume; + c->pan_flag_with_phase_invert = s->phase_invert; + if (!sr->enabled_voices) { + sr->cur_sound = 0; + sr->priority = 0; + sr->init_flag = 0; + } +} + +static const uint16 kSfx1InstrListPtrs[] = { + 0x2b71, 0x2baf, 0x2bb7, 0x2bc4, 0x2bd1, 0x2bfc, 0x2c2f, 0x2c37, + 0x2cff, 0x2d12, 0x2d1a, 0x2d27, 0x2d4b, 0x2d5d, 0x2d5f, 0x2d76, + 0x2d95, 0x2d97, 0x2d99, 0x2da6, 0x2da8, 0x2daa, 0x2dac, 0x2dc8, + 0x2de7, 0x2dfe, 0x2e00, 0x2e17, 0x2e19, 0x2e1b, 0x2e1d, 0x2e34, + 0x2e36, 0x2e38, 0x2e3a, 0x2e68, 0x2eaf, 0x2ed0, 0x2ef6, 0x2f2c, + 0x2f37, 0x2f3f, 0x2f47, 0x2f4a, 0x2f4d, 0x2f50, 0x2fb0, 0x2fb8, + 0x2fc3, 0x2fdd, 0x2fe5, 0x3040, 0x3048, 0x3055, 0x305d, 0x3065, + 0x3070, 0x3078, 0x307b, 0x308b, 0x309b, 0x30a8, 0x30d6, 0x30e1, + 0x312a, 0x313f +}; + +static const uint8 kSfx1Conf[] = { + 5, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 2, 2 +}; + +void Sfx1_HandleCmdFromSnes(SpcPlayer *p) { + uint8 a = p->input_ports[1]; + p->input_ports[1] = 255; + if (a == 255 || a == 0 || a != 1 && a != 2 && p->sfx1.priority) { + if (p->sfx1.cur_sound) + Sfx1_Process(p); + return; + } + if (p->sfx1.cur_sound) { + p->sfx1.enabled_voices = 0; + Sfx_Chan_Reset(p, &p->sfx1, &p->sfx_chans_1[0]); + Sfx_Chan_Reset(p, &p->sfx1, &p->sfx_chans_1[1]); + Sfx_Chan_Reset(p, &p->sfx1, &p->sfx_chans_1[2]); + Sfx_Chan_Reset(p, &p->sfx1, &p->sfx_chans_1[3]); + } + for (int i = 0; i != 4; i++) + p->sfx_chans_1[i].legato = 0; + p->sfx1.cur_sound_index = (a - 1) * 2; + + p->sfx1.cur_ptr = kSfx1InstrListPtrs[p->sfx1.cur_sound_index >> 1]; + p->sfx1.cur_sound = a; + + switch (kSfx1Conf[a - 1]) { + case 0: + p->sfx1.voices_to_setup = 1; + p->sfx1.priority = 0; + break; + case 1: + p->sfx1.voices_to_setup = 1; + p->sfx1.priority = 1; + break; + case 2: + p->sfx1.voices_to_setup = 2; + p->sfx1.priority = 0; + break; + case 3: + p->sfx1.voices_to_setup = 3; + p->sfx1.priority = 1; + break; + case 4: + p->sfx1.voices_to_setup = 4; + p->sfx1.priority = 0; + break; + case 5: + p->sfx1.voices_to_setup = 4; + p->sfx1.priority = 0; + break; + } +} + +static const uint16 kSfx2InstrListPtrs[] = { + 0x3ab1, 0x3ac3, 0x3ad5, 0x3af1, 0x3af3, 0x3af5, 0x3b0c, 0x3b28, + 0x3b2a, 0x3b3a, 0x3b42, 0x3b5e, 0x3b73, 0x3b85, 0x3b92, 0x3ba9, + 0x3bb4, 0x3bc1, 0x3be7, 0x3c08, 0x3c33, 0x3c3b, 0x3c43, 0x3c56, + 0x3c90, 0x3cff, 0x3d46, 0x3d4e, 0x3d65, 0x3d81, 0x3d9b, 0x3da8, + 0x3dbf, 0x3dd6, 0x3ded, 0x3e04, 0x3e20, 0x3e41, 0x3e66, 0x3e94, + 0x3eb0, 0x3ecc, 0x3ece, 0x3f03, 0x3f18, 0x3f20, 0x3f44, 0x3f5e, + 0x3f75, 0x3f82, 0x3f8a, 0x3f97, 0x3f9f, 0x401f, 0x4036, 0x4066, + 0x407c, 0x407e, 0x4086, 0x4088, 0x408a, 0x408c, 0x409e, 0x40a6, + 0x40b1, 0x40b4, 0x40bc, 0x40ce, 0x40d1, 0x40de, 0x40f5, 0x410c, + 0x412c, 0x4143, 0x415a, 0x4162, 0x416f, 0x41a9, 0x41c7, 0x41d9, + 0x41ee, 0x421c, 0x4224, 0x4236, 0x424d, 0x4268, 0x4288, 0x429a, + 0x42af, 0x42bf, 0x42d4, 0x42d6, 0x42fe, 0x4310, 0x4322, 0x4334, + 0x433c, 0x4347, 0x4352, 0x43c1, 0x43cc, 0x43e8, 0x43fa, 0x4422, + 0x442f, 0x4441, 0x4443, 0x4446, 0x444e, 0x446f, 0x447f, 0x448f, + 0x449c, 0x44a4, 0x44b9, 0x44ce, 0x44ed, 0x4598, 0x459a, 0x4618, + 0x462d, 0x4642, 0x4657, 0x466c, 0x4679, 0x4686, 0x468e +}; + +static const uint8 kSfx2Conf[] = { + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 2, 2, 0, 1, 0, 3, 1, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 1, 3, 0, 0, + 0, 0, 0, 0, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, + 3, 0, 0, 1, 0, 2, 0, 2, 3, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, + 0, 3, 3, 3, 3, 0, 3, 2, 2, 2, 2, 1, 1, 1, 2 +}; + +void Sfx2_HandleCmdFromSnes(SpcPlayer *p) { + uint8 a = p->input_ports[2]; + p->input_ports[2] = 255; + if (a == 255 || a == 0 || a != 0x71 && a != 0x7e && p->sfx2.priority) { + if (p->sfx2.cur_sound) + Sfx2_Process(p); + return; + } + if (p->sfx2.cur_sound) { + p->sfx2.enabled_voices = 0; + Sfx_Chan_Reset(p, &p->sfx2, &p->sfx_chans_2[0]); + Sfx_Chan_Reset(p, &p->sfx2, &p->sfx_chans_2[1]); + } + for (int i = 0; i != 2; i++) + p->sfx_chans_2[i].legato = 0; + p->sfx2.cur_sound_index = (a - 1) * 2; + p->sfx2.cur_ptr = kSfx2InstrListPtrs[p->sfx2.cur_sound_index >> 1]; + p->sfx2.cur_sound = a; + switch (kSfx2Conf[a - 1]) { + case 0: + p->sfx2.voices_to_setup = 1; + p->sfx2.priority = 0; + break; + case 1: + p->sfx2.voices_to_setup = 1; + p->sfx2.priority = 1; + break; + case 2: + p->sfx2.voices_to_setup = 2; + p->sfx2.priority = 0; + break; + case 3: + p->sfx2.voices_to_setup = 2; + p->sfx2.priority = 1; + break; + } +} + +static const uint16 kSfx3InstrListPtrs[] = { + 0x4eed, 0x4ef5, 0x4f00, 0x4f4b, 0x4f5b, 0x4f6b, 0x4f73, 0x4f89, + 0x4f9f, 0x4fb6, 0x4fe1, 0x4ff7, 0x4fff, 0x500c, 0x5047, 0x50a8, + 0x50c4, 0x50d1, 0x50d4, 0x50f0, 0x511a, 0x5130, 0x5142, 0x5175, + 0x5178, 0x5188, 0x518b, 0x51b9, 0x51c1, 0x51d4, 0x51f0, 0x51fd, + 0x5200, 0x5208, 0x5229, 0x5231, 0x5239, 0x5241, 0x524e, 0x5256, + 0x5277, 0x5293, 0x52a5, 0x52b0, 0x52c6, 0x52f1, 0x530b +}; + +static const uint8 kSfx3Conf[] = { + 0, 1, 2, 3, 3, 2, 4, 4, 2, 5, 3, 2, 2, 4, 3, 2, + 2, 5, 2, 4, 4, 2, 2, 2, 4, 2, 4, 2, 2, 2, 2, 5, + 5, 2, 2, 5, 2, 2, 2, 2, 2, 2, 2, 4, 2, 4, 2 +}; + +void Sfx3_HandleCmdFromSnes(SpcPlayer *p) { + uint8 a = p->input_ports[3]; + p->input_ports[3] = 255; + if (a == 255 || a == 0 || a != 1 && (p->sfx3.some_value == 2 || a != 2 && p->sfx3.priority)) { + if (p->sfx3.cur_sound) + Sfx3_Process(p); + return; + } + if (p->sfx3.cur_sound) { + p->sfx3.enabled_voices = 0; + Sfx_Chan_Reset(p, &p->sfx3, &p->sfx_chans_3[0]); + Sfx_Chan_Reset(p, &p->sfx3, &p->sfx_chans_3[1]); + } + for (int i = 0; i != 2; i++) + p->sfx_chans_3[i].legato = 0; + p->sfx3.cur_sound_index = (a - 1) * 2; + p->sfx3.cur_ptr = kSfx3InstrListPtrs[p->sfx3.cur_sound_index >> 1]; + p->sfx3.cur_sound = a; + + if (p->sfx3.cur_sound >= 0xfe) { + Sfx3_Process(p); + return; + } + + switch (kSfx3Conf[a - 1]) { + case 0: + p->sfx3.voices_to_setup = 1; + p->sfx3.some_value = 0; + p->sfx3.priority = 1; + break; + case 1: + p->sfx3.voices_to_setup = 1; + p->sfx3.some_value = 2; + break; + case 2: + p->sfx3.voices_to_setup = 1; + p->sfx3.priority = 0; + break; + case 3: + p->sfx3.voices_to_setup = 2; + p->sfx3.priority = 0; + break; + case 4: + p->sfx3.voices_to_setup = 2; + p->sfx3.priority = 1; + break; + case 5: + p->sfx3.voices_to_setup = 1; + p->sfx3.priority = 1; + break; + } +} + +uint8 SfxChan_GetByte(SpcPlayer *p, SfxChan *s) { + return p->ram[s->ptr + s->ptr_idx++]; +} + +void Sfx_RunChan(SpcPlayer *p, SfxRegs *sr, SfxChan *s) { + if (s->disable == 0xff) + return; + if (--s->instr_timer == 0) { + if (!s->legato) { + s->enable_pitch_slide = 0; + s->subnote_delta = 0; + s->target_note = 0; + if (s->release_flag != 0xff) { + p->key_OFF |= s->voice_bitset; + s->release_timer = 2; + s->instr_timer = 1; + s->release_flag = 0xff; + } + if (--s->release_timer) + return; + s->release_flag = 0; + p->cur_chan_bit &= s->channel_mask; + p->reg_NON &= s->channel_mask; + } + // chan0_loop_cmds + uint8 a; +next: + a = SfxChan_GetByte(p, s); + if (a == 0xf9) { + s->adsr_settings = SfxChan_GetByte(p, s); + s->adsr_settings |= SfxChan_GetByte(p, s) << 8; + s->ptr_idx += 2; + s->update_adsr = 0xff; + goto next; + } + if (a == 0xf5 || a == 0xf8) { + s->enable_pitch_slide_legato = (a == 0xf5) ? 0xf5 : 0; + s->subnote_delta = SfxChan_GetByte(p, s); + s->target_note = SfxChan_GetByte(p, s); + s->enable_pitch_slide = 0xff; + a = SfxChan_GetByte(p, s); + } + if (a == 0xff) { + Sfx_Chan_Reset(p, sr, s); + return; + } + if (a == 0xfe) { + s->repeat_ctr = SfxChan_GetByte(p, s); + s->repeat_pt = s->ptr_idx; + a = SfxChan_GetByte(p, s); + } + if (a == 0xfb || a == 0xfd) { + if (a != 0xfb && --s->repeat_ctr == 0) + goto next; + s->ptr_idx = s->repeat_pt; + a = SfxChan_GetByte(p, s); + } + if (a == 0xfc) { + p->reg_NON |= s->voice_bitset; + goto next; + } + Channel *c = &p->channel[s->voice_index >> 1]; + Channel_SetInstrument_NoSetId(p, c, a); + c->final_volume = SfxChan_GetByte(p, s); + c->pan_flag_with_phase_invert = 0; + WriteVolumeToDsp(p, c, SfxChan_GetByte(p, s) << 8); + a = SfxChan_GetByte(p, s); + if (a != 0xf6) { + s->note = a; + s->subnote = 0; + } + WritePitchInner(p, c, s->note << 8 | s->subnote); + s->instr_timer = SfxChan_GetByte(p, s); + if (s->update_adsr) { + Dsp_Write(p, s->voice_index_mult8 | V0ADSR1, s->adsr_settings); + Dsp_Write(p, s->voice_index_mult8 | V0ADSR2, s->adsr_settings >> 8); + } + if (!s->legato) + p->key_ON |= s->voice_bitset; + } + // chan0_instr_end + if (s->enable_pitch_slide != 0xff) + return; + + if (s->enable_pitch_slide_legato) + s->legato = 0xff; + + if (s->note >= s->target_note) { + int t = s->subnote - s->subnote_delta; + s->subnote = t; + if (t & 256 && --s->note == s->target_note) + s->enable_pitch_slide = s->legato = 0; + } else { + int t = s->subnote + s->subnote_delta; + s->subnote = t; + if (t & 256 && ++s->note == s->target_note) + s->enable_pitch_slide = s->legato = 0; + } + WritePitchInner(p, &p->channel[s->voice_index >> 1], s->note << 8 | s->subnote); +} + +void Sfx1_Init(SpcPlayer *p); +void Sfx2_Init(SpcPlayer *p); +void Sfx3_Init(SpcPlayer *p); + +void Sfx1_Process(SpcPlayer *p) { + if (p->sfx1.init_flag != 0xff) { + Sfx1_Init(p); + for (int i = 0; i < 4; i++) { + SfxChan *s = &p->sfx_chans_1[i]; + s->ptr = WORD(p->ram[p->sfx1.cur_ptr + i * 2]); + s->voice_index_mult8 = s->voice_index * 8; + s->ptr_idx = 0; + s->instr_timer = 1; + } + } + for (int i = 0; i < 4; i++) + Sfx_RunChan(p, &p->sfx1, &p->sfx_chans_1[i]); +} + +void Sfx2_Process(SpcPlayer *p) { + if (p->sfx2.init_flag != 0xff) { + Sfx2_Init(p); + for (int i = 0; i < 2; i++) { + SfxChan *s = &p->sfx_chans_2[i]; + s->ptr = WORD(p->ram[p->sfx2.cur_ptr + i * 2]); + s->voice_index_mult8 = s->voice_index * 8; + s->ptr_idx = 0; + s->instr_timer = 1; + } + } + for (int i = 0; i < 2; i++) + Sfx_RunChan(p, &p->sfx2, &p->sfx_chans_2[i]); +} + +void Sfx3_Process(SpcPlayer *p) { + if (p->sfx3.init_flag != 0xff) { + Sfx3_Init(p); + for (int i = 0; i < 2; i++) { + SfxChan *s = &p->sfx_chans_3[i]; + s->ptr = WORD(p->ram[p->sfx3.cur_ptr + i * 2]); + s->voice_index_mult8 = s->voice_index * 8; + s->ptr_idx = 0; + s->instr_timer = 1; + } + } + for (int i = 0; i < 2; i++) + Sfx_RunChan(p, &p->sfx3, &p->sfx_chans_3[i]); +} + +void Sfx_Init(SpcPlayer *p, SfxRegs *sr, SfxChan *channels, int which_sfx) { + int num = (which_sfx == 0) ? 4 : 2; + static const uint16 kSomeAddrs[3][3] = { + {0x3a6, 0x3aa, 0x3af}, + {0x446, 0x448, 0x44b}, + {0x47e, 0x480, 0x483}, + }; + sr->voice_id = 9; + sr->voices_remaining = p->is_chan_on; + sr->init_flag = 0xff; + sr->chan_idx = sr->chan_idx_x2 = 0; + for (int i = 0; i < num; i++) { + channels[i].voice_bitset = 0; + channels[i].voice_index = 0; + channels[i].channel_mask = 0xff; + channels[i].disable = 0xff; + } + + while (--sr->voice_id) { + int t = sr->voices_remaining; + sr->voices_remaining <<= 1; + if (!(t & 0x80)) { + if (!sr->voices_to_setup) + return; + sr->voices_to_setup--; + SfxChan *c = &channels[sr->chan_idx]; + c->disable = 0; + sr->chan_voice_bitset_ptr = kSomeAddrs[which_sfx][0] + sr->chan_idx; + sr->chan_voice_mask_ptr = kSomeAddrs[which_sfx][1] + sr->chan_idx; + sr->chan_voice_index_ptr = kSomeAddrs[which_sfx][2] + sr->chan_idx; + sr->chan_idx += 1, sr->chan_idx_x2 += 2; + + sr->voice_index = (sr->voice_id - 1) * 2; + c->voice_index = sr->voice_index; + int t = sr->voice_id - 1; + c->volume = p->channel[t].final_volume | + p->channel[t].pan_flag_with_phase_invert << 8; + int m = 1 << t; + p->is_chan_on |= m; + p->cur_chan_bit &= ~m; + p->reg_EON &= ~m; + sr->enabled_voices |= m; + c->voice_bitset = m; + c->channel_mask = ~m; + } + } +} + +void Sfx1_Init(SpcPlayer *p) { + Sfx_Init(p, &p->sfx1, p->sfx_chans_1, 0); +} + +void Sfx2_Init(SpcPlayer *p) { + Sfx_Init(p, &p->sfx2, p->sfx_chans_2, 1); +} + +void Sfx3_Init(SpcPlayer *p) { + Sfx_Init(p, &p->sfx3, p->sfx_chans_3, 2); +} + +SpcPlayer *SpcPlayer_Create(void) { + SpcPlayer *p = (SpcPlayer *)malloc(sizeof(SpcPlayer)); + memset(p, 0, sizeof(SpcPlayer)); + p->dsp = dsp_init(p->ram); + p->reg_write_history = 0; + return p; +} + +void SpcPlayer_Initialize(SpcPlayer *p) { + Vector_Reset_Spc(p); + Spc_Loop_Part1(p); +} + +void SpcPlayer_CopyVariablesToRam(SpcPlayer *p) { + Channel *c = p->channel; + for (int i = 0; i < 8; i++, c++) { + for (const MemMap *m = &kChannel_Maps[0]; m != &kChannel_Maps[countof(kChannel_Maps)]; m++) + memcpy(&p->ram[(m->org_off & 0x7fff) + i * 2], (uint8 *)c + m->off, m->org_off & 0x8000 ? 2 : 1); + } + for (const MemMapSized *m = &kSpcPlayer_Maps[0]; m != &kSpcPlayer_Maps[countof(kSpcPlayer_Maps)]; m++) + memcpy(&p->ram[m->org_off], (uint8 *)p + m->off, m->size); +} + +void SpcPlayer_CopyVariablesFromRam(SpcPlayer *p) { + Channel *c = p->channel; + for (int i = 0; i < 8; i++, c++) { + for (const MemMap *m = &kChannel_Maps[0]; m != &kChannel_Maps[countof(kChannel_Maps)]; m++) + memcpy((uint8 *)c + m->off, &p->ram[(m->org_off & 0x7fff) + i * 2], m->org_off & 0x8000 ? 2 : 1); + } + for (const MemMapSized *m = &kSpcPlayer_Maps[0]; m != &kSpcPlayer_Maps[countof(kSpcPlayer_Maps)]; m++) + memcpy((uint8 *)p + m->off, &p->ram[m->org_off], m->size); + + for (int i = 0; i < 8; i++) + p->channel[i].index = i; +} + +void SpcPlayer_GenerateSamples(SpcPlayer *p) { + assert(p->timer_cycles <= 64); + + assert(p->dsp->sampleOffset <= 534); + + for (;;) { + if (p->timer_cycles >= 64) { + Spc_Loop_Part2(p, p->timer_cycles >> 6); + Spc_Loop_Part1(p); + p->timer_cycles &= 63; + } + + // sample rate 32000 + int n = 534 - p->dsp->sampleOffset; + if (n > (64 - p->timer_cycles)) + n = (64 - p->timer_cycles); + + p->timer_cycles += n; + + for (int i = 0; i < n; i++) + dsp_cycle(p->dsp); + + if (p->dsp->sampleOffset == 534) + break; + } +} + +void SpcPlayer_Upload(SpcPlayer *p, const uint8_t *data) { + Dsp_Write(p, EVOLL, 0); + Dsp_Write(p, EVOLR, 0); + Dsp_Write(p, KOF, 0xff); + + for (;;) { + int numbytes = *(uint16 *)(data); + if (numbytes == 0) + break; + int target = *(uint16 *)(data + 2); + data += 4; + do { + p->ram[target++ & 0xffff] = *data++; + } while (--numbytes); + } + p->port_to_snes[0] = 0; + p->input_ports[0] = p->input_ports[1] = p->input_ports[2] = p->input_ports[3] = 255; + p->music_ptr_toplevel = WORD(p->ram[0x581e]); + p->counter_sf0c = 2; + p->key_OFF |= ~p->is_chan_on; +} + +// ======================================= +#define WITH_SPC_PLAYER_DEBUGGING 0 + +#if WITH_SPC_PLAYER_DEBUGGING + +#include + +static DspRegWriteHistory my_write_hist; +static SpcPlayer my_spc, my_spc_snapshot; +static int loop_ctr; + +bool CompareSpcImpls(SpcPlayer *p, SpcPlayer *p_org, Apu *apu) { + SpcPlayer_CopyVariablesToRam(p); + memcpy(p->ram + 0x18, apu->ram + 0x18, 2); //lfsr_value + memcpy(p->ram + 0x110, apu->ram + 0x110, 256-16); // stack + memcpy(p->ram + 0xf1, apu->ram + 0xf1, 15); // dsp regs + memcpy(p->ram + 0x10, apu->ram + 0x10, 8); // temp regs + memcpy(p->ram + 0x20, apu->ram + 0x20, 2); // temp regs + p->ram[0x44] = apu->ram[0x44]; // chn + memcpy(p->ram + 0xee, apu->ram + 0xee, 2); // memset ptr + p->ram[0x390] = apu->ram[0x390]; // memset count + int errs = 0; + static const uint16 ranges[][2] = { + {0x0, 0x4ff}, + {0x1500, 0xffff}, + }; + + for (int j = 0; j < 2; j++) { + for (int i = ranges[j][0], i_end = ranges[j][1]; i != i_end; i++) { // skip compare echo etc + if (p->ram[i] != apu->ram[i]) { + if (errs < 16) { + if (errs == 0) + printf("@%d\n", loop_ctr); + printf("%.4X: %.2X != %.2X (mine, theirs) orig %.2X\n", i, p->ram[i], apu->ram[i], p_org->ram[i]); + errs++; + } + } + } + } + + int n = my_write_hist.count < apu->hist.count ? apu->hist.count : my_write_hist.count; + for (int i = 0; i != n; i++) { + if (i >= my_write_hist.count || i >= apu->hist.count || my_write_hist.addr[i] != apu->hist.addr[i] || my_write_hist.val[i] != apu->hist.val[i]) { + if (errs == 0) + printf("@%d\n", loop_ctr); + printf("%d: ", i); + if (i >= my_write_hist.count) printf("[??: ??]"); else printf("[%.2x: %.2x]", my_write_hist.addr[i], my_write_hist.val[i]); + printf(" != "); + if (i >= apu->hist.count) printf("[??: ??]"); else printf("[%.2x: %.2x]", apu->hist.addr[i], apu->hist.val[i]); + printf("\n"); + errs++; + } + } + + if (errs) { + printf("Total %d errors\n", errs); + return false; + } + + apu->hist.count = 0; + my_write_hist.count = 0; + loop_ctr++; + return true; +} + +extern bool g_debug_apu_cycles; + +void RunAudioPlayer(void) { + if(SDL_Init(SDL_INIT_AUDIO) != 0) { + printf("Failed to init SDL: %s\n", SDL_GetError()); + return; + } + + SDL_AudioSpec want, have; + SDL_AudioDeviceID device; + SDL_memset(&want, 0, sizeof(want)); + want.freq = 44100; + want.format = AUDIO_S16; + want.channels = 2; + want.samples = 2048; + want.callback = NULL; // use queue + device = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0); + if(device == 0) { + printf("Failed to open audio device: %s\n", SDL_GetError()); + return; + } + int16_t* audioBuffer = (int16_t*)malloc(735 * 4); // *2 for stereo, *2 for sizeof(int16) + SDL_PauseAudioDevice(device, 0); + + memset(&my_spc, 0, sizeof(my_spc)); + FILE *f = fopen("../spc1.bin", "rb"); + fread(my_spc.ram, 1, 65536, f); + fclose(f); + + my_spc.reg_write_history = &my_write_hist; + + bool run_both = true;// false;// false; + + if (!run_both) { + SpcPlayer *p = &my_spc; + Dsp *dsp = dsp_init(p->ram); + dsp_reset(dsp); + p->dsp = dsp; + SpcPlayer_Initialize(p); + + p->input_ports[0] = 4; + + for (;;) { + SpcPlayer_GenerateSamples(p); + + int16_t audioBuffer[736 * 2]; + dsp_getSamples(p->dsp, audioBuffer, 736); + SDL_QueueAudio(device, audioBuffer, 736 * 2 * have.channels); + while (SDL_GetQueuedAudioSize(device) >= 736 * 4 * 3/* 44100 * 4 * 300*/) + SDL_Delay(1); + + } + + } else { + SpcPlayer *p = &my_spc; + Dsp *dsp = dsp_init(p->ram); + dsp_reset(dsp); + p->dsp = dsp; + + Apu *apu = apu_init(); + apu_reset(apu); + apu->spc->pc = 0x1500; + + memcpy(apu->ram, my_spc.ram, 65536); + + CompareSpcImpls(&my_spc, &my_spc_snapshot, apu); + + // g_debug_apu_cycles = true; + + uint64_t cycle_counter = 0; + int tgt = 0x15C4; + uint8 ticks_next = 0; + bool apu_debug = false; + bool is_initialize = true; + for (;;) { + if (apu_debug && apu->cpuCyclesLeft == 0) { + char line[80]; + getProcessorStateSpc(apu, line); + puts(line); + } + + apu_cycle(apu); + + if (((apu->cycles - 1) & 0x1f) == 0) + dsp_cycle(p->dsp); + + if (apu->spc->pc == tgt) { + tgt ^= 0x15C4 ^ 0x15C5; + if (tgt == 0x15C4) { + uint8 ticks = ticks_next; + ticks_next = apu->spc->y; + my_spc_snapshot = my_spc; + for (;;) { + my_write_hist.count = 0; + if (is_initialize) + SpcPlayer_Initialize(&my_spc); + else { + Spc_Loop_Part2(&my_spc, ticks); + Spc_Loop_Part1(&my_spc); + } + if (CompareSpcImpls(&my_spc, &my_spc_snapshot, apu)) + break; + my_spc = my_spc_snapshot; + } + is_initialize = false; + + if (cycle_counter % 1000 == 0) + apu->inPorts[3] = my_spc.input_ports[3] = 3 + cycle_counter / 1000; + //else if (cycle_counter % 1000 == 990) + // apu->inPorts[3] = my_spc.input_ports[3] = 1; + cycle_counter++; + } + } + + if (p->dsp->sampleOffset == 534) { + int16_t audioBuffer[736 * 2]; + dsp_getSamples(p->dsp, audioBuffer, 736); + SDL_QueueAudio(device, audioBuffer, 736 * 2 * have.channels); + while (SDL_GetQueuedAudioSize(device) >= 736 * 4 * 3/* 44100 * 4 * 300*/) { + SDL_Delay(1); + } + } + } + } +} +#endif // WITH_SPC_PLAYER_DEBUGGING \ No newline at end of file diff --git a/src/spc_player.h b/src/spc_player.h new file mode 100644 index 0000000..08e2929 --- /dev/null +++ b/src/spc_player.h @@ -0,0 +1,174 @@ +#include +#include +#include "types.h" +#include "snes/dsp.h" + +typedef struct Channel { + uint16 pattern_order_ptr_for_chan; + uint8 index; + uint8 note_ticks_left; + uint8 note_keyoff_ticks_left; + uint8 subroutine_num_loops; + uint8 volume_fade_ticks; + uint8 pan_num_ticks; + uint8 pitch_slide_length; + uint8 pitch_slide_delay_left; + uint8 vibrato_hold_count; + uint8 vib_depth; + uint8 tremolo_hold_count; + uint8 tremolo_depth; + uint8 vibrato_change_count; + uint8 note_length; + uint8 note_gate_off_fixedpt; + uint8 channel_volume_master; + uint8 instrument_id; + uint16 instrument_pitch_base; + uint16 saved_pattern_ptr; + uint16 pattern_start_ptr; + uint8 pitch_envelope_num_ticks; + uint8 pitch_envelope_delay; + uint8 pitch_envelope_direction; + uint8 pitch_envelope_slide_value; + uint8 vibrato_count; + uint8 vibrato_rate; + uint8 vibrato_delay_ticks; + uint8 vibrato_fade_num_ticks; + uint8 vibrato_fade_add_per_tick; + uint8 vibrato_depth_target; + uint8 tremolo_count; + uint8 tremolo_rate; + uint8 tremolo_delay_ticks; + uint8 channel_transposition; + uint16 channel_volume; + uint16 volume_fade_addpertick; + uint8 volume_fade_target; + uint8 final_volume; + uint16 pan_value; + uint16 pan_add_per_tick; + uint8 pan_target_value; + uint8 pan_flag_with_phase_invert; + uint16 pitch; + uint16 pitch_add_per_tick; + uint8 pitch_target; + uint8 fine_tune; + uint8 cutk; +} Channel; + +typedef struct SfxRegs { + uint8 priority; + uint8 chan_idx_x2; + uint16 chan_voice_bitset_ptr; + uint8 cur_sound; + uint16 chan_voice_mask_ptr; + uint16 chan_voice_index_ptr; + uint8 some_value; + uint16 cur_ptr; + uint8 enabled_voices; + uint8 voices_to_setup; + uint8 chan_idx; + uint8 voices_remaining; + uint8 cur_sound_index; + uint8 voice_id; + uint8 init_flag; + uint8 voice_index; +} SfxRegs; +typedef struct SfxChan { + uint8 voice_bitset; + uint8 instr_timer; + uint8 subnote; + uint8 repeat_pt; + uint8 note; + uint8 ptr_idx; + uint8 voice_index; + uint8 voice_index_mult8; + uint8 release_timer; + uint8 volume; + uint8 target_note; + uint8 phase_invert; + uint16 ptr; + uint8 repeat_ctr; + uint8 enable_pitch_slide; + uint8 release_flag; + uint8 enable_pitch_slide_legato; + uint16 adsr_settings; + uint8 channel_mask; + uint8 legato; + uint8 disable; + uint8 subnote_delta; + uint8 update_adsr; +} SfxChan; + + +typedef struct SpcPlayer { + DspRegWriteHistory *reg_write_history; + uint8 timer_cycles; + Dsp *dsp; + + uint8 port_to_snes[4]; + uint8 last_value_from_snes[4]; + uint16 counter_sf0c; + uint16 always_zero; + uint16 temp_accum; + uint8 ttt; + uint8 did_affect_volumepitch_flag; + uint16 addr0; + uint16 addr1; + uint16 lfsr_value; + uint8 is_chan_on; + uint8 fast_forward; + uint16 word_20; + uint16 music_ptr_toplevel; + uint8 block_count; + uint8 sfx_timer_accum; + uint8 chn; + uint8 key_ON; + uint8 key_OFF; + uint8 cur_chan_bit; + uint8 reg_FLG; + uint8 reg_NON; + uint8 reg_EON; + uint8 echo_stored_time; + uint8 echo_parameter_EDL; + uint8 reg_EFB; + uint8 global_transposition; + uint8 main_tempo_accum; + uint16 tempo; + uint8 tempo_fade_num_ticks; + uint8 tempo_fade_final; + uint16 tempo_fade_add; + uint16 master_volume; + uint8 master_volume_fade_ticks; + uint8 master_volume_fade_target; + uint16 master_volume_fade_add_per_tick; + uint8 vol_dirty; + uint8 percussion_base_id; + uint16 echo_volume_left; + uint16 echo_volume_right; + uint16 echo_volume_fade_add_left; + uint16 echo_volume_fade_add_right; + uint8 echo_volume_fade_ticks; + uint8 echo_volume_fade_target_left; + uint8 echo_volume_fade_target_right; + uint16 p_echoBuffer; + uint16 memset_ptr; + uint8 memset_ctr; + uint8 disable_sfx2; + uint8 byte_4B1; + Channel channel[8]; + SfxRegs sfx1; + SfxRegs sfx2; + SfxRegs sfx3; + SfxChan sfx_chans_1[4]; + SfxChan sfx_chans_2[2]; + SfxChan sfx_chans_3[2]; + uint8 last_written_edl; + uint8 input_ports[4]; + uint8 ram[65536]; // rest of ram +} SpcPlayer; + +SpcPlayer *SpcPlayer_Create(); +void SpcPlayer_GenerateSamples(SpcPlayer *p); +void SpcPlayer_Initialize(SpcPlayer *p); +void SpcPlayer_Upload(SpcPlayer *p, const uint8_t *data); +void SpcPlayer_CopyVariablesFromRam(SpcPlayer *p); +void SpcPlayer_CopyVariablesToRam(SpcPlayer *p); diff --git a/src/spc_variables.h b/src/spc_variables.h new file mode 100644 index 0000000..5a7d5e0 --- /dev/null +++ b/src/spc_variables.h @@ -0,0 +1,495 @@ +#include +typedef struct Channel { + uint16 pattern_order_ptr_for_chan; + uint8 note_ticks_left; + uint8 note_keyoff_ticks_left; + uint8 subroutine_num_loops; + uint8 volume_fade_ticks; + uint8 pan_num_ticks; + uint8 pitch_slide_length; + uint8 pitch_slide_delay_left; + uint8 vibrato_hold_count; + uint8 vib_depth; + uint8 tremolo_hold_count; + uint8 tremolo_depth; + uint8 vibrato_change_count; + uint8 note_length; + uint8 note_gate_off_fixedpt; + uint8 channel_volume_master; + uint8 instrument_id; + uint16 instrument_pitch_base; + uint16 saved_pattern_ptr; + uint16 pattern_start_ptr; + uint8 pitch_envelope_num_ticks; + uint8 pitch_envelope_delay; + uint8 pitch_envelope_direction; + uint8 pitch_envelope_slide_value; + uint8 vibrato_count; + uint8 vibrato_rate; + uint8 vibrato_delay_ticks; + uint8 vibrato_fade_num_ticks; + uint8 vibrato_fade_add_per_tick; + uint8 vibrato_depth_target; + uint8 tremolo_count; + uint8 tremolo_rate; + uint8 tremolo_delay_ticks; + uint8 channel_transposition; + uint16 channel_volume; + uint16 volume_fade_addpertick; + uint8 volume_fade_target; + uint8 final_volume; + uint16 pan_value; + uint16 pan_add_per_tick; + uint8 pan_target_value; + uint8 pan_flag_with_phase_invert; + uint16 pitch; + uint16 pitch_add_per_tick; + uint8 pitch_target; + uint8 fine_tune; + uint8 cutk; +} Channel; +typedef struct SfxRegs { + uint8 priority; + uint8 chan_idx_x2; + uint16 chan_voice_bitset_ptr; + uint8 cur_sound; + uint16 chan_voice_mask_ptr; + uint16 chan_voice_index_ptr; + uint8 current_sound; + uint8 some_value; + uint16 cur_ptr; + uint8 enabled_voices; + uint8 voices_to_setup; + uint8 chan_idx; + uint8 voices_remaining; + uint8 cur_sound_index; + uint8 voice_id; + uint8 init_flag; + uint16 chan_voice_index; + uint8 voice_index; +} SfxRegs; +typedef struct SfxChan { + uint8 voice_bitset; + uint8 instr_timer; + uint8 subnote; + uint8 repeat_pt; + uint8 note; + uint8 ptr_idx; + uint8 voice_index; + uint8 phase_setting; + uint8 voice_index_mult8; + uint8 release_timer; + uint8 phase_options; + uint8 volume; + uint8 target_node; + uint8 phase_invert; + uint8 instr_timers; + uint16 ptr; + uint8 ptr_index; + uint8 repeat_ctr; + uint8 enable_pitch_slide; + uint8 release_flag; + uint8 enable_pitch_slide_legato; + uint16 adsr_settings; + uint8 channel_mask; + uint8 legato; + uint8 disable; + uint8 target_note; + uint8 subnote_delta; + uint8 update_adsr; +} SfxChan; +struct SpcPlayer { + uint8 new_value_from_snes[4]; + uint8 port_to_snes[4]; + uint8 last_value_from_snes[4]; + uint16 counter_sf0c; + uint16 always_zero; + uint16 temp_accum; + uint8 ttt; + uint8 did_affect_volumepitch_flag; + uint16 addr0; + uint16 addr1; + uint16 lfsr_value; + uint8 is_chan_on; + uint8 fast_forward; + uint16 word_20; + uint16 music_ptr_toplevel; + uint8 block_count; + uint8 sfx_timer_accum; + uint8 chn; + uint8 key_ON; + uint8 key_OFF; + uint8 cur_chan_bit; + uint8 reg_FLG; + uint8 reg_NON; + uint8 reg_EON; + uint8 echo_stored_time; + uint8 echo_parameter_EDL; + uint8 reg_EFB; + uint8 global_transposition; + uint8 main_tempo_accum; + uint16 tempo; + uint8 tempo_fade_num_ticks; + uint8 tempo_fade_final; + uint16 tempo_fade_add; + uint16 master_volume; + uint8 master_volume_fade_ticks; + uint8 master_volume_fade_target; + uint16 master_volume_fade_add_per_tick; + uint8 vol_dirty; + uint8 percussion_base_id; + uint16 echo_volume_left; + uint16 echo_volume_right; + uint16 echo_volume_fade_add_left; + uint16 echo_volume_fade_add_right; + uint8 echo_volume_fade_ticks; + uint8 echo_volume_fade_target_left; + uint8 echo_volume_fade_target_right; + uint16 p_echoBuffer; + uint16 memset_ptr; + uint8 memset_ctr; + uint8 disable_sfx2; + uint8 byte_4B1; + Channel channel[8]; + uint8 ram[65536]; // rest of ram + uint8 last_written_edl; + uint8 input_ports[4]; +}; +struct MemMap { +uint16 off, org_off; +}; +struct MemMap2 { +uint16 off, org_off, size; +}; +const MemMap kChannel_Maps[] = { +{offsetof(Channel, pattern_order_ptr_for_chan), 0x8030}, +{offsetof(Channel, note_ticks_left), 0x70}, +{offsetof(Channel, note_keyoff_ticks_left), 0x71}, +{offsetof(Channel, subroutine_num_loops), 0x80}, +{offsetof(Channel, volume_fade_ticks), 0x90}, +{offsetof(Channel, pan_num_ticks), 0x91}, +{offsetof(Channel, pitch_slide_length), 0xa0}, +{offsetof(Channel, pitch_slide_delay_left), 0xa1}, +{offsetof(Channel, vibrato_hold_count), 0xb0}, +{offsetof(Channel, vib_depth), 0xb1}, +{offsetof(Channel, tremolo_hold_count), 0xc0}, +{offsetof(Channel, tremolo_depth), 0xc1}, +{offsetof(Channel, vibrato_change_count), 0x100}, +{offsetof(Channel, note_length), 0x200}, +{offsetof(Channel, note_gate_off_fixedpt), 0x201}, +{offsetof(Channel, channel_volume_master), 0x210}, +{offsetof(Channel, instrument_id), 0x211}, +{offsetof(Channel, instrument_pitch_base), 0x8220}, +{offsetof(Channel, saved_pattern_ptr), 0x8230}, +{offsetof(Channel, pattern_start_ptr), 0x8240}, +{offsetof(Channel, pitch_envelope_num_ticks), 0x280}, +{offsetof(Channel, pitch_envelope_delay), 0x281}, +{offsetof(Channel, pitch_envelope_direction), 0x290}, +{offsetof(Channel, pitch_envelope_slide_value), 0x291}, +{offsetof(Channel, vibrato_count), 0x2a0}, +{offsetof(Channel, vibrato_rate), 0x2a1}, +{offsetof(Channel, vibrato_delay_ticks), 0x2b0}, +{offsetof(Channel, vibrato_fade_num_ticks), 0x2b1}, +{offsetof(Channel, vibrato_fade_add_per_tick), 0x2c0}, +{offsetof(Channel, vibrato_depth_target), 0x2c1}, +{offsetof(Channel, tremolo_count), 0x2d0}, +{offsetof(Channel, tremolo_rate), 0x2d1}, +{offsetof(Channel, tremolo_delay_ticks), 0x2e0}, +{offsetof(Channel, channel_transposition), 0x2f0}, +{offsetof(Channel, channel_volume), 0x8300}, +{offsetof(Channel, volume_fade_addpertick), 0x8310}, +{offsetof(Channel, volume_fade_target), 0x320}, +{offsetof(Channel, final_volume), 0x321}, +{offsetof(Channel, pan_value), 0x8330}, +{offsetof(Channel, pan_add_per_tick), 0x8340}, +{offsetof(Channel, pan_target_value), 0x350}, +{offsetof(Channel, pan_flag_with_phase_invert), 0x351}, +{offsetof(Channel, pitch), 0x8360}, +{offsetof(Channel, pitch_add_per_tick), 0x8370}, +{offsetof(Channel, pitch_target), 0x380}, +{offsetof(Channel, fine_tune), 0x381}, +{offsetof(Channel, cutk), 0x400}, +}; +const MemMap2 kSpcPlayer_Maps[] = { +{offsetof(SpcPlayer, new_value_from_snes), 0x0, 4}, +{offsetof(SpcPlayer, port_to_snes), 0x4, 4}, +{offsetof(SpcPlayer, last_value_from_snes), 0x8, 4}, +{offsetof(SpcPlayer, counter_sf0c), 0xc, 2}, +{offsetof(SpcPlayer, always_zero), 0xe, 2}, +{offsetof(SpcPlayer, temp_accum), 0x10, 2}, +{offsetof(SpcPlayer, ttt), 0x12, 1}, +{offsetof(SpcPlayer, did_affect_volumepitch_flag), 0x13, 1}, +{offsetof(SpcPlayer, addr0), 0x14, 2}, +{offsetof(SpcPlayer, addr1), 0x16, 2}, +{offsetof(SpcPlayer, lfsr_value), 0x18, 2}, +{offsetof(SpcPlayer, is_chan_on), 0x1a, 1}, +{offsetof(SpcPlayer, fast_forward), 0x1b, 1}, +{offsetof(SpcPlayer, word_20), 0x20, 2}, +{offsetof(SpcPlayer, sfx1.cur_ptr), 0x22, 2}, +{offsetof(SpcPlayer, sfx1.chan_voice_bitset_ptr), 0x24, 2}, +{offsetof(SpcPlayer, sfx1.chan_voice_mask_ptr), 0x26, 2}, +{offsetof(SpcPlayer, sfx1.chan_voice_index), 0x28, 2}, +{offsetof(SpcPlayer, sfx_chans_1[0].ptr), 0x2a, 2}, +{offsetof(SpcPlayer, sfx_chans_1[1].ptr), 0x2c, 2}, +{offsetof(SpcPlayer, sfx_chans_1[2].ptr), 0x2e, 2}, +{offsetof(SpcPlayer, music_ptr_toplevel), 0x40, 2}, +{offsetof(SpcPlayer, block_count), 0x42, 1}, +{offsetof(SpcPlayer, sfx_timer_accum), 0x43, 1}, +{offsetof(SpcPlayer, chn), 0x44, 1}, +{offsetof(SpcPlayer, key_ON), 0x45, 1}, +{offsetof(SpcPlayer, key_OFF), 0x46, 1}, +{offsetof(SpcPlayer, cur_chan_bit), 0x47, 1}, +{offsetof(SpcPlayer, reg_FLG), 0x48, 1}, +{offsetof(SpcPlayer, reg_NON), 0x49, 1}, +{offsetof(SpcPlayer, reg_EON), 0x4a, 1}, +{offsetof(SpcPlayer, echo_stored_time), 0x4c, 1}, +{offsetof(SpcPlayer, echo_parameter_EDL), 0x4d, 1}, +{offsetof(SpcPlayer, reg_EFB), 0x4e, 1}, +{offsetof(SpcPlayer, global_transposition), 0x50, 1}, +{offsetof(SpcPlayer, main_tempo_accum), 0x51, 1}, +{offsetof(SpcPlayer, tempo), 0x52, 2}, +{offsetof(SpcPlayer, tempo_fade_num_ticks), 0x54, 1}, +{offsetof(SpcPlayer, tempo_fade_final), 0x55, 1}, +{offsetof(SpcPlayer, tempo_fade_add), 0x56, 2}, +{offsetof(SpcPlayer, master_volume), 0x58, 2}, +{offsetof(SpcPlayer, master_volume_fade_ticks), 0x5a, 1}, +{offsetof(SpcPlayer, master_volume_fade_target), 0x5b, 1}, +{offsetof(SpcPlayer, master_volume_fade_add_per_tick), 0x5c, 2}, +{offsetof(SpcPlayer, vol_dirty), 0x5e, 1}, +{offsetof(SpcPlayer, percussion_base_id), 0x5f, 1}, +{offsetof(SpcPlayer, echo_volume_left), 0x60, 2}, +{offsetof(SpcPlayer, echo_volume_right), 0x62, 2}, +{offsetof(SpcPlayer, echo_volume_fade_add_left), 0x64, 2}, +{offsetof(SpcPlayer, echo_volume_fade_add_right), 0x66, 2}, +{offsetof(SpcPlayer, echo_volume_fade_ticks), 0x68, 1}, +{offsetof(SpcPlayer, echo_volume_fade_target_left), 0x69, 1}, +{offsetof(SpcPlayer, echo_volume_fade_target_right), 0x6a, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].ptr), 0xd0, 2}, +{offsetof(SpcPlayer, p_echoBuffer), 0xd2, 2}, +{offsetof(SpcPlayer, sfx2.cur_ptr), 0xd4, 2}, +{offsetof(SpcPlayer, sfx2.chan_voice_bitset_ptr), 0xd6, 2}, +{offsetof(SpcPlayer, sfx2.chan_voice_mask_ptr), 0xd8, 2}, +{offsetof(SpcPlayer, sfx2.chan_voice_index_ptr), 0xda, 2}, +{offsetof(SpcPlayer, sfx_chans_2[0].ptr), 0xdc, 2}, +{offsetof(SpcPlayer, sfx_chans_2[1].ptr), 0xde, 2}, +{offsetof(SpcPlayer, sfx3.cur_ptr), 0xe0, 2}, +{offsetof(SpcPlayer, sfx3.chan_voice_bitset_ptr), 0xe2, 2}, +{offsetof(SpcPlayer, sfx3.chan_voice_mask_ptr), 0xe4, 2}, +{offsetof(SpcPlayer, sfx3.chan_voice_index_ptr), 0xe6, 2}, +{offsetof(SpcPlayer, sfx_chans_3[0].ptr), 0xe8, 2}, +{offsetof(SpcPlayer, sfx_chans_3[1].ptr), 0xea, 2}, +{offsetof(SpcPlayer, memset_ptr), 0xee, 2}, +{offsetof(SpcPlayer, memset_ctr), 0x390, 1}, +{offsetof(SpcPlayer, sfx1.cur_sound), 0x392, 1}, +{offsetof(SpcPlayer, sfx1.cur_sound_index), 0x393, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].ptr_idx), 0x394, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].ptr_idx), 0x395, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].ptr_idx), 0x396, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].ptr_idx), 0x397, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].instr_timer), 0x398, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].instr_timer), 0x399, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].instr_timer), 0x39a, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].instr_timer), 0x39b, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].disable), 0x39c, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].disable), 0x39d, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].disable), 0x39e, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].disable), 0x39f, 1}, +{offsetof(SpcPlayer, sfx1.chan_idx), 0x3a0, 1}, +{offsetof(SpcPlayer, sfx1.voices_to_setup), 0x3a1, 1}, +{offsetof(SpcPlayer, sfx1.voice_index), 0x3a2, 1}, +{offsetof(SpcPlayer, sfx1.voices_remaining), 0x3a3, 1}, +{offsetof(SpcPlayer, sfx1.init_flag), 0x3a4, 1}, +{offsetof(SpcPlayer, sfx1.voice_id), 0x3a5, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].voice_bitset), 0x3a6, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].voice_bitset), 0x3a7, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].voice_bitset), 0x3a8, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].voice_bitset), 0x3a9, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].channel_mask), 0x3aa, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].channel_mask), 0x3ab, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].channel_mask), 0x3ac, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].channel_mask), 0x3ad, 1}, +{offsetof(SpcPlayer, sfx1.chan_idx_x2), 0x3ae, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].voice_index), 0x3af, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].voice_index), 0x3b0, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].voice_index), 0x3b1, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].voice_index), 0x3b2, 1}, +{offsetof(SpcPlayer, sfx1.enabled_voices), 0x3b3, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].voice_index_mult8), 0x3b4, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].voice_index_mult8), 0x3b5, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].voice_index_mult8), 0x3b6, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].voice_index_mult8), 0x3b7, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].volume), 0x3b8, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].phase_options), 0x3b9, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].volume), 0x3ba, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].phase_options), 0x3bb, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].volume), 0x3bc, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].phase_options), 0x3bd, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].volume), 0x3be, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].phase_options), 0x3bf, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].release_flag), 0x3c0, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].release_timer), 0x3c1, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].release_flag), 0x3c2, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].release_timer), 0x3c3, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].release_flag), 0x3c4, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].release_timer), 0x3c5, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].release_flag), 0x3c6, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].release_timer), 0x3c7, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].repeat_ctr), 0x3c8, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].repeat_ctr), 0x3c9, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].repeat_ctr), 0x3ca, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].repeat_ctr), 0x3cb, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].repeat_pt), 0x3cc, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].repeat_pt), 0x3cd, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].repeat_pt), 0x3ce, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].repeat_pt), 0x3cf, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].adsr_settings), 0x3d0, 2}, +{offsetof(SpcPlayer, sfx_chans_1[1].adsr_settings), 0x3d2, 2}, +{offsetof(SpcPlayer, sfx_chans_1[2].adsr_settings), 0x3d4, 2}, +{offsetof(SpcPlayer, sfx_chans_1[3].adsr_settings), 0x3d6, 2}, +{offsetof(SpcPlayer, sfx_chans_1[0].update_adsr), 0x3d8, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].update_adsr), 0x3d9, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].update_adsr), 0x3da, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].update_adsr), 0x3db, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].note), 0x3dc, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].subnote), 0x3dd, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].subnote_delta), 0x3de, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].target_note), 0x3df, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].enable_pitch_slide), 0x3e0, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].legato), 0x3e1, 1}, +{offsetof(SpcPlayer, sfx_chans_1[0].enable_pitch_slide_legato), 0x3e2, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].note), 0x3e3, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].subnote), 0x3e4, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].subnote_delta), 0x3e5, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].target_note), 0x3e6, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].enable_pitch_slide), 0x3e7, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].legato), 0x3e8, 1}, +{offsetof(SpcPlayer, sfx_chans_1[1].enable_pitch_slide_legato), 0x3e9, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].note), 0x3ea, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].subnote), 0x3eb, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].subnote_delta), 0x3ec, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].target_node), 0x3ed, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].enable_pitch_slide), 0x3ee, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].legato), 0x3ef, 1}, +{offsetof(SpcPlayer, sfx_chans_1[2].enable_pitch_slide_legato), 0x3f0, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].note), 0x3f1, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].subnote), 0x3f2, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].subnote_delta), 0x3f3, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].target_note), 0x3f4, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].enable_pitch_slide), 0x3f5, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].legato), 0x3f6, 1}, +{offsetof(SpcPlayer, sfx_chans_1[3].enable_pitch_slide_legato), 0x3f7, 1}, +{offsetof(SpcPlayer, sfx2.current_sound), 0x3f8, 1}, +{offsetof(SpcPlayer, sfx2.cur_sound_index), 0x3f9, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].ptr_idx), 0x3fa, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].ptr_index), 0x3fb, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].instr_timers), 0x3fc, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].instr_timers), 0x3fd, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].disable), 0x3fe, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].disable), 0x3ff, 1}, +{offsetof(SpcPlayer, sfx2.chan_idx), 0x440, 1}, +{offsetof(SpcPlayer, sfx2.voices_to_setup), 0x441, 1}, +{offsetof(SpcPlayer, sfx2.voice_index), 0x442, 1}, +{offsetof(SpcPlayer, sfx2.voices_remaining), 0x443, 1}, +{offsetof(SpcPlayer, sfx2.init_flag), 0x444, 1}, +{offsetof(SpcPlayer, sfx2.voice_id), 0x445, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].voice_bitset), 0x446, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].voice_bitset), 0x447, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].channel_mask), 0x448, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].channel_mask), 0x449, 1}, +{offsetof(SpcPlayer, sfx2.chan_idx_x2), 0x44a, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].voice_index), 0x44b, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].voice_index), 0x44c, 1}, +{offsetof(SpcPlayer, sfx2.enabled_voices), 0x44d, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].voice_index_mult8), 0x44e, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].voice_index_mult8), 0x44f, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].volume), 0x450, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].phase_setting), 0x451, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].volume), 0x452, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].phase_setting), 0x453, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].release_flag), 0x454, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].release_timer), 0x455, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].release_flag), 0x456, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].release_timer), 0x457, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].repeat_ctr), 0x458, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].repeat_ctr), 0x459, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].repeat_pt), 0x45a, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].repeat_pt), 0x45b, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].adsr_settings), 0x45c, 2}, +{offsetof(SpcPlayer, sfx_chans_2[1].adsr_settings), 0x45e, 2}, +{offsetof(SpcPlayer, sfx_chans_2[0].update_adsr), 0x460, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].update_adsr), 0x461, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].note), 0x462, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].subnote), 0x463, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].subnote_delta), 0x464, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].target_note), 0x465, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].enable_pitch_slide), 0x466, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].legato), 0x467, 1}, +{offsetof(SpcPlayer, sfx_chans_2[0].enable_pitch_slide_legato), 0x468, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].note), 0x469, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].subnote), 0x46a, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].subnote_delta), 0x46b, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].target_note), 0x46c, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].enable_pitch_slide), 0x46d, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].legato), 0x46e, 1}, +{offsetof(SpcPlayer, sfx_chans_2[1].enable_pitch_slide_legato), 0x46f, 1}, +{offsetof(SpcPlayer, sfx3.current_sound), 0x470, 1}, +{offsetof(SpcPlayer, sfx3.cur_sound_index), 0x471, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].ptr_idx), 0x472, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].ptr_idx), 0x473, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].instr_timers), 0x474, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].instr_timers), 0x475, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].disable), 0x476, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].disable), 0x477, 1}, +{offsetof(SpcPlayer, sfx3.chan_idx), 0x478, 1}, +{offsetof(SpcPlayer, sfx3.voices_to_setup), 0x479, 1}, +{offsetof(SpcPlayer, sfx3.voice_index), 0x47a, 1}, +{offsetof(SpcPlayer, sfx3.voices_remaining), 0x47b, 1}, +{offsetof(SpcPlayer, sfx3.init_flag), 0x47c, 1}, +{offsetof(SpcPlayer, sfx3.voice_id), 0x47d, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].voice_bitset), 0x47e, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].voice_bitset), 0x47f, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].channel_mask), 0x480, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].channel_mask), 0x481, 1}, +{offsetof(SpcPlayer, sfx3.chan_idx_x2), 0x482, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].voice_index), 0x483, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].voice_index), 0x484, 1}, +{offsetof(SpcPlayer, sfx3.enabled_voices), 0x485, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].voice_index_mult8), 0x486, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].voice_index_mult8), 0x487, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].volume), 0x488, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].phase_invert), 0x489, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].volume), 0x48a, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].phase_invert), 0x48b, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].release_flag), 0x48c, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].release_timer), 0x48d, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].release_flag), 0x48e, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].release_timer), 0x48f, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].repeat_ctr), 0x490, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].repeat_ctr), 0x491, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].repeat_pt), 0x492, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].repeat_pt), 0x493, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].adsr_settings), 0x494, 2}, +{offsetof(SpcPlayer, sfx_chans_3[1].adsr_settings), 0x496, 2}, +{offsetof(SpcPlayer, sfx_chans_3[0].update_adsr), 0x498, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].update_adsr), 0x499, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].note), 0x49a, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].subnote), 0x49b, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].subnote_delta), 0x49c, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].target_node), 0x49d, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].enable_pitch_slide), 0x49e, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].legato), 0x49f, 1}, +{offsetof(SpcPlayer, sfx_chans_3[0].enable_pitch_slide_legato), 0x4a0, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].note), 0x4a1, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].subnote), 0x4a2, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].subnote_delta), 0x4a3, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].target_node), 0x4a4, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].enable_pitch_slide), 0x4a5, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].legato), 0x4a6, 1}, +{offsetof(SpcPlayer, sfx_chans_3[1].enable_pitch_slide_legato), 0x4a7, 1}, +{offsetof(SpcPlayer, disable_sfx2), 0x4a9, 1}, +{offsetof(SpcPlayer, byte_4B1), 0x4b1, 1}, +{offsetof(SpcPlayer, sfx3.some_value), 0x4ba, 1}, +{offsetof(SpcPlayer, sfx1.priority), 0x4bb, 1}, +{offsetof(SpcPlayer, sfx2.priority), 0x4bc, 1}, +{offsetof(SpcPlayer, sfx3.priority), 0x4bd, 1}, +}; diff --git a/src/tracing.c b/src/tracing.c new file mode 100644 index 0000000..0464bbf --- /dev/null +++ b/src/tracing.c @@ -0,0 +1,206 @@ + +#include +#include +#include +#include +#include + +#include "tracing.h" +#include "snes/snes.h" +#include "snes/apu.h" + +// name for each opcode, to be filled in with sprintf (length = 14 (13+\0)) +static const char* opcodeNames[256] = { + "brk ", "ora ($%02x,x) ", "cop #$%02x ", "ora $%02x,s ", "tsb $%02x ", "ora $%02x ", "asl $%02x ", "ora [$%02x] ", "php ", "ora #$%04x ", "asl ", "phd ", "tsb $%04x ", "ora $%04x ", "asl $%04x ", "ora $%06x ", + "bpl $%04x ", "ora ($%02x),y ", "ora ($%02x) ", "ora ($%02x,s),y", "trb $%02x ", "ora $%02x,x ", "asl $%02x,x ", "ora [$%02x],y ", "clc ", "ora $%04x,y ", "inc ", "tcs ", "trb $%04x ", "ora $%04x,x ", "asl $%04x,x ", "ora $%06x,x", + "jsr $%04x ", "and ($%02x,x) ", "jsl $%06x ", "and $%02x,s ", "bit $%02x ", "and $%02x ", "rol $%02x ", "and [$%02x] ", "plp ", "and #$%04x ", "rol ", "pld ", "bit $%04x ", "and $%04x ", "rol $%04x ", "and $%06x ", + "bmi $%04x ", "and ($%02x),y ", "and ($%02x) ", "and ($%02x,s),y", "bit $%02x,x ", "and $%02x,x ", "rol $%02x,x ", "and [$%02x],y ", "sec ", "and $%04x,y ", "dec ", "tsc ", "bit $%04x,x ", "and $%04x,x ", "rol $%04x,x ", "and $%06x,x", + "rti ", "eor ($%02x,x) ", "wdm #$%02x ", "eor $%02x,s ", "mvp $%02x, $%02x ", "eor $%02x ", "lsr $%02x ", "eor [$%02x] ", "pha ", "eor #$%04x ", "lsr ", "phk ", "jmp $%04x ", "eor $%04x ", "lsr $%04x ", "eor $%06x ", + "bvc $%04x ", "eor ($%02x),y ", "eor ($%02x) ", "eor ($%02x,s),y", "mvn $%02x, $%02x ", "eor $%02x,x ", "lsr $%02x,x ", "eor [$%02x],y ", "cli ", "eor $%04x,y ", "phy ", "tcd ", "jml $%06x ", "eor $%04x,x ", "lsr $%04x,x ", "eor $%06x,x", + "rts ", "adc ($%02x,x) ", "per $%04x ", "adc $%02x,s ", "stz $%02x ", "adc $%02x ", "ror $%02x ", "adc [$%02x] ", "pla ", "adc #$%04x ", "ror ", "rtl ", "jmp ($%04x) ", "adc $%04x ", "ror $%04x ", "adc $%06x ", + "bvs $%04x ", "adc ($%02x),y ", "adc ($%02x) ", "adc ($%02x,s),y", "stz $%02x,x ", "adc $%02x,x ", "ror $%02x,x ", "adc [$%02x],y ", "sei ", "adc $%04x,y ", "ply ", "tdc ", "jmp ($%04x,x)", "adc $%04x,x ", "ror $%04x,x ", "adc $%06x,x", + "bra $%04x ", "sta ($%02x,x) ", "brl $%04x ", "sta $%02x,s ", "sty $%02x ", "sta $%02x ", "stx $%02x ", "sta [$%02x] ", "dey ", "bit #$%04x ", "txa ", "phb ", "sty $%04x ", "sta $%04x ", "stx $%04x ", "sta $%06x ", + "bcc $%04x ", "sta ($%02x),y ", "sta ($%02x) ", "sta ($%02x,s),y", "sty $%02x,x ", "sta $%02x,x ", "stx $%02x,y ", "sta [$%02x],y ", "tya ", "sta $%04x,y ", "txs ", "txy ", "stz $%04x ", "sta $%04x,x ", "stz $%04x,x ", "sta $%06x,x", + "ldy #$%04x ", "lda ($%02x,x) ", "ldx #$%04x ", "lda $%02x,s ", "ldy $%02x ", "lda $%02x ", "ldx $%02x ", "lda [$%02x] ", "tay ", "lda #$%04x ", "tax ", "plb ", "ldy $%04x ", "lda $%04x ", "ldx $%04x ", "lda $%06x ", + "bcs $%04x ", "lda ($%02x),y ", "lda ($%02x) ", "lda ($%02x,s),y", "ldy $%02x,x ", "lda $%02x,x ", "ldx $%02x,y ", "lda [$%02x],y ", "clv ", "lda $%04x,y ", "tsx ", "tyx ", "ldy $%04x,x ", "lda $%04x,x ", "ldx $%04x,y ", "lda $%06x,x", + "cpy #$%04x ", "cmp ($%02x,x) ", "rep #$%02x ", "cmp $%02x,s ", "cpy $%02x ", "cmp $%02x ", "dec $%02x ", "cmp [$%02x] ", "iny ", "cmp #$%04x ", "dex ", "wai ", "cpy $%04x ", "cmp $%04x ", "dec $%04x ", "cmp $%06x ", + "bne $%04x ", "cmp ($%02x),y ", "cmp ($%02x) ", "cmp ($%02x,s),y", "pei $%02x ", "cmp $%02x,x ", "dec $%02x,x ", "cmp [$%02x],y ", "cld ", "cmp $%04x,y ", "phx ", "stp ", "jml [$%04x] ", "cmp $%04x,x ", "dec $%04x,x ", "cmp $%06x,x", + "cpx #$%04x ", "sbc ($%02x,x) ", "sep #$%02x ", "sbc $%02x,s ", "cpx $%02x ", "sbc $%02x ", "inc $%02x ", "sbc [$%02x] ", "inx ", "sbc #$%04x ", "nop ", "xba ", "cpx $%04x ", "sbc $%04x ", "inc $%04x ", "sbc $%06x ", + "beq $%04x ", "sbc ($%02x),y ", "sbc ($%02x) ", "sbc ($%02x,s),y", "pea #$%04x ", "sbc $%02x,x ", "inc $%02x,x ", "sbc [$%02x],y ", "sed ", "sbc $%04x,y ", "plx ", "xce ", "jsr ($%04x,x)", "sbc $%04x,x ", "inc $%04x,x ", "sbc $%06x,x" +}; + +// for 8/16 bit immediates +// TODO: probably a better way to do this... +static const char* opcodeNamesSp[256] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "ora #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "and #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "eor #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "adc #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "bit #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "ldy #$%02x ", NULL, "ldx #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, "lda #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "cpy #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "cmp #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "cpx #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "sbc #$%02x ", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +// address types for each opcode +static const int opcodeType[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 0, 4, 0, 0, 2, 2, 2, 3, + 6, 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, 0, 2, 2, 2, 3, + 2, 1, 3, 1, 1, 1, 1, 1, 0, 4, 0, 0, 2, 2, 2, 3, + 6, 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, 0, 2, 2, 2, 3, + 0, 1, 1, 1, 8, 1, 1, 1, 0, 4, 0, 0, 2, 2, 2, 3, + 6, 1, 1, 1, 8, 1, 1, 1, 0, 2, 0, 0, 3, 2, 2, 3, + 0, 1, 7, 1, 1, 1, 1, 1, 0, 4, 0, 0, 2, 2, 2, 3, + 6, 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, 0, 2, 2, 2, 3, + 6, 1, 7, 1, 1, 1, 1, 1, 0, 4, 0, 0, 2, 2, 2, 3, + 6, 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, 0, 2, 2, 2, 3, + 5, 1, 5, 1, 1, 1, 1, 1, 0, 4, 0, 0, 2, 2, 2, 3, + 6, 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, 0, 2, 2, 2, 3, + 5, 1, 1, 1, 1, 1, 1, 1, 0, 4, 0, 0, 2, 2, 2, 3, + 6, 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, 0, 2, 2, 2, 3, + 5, 1, 1, 1, 1, 1, 1, 1, 0, 4, 0, 0, 2, 2, 2, 3, + 6, 1, 1, 1, 2, 1, 1, 1, 0, 2, 0, 0, 2, 2, 2, 3 +}; + +// name for each opcode, for spc +static const char* opcodeNamesSpc[256] = { + "nop ", "tcall 0 ", "set1 $%02x.0 ", "bbs $%02x.0, $%04x ", "or a, $%02x ", "or a, $%04x ", "or a, [X] ", "or a, [$%02x+x] ", "or a, #$%02x ", "or $%02x, $%02x ", "or1 c, $%04x.%01x ", "asl $%02x ", "asl $%04x ", "push p ", "tset $%04x ", "brk ", + "bpl $%04x ", "tcall 1 ", "clr1 $%02x.0 ", "bbc $%02x.0, $%04x ", "or a, $%02x+x ", "or a, $%04x+x ", "or a, $%04x+y ", "or a, [$%02x]+y ", "or $%02x, #$%02x ", "or [X], [Y] ", "decw $%02x ", "asl $%02x+x ", "asl a ", "dec x ", "cmp x, $%04x ", "jmp [$%04x+x] ", + "clrp ", "tcall 2 ", "set1 $%02x.1 ", "bbs $%02x.1, $%04x ", "and a, $%02x ", "and a, $%04x ", "and a, [X] ", "and a, [$%02x+x] ", "and a, #$%02x ", "and $%02x, $%02x ", "or1 c, /$%04x.%01x ", "rol $%02x ", "rol $%04x ", "push a ", "cbne $%02x, $%04x ", "bra $%04x ", + "bmi $%04x ", "tcall 3 ", "clr1 $%02x.1 ", "bbc $%02x.1, $%04x ", "and a, $%02x+x ", "and a, $%04x+x ", "and a, $%04x+y ", "and a, [$%02x]+y ", "and $%02x, #$%02x ", "and [X], [Y] ", "incw $%02x ", "rol $%02x+x ", "rol a ", "inc x ", "cmp x, $%02x ", "call $%04x ", + "setp ", "tcall 4 ", "set1 $%02x.2 ", "bbs $%02x.2, $%04x ", "eor a, $%02x ", "eor a, $%04x ", "eor a, [X] ", "eor a, [$%02x+x] ", "eor a, #$%02x ", "eor $%02x, $%02x ", "and1 c, $%04x.%01x ", "lsr $%02x ", "lsr $%04x ", "push x ", "tclr $%04x ", "pcall $%02x ", + "bvc $%04x ", "tcall 5 ", "clr1 $%02x.2 ", "bbc $%02x.2, $%04x ", "eor a, $%02x+x ", "eor a, $%04x+x ", "eor a, $%04x+y ", "eor a, [$%02x]+y ", "eor $%02x, #$%02x ", "eor [X], [Y] ", "cmpw ya, $%02x ", "lsr $%02x+x ", "lsr a ", "mov x, a ", "cmp y, $%04x ", "jmp $%04x ", + "clrc ", "tcall 6 ", "set1 $%02x.3 ", "bbs $%02x.3, $%04x ", "cmp a, $%02x ", "cmp a, $%04x ", "cmp a, [X] ", "cmp a, [$%02x+x] ", "cmp a, #$%02x ", "cmp $%02x, $%02x ", "and1 c, /$%04x.%01x ", "ror $%02x ", "ror $%04x ", "push y ", "dbnz $%02x, $%04x ", "ret ", + "bvs $%04x ", "tcall 7 ", "clr1 $%02x.3 ", "bbc $%02x.3, $%04x ", "cmp a, $%02x+x ", "cmp a, $%04x+x ", "cmp a, $%04x+y ", "cmp a, [$%02x]+y ", "cmp $%02x, #$%02x ", "cmp [X], [Y] ", "addw ya, $%02x ", "ror $%02x+x ", "ror a ", "mov a, x ", "cmp y, $%02x ", "reti ", + "setc ", "tcall 8 ", "set1 $%02x.4 ", "bbs $%02x.4, $%04x ", "adc a, $%02x ", "adc a, $%04x ", "adc a, [X] ", "adc a, [$%02x+x] ", "adc a, #$%02x ", "adc $%02x, $%02x ", "eor1 c, $%04x.%01x ", "dec $%02x ", "dec $%04x ", "mov y, #$%02x ", "pop p ", "mov $%02x, #$%02x ", + "bcc $%04x ", "tcall 9 ", "clr1 $%02x.4 ", "bbc $%02x.4, $%04x ", "adc a, $%02x+x ", "adc a, $%04x+x ", "adc a, $%04x+y ", "adc a, [$%02x]+y ", "adc $%02x, #$%02x ", "adc [X], [Y] ", "subw ya, $%02x ", "dec $%02x+x ", "dec a ", "mov x, sp ", "div ya, x ", "xcn a ", + "ei ", "tcall 10 ", "set1 $%02x.5 ", "bbs $%02x.5, $%04x ", "sbc a, $%02x ", "sbc a, $%04x ", "sbc a, [X] ", "sbc a, [$%02x+x] ", "sbc a, #$%02x ", "sbc $%02x, $%02x ", "mov1 c, $%04x.%01x ", "inc $%02x ", "inc $%04x ", "cmp y, #$%02x ", "pop a ", "mov [x+], a ", + "bcs $%04x ", "tcall 11 ", "clr1 $%02x.5 ", "bbc $%02x.5, $%04x ", "sbc a, $%02x+x ", "sbc a, $%04x+x ", "sbc a, $%04x+y ", "sbc a, [$%02x]+y ", "sbc $%02x, #$%02x ", "sbc [X], [Y] ", "movw ya, $%02x ", "inc $%02x+x ", "inc a ", "mov sp, x ", "das a ", "mov a, [x+] ", + "di ", "tcall 12 ", "set1 $%02x.6 ", "bbs $%02x.6, $%04x ", "mov $%02x, a ", "mov $%04x, a ", "mov [X], a ", "mov [$%02x+x], a ", "cmp x, #$%02x ", "mov $%04x, x ", "mov1 $%04x.%01x, c ", "mov $%02x, y ", "mov $%04x, y ", "mov x, #$%02x ", "pop x ", "mul ya ", + "bne $%04x ", "tcall 13 ", "clr1 $%02x.6 ", "bbc $%02x.6, $%04x ", "mov $%02x+x, a ", "mov $%04x+x, a ", "mov $%04x+y, a ", "mov [$%02x]+y, a ", "mov $%02x, x ", "mov $%02x+y, x ", "movw $%02x, ya ", "mov $%02x+x, y ", "dec y ", "mov a, y ", "cbne $%02x+x, $%04x", "daa a ", + "clrv ", "tcall 14 ", "set1 $%02x.7 ", "bbs $%02x.7, $%04x ", "mov a, $%02x ", "mov a, $%04x ", "mov a, [X] ", "mov a, [$%02x+x] ", "mov a, #$%02x ", "mov x, $%04x ", "not1 $%04x.%01x ", "mov y, $%02x ", "mov y, $%04x ", "notc ", "pop y ", "sleep ", + "beq $%04x ", "tcall 15 ", "clr1 $%02x.7 ", "bbc $%02x.7, $%04x ", "mov a, $%02x+x ", "mov a, $%04x+x ", "mov a, $%04x+y ", "mov a, [$%02x]+y ", "mov x, $%02x ", "mov x, $%02x+y ", "mov $%02x, $%02x ", "mov y, $%02x+x ", "inc y ", "mov y, a ", "dbnz y, $%04x ", "stop " +}; + +// address types for each opcode, for spc +static const int opcodeTypeSpc[256] = { + 0, 0, 1, 5, 1, 2, 0, 1, 1, 4, 6, 1, 2, 0, 2, 0, + 3, 0, 1, 5, 1, 2, 2, 1, 4, 0, 1, 1, 0, 0, 2, 2, + 0, 0, 1, 5, 1, 2, 0, 1, 1, 4, 6, 1, 2, 0, 5, 3, + 3, 0, 1, 5, 1, 2, 2, 1, 4, 0, 1, 1, 0, 0, 1, 2, + 0, 0, 1, 5, 1, 2, 0, 1, 1, 4, 6, 1, 2, 0, 2, 1, + 3, 0, 1, 5, 1, 2, 2, 1, 4, 0, 1, 1, 0, 0, 2, 2, + 0, 0, 1, 5, 1, 2, 0, 1, 1, 4, 6, 1, 2, 0, 5, 0, + 3, 0, 1, 5, 1, 2, 2, 1, 4, 0, 1, 1, 0, 0, 1, 0, + 0, 0, 1, 5, 1, 2, 0, 1, 1, 4, 6, 1, 2, 1, 0, 4, + 3, 0, 1, 5, 1, 2, 2, 1, 4, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 5, 1, 2, 0, 1, 1, 4, 6, 1, 2, 1, 0, 0, + 3, 0, 1, 5, 1, 2, 2, 1, 4, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 5, 1, 2, 0, 1, 1, 2, 6, 1, 2, 1, 0, 0, + 3, 0, 1, 5, 1, 2, 2, 1, 1, 1, 1, 1, 0, 0, 5, 0, + 0, 0, 1, 5, 1, 2, 0, 1, 1, 2, 6, 1, 2, 0, 0, 0, + 3, 0, 1, 5, 1, 2, 2, 1, 1, 1, 4, 1, 0, 0, 3, 0 +}; + +static void getDisassemblyCpu(Snes* snes, char* line); +static void getDisassemblySpc(Apu* apu, char* line); + +void getProcessorStateCpu(Snes* snes, char* line) { + // 0 1 2 3 4 5 6 7 8 + // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 + // CPU 12:3456 1234567890123 A:1234 X:1234 Y:1234 SP:1234 DP:1234 DP:12 e nvmxdizc + char disLine[14] = " "; + getDisassemblyCpu(snes, disLine); + sprintf( + line, "CPU %02x:%04x %s A:%04x X:%04x Y:%04x SP:%04x DP:%04x DB:%02x %c %c%c%c%c%c%c%c%c", + snes->cpu->k, snes->cpu->pc, disLine, snes->cpu->a, snes->cpu->x, snes->cpu->y, + snes->cpu->sp, snes->cpu->dp, snes->cpu->db, snes->cpu->e ? 'E' : 'e', + snes->cpu->n ? 'N' : 'n', snes->cpu->v ? 'V' : 'v', snes->cpu->mf ? 'M' : 'm', snes->cpu->xf ? 'X' : 'x', + snes->cpu->d ? 'D' : 'd', snes->cpu->i ? 'I' : 'i', snes->cpu->z ? 'Z' : 'z', snes->cpu->c ? 'C' : 'c' + ); +} + +void getProcessorStateSpc(Apu* apu, char* line) { + // 0 1 2 3 4 5 6 7 8 + // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 + // SPC 3456 12345678901234567 A:12 X:12 Y:12 SP:12 nvpbhizc + char disLine[18] = " "; + getDisassemblySpc(apu, disLine); + sprintf( + line, "SPC %04x %s A:%02x X:%02x Y:%02x SP:%02x %c%c%c%c%c%c%c%c", + apu->spc->pc, disLine, apu->spc->a, apu->spc->x, apu->spc->y, apu->spc->sp, + apu->spc->n ? 'N' : 'n', apu->spc->v ? 'V' : 'v', apu->spc->p ? 'P' : 'p', apu->spc->b ? 'B' : 'b', + apu->spc->h ? 'H' : 'h', apu->spc->i ? 'I' : 'i', apu->spc->z ? 'Z' : 'z', apu->spc->c ? 'C' : 'c' + ); +} + +static void getDisassemblyCpu(Snes* snes, char* line) { + uint32_t adr = snes->cpu->pc | (snes->cpu->k << 16); + // read 4 bytes + // TODO: this can have side effects, implement and use peaking + uint8_t opcode = snes_read(snes, adr); + uint8_t byte = snes_read(snes, (adr + 1) & 0xffffff); + uint8_t byte2 = snes_read(snes, (adr + 2) & 0xffffff); + uint16_t word = (byte2 << 8) | byte; + uint32_t longv = (snes_read(snes, (adr + 3) & 0xffffff) << 16) | word; + uint16_t rel = snes->cpu->pc + 2 + (int8_t) byte; + uint16_t rell = snes->cpu->pc + 3 + (int16_t) word; + // switch on type + switch(opcodeType[opcode]) { + case 0: sprintf(line, "%s", opcodeNames[opcode]); break; + case 1: sprintf(line, opcodeNames[opcode], byte); break; + case 2: sprintf(line, opcodeNames[opcode], word); break; + case 3: sprintf(line, opcodeNames[opcode], longv); break; + case 4: { + if(snes->cpu->mf) { + sprintf(line, opcodeNamesSp[opcode], byte); + } else { + sprintf(line, opcodeNames[opcode], word); + } + break; + } + case 5: { + if(snes->cpu->xf) { + sprintf(line, opcodeNamesSp[opcode], byte); + } else { + sprintf(line, opcodeNames[opcode], word); + } + break; + } + case 6: sprintf(line, opcodeNames[opcode], rel); break; + case 7: sprintf(line, opcodeNames[opcode], rell); break; + case 8: sprintf(line, opcodeNames[opcode], byte2, byte); break; + } +} + +void getDisassemblySpc(Apu* apu, char* line) { + uint16_t adr = apu->spc->pc; + // read 3 bytes + // TODO: this can have side effects, implement and use peaking + uint8_t opcode = apu_cpuRead(apu, adr); + uint8_t byte = apu_cpuRead(apu, (adr + 1) & 0xffff); + uint8_t byte2 = apu_cpuRead(apu, (adr + 2) & 0xffff); + uint16_t word = (byte2 << 8) | byte; + uint16_t rel = apu->spc->pc + 2 + (int8_t) byte; + uint16_t rel2 = apu->spc->pc + 2 + (int8_t) byte2; + uint16_t wordb = word & 0x1fff; + uint8_t bit = word >> 13; + // switch on type + switch(opcodeTypeSpc[opcode]) { + case 0: sprintf(line, "%s", opcodeNamesSpc[opcode]); break; + case 1: sprintf(line, opcodeNamesSpc[opcode], byte); break; + case 2: sprintf(line, opcodeNamesSpc[opcode], word); break; + case 3: sprintf(line, opcodeNamesSpc[opcode], rel); break; + case 4: sprintf(line, opcodeNamesSpc[opcode], byte2, byte); break; + case 5: sprintf(line, opcodeNamesSpc[opcode], byte, rel2); break; + case 6: sprintf(line, opcodeNamesSpc[opcode], wordb, bit); break; + } +} diff --git a/src/tracing.h b/src/tracing.h new file mode 100644 index 0000000..3996ed3 --- /dev/null +++ b/src/tracing.h @@ -0,0 +1,16 @@ + +#ifndef TRACING_H +#define TRACING_H + +#include +#include +#include +#include +#include + +#include "snes/snes.h" + +void getProcessorStateCpu(Snes* snes, char* line); +void getProcessorStateSpc(Apu* snes, char* line); + +#endif diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..72f37d7 --- /dev/null +++ b/src/types.h @@ -0,0 +1,157 @@ +#ifndef SM_TYPES_H_ +#define SM_TYPES_H_ + +#pragma warning(disable: 4244) + +#include +#include +#include + +#if defined(_WIN32) && !COMPILER_TCC +#include +#define assert _ASSERTE +#else +#include +#endif + + +typedef uint8_t uint8; +typedef int8_t int8; +typedef uint16_t uint16; +typedef int16_t int16; +typedef uint32_t uint32; +typedef int32_t int32; +typedef uint64_t uint64; +typedef int64_t int64; +typedef unsigned int uint; + +typedef uint16 VoidP; + +#define arraysize(x) sizeof(x)/sizeof(x[0]) +#define sign8(x) ((x) & 0x80) +#define sign16(x) ((x) & 0x8000) +#define load24(x) ((*(uint32*)&(x))&0xffffff) + +#ifdef _MSC_VER +#define countof _countof +#define NORETURN __declspec(noreturn) +#define FORCEINLINE __forceinline +#define NOINLINE __declspec(noinline) +#else +#define countof(a) (sizeof(a)/sizeof(*(a))) +#define NORETURN +#define FORCEINLINE inline +#define NOINLINE +#endif + +#ifdef _DEBUG +#define kDebugFlag 1 +#else +#define kDebugFlag 0 +#endif + +static FORCEINLINE uint16 abs16(uint16 t) { return sign16(t) ? -t : t; } +static FORCEINLINE uint8 abs8(uint8 t) { return sign8(t) ? -t : t; } +static FORCEINLINE int IntMin(int a, int b) { return a < b ? a : b; } +static FORCEINLINE int IntMax(int a, int b) { return a > b ? a : b; } +static FORCEINLINE uint UintMin(uint a, uint b) { return a < b ? a : b; } +static FORCEINLINE uint UintMax(uint a, uint b) { return a > b ? a : b; } + +// windows.h defines this too +#ifdef HIBYTE +#undef HIBYTE +#endif + +#define BYTE(x) (*(uint8*)&(x)) +#define WORD(x) (*(uint16*)&(x)) +#define DWORD(x) (*(uint32*)&(x)) +#define XY(x, y) ((y)*64+(x)) + +static inline uint16 swap16(uint16 v) { return (v << 8) | (v >> 8); } + +void NORETURN Die(const char *error); + +// compile time assertion +#define __CASSERT_N0__(l) COMPILE_TIME_ASSERT_ ## l +#define __CASSERT_N1__(l) __CASSERT_N0__(l) +#define CASSERT(cnd) typedef char __CASSERT_N1__(__LINE__) [(cnd) ? 1 : -1] + +#define USE_COROUTINES 1 + +typedef uint8_t CoroutineRet; + +#define COROUTINE_BEGIN(state_var, start_pos) \ + uint8 *_state_variable_ = &(state_var); \ + switch(*_state_variable_) { \ + case start_pos: + +#define COROUTINE_MANUAL_POS(position) \ + case (position): + +#define COROUTINE_AWAIT(position, function) \ + case (position): \ + { uint8 _coret_ = (function); \ + if (_coret_) { \ + *_state_variable_ = (position); \ + return _coret_; \ + }} + +#define COROUTINE_AWAIT_ONLY(function) \ + { uint8 _coret_ = (function); \ + if (_coret_) \ + return _coret_; \ + } + +#define COROUTINE_END(position) \ + } \ + *_state_variable_ = (position); \ + return 0 + +#define kCoroutineNone 0 + +/* 90 */ +#pragma pack(push, 1) +typedef struct LongPtr { + VoidP addr; + uint8 bank; +} LongPtr; +#pragma pack (pop) + +static inline bool __CFADD__uint16(uint16 x, uint16 y) { return (uint16)(x) > (uint16)(x + y); } +static inline bool __CFADD__uint8(uint8 x, uint8 y) { return (uint8)(x) > (uint8)(x + y); } + +typedef struct PairU16 { + uint16 k, j; +} PairU16; + +typedef struct Point16U { + uint16 x, y; +} Point16U; + + +// Some convenience macros to make partial accesses nicer +#define LAST_IND(x,part_type) (sizeof(x)/sizeof(part_type) - 1) +#define HIGH_IND(x,part_type) LAST_IND(x,part_type) +#define LOW_IND(x,part_type) 0 +// first unsigned macros: +#define BYTEn(x, n) (*((uint8*)&(x)+n)) +#define WORDn(x, n) (*((uint16*)&(x)+n)) + +#define LOBYTE(x) BYTEn(x,LOW_IND(x,uint8)) +#define LOWORD(x) WORDn(x,LOW_IND(x,uint16)) +#define HIBYTE(x) BYTEn(x,HIGH_IND(x,uint8)) +#define HIWORD(x) WORDn(x,HIGH_IND(x,uint16)) + +// Generate a pair of operands. +#define __PAIR32__(high, low) (((uint32) (high) << 16) | (uint16)(low)) + +// Helper functions to represent some assembly instructions. + +// compile time assertion +#define __CASSERT_N0__(l) COMPILE_TIME_ASSERT_ ## l +#define __CASSERT_N1__(l) __CASSERT_N0__(l) +#define CASSERT(cnd) typedef char __CASSERT_N1__(__LINE__) [(cnd) ? 1 : -1] + + +#endif // SM_TYPES_H_ + diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..aa4e4ad --- /dev/null +++ b/src/util.c @@ -0,0 +1,172 @@ +#include "util.h" +#include +#include +#include + +char *NextDelim(char **s, int sep) { + char *r = *s; + if (r) { + while (r[0] == ' ' || r[0] == '\t') + r++; + char *t = strchr(r, sep); + *s = t ? (*t++ = 0, t) : NULL; + } + return r; +} + +static inline int ToLower(int a) { + return a + (a >= 'A' && a <= 'Z') * 32; +} + +bool StringEqualsNoCase(const char *a, const char *b) { + for (;;) { + int aa = ToLower(*a++), bb = ToLower(*b++); + if (aa != bb) + return false; + if (aa == 0) + return true; + } +} + +const char *StringStartsWithNoCase(const char *a, const char *b) { + for (;; a++, b++) { + int aa = ToLower(*a), bb = ToLower(*b); + if (bb == 0) + return a; + if (aa != bb) + return NULL; + } +} + +uint8 *ReadWholeFile(const char *name, size_t *length) { + FILE *f = fopen(name, "rb"); + if (f == NULL) + return NULL; + fseek(f, 0, SEEK_END); + size_t size = ftell(f); + rewind(f); + uint8 *buffer = (uint8 *)malloc(size + 1); + if (!buffer) Die("malloc failed"); + // Always zero terminate so this function can be used also for strings. + buffer[size] = 0; + if (fread(buffer, 1, size, f) != size) + Die("fread failed"); + fclose(f); + if (length) *length = size; + return buffer; +} + +char *NextLineStripComments(char **s) { + char *p = *s; + if (p == NULL) + return NULL; + // find end of line + char *eol = strchr(p, '\n'); + *s = eol ? eol + 1 : NULL; + eol = eol ? eol : p + strlen(p); + // strip comments + char *comment = (char*)memchr(p, '#', eol - p); + eol = comment ? comment : eol; + // strip trailing whitespace + while (eol > p && (eol[-1] == '\r' || eol[-1] == ' ' || eol[-1] == '\t')) + eol--; + *eol = 0; + // strip leading whitespace + while (p[0] == ' ' || p[0] == '\t') + p++; + return p; +} + +// Return the next possibly quoted string, space separated, or the empty string +char *NextPossiblyQuotedString(char **s) { + char *r = *s, *t; + while (*r == ' ' || *r == '\t') + r++; + if (*r == '"') { + for (t = ++r; *t && *t != '"'; t++); + } else { + for (t = r; *t && *t != ' ' && *t != '\t'; t++); + } + if (*t) *t++ = 0; + while (*t == ' ' || *t == '\t') + t++; + *s = t; + return r; +} + +char *ReplaceFilenameWithNewPath(const char *old_path, const char *new_path) { + size_t olen = strlen(old_path); + size_t nlen = strlen(new_path) + 1; + while (olen && old_path[olen - 1] != '/' && old_path[olen - 1] != '\\') + olen--; + char *result = (char *)malloc(olen + nlen); + memcpy(result, old_path, olen); + memcpy(result + olen, new_path, nlen); + return result; +} + +char *SplitKeyValue(char *p) { + char *equals = strchr(p, '='); + if (equals == NULL) + return NULL; + char *kr = equals; + while (kr > p && (kr[-1] == ' ' || kr[-1] == '\t')) + kr--; + *kr = 0; + char *v = equals + 1; + while (v[0] == ' ' || v[0] == '\t') + v++; + return v; +} + +const char *SkipPrefix(const char *big, const char *little) { + for (; *little; big++, little++) { + if (*little != *big) + return NULL; + } + return big; +} + +void StrSet(char **rv, const char *s) { + char *news = strdup(s); + char *old = *rv; + *rv = news; + free(old); +} + +char *StrFmt(const char *fmt, ...) { + char buf[4096]; + va_list va; + va_start(va, fmt); + int n = vsnprintf(buf, sizeof(buf), fmt, va); + if (n < 0 || n >= sizeof(buf)) Die("vsnprintf failed"); + va_end(va); + return strdup(buf); +} + +void ByteArray_Resize(ByteArray *arr, size_t new_size) { + arr->size = new_size; + if (new_size > arr->capacity) { + size_t minsize = arr->capacity + (arr->capacity >> 1) + 8; + arr->capacity = new_size < minsize ? minsize : new_size; + uint8 *data = (uint8*)realloc(arr->data, arr->capacity); + if (!data) Die("memory allocation failed"); + arr->data = data; + } +} + +void ByteArray_Destroy(ByteArray *arr) { + void *data = arr->data; + arr->data = NULL; + free(data); +} + +void ByteArray_AppendData(ByteArray *arr, const uint8 *data, size_t data_size) { + ByteArray_Resize(arr, arr->size + data_size); + memcpy(arr->data + arr->size - data_size, data, data_size); +} + +void ByteArray_AppendByte(ByteArray *arr, uint8 v) { + ByteArray_Resize(arr, arr->size + 1); + arr->data[arr->size - 1] = v; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..7ae3ecd --- /dev/null +++ b/src/util.h @@ -0,0 +1,39 @@ +#ifndef ZELDA3_UTIL_H_ +#define ZELDA3_UTIL_H_ + +#include "types.h" + +typedef struct SDL_Window SDL_Window; + +struct RendererFuncs { + bool (*Initialize)(SDL_Window *window); + void (*Destroy)(); + void (*BeginDraw)(int width, int height, uint8 **pixels, int *pitch); + void (*EndDraw)(); +}; + + +typedef struct ByteArray { + uint8 *data; + size_t size, capacity; +} ByteArray; + +void ByteArray_Resize(ByteArray *arr, size_t new_size); +void ByteArray_Destroy(ByteArray *arr); +void ByteArray_AppendData(ByteArray *arr, const uint8 *data, size_t data_size); +void ByteArray_AppendByte(ByteArray *arr, uint8 v); + +uint8 *ReadWholeFile(const char *name, size_t *length); +char *NextDelim(char **s, int sep); +char *NextLineStripComments(char **s); +char *NextPossiblyQuotedString(char **s); +char *SplitKeyValue(char *p); +bool StringEqualsNoCase(const char *a, const char *b); +const char *StringStartsWithNoCase(const char *a, const char *b); +bool ParseBool(const char *value, bool *result); +const char *SkipPrefix(const char *big, const char *little); +void StrSet(char **rv, const char *s); +char *StrFmt(const char *fmt, ...); +char *ReplaceFilenameWithNewPath(const char *old_path, const char *new_path); + +#endif // ZELDA3_UTIL_H_ \ No newline at end of file diff --git a/src/variables.h b/src/variables.h new file mode 100644 index 0000000..caf7ae1 --- /dev/null +++ b/src/variables.h @@ -0,0 +1,1159 @@ +#define R0_ (*(LongPtr*)(g_ram+0x0)) +#define R3_ (*(LongPtr*)(g_ram+0x3)) +#define R6_ (*(uint16*)(g_ram+0x6)) +#define R8_ (*(uint16*)(g_ram+0x8)) +#define R10_ (*(uint16*)(g_ram+0xA)) +#define R12_ (*(uint16*)(g_ram+0xC)) +#define R14_ (*(uint16*)(g_ram+0xE)) +#define R16_ (*(uint16*)(g_ram+0x10)) +#define R18_ (*(uint16*)(g_ram+0x12)) +#define R20_ (*(uint16*)(g_ram+0x14)) +#define R22_ (*(uint16*)(g_ram+0x16)) +#define R24_ (*(uint16*)(g_ram+0x18)) +#define R26_ (*(uint16*)(g_ram+0x1A)) +#define R28_ (*(uint16*)(g_ram+0x1C)) +#define g_word_7E001E (*(uint16*)(g_ram+0x1E)) +#define R32 (*(uint16*)(g_ram+0x20)) +#define R34 (*(uint16*)(g_ram+0x22)) +#define R36 (*(uint16*)(g_ram+0x24)) +#define R38 (*(uint16*)(g_ram+0x26)) +#define R40 (*(uint16*)(g_ram+0x28)) +#define R42 (*(uint16*)(g_ram+0x2A)) +#define R44 (*(uint16*)(g_ram+0x2C)) +#define R46 (*(uint16*)(g_ram+0x2E)) +#define R48 (*(uint16*)(g_ram+0x30)) +#define R50 (*(uint16*)(g_ram+0x32)) +#define bg3_tilemap_offset (*(uint16*)(g_ram+0x34)) +#define copywithflip_src (*(LongPtr*)(g_ram+0x36)) +#define g_byte_7E0039 (*(uint8*)(g_ram+0x39)) +#define g_byte_7E003A (*(uint8*)(g_ram+0x3A)) +#define nmicopy1_var_d (*(uint16*)(g_ram+0x3C)) +#define g_word_7E003E (*(uint16*)(g_ram+0x3E)) +#define decompress_dst_tmp (*(LongPtr*)(g_ram+0x44)) +#define decompress_src (*(LongPtr*)(g_ram+0x47)) +#define decompress_last_byte (*(uint8*)(g_ram+0x4A)) +#define decompress_tmp1 (*(uint8*)(g_ram+0x4B)) +#define decompress_dst (*(LongPtr*)(g_ram+0x4C)) +#define decompress_want_xor (*(uint16*)(g_ram+0x4F)) +#define reg_INIDISP (*(uint8*)(g_ram+0x51)) +#define reg_OBSEL (*(uint8*)(g_ram+0x52)) +#define reg_OAMaddr_UNUSED (*(uint16*)(g_ram+0x53)) +#define reg_BGMODE (*(uint8*)(g_ram+0x55)) +#define reg_BGMODE_fake (*(uint8*)(g_ram+0x56)) +#define reg_MOSAIC (*(uint8*)(g_ram+0x57)) +#define reg_BG1SC (*(uint8*)(g_ram+0x58)) +#define reg_BG2SC (*(uint8*)(g_ram+0x59)) +#define reg_BG3SC (*(uint8*)(g_ram+0x5A)) +#define gameplay_BG3SC (*(uint8*)(g_ram+0x5B)) +#define reg_BG4SC (*(uint8*)(g_ram+0x5C)) +#define reg_BG12NBA (*(uint8*)(g_ram+0x5D)) +#define reg_BG34NBA (*(uint8*)(g_ram+0x5E)) +#define reg_M7SEL (*(uint8*)(g_ram+0x5F)) +#define reg_W12SEL (*(uint8*)(g_ram+0x60)) +#define reg_W34SEL (*(uint8*)(g_ram+0x61)) +#define reg_WOBJSEL (*(uint8*)(g_ram+0x62)) +#define reg_WH0 (*(uint8*)(g_ram+0x63)) +#define reg_WH1 (*(uint8*)(g_ram+0x64)) +#define reg_WH2 (*(uint8*)(g_ram+0x65)) +#define reg_WH3 (*(uint8*)(g_ram+0x66)) +#define reg_WBGLOG (*(uint8*)(g_ram+0x67)) +#define reg_WOBJLOG (*(uint8*)(g_ram+0x68)) +#define reg_TM (*(uint8*)(g_ram+0x69)) +#define gameplay_TM (*(uint8*)(g_ram+0x6A)) +#define reg_TS (*(uint8*)(g_ram+0x6B)) +#define reg_TMW (*(uint8*)(g_ram+0x6C)) +#define reg_TSW (*(uint8*)(g_ram+0x6D)) +#define next_gameplay_CGWSEL (*(uint8*)(g_ram+0x6E)) +#define reg_CGWSEL (*(uint8*)(g_ram+0x6F)) +#define gameplay_CGWSEL (*(uint8*)(g_ram+0x70)) +#define next_gameplay_CGADSUB (*(uint8*)(g_ram+0x71)) +#define reg_CGADSUB (*(uint8*)(g_ram+0x72)) +#define gameplay_CGADSUB (*(uint8*)(g_ram+0x73)) +#define reg_COLDATA ((uint8*)(g_ram+0x74)) +#define reg_SETINI (*(uint8*)(g_ram+0x77)) +#define reg_M7A (*(uint16*)(g_ram+0x78)) +#define reg_M7B (*(uint16*)(g_ram+0x7A)) +#define reg_M7C (*(uint16*)(g_ram+0x7C)) +#define reg_M7D (*(uint16*)(g_ram+0x7E)) +#define reg_M7X (*(uint16*)(g_ram+0x80)) +#define reg_M7Y (*(uint16*)(g_ram+0x82)) +#define reg_NMITIMEN (*(uint8*)(g_ram+0x84)) +#define reg_HDMAEN (*(uint8*)(g_ram+0x85)) +#define reg_MEMSEL (*(uint8*)(g_ram+0x86)) +#define joypad_ctr_repeat_first (*(uint16*)(g_ram+0x87)) +#define joypad_ctr_repeat_next (*(uint16*)(g_ram+0x89)) +#define joypad1_lastkeys (*(uint16*)(g_ram+0x8B)) +#define joypad2_last (*(uint16*)(g_ram+0x8D)) +#define joypad1_newkeys (*(uint16*)(g_ram+0x8F)) +#define joypad2_new_keys (*(uint16*)(g_ram+0x91)) +#define joypad1_newkeys2_UNUSED (*(uint16*)(g_ram+0x93)) +#define joypad2_newkeys2 (*(uint16*)(g_ram+0x95)) +#define joypad1_prev (*(uint16*)(g_ram+0x97)) +#define joypad2_prev (*(uint16*)(g_ram+0x99)) +#define joypad1_keyrepeat_ctr (*(uint16*)(g_ram+0xA3)) +#define joypad2_keyrepeat_ctr (*(uint16*)(g_ram+0xA5)) +#define irqhandler_next_handler (*(uint16*)(g_ram+0xA7)) +#define room_loading_irq_handler (*(uint16*)(g_ram+0xA9)) +#define cur_irq_handler (*(uint16*)(g_ram+0xAB)) +#define ptr_to_retaddr_parameters (*(uint16*)(g_ram+0xAD)) +#define current_region_animated_palette_fx (*(uint16*)(g_ram+0xAF)) +#define reg_BG1HOFS (*(uint16*)(g_ram+0xB1)) +#define reg_BG1VOFS (*(uint16*)(g_ram+0xB3)) +#define reg_BG2HOFS (*(uint16*)(g_ram+0xB5)) +#define reg_BG2VOFS (*(uint16*)(g_ram+0xB7)) +#define reg_BG3HOFS (*(uint16*)(g_ram+0xB9)) +#define reg_BG3VOFS (*(uint16*)(g_ram+0xBB)) +#define reg_BG4HOFS (*(uint16*)(g_ram+0xBD)) +#define reg_BG4VOFS (*(uint16*)(g_ram+0xBF)) +#define g_word_7E00C4 ((uint16*)(g_ram+0xC4)) +#define vram_write_queue ((VramWriteEntry*)(g_ram+0xD0)) +#define mode7_write_queue ((Mode7VramWriteQueue*)(g_ram+0x2D0)) +#define vram_write_queue_tail (*(uint16*)(g_ram+0x330)) +#define mode7_vram_write_queue_tail (*(uint16*)(g_ram+0x334)) +#define vram_read_queue ((VramReadQueueEnt*)(g_ram+0x340)) +#define vram_read_queue_tail (*(uint16*)(g_ram+0x360)) +#define oam_ent ((OamEnt*)(g_ram+0x370)) +#define oam_ext ((uint16*)(g_ram+0x570)) +#define oam_next_ptr (*(uint16*)(g_ram+0x590)) +#define power_bomb_explosion_status (*(uint16*)(g_ram+0x592)) + +// This is used to handle WaitForNMI that is nested deep inside other +// functions. +#define coroutine_state_0 (*(uint8*)(g_ram+0x611)) +#define coroutine_state_1 (*(uint8*)(g_ram+0x612)) +#define coroutine_state_2 (*(uint8*)(g_ram+0x613)) +#define coroutine_state_3 (*(uint8*)(g_ram+0x614)) +#define coroutine_state_4 (*(uint8*)(g_ram+0x615)) +#define coroutine_completion_flags (*(uint8*)(g_ram+0x782)) +#define my_counter (*(uint16*)(g_ram+0x77E)) + +#define g_word_7E0596 (*(uint16*)(g_ram+0x596)) +#define g_word_7E0598 (*(uint16*)(g_ram+0x598)) +#define set_to_e0_by_scrolling_sky (*(uint16*)(g_ram+0x59A)) +#define UNUSED_word_7E059C (*(uint16*)(g_ram+0x59C)) +#define UNUSED_hdma_contracting_flag (*(uint16*)(g_ram+0x5A0)) +#define message_box_animation_y_radius (*(uint16*)(g_ram+0x5A2)) +#define message_box_animation_y0 (*(uint16*)(g_ram+0x5A4)) +#define message_box_animation_y1 (*(uint16*)(g_ram+0x5A6)) +#define message_box_animation_y2 (*(uint16*)(g_ram+0x5A8)) +#define message_box_animation_y3 (*(uint16*)(g_ram+0x5AA)) +#define map_min_x_scroll (*(uint16*)(g_ram+0x5AC)) +#define map_max_x_scroll (*(uint16*)(g_ram+0x5AE)) +#define map_min_y_scroll (*(uint16*)(g_ram+0x5B0)) +#define map_max_y_scroll (*(uint16*)(g_ram+0x5B2)) +#define waiting_for_nmi (*(uint8*)(g_ram+0x5B4)) +#define nmi_frame_counter_byte (*(uint8*)(g_ram+0x5B5)) +#define nmi_frame_counter_word (*(uint16*)(g_ram+0x5B6)) +#define nmi_frame_counter_including_lag (*(uint16*)(g_ram+0x5B8)) +#define nmi_frames_missed (*(uint8*)(g_ram+0x5BA)) +#define nmi_frames_missed_max (*(uint8*)(g_ram+0x5BB)) +#define door_transition_vram_update_enabled (*(uint16*)(g_ram+0x5BC)) +#define door_transition_vram_update_dst (*(uint16*)(g_ram+0x5BE)) +#define door_transition_vram_update_src (*(LongPtr*)(g_ram+0x5C0)) +#define door_transition_vram_update_size (*(uint16*)(g_ram+0x5C3)) +#define joypad_dbg_1 (*(uint16*)(g_ram+0x5C5)) +#define joypad_dbg_2 (*(uint16*)(g_ram+0x5C7)) +#define joypad_dbg_missiles_swap (*(uint16*)(g_ram+0x5C9)) +#define joypad_dbg_super_missiles_swap (*(uint16*)(g_ram+0x5CB)) +#define joypad_dbg_power_bombs_swap (*(uint16*)(g_ram+0x5CD)) +#define joypad_dbg_flags (*(uint16*)(g_ram+0x5CF)) +#define enable_debug (*(uint16*)(g_ram+0x5D1)) +#define debug_saveload_scrollpos_toggle (*(uint16*)(g_ram+0x5D3)) +#define debug_saved_xscroll (*(uint16*)(g_ram+0x5D5)) +#define debug_saved_yscroll (*(uint16*)(g_ram+0x5D7)) +#define joypad_released_keys (*(uint16*)(g_ram+0x5D9)) +#define timed_held_input_timer (*(uint16*)(g_ram+0x5DB)) +#define timed_held_input_timer_reset (*(uint16*)(g_ram+0x5DD)) +#define timed_held_input (*(uint16*)(g_ram+0x5DF)) +#define newly_held_down_timed_held_input (*(uint16*)(g_ram+0x5E1)) +#define previous_timed_held_input (*(uint16*)(g_ram+0x5E3)) +#define random_number (*(uint16*)(g_ram+0x5E5)) +#define bitmask (*(uint16*)(g_ram+0x5E7)) +#define mult_tmp_a (*(uint16*)(g_ram+0x5E9)) +#define mult_tmp_y (*(uint16*)(g_ram+0x5EB)) +#define mult_product_lo (*(uint16*)(g_ram+0x5F1)) +#define mult_product_hi (*(uint16*)(g_ram+0x5F3)) +#define debug_disable_sounds (*(uint16*)(g_ram+0x5F5)) +#define debug_disable_minimap (*(uint16*)(g_ram+0x5F7)) +#define save_confirmation_selection (*(uint16*)(g_ram+0x5F9)) +#define map_scrolling_gear_switch_timer (*(uint16*)(g_ram+0x5FB)) +#define map_scrolling_direction (*(uint16*)(g_ram+0x5FD)) +#define map_scrolling_speed_index (*(uint16*)(g_ram+0x5FF)) +#define pause_hook (*(LongPtr*)(g_ram+0x601)) +#define unpause_hook (*(LongPtr*)(g_ram+0x604)) +#define earthquake_sfx_index (*(uint16*)(g_ram+0x607)) +#define earthquake_sfx_timer (*(uint16*)(g_ram+0x609)) +#define remaining_enemy_spritemap_entries (*(uint16*)(g_ram+0x60B)) +#define remaining_enemy_hitbox_entries (*(uint16*)(g_ram+0x60D)) +#define num_projectiles_to_check_enemy_coll (*(uint16*)(g_ram+0x60F)) +#define is_uploading_apu (*(uint16*)(g_ram+0x617)) +#define music_queue_track ((uint16*)(g_ram+0x619)) +#define music_queue_delay ((uint16*)(g_ram+0x629)) +#define music_queue_write_pos (*(uint16*)(g_ram+0x639)) +#define music_queue_read_pos (*(uint16*)(g_ram+0x63B)) +#define music_entry (*(uint16*)(g_ram+0x63D)) +#define music_timer (*(uint16*)(g_ram+0x63F)) +#define apu_attempts_countdown (*(uint16*)(g_ram+0x641)) +#define sfx_readpos ((uint8*)(g_ram+0x643)) +#define sfx_writepos ((uint8*)(g_ram+0x646)) +#define sfx_state ((uint8*)(g_ram+0x649)) +#define cur_music_track (*(uint8*)(g_ram+0x64C)) +#define sfx_cur ((uint8*)(g_ram+0x64D)) +#define sfx_clear_delay ((uint8*)(g_ram+0x650)) +#define sfx_max_queued ((uint8*)(g_ram+0x653)) +#define sfx1_queue ((uint8*)(g_ram+0x656)) +#define sfx2_queue ((uint8*)(g_ram+0x666)) +#define sfx3_queue ((uint8*)(g_ram+0x676)) +#define sound_handler_downtime (*(uint16*)(g_ram+0x686)) +#define g_byte_7E0688 (*(uint8*)(g_ram+0x688)) +#define g_word_7E068A (*(uint16*)(g_ram+0x68A)) +#define g_byte_7E068C (*(uint8*)(g_ram+0x68C)) +#define g_word_7E068E (*(uint16*)(g_ram+0x68E)) +#define g_word_7E0690 (*(uint16*)(g_ram+0x690)) +#define g_word_7E0692 (*(uint16*)(g_ram+0x692)) +#define g_word_7E0694 (*(uint16*)(g_ram+0x694)) +#define g_word_7E0696 (*(uint16*)(g_ram+0x696)) +#define g_word_7E0698 (*(uint16*)(g_ram+0x698)) +#define g_word_7E069A (*(uint16*)(g_ram+0x69A)) +#define g_byte_7E069C ((uint8*)(g_ram+0x69C)) +#define UNUSED_byte_7E071C (*(uint8*)(g_ram+0x71C)) +#define nmi_copy_samus_halves (*(uint16*)(g_ram+0x71D)) +#define nmi_copy_samus_top_half_src (*(uint16*)(g_ram+0x71F)) +#define nmi_copy_samus_bottom_half_src (*(uint16*)(g_ram+0x721)) +#define screen_fade_delay (*(uint16*)(g_ram+0x723)) +#define screen_fade_counter (*(uint16*)(g_ram+0x725)) +#define menu_index (*(uint16*)(g_ram+0x727)) +#define pausemenu_start_lr_pressed_highlight_timer (*(uint16*)(g_ram+0x729)) +#define pausemenu_lr_animation_timer (*(uint16*)(g_ram+0x72B)) +#define pausemenu_item_selector_animation_timer (*(uint16*)(g_ram+0x72D)) +#define pausemenu_reserve_tank_animation_timer (*(uint16*)(g_ram+0x72F)) +#define UNUSED_word_7E0731 (*(uint16*)(g_ram+0x731)) +#define pausemenu_uparrow_animation_timer (*(uint16*)(g_ram+0x733)) +#define pausemenu_downarrow_animation_timer (*(uint16*)(g_ram+0x735)) +#define pausemenu_rightarrow_animation_timer (*(uint16*)(g_ram+0x737)) +#define pausemenu_leftarrow_animation_timer (*(uint16*)(g_ram+0x739)) +#define pausemenu_palette_animation_timer (*(uint16*)(g_ram+0x73B)) +#define UNUSED_word_7E073D (*(uint16*)(g_ram+0x73D)) +#define pausemenu_lr_animation_frame (*(uint16*)(g_ram+0x73F)) +#define pausemenu_item_selector_animation_frame (*(uint16*)(g_ram+0x741)) +#define pausemenu_reserve_tank_animation_frame (*(uint16*)(g_ram+0x743)) +#define UNUSED_word_7E0745 (*(uint16*)(g_ram+0x745)) +#define pausemenu_uparrow_animation_frame (*(uint16*)(g_ram+0x747)) +#define pausemenu_downarrow_animation_frame (*(uint16*)(g_ram+0x749)) +#define pausemenu_rightarrow_animation_frame (*(uint16*)(g_ram+0x74B)) +#define pausemenu_leftarrow_animation_frame (*(uint16*)(g_ram+0x74D)) +#define pausemenu_palette_animation_frame (*(uint16*)(g_ram+0x74F)) +#define pausemenu_shoulder_button_highlight (*(uint16*)(g_ram+0x751)) +#define pausemenu_button_label_mode (*(uint16*)(g_ram+0x753)) +#define pausemenu_equipment_category_item (*(uint16*)(g_ram+0x755)) +#define pausemenu_reserve_tank_delay_ctr (*(uint16*)(g_ram+0x757)) +#define UNUSED_word_7E0759 (*(uint16*)(g_ram+0x759)) +#define UNUSED_word_7E075B (*(uint16*)(g_ram+0x75B)) +#define UNUSED_word_7E075D (*(uint16*)(g_ram+0x75D)) +#define UNUSED_word_7E075F (*(uint16*)(g_ram+0x75F)) +#define UNUSED_word_7E0761 (*(uint16*)(g_ram+0x761)) +#define pause_screen_mode (*(uint16*)(g_ram+0x763)) +#define pausemenu_bak_BG1SC (*(uint8*)(g_ram+0x765)) +#define pausemenu_bak_BG2SC (*(uint8*)(g_ram+0x766)) +#define pausemenu_bak_BG3SC (*(uint8*)(g_ram+0x767)) +#define pausemenu_bak_BG12NBA (*(uint8*)(g_ram+0x768)) +#define pausemenu_bak_BG34NBA (*(uint8*)(g_ram+0x769)) +#define pausemenu_bak_OBSEL (*(uint8*)(g_ram+0x76A)) +#define pausemenu_bak_BG1HOFS (*(uint8*)(g_ram+0x76B)) +#define pausemenu_bak_BG2HOFS (*(uint8*)(g_ram+0x76C)) +#define pausemenu_bak_BG3HOFS (*(uint8*)(g_ram+0x76D)) +#define pausemenu_bak_BG1VOFS (*(uint8*)(g_ram+0x76E)) +#define pausemenu_bak_BG2VOFS (*(uint8*)(g_ram+0x76F)) +#define pausemenu_bak_BG3VOFS (*(uint8*)(g_ram+0x770)) +#define pausemenu_bak_BGMODE (*(uint8*)(g_ram+0x771)) +#define pausemenu_bak_layer2_scroll_x (*(uint8*)(g_ram+0x772)) +#define pausemenu_bak_layer2_scroll_y (*(uint8*)(g_ram+0x773)) +#define pausemenu_bak_MOSAIC (*(uint8*)(g_ram+0x774)) +#define pausemenu_bak_CGADSUB (*(uint8*)(g_ram+0x775)) +#define samus_position_indicator_animation_frame (*(uint16*)(g_ram+0x776)) +#define samus_position_indicator_animation_timer (*(uint16*)(g_ram+0x778)) +#define samus_position_indicator_animation_loop_counter (*(uint16*)(g_ram+0x77A)) +#define hud_item_tilemap_palette_bits (*(uint16*)(g_ram+0x77C)) +#define irq_enable_mode7 (*(uint16*)(g_ram+0x783)) +#define mode7_rotation_angle (*(uint16*)(g_ram+0x785)) +#define g_word_7E0787 (*(uint16*)(g_ram+0x787)) +#define has_area_map (*(uint16*)(g_ram+0x789)) +#define load_station_index (*(uint16*)(g_ram+0x78B)) +#define door_def_ptr (*(uint16*)(g_ram+0x78D)) +#define door_bts (*(uint16*)(g_ram+0x78F)) +#define door_direction (*(uint16*)(g_ram+0x791)) +#define elevator_door_properties_orientation (*(uint16*)(g_ram+0x793)) +#define door_transition_flag_elevator_zebetites (*(uint16*)(g_ram+0x795)) +#define door_transition_flag_enemies (*(uint16*)(g_ram+0x797)) +#define elevator_direction (*(uint16*)(g_ram+0x799)) +#define room_ptr (*(uint16*)(g_ram+0x79B)) +#define room_index (*(uint16*)(g_ram+0x79D)) +#define area_index (*(uint16*)(g_ram+0x79F)) +#define room_x_coordinate_on_map (*(uint16*)(g_ram+0x7A1)) +#define room_y_coordinate_on_map (*(uint16*)(g_ram+0x7A3)) +#define room_width_in_blocks (*(uint16*)(g_ram+0x7A5)) +#define room_height_in_blocks (*(uint16*)(g_ram+0x7A7)) +#define room_width_in_scrolls (*(uint16*)(g_ram+0x7A9)) +#define room_height_in_scrolls (*(uint16*)(g_ram+0x7AB)) +#define up_scroller (*(uint16*)(g_ram+0x7AD)) +#define down_scroller (*(uint16*)(g_ram+0x7AF)) +#define previous_cre_bitset (*(uint16*)(g_ram+0x7B1)) +#define cre_bitset (*(uint16*)(g_ram+0x7B3)) +#define door_list_pointer (*(uint16*)(g_ram+0x7B5)) +#define event_pointer (*(uint16*)(g_ram+0x7B7)) +#define room_size_in_blocks (*(uint16*)(g_ram+0x7B9)) +#define roomdefroomstate_ptr (*(uint16*)(g_ram+0x7BB)) +#define room_compr_level_data_ptr (*(LongPtr*)(g_ram+0x7BD)) +#define tileset_tile_table_pointer (*(LongPtr*)(g_ram+0x7C0)) +#define tileset_tiles_pointer (*(LongPtr*)(g_ram+0x7C3)) +#define tileset_compr_palette_ptr (*(LongPtr*)(g_ram+0x7C6)) +#define room_music_track_index (*(uint16*)(g_ram+0x7C9)) +#define room_music_data_index (*(uint16*)(g_ram+0x7CB)) +#define room_layer3_asm_ptr (*(uint16*)(g_ram+0x7CD)) +#define room_enemy_population_ptr (*(uint16*)(g_ram+0x7CF)) +#define room_enemy_tilesets_ptr (*(uint16*)(g_ram+0x7D1)) +#define room_main_code_ptr (*(uint16*)(g_ram+0x7DF)) +#define room_main_asm_variables ((uint8*)(g_ram+0x7E1)) +#define scrolling_finished_hook (*(uint16*)(g_ram+0x7E9)) +#define hdma_data_table_in_ceres (*(uint16*)(g_ram+0x7EB)) +#define music_data_index (*(uint16*)(g_ram+0x7F3)) +#define music_track_index (*(uint16*)(g_ram+0x7F5)) +#define map_tiles_explored ((uint8*)(g_ram+0x7F7)) +#define layer1_x_block (*(uint16*)(g_ram+0x8F7)) +#define layer1_y_block (*(uint16*)(g_ram+0x8F9)) +#define layer2_x_block (*(uint16*)(g_ram+0x8FB)) +#define layer2_y_block (*(uint16*)(g_ram+0x8FD)) +#define previous_layer1_x_block (*(uint16*)(g_ram+0x8FF)) +#define previous_layer1_y_block (*(uint16*)(g_ram+0x901)) +#define previous_layer2_x_block (*(uint16*)(g_ram+0x903)) +#define previous_layer2_y_block (*(uint16*)(g_ram+0x905)) +#define bg1_x_block (*(uint16*)(g_ram+0x907)) +#define bg1_y_block (*(uint16*)(g_ram+0x909)) +#define bg2_x_block (*(uint16*)(g_ram+0x90B)) +#define bg2_y_block (*(uint16*)(g_ram+0x90D)) +#define layer1_x_subpos (*(uint16*)(g_ram+0x90F)) +#define layer1_x_pos (*(uint16*)(g_ram+0x911)) +#define layer1_y_subpos (*(uint16*)(g_ram+0x913)) +#define layer1_y_pos (*(uint16*)(g_ram+0x915)) +#define layer2_x_pos (*(uint16*)(g_ram+0x917)) +#define layer2_y_pos (*(uint16*)(g_ram+0x919)) +#define layer2_scroll_x (*(uint8*)(g_ram+0x91B)) +#define layer2_scroll_y (*(uint8*)(g_ram+0x91C)) +#define bg1_x_offset (*(uint16*)(g_ram+0x91D)) +#define bg1_y_offset (*(uint16*)(g_ram+0x91F)) +#define bg2_x_scroll (*(uint16*)(g_ram+0x921)) +#define bg2_y_scroll (*(uint16*)(g_ram+0x923)) +#define door_transition_frame_counter (*(uint16*)(g_ram+0x925)) +#define door_destination_x_pos (*(uint16*)(g_ram+0x927)) +#define door_destination_y_pos (*(uint16*)(g_ram+0x929)) +#define samus_door_transition_subspeed (*(uint16*)(g_ram+0x92B)) +#define samus_door_transition_speed (*(uint16*)(g_ram+0x92D)) +#define downwards_elevator_delay_timer (*(uint16*)(g_ram+0x92F)) +#define door_transition_flag (*(uint16*)(g_ram+0x931)) +#define temp933 (*(uint16*)(g_ram+0x933)) +#define x_block_of_vram_blocks_to_update (*(uint16*)(g_ram+0x935)) +#define tmp_vram_base_addr (*(uint16*)(g_ram+0x937)) +#define loopcounter (*(uint16*)(g_ram+0x939)) +#define tmp_block_to_update (*(uint16*)(g_ram+0x93B)) +#define ceres_status (*(uint16*)(g_ram+0x93F)) +#define camera_distance_index (*(uint16*)(g_ram+0x941)) +#define timer_status (*(uint16*)(g_ram+0x943)) +#define timer_centiseconds (*(uint8*)(g_ram+0x945)) +#define timer_seconds (*(uint8*)(g_ram+0x946)) +#define timer_minutes (*(uint8*)(g_ram+0x947)) +#define timer_x_pos (*(uint16*)(g_ram+0x948)) +#define timer_y_pos (*(uint16*)(g_ram+0x94A)) +#define file_select_map_area_index (*(uint16*)(g_ram+0x950)) +#define selected_save_slot (*(uint16*)(g_ram+0x952)) +#define nonempty_save_slots (*(uint16*)(g_ram+0x954)) +#define bg1_update_col_unwrapped_size (*(uint16*)(g_ram+0x956)) +#define bg1_update_col_wrapped_size (*(uint16*)(g_ram+0x958)) +#define bg1_update_col_unwrapped_dst (*(uint16*)(g_ram+0x95A)) +#define bg1_update_col_wrapped_dst (*(uint16*)(g_ram+0x95C)) +#define bg1_update_col_wrapped_left_src (*(uint16*)(g_ram+0x95E)) +#define bg1_update_col_wrapped_right_src (*(uint16*)(g_ram+0x960)) +#define bg1_update_col_enable (*(uint16*)(g_ram+0x962)) +#define bg1_update_row_unwrapped_size (*(uint16*)(g_ram+0x964)) +#define bg1_update_row_wrapped_size (*(uint16*)(g_ram+0x966)) +#define bg1_update_row_unwrapped_dst (*(uint16*)(g_ram+0x968)) +#define bg1_update_row_wrapped_dst (*(uint16*)(g_ram+0x96A)) +#define bg1_update_row_wrapped_top_src (*(uint16*)(g_ram+0x96C)) +#define bg1_update_row_wrapped_bottom_src (*(uint16*)(g_ram+0x96E)) +#define bg1_update_row_enable (*(uint16*)(g_ram+0x970)) +#define bg2_update_col_unwrapped_size (*(uint16*)(g_ram+0x972)) +#define bg2_update_col_wrapped_size (*(uint16*)(g_ram+0x974)) +#define bg2_update_col_unwrapped_dst (*(uint16*)(g_ram+0x976)) +#define bg2_update_col_wrapped_dst (*(uint16*)(g_ram+0x978)) +#define bg2_update_col_wrapped_left_src (*(uint16*)(g_ram+0x97A)) +#define bg2_update_col_wrapped_right_src (*(uint16*)(g_ram+0x97C)) +#define bg2_update_col_enable (*(uint16*)(g_ram+0x97E)) +#define bg2_update_row_unwrapped_size (*(uint16*)(g_ram+0x980)) +#define bg2_update_row_wrapped_size (*(uint16*)(g_ram+0x982)) +#define bg2_update_row_unwrapped_dst (*(uint16*)(g_ram+0x984)) +#define bg2_update_row_wrapped_dst (*(uint16*)(g_ram+0x986)) +#define bg2_update_row_wrapped_top_src (*(uint16*)(g_ram+0x988)) +#define bg2_update_row_wrapped_bottom_src (*(uint16*)(g_ram+0x98A)) +#define bg2_update_row_enable (*(uint16*)(g_ram+0x98C)) +#define size_of_bg2 (*(uint16*)(g_ram+0x98E)) +#define blocks_to_update_x_block (*(uint16*)(g_ram+0x990)) +#define blocks_to_update_y_block (*(uint16*)(g_ram+0x992)) +#define vram_blocks_to_update_x_block (*(uint16*)(g_ram+0x994)) +#define vram_blocks_to_update_y_block (*(uint16*)(g_ram+0x996)) +#define game_state (*(uint16*)(g_ram+0x998)) +#define door_transition_function (*(uint16*)(g_ram+0x99C)) +#define menu_option_index (*(uint16*)(g_ram+0x99E)) +#define equipped_items (*(uint16*)(g_ram+0x9A2)) +#define collected_items (*(uint16*)(g_ram+0x9A4)) +#define equipped_beams (*(uint16*)(g_ram+0x9A6)) +#define collected_beams (*(uint16*)(g_ram+0x9A8)) +#define button_config_up (*(uint16*)(g_ram+0x9AA)) +#define button_config_down (*(uint16*)(g_ram+0x9AC)) +#define button_config_left (*(uint16*)(g_ram+0x9AE)) +#define button_config_right (*(uint16*)(g_ram+0x9B0)) +#define button_config_shoot_x (*(uint16*)(g_ram+0x9B2)) +#define button_config_jump_a (*(uint16*)(g_ram+0x9B4)) +#define button_config_run_b (*(uint16*)(g_ram+0x9B6)) +#define button_config_itemcancel_y (*(uint16*)(g_ram+0x9B8)) +#define button_config_itemswitch (*(uint16*)(g_ram+0x9BA)) +#define button_config_aim_down_L (*(uint16*)(g_ram+0x9BC)) +#define button_config_aim_up_R (*(uint16*)(g_ram+0x9BE)) +#define reserve_health_mode (*(uint16*)(g_ram+0x9C0)) +#define samus_health (*(uint16*)(g_ram+0x9C2)) +#define samus_max_health (*(uint16*)(g_ram+0x9C4)) +#define samus_missiles (*(uint16*)(g_ram+0x9C6)) +#define samus_max_missiles (*(uint16*)(g_ram+0x9C8)) +#define samus_super_missiles (*(uint16*)(g_ram+0x9CA)) +#define samus_max_super_missiles (*(uint16*)(g_ram+0x9CC)) +#define samus_power_bombs (*(uint16*)(g_ram+0x9CE)) +#define samus_max_power_bombs (*(uint16*)(g_ram+0x9D0)) +#define hud_item_index (*(uint16*)(g_ram+0x9D2)) +#define samus_max_reserve_health (*(uint16*)(g_ram+0x9D4)) +#define samus_reserve_health (*(uint16*)(g_ram+0x9D6)) +#define samus_reserve_missiles (*(uint16*)(g_ram+0x9D8)) +#define game_time_frames (*(uint16*)(g_ram+0x9DA)) +#define game_time_seconds (*(uint16*)(g_ram+0x9DC)) +#define game_time_minutes (*(uint16*)(g_ram+0x9DE)) +#define game_time_hours (*(uint16*)(g_ram+0x9E0)) +#define japanese_text_flag (*(uint16*)(g_ram+0x9E2)) +#define moonwalk_flag (*(uint16*)(g_ram+0x9E4)) +#define debug_flag (*(uint16*)(g_ram+0x9E6)) +#define UNUSED_word_7E09E8 (*(uint16*)(g_ram+0x9E8)) +#define hud_auto_cancel_flag (*(uint16*)(g_ram+0x9EA)) +#define samus_auto_cancel_hud_item_index (*(uint16*)(g_ram+0xA04)) +#define samus_prev_health (*(uint16*)(g_ram+0xA06)) +#define samus_prev_missiles (*(uint16*)(g_ram+0xA08)) +#define samus_prev_super_missiles (*(uint16*)(g_ram+0xA0A)) +#define samus_prev_power_bombs (*(uint16*)(g_ram+0xA0C)) +#define samus_prev_hud_item_index (*(uint16*)(g_ram+0xA0E)) +#define samus_prev_movement_type (*(uint8*)(g_ram+0xA11)) +#define samus_prev_health_for_flash (*(uint16*)(g_ram+0xA12)) +#define controller1_input_for_demo (*(uint16*)(g_ram+0xA14)) +#define controller1_new_input_for_demo (*(uint16*)(g_ram+0xA16)) +#define UNUSED_word_7E0A18 (*(uint16*)(g_ram+0xA18)) +#define samus_pose (*(uint16*)(g_ram+0xA1C)) +#define samus_pose_x_dir (*(uint8*)(g_ram+0xA1E)) +#define samus_movement_type (*(uint8*)(g_ram+0xA1F)) +#define samus_prev_pose (*(uint16*)(g_ram+0xA20)) +#define samus_prev_pose_x_dir (*(uint8*)(g_ram+0xA22)) +#define samus_prev_movement_type2 (*(uint8*)(g_ram+0xA23)) +#define samus_last_different_pose (*(uint16*)(g_ram+0xA24)) +#define samus_last_different_pose_x_dir (*(uint8*)(g_ram+0xA26)) +#define samus_last_different_pose_movement_type (*(uint8*)(g_ram+0xA27)) +#define samus_new_pose (*(uint16*)(g_ram+0xA28)) +#define samus_new_pose_interrupted (*(uint16*)(g_ram+0xA2A)) +#define samus_new_pose_transitional (*(uint16*)(g_ram+0xA2C)) +#define samus_momentum_routine_index (*(uint16*)(g_ram+0xA2E)) +#define samus_special_transgfx_index (*(uint16*)(g_ram+0xA30)) +#define samus_hurt_switch_index (*(uint16*)(g_ram+0xA32)) +#define solid_enemy_collision_flags (*(uint16*)(g_ram+0xA34)) +#define block_collision_flags (*(uint16*)(g_ram+0xA36)) +#define samus_space_to_move_up_blocks (*(uint16*)(g_ram+0xA38)) +#define samus_y_radius_diff (*(uint16*)(g_ram+0xA3A)) +#define samus_space_to_move_down_blocks (*(uint16*)(g_ram+0xA3C)) +#define samus_space_to_move_up_enemy (*(uint16*)(g_ram+0xA3E)) +#define samus_space_to_move_down_enemy (*(uint16*)(g_ram+0xA40)) +#define frame_handler_alfa (*(uint16*)(g_ram+0xA42)) +#define frame_handler_beta (*(uint16*)(g_ram+0xA44)) +#define enable_horiz_slope_coll (*(uint16*)(g_ram+0xA46)) +#define samus_hurt_flash_counter (*(uint16*)(g_ram+0xA48)) +#define samus_special_super_palette_flags (*(uint16*)(g_ram+0xA4A)) +#define samus_subunit_health (*(uint16*)(g_ram+0xA4C)) +#define samus_periodic_subdamage (*(uint16*)(g_ram+0xA4E)) +#define samus_periodic_damage (*(uint16*)(g_ram+0xA50)) +#define knockback_dir (*(uint16*)(g_ram+0xA52)) +#define knockback_x_dir (*(uint16*)(g_ram+0xA54)) +#define bomb_jump_dir (*(uint16*)(g_ram+0xA56)) +#define samus_movement_handler (*(uint16*)(g_ram+0xA58)) +#define frame_handler_gamma (*(uint16*)(g_ram+0xA5A)) +#define samus_draw_handler (*(uint16*)(g_ram+0xA5C)) +#define UNUSED_word_7E0A5E (*(uint16*)(g_ram+0xA5E)) +#define samus_input_handler (*(uint16*)(g_ram+0xA60)) +#define samus_var62 (*(uint16*)(g_ram+0xA62)) +#define samus_grapple_flags (*(uint16*)(g_ram+0xA64)) +#define samus_x_speed_divisor (*(uint16*)(g_ram+0xA66)) +#define samus_shine_timer (*(uint16*)(g_ram+0xA68)) +#define samus_health_warning (*(uint16*)(g_ram+0xA6A)) +#define samus_x_speed_table_pointer (*(uint16*)(g_ram+0xA6C)) +#define samus_contact_damage_index (*(uint16*)(g_ram+0xA6E)) +#define samus_visor_palette_timer_index (*(uint16*)(g_ram+0xA72)) +#define samus_suit_palette_index (*(uint16*)(g_ram+0xA74)) +#define hyper_beam_flag (*(uint16*)(g_ram+0xA76)) +#define time_is_frozen_flag (*(uint16*)(g_ram+0xA78)) +#define demo_input_pre_instr (*(uint16*)(g_ram+0xA7A)) +#define demo_input_instr_timer (*(uint16*)(g_ram+0xA7C)) +#define demo_input_instr_ptr (*(uint16*)(g_ram+0xA7E)) +#define demo_timer_counter (*(uint16*)(g_ram+0xA80)) +#define xray_angle (*(uint16*)(g_ram+0xA82)) +#define demo_input (*(uint16*)(g_ram+0xA84)) +#define demo_input_new (*(uint16*)(g_ram+0xA86)) +#define demo_enable (*(uint16*)(g_ram+0xA88)) +#define demo_num_input_frames (*(uint16*)(g_ram+0xA8A)) +#define demo_input_prev (*(uint16*)(g_ram+0xA8C)) +#define demo_input_prev_new (*(uint16*)(g_ram+0xA8E)) +#define demo_backup_prev_controller_input (*(uint16*)(g_ram+0xA90)) +#define demo_backup_prev_controller_input_new (*(uint16*)(g_ram+0xA92)) +#define samus_anim_frame_timer (*(uint16*)(g_ram+0xA94)) +#define samus_anim_frame (*(uint16*)(g_ram+0xA96)) +#define samus_anim_frame_skip (*(uint16*)(g_ram+0xA9A)) +#define samus_anim_frame_buffer (*(uint16*)(g_ram+0xA9C)) +#define grapple_walljump_timer (*(uint16*)(g_ram+0xA9E)) +#define reached_ceres_elevator_fade_timer (*(uint16*)(g_ram+0xAA0)) +#define timer_for_shinesparks_startstop (*(uint16*)(g_ram+0xAA2)) +#define UNUSEDword_7E0AA4 (*(uint16*)(g_ram+0xAA4)) +#define flag_arm_cannon_open_or_opening (*(uint8*)(g_ram+0xAA6)) +#define flag_arm_cannon_opening_or_closing (*(uint8*)(g_ram+0xAA7)) +#define arm_cannon_frame (*(uint16*)(g_ram+0xAA8)) +#define hud_item_changed_this_frame (*(uint16*)(g_ram+0xAAA)) +#define arm_cannon_drawing_mode (*(uint16*)(g_ram+0xAAC)) +#define speed_echoes_index (*(uint16*)(g_ram+0xAAE)) +#define speed_echo_xpos ((uint16*)(g_ram+0xAB0)) +#define speed_echo_ypos ((uint16*)(g_ram+0xAB8)) +#define speed_echo_xspeed ((uint16*)(g_ram+0xAC0)) +#define samus_top_half_spritemap_index (*(uint16*)(g_ram+0xAC8)) +#define samus_bottom_half_spritemap_index (*(uint16*)(g_ram+0xACA)) +#define timer_for_shine_timer (*(uint16*)(g_ram+0xACC)) +#define special_samus_palette_frame (*(uint16*)(g_ram+0xACE)) +#define special_samus_palette_timer (*(uint16*)(g_ram+0xAD0)) +#define liquid_physics_type (*(uint16*)(g_ram+0xAD2)) +#define atmospheric_gfx_anim_timer ((uint16*)(g_ram+0xAD4)) +#define atmospheric_gfx_x_pos ((uint16*)(g_ram+0xADC)) +#define atmospheric_gfx_y_pos ((uint16*)(g_ram+0xAE4)) +#define atmospheric_gfx_frame_and_type ((uint16*)(g_ram+0xAEC)) +#define autojump_timer (*(uint16*)(g_ram+0xAF4)) +#define samus_x_pos (*(uint16*)(g_ram+0xAF6)) +#define samus_x_subpos (*(uint16*)(g_ram+0xAF8)) +#define samus_y_pos (*(uint16*)(g_ram+0xAFA)) +#define samus_y_subpos (*(uint16*)(g_ram+0xAFC)) +#define samus_x_radius (*(uint16*)(g_ram+0xAFE)) +#define samus_y_radius (*(uint16*)(g_ram+0xB00)) +#define samus_collision_direction (*(uint16*)(g_ram+0xB02)) +#define samus_spritemap_x_pos (*(uint16*)(g_ram+0xB04)) +#define samus_spritemap_y_pos (*(uint16*)(g_ram+0xB06)) +#define ideal_layer1_xpos (*(uint16*)(g_ram+0xB0A)) +#define ideal_layer1_ypos (*(uint16*)(g_ram+0xB0E)) +#define samus_prev_x_pos (*(uint16*)(g_ram+0xB10)) +#define samus_prev_x_subpos (*(uint16*)(g_ram+0xB12)) +#define samus_prev_y_pos (*(uint16*)(g_ram+0xB14)) +#define samus_prev_y_subpos (*(uint16*)(g_ram+0xB16)) +#define charged_shot_glow_timer (*(uint16*)(g_ram+0xB18)) +#define UNUSED_word_7E0B1A (*(uint16*)(g_ram+0xB1A)) +#define used_for_ball_bounce_on_landing (*(uint16*)(g_ram+0xB20)) +#define samus_is_falling_flag (*(uint16*)(g_ram+0xB22)) +#define tempB24 (*(uint16*)(g_ram+0xB24)) +#define tempB26 (*(uint16*)(g_ram+0xB26)) +#define UNUSED_word_7E0B2A (*(uint16*)(g_ram+0xB2A)) +#define samus_y_subspeed (*(uint16*)(g_ram+0xB2C)) +#define samus_y_speed (*(uint16*)(g_ram+0xB2E)) +#define samus_y_subaccel (*(uint16*)(g_ram+0xB32)) +#define samus_y_accel (*(uint16*)(g_ram+0xB34)) +#define samus_y_dir (*(uint16*)(g_ram+0xB36)) +#define UNUSED_word_7E0B38 (*(uint16*)(g_ram+0xB38)) +#define samus_has_momentum_flag (*(uint16*)(g_ram+0xB3C)) +#define speed_boost_counter (*(uint16*)(g_ram+0xB3E)) +#define samus_echoes_sound_flag (*(uint16*)(g_ram+0xB40)) +#define samus_x_extra_run_speed (*(uint16*)(g_ram+0xB42)) +#define samus_x_extra_run_subspeed (*(uint16*)(g_ram+0xB44)) +#define samus_x_base_speed (*(uint16*)(g_ram+0xB46)) +#define samus_x_base_subspeed (*(uint16*)(g_ram+0xB48)) +#define samus_x_accel_mode (*(uint16*)(g_ram+0xB4A)) +#define samus_x_decel_mult (*(uint8*)(g_ram+0xB4C)) +#define extra_samus_x_subdisplacement (*(uint16*)(g_ram+0xB56)) +#define extra_samus_x_displacement (*(uint16*)(g_ram+0xB58)) +#define extra_samus_y_subdisplacement (*(uint16*)(g_ram+0xB5A)) +#define extra_samus_y_displacement (*(uint16*)(g_ram+0xB5C)) +#define new_projectile_direction_changed_pose (*(uint16*)(g_ram+0xB5E)) +#define used_for_sba_attacksB60 (*(uint16*)(g_ram+0xB60)) +#define samus_charge_palette_index (*(uint16*)(g_ram+0xB62)) +#define projectile_x_pos ((uint16*)(g_ram+0xB64)) +#define projectile_y_pos ((uint16*)(g_ram+0xB78)) +#define projectile_bomb_x_subpos ((uint16*)(g_ram+0xB8C)) +#define projectile_bomb_y_subpos ((uint16*)(g_ram+0xBA0)) +#define projectile_x_radius ((uint16*)(g_ram+0xBB4)) +#define projectile_y_radius ((uint16*)(g_ram+0xBC8)) +#define projectile_bomb_x_speed ((uint16*)(g_ram+0xBDC)) +#define projectile_bomb_y_speed ((uint16*)(g_ram+0xBF0)) +#define projectile_dir ((uint16*)(g_ram+0xC04)) +#define projectile_type ((uint16*)(g_ram+0xC18)) +#define projectile_damage ((uint16*)(g_ram+0xC2C)) +#define projectile_bomb_instruction_ptr ((uint16*)(g_ram+0xC40)) +#define projectile_bomb_instruction_timers ((uint16*)(g_ram+0xC54)) +#define projectile_bomb_pre_instructions ((uint16*)(g_ram+0xC68)) +#define bomb_functions ((uint16*)(g_ram+0xC72)) +#define projectile_variables ((uint16*)(g_ram+0xC7C)) +#define bomb_timers ((uint16*)(g_ram+0xC86)) +#define projectile_timers ((uint16*)(g_ram+0xC90)) +#define bomb_subspeeds ((uint16*)(g_ram+0xC9A)) +#define projectile_unk_A ((uint16*)(g_ram+0xCA4)) +#define projectile_spritemap_pointers ((uint16*)(g_ram+0xCB8)) +#define cooldown_timer (*(uint16*)(g_ram+0xCCC)) +#define projectile_counter (*(uint16*)(g_ram+0xCCE)) +#define flare_counter (*(uint16*)(g_ram+0xCD0)) +#define bomb_counter (*(uint16*)(g_ram+0xCD2)) +#define bomb_spread_charge_timeout_counter (*(uint16*)(g_ram+0xCD4)) +#define flare_animation_frame (*(uint16*)(g_ram+0xCD6)) +#define flare_slow_sparks_anim_frame (*(uint16*)(g_ram+0xCD8)) +#define flare_fast_sparks_anim_frame (*(uint16*)(g_ram+0xCDA)) +#define flare_animation_timer (*(uint16*)(g_ram+0xCDC)) +#define flare_slow_sparks_anim_timer (*(uint16*)(g_ram+0xCDE)) +#define flare_fast_sparks_anim_timer (*(uint16*)(g_ram+0xCE0)) +#define power_bomb_explosion_x_pos (*(uint16*)(g_ram+0xCE2)) +#define power_bomb_explosion_y_pos (*(uint16*)(g_ram+0xCE4)) +#define power_bomb_explosion_x_pos_plus_0x100 (*(uint16*)(g_ram+0xCE6)) +#define power_bomb_explosion_y_pos_rsub_0x1ff (*(uint16*)(g_ram+0xCE8)) +#define power_bomb_explosion_radius (*(uint16*)(g_ram+0xCEA)) +#define power_bomb_pre_explosion_flash_radius (*(uint16*)(g_ram+0xCEC)) +#define power_bomb_flag (*(uint16*)(g_ram+0xCEE)) +#define power_bomb_pre_explosion_radius_speed (*(uint16*)(g_ram+0xCF0)) +#define pre_scaled_power_bomb_explosion_shape_def_ptr (*(uint16*)(g_ram+0xCF2)) +#define grapple_beam_flags (*(uint16*)(g_ram+0xCF4)) +#define grapple_varCF6 (*(uint16*)(g_ram+0xCF6)) +#define slow_grabble_scrolling_flag (*(uint16*)(g_ram+0xCF8)) +#define grapple_beam_end_subangle (*(uint8*)(g_ram+0xCFA)) +#define grapple_beam_end_angle (*(uint8*)(g_ram+0xCFB)) +#define grapple_beam_end_angles_mirror (*(uint16*)(g_ram+0xCFC)) +#define grapple_beam_length (*(uint16*)(g_ram+0xCFE)) +#define grapple_beam_length_delta (*(uint16*)(g_ram+0xD00)) +#define grapple_beam_origin_x_offset (*(uint16*)(g_ram+0xD02)) +#define grapple_beam_origin_y_offset (*(uint16*)(g_ram+0xD04)) +#define grapple_beam_end_x_subpos (*(uint16*)(g_ram+0xD06)) +#define grapple_beam_end_x_pos (*(uint16*)(g_ram+0xD08)) +#define grapple_beam_end_y_subpos (*(uint16*)(g_ram+0xD0A)) +#define grapple_beam_end_y_pos (*(uint16*)(g_ram+0xD0C)) +#define grapple_beam_end_x_suboffset (*(uint16*)(g_ram+0xD0E)) +#define grapple_beam_end_x_offset (*(uint16*)(g_ram+0xD10)) +#define grapple_beam_end_y_suboffset (*(uint16*)(g_ram+0xD12)) +#define grapple_beam_end_y_offset (*(uint16*)(g_ram+0xD14)) +#define x_pos_of_start_of_grapple_beam (*(uint16*)(g_ram+0xD16)) +#define y_pos_of_start_of_grapple_beam (*(uint16*)(g_ram+0xD18)) +#define x_pos_of_start_of_grapple_beam_prevframe (*(uint16*)(g_ram+0xD1A)) +#define y_pos_of_start_of_grapple_beam_prevframe (*(uint16*)(g_ram+0xD1C)) +#define grapple_beam_unkD1E (*(uint16*)(g_ram+0xD1E)) +#define grapple_beam_unkD20 (*(uint16*)(g_ram+0xD20)) +#define grapple_beam_extension_x_velocity (*(uint16*)(g_ram+0xD22)) +#define grapple_beam_extension_y_velocity (*(uint16*)(g_ram+0xD24)) +#define grapple_beam_unkD26 (*(uint16*)(g_ram+0xD26)) +#define grapple_beam_unkD28 (*(uint16*)(g_ram+0xD28)) +#define grapple_beam_unkD2A (*(uint16*)(g_ram+0xD2A)) +#define grapple_beam_unkD2C (*(uint16*)(g_ram+0xD2C)) +#define grapple_beam_unkD2E (*(uint16*)(g_ram+0xD2E)) +#define grapple_beam_unkD30 (*(uint16*)(g_ram+0xD30)) +#define grapple_beam_function (*(uint16*)(g_ram+0xD32)) +#define grapple_beam_direction (*(uint16*)(g_ram+0xD34)) +#define grapple_beam_unkD36 (*(uint16*)(g_ram+0xD36)) +#define grapple_beam_unkD38 (*(uint16*)(g_ram+0xD38)) +#define grapple_beam_unkD3A (*(uint16*)(g_ram+0xD3A)) +#define grapple_beam_unkD3C (*(uint16*)(g_ram+0xD3C)) +#define grapple_point_anim_timer (*(uint16*)(g_ram+0xD3E)) +#define grapple_point_anim_ptr (*(uint16*)(g_ram+0xD40)) +#define grapple_segment_anim_instr_timers ((uint16*)(g_ram+0xD42)) +#define grapple_segment_anim_instr_ptrs ((uint16*)(g_ram+0xD62)) +#define grapple_beam_tmpD82 (*(uint16*)(g_ram+0xD82)) +#define grapple_beam_tmpD84 (*(uint16*)(g_ram+0xD84)) +#define grapple_beam_y_quarter_subvel (*(uint16*)(g_ram+0xD86)) +#define grapple_beam_y_quarter_vel (*(uint16*)(g_ram+0xD88)) +#define grapple_beam_tmpD8A (*(uint16*)(g_ram+0xD8A)) +#define grapple_beam_varD8C (*(uint16*)(g_ram+0xD8C)) +#define grapple_beam_varD8E (*(uint16*)(g_ram+0xD8E)) +#define grapple_beam_grapple_start_x (*(uint16*)(g_ram+0xD90)) +#define grapple_beam_grapple_start_y (*(uint16*)(g_ram+0xD92)) +#define grapple_beam_grapple_start_block_x (*(uint16*)(g_ram+0xD94)) +#define grapple_beam_grapple_start_block_y (*(uint16*)(g_ram+0xD96)) +#define g_word_7E0D98 (*(uint16*)(g_ram+0xD98)) +#define g_word_7E0D9C (*(uint16*)(g_ram+0xD9C)) +#define g_byte_7E0D9E (*(uint8*)(g_ram+0xD9E)) +#define g_byte_7E0D9F (*(uint8*)(g_ram+0xD9F)) +#define loop_counter_transfer_enemies_to_vram (*(uint16*)(g_ram+0xDA0)) +#define absolute_moved_last_frame_x (*(uint16*)(g_ram+0xDA2)) +#define absolute_moved_last_frame_x_fract (*(uint16*)(g_ram+0xDA4)) +#define absolute_moved_last_frame_y (*(uint16*)(g_ram+0xDA6)) +#define absolute_moved_last_frame_y_fract (*(uint16*)(g_ram+0xDA8)) +#define projectile_init_speed_samus_moved_left (*(uint16*)(g_ram+0xDAA)) +#define projectile_init_speed_samus_moved_left_fract (*(uint16*)(g_ram+0xDAC)) +#define projectile_init_speed_samus_moved_right (*(uint16*)(g_ram+0xDAE)) +#define projectile_init_speed_samus_moved_right_fract (*(uint16*)(g_ram+0xDB0)) +#define projectile_init_speed_samus_moved_up (*(uint16*)(g_ram+0xDB2)) +#define projectile_init_speed_samus_moved_up_fract (*(uint16*)(g_ram+0xDB4)) +#define projectile_init_speed_samus_moved_down (*(uint16*)(g_ram+0xDB6)) +#define projectile_init_speed_samus_moved_down_fract (*(uint16*)(g_ram+0xDB8)) +#define samus_pos_adjusted_by_slope_flag (*(uint16*)(g_ram+0xDBA)) +#define samus_total_x_speed (*(uint16*)(g_ram+0xDBC)) +#define samus_total_x_subspeed (*(uint16*)(g_ram+0xDBE)) +#define play_resume_charging_beam_sfx (*(uint16*)(g_ram+0xDC0)) +#define prev_beam_charge_counter (*(uint16*)(g_ram+0xDC2)) +#define cur_block_index (*(uint16*)(g_ram+0xDC4)) +#define input_to_pose_calc (*(uint16*)(g_ram+0xDC6)) +#define queued_message_box_index (*(uint16*)(g_ram+0xDC8)) +#define samus_collides_with_solid_enemy (*(uint16*)(g_ram+0xDCE)) +#define samus_collision_flag (*(uint16*)(g_ram+0xDD0)) +#define temp_collision_DD2 (*(uint16*)(g_ram+0xDD2)) +#define temp_collision_DD4 (*(uint16*)(g_ram+0xDD4)) +#define temp_collision_DD6 (*(uint16*)(g_ram+0xDD6)) +#define suit_pickup_light_beam_widening_speed (*(uint16*)(g_ram+0xDDC)) +#define projectile_index (*(uint16*)(g_ram+0xDDE)) +#define debug_invincibility (*(uint16*)(g_ram+0xDE0)) +#define game_options_screen_index (*(uint16*)(g_ram+0xDE2)) +#define g_word_7E0DE4 (*(uint16*)(g_ram+0xDE4)) +#define g_word_7E0DE6 (*(uint16*)(g_ram+0xDE6)) +#define g_word_7E0DE8 (*(uint16*)(g_ram+0xDE8)) +#define which_item_to_pickup (*(uint16*)(g_ram+0xDEA)) +#define substate (*(uint16*)(g_ram+0xDEC)) +#define suit_pickup_light_beam_pos (*(uint16*)(g_ram+0xDEE)) +#define suit_pickup_color_math_R (*(uint8*)(g_ram+0xDF0)) +#define suit_pickup_color_math_G (*(uint8*)(g_ram+0xDF1)) +#define suit_pickup_color_math_B (*(uint8*)(g_ram+0xDF2)) +#define suit_pickup_palette_transition_color (*(uint8*)(g_ram+0xDF3)) +#define debug_spare_cpu_display_flag (*(uint16*)(g_ram+0xDF4)) +#define g_word_7E0DF6 (*(uint16*)(g_ram+0xDF6)) +#define UNUSED_word_7E0DF8 (*(uint16*)(g_ram+0xDF8)) +#define UNUSED_word_7E0DFA (*(uint16*)(g_ram+0xDFA)) +#define UNUSED_word_7E0DFC (*(uint16*)(g_ram+0xDFC)) +#define joypad1_input_samusfilter (*(uint16*)(g_ram+0xDFE)) +#define joypad1_newinput_samusfilter (*(uint16*)(g_ram+0xE00)) +#define samus_bottom_boundary_position (*(uint16*)(g_ram+0xE02)) +#define distance_to_eject_samus_left (*(uint16*)(g_ram+0xE04)) +#define distance_to_eject_samus_right (*(uint16*)(g_ram+0xE06)) +#define distance_to_eject_samus_up (*(uint16*)(g_ram+0xE08)) +#define distance_to_eject_samus_down (*(uint16*)(g_ram+0xE0A)) +#define g_byte_7E0E0C ((uint8*)(g_ram+0xE0C)) +#define debug_disable_sprite_interact (*(uint16*)(g_ram+0xE12)) +#define elevator_flags (*(uint16*)(g_ram+0xE16)) +#define elevator_status (*(uint16*)(g_ram+0xE18)) +#define health_drop_bias_flag (*(uint16*)(g_ram+0xE1A)) +#define enemy_index_to_shake (*(uint16*)(g_ram+0xE1C)) +#define nmi_flag_bg2_enemy_vram_transfer (*(uint16*)(g_ram+0xE1E)) +#define enemy_population_ptr (*(uint16*)(g_ram+0xE20)) +#define draw_oam_x_offset (*(uint16*)(g_ram+0xE22)) +#define varE24 (*(uint16*)(g_ram+0xE24)) +#define varE26 (*(uint16*)(g_ram+0xE26)) +#define varE28 (*(uint16*)(g_ram+0xE28)) +#define varE2A (*(uint16*)(g_ram+0xE2A)) +#define varE2C (*(uint16*)(g_ram+0xE2C)) +#define varE2E (*(uint16*)(g_ram+0xE2E)) +#define draw_enemy_layer (*(uint16*)(g_ram+0xE32)) +#define enemy_drawing_queue_index (*(uint16*)(g_ram+0xE34)) +#define loop_index_end (*(uint16*)(g_ram+0xE36)) +#define loop_index (*(uint16*)(g_ram+0xE38)) +#define enemy_drawing_queue_base (*(uint16*)(g_ram+0xE3A)) +#define g_word_7E0E3C (*(uint16*)(g_ram+0xE3C)) +#define g_word_7E0E3E (*(uint16*)(g_ram+0xE3E)) +#define enemy_damage_multiplier (*(uint16*)(g_ram+0xE40)) +#define enemy_damage_routine_exec_count (*(uint16*)(g_ram+0xE44)) +#define UNUSED_word_7E0E46 (*(uint16*)(g_ram+0xE46)) +#define UNUSED_word_7E0E48 (*(uint16*)(g_ram+0xE48)) +#define new_enemy_index (*(uint16*)(g_ram+0xE4A)) +#define first_free_enemy_index (*(uint16*)(g_ram+0xE4C)) +#define num_enemies_in_room (*(uint16*)(g_ram+0xE4E)) +#define num_enemies_killed_in_room (*(uint16*)(g_ram+0xE50)) +#define num_enemy_deaths_left_to_clear (*(uint16*)(g_ram+0xE52)) +#define cur_enemy_index (*(uint16*)(g_ram+0xE54)) +#define cur_enemy_index_backup (*(uint16*)(g_ram+0xE56)) +#define enemy_data_ptr (*(uint16*)(g_ram+0xE58)) +#define enemy_tile_load_data ((EnemyTileLoadData*)(g_ram+0xE5A)) +#define enemy_tile_load_data_write_pos (*(uint16*)(g_ram+0xE7A)) +#define enemy_tile_vram_src (*(uint16*)(g_ram+0xE7C)) +#define enemy_tile_vram_dst (*(uint16*)(g_ram+0xE7E)) +#define enemy_drawing_queue ((uint16*)(g_ram+0xE84)) +#define enemy_drawing_queue_sizes ((uint16*)(g_ram+0xF68)) +#define enemy_data ((EnemyData*)(g_ram+0xF78)) +#define fireflea_flashing_timer (*(uint16*)(g_ram+0x1778)) +#define fireflea_flashing_index (*(uint16*)(g_ram+0x177A)) +#define UNUSED_word_7E177C (*(uint16*)(g_ram+0x177C)) +#define fireflea_darkness_level (*(uint16*)(g_ram+0x177E)) +#define UNUSED_word_7E1780 (*(uint16*)(g_ram+0x1780)) +#define UNUSED_word_7E1782 (*(uint16*)(g_ram+0x1782)) +#define enemy_ai_pointer (*(LongPtr*)(g_ram+0x1784)) +#define enemy_ai_pointer_backup (*(LongPtr*)(g_ram+0x1788)) +#define enemy_gfx_drawn_hook (*(LongPtr*)(g_ram+0x178C)) +#define set_to_rtl_when_loading_enemies_unused (*(LongPtr*)(g_ram+0x1790)) +#define variables_for_enemy_graphics_drawn_hook ((uint16*)(g_ram+0x1794)) +#define enemy_bg2_tilemap_size (*(uint16*)(g_ram+0x179A)) +#define boss_id (*(uint16*)(g_ram+0x179C)) +#define UNUSED_word_7E179E (*(uint16*)(g_ram+0x179E)) +#define UNUSED_word_7E17A0 (*(uint16*)(g_ram+0x17A0)) +#define UNUSED_word_7E17A2 (*(uint16*)(g_ram+0x17A2)) +#define active_enemy_indexes_write_ptr (*(uint16*)(g_ram+0x17A4)) +#define interactive_enemy_indexes_write_ptr (*(uint16*)(g_ram+0x17A6)) +#define active_enemy_indexes_index (*(uint16*)(g_ram+0x17A8)) +#define interactive_enemy_indexes_index (*(uint16*)(g_ram+0x17AA)) +#define active_enemy_indexes ((uint16*)(g_ram+0x17AC)) +#define interactive_enemy_indexes ((uint16*)(g_ram+0x17EC)) +#define enemy_index_colliding_dirs ((uint16*)(g_ram+0x182C)) +#define distance_to_enemy_colliding_dirs ((uint16*)(g_ram+0x1834)) +#define flag_process_all_enemies (*(uint16*)(g_ram+0x183C)) +#define earthquake_type (*(uint16*)(g_ram+0x183E)) +#define earthquake_timer (*(uint16*)(g_ram+0x1840)) +#define frame_counter_every_frame (*(uint16*)(g_ram+0x1842)) +#define sprite_object_index (*(uint16*)(g_ram+0x1844)) +#define debug_enemy_index (*(uint16*)(g_ram+0x1846)) +#define log_index_UNUSED (*(uint16*)(g_ram+0x1848)) +#define samus_x_pos_colliding_solid (*(uint16*)(g_ram+0x184A)) +#define samus_x_subpos_colliding_solid (*(uint16*)(g_ram+0x184C)) +#define enemy_x_pos_colliding_solid (*(uint16*)(g_ram+0x184E)) +#define enemy_x_subpos_colliding_solid (*(uint16*)(g_ram+0x1850)) +#define samus_pos_delta_colliding_solid (*(uint16*)(g_ram+0x1852)) +#define samus_subpos_delta_colliding_solid (*(uint16*)(g_ram+0x1854)) +#define samus_y_pos_colliding_solid (*(uint16*)(g_ram+0x1856)) +#define samus_y_subpos_colliding_solid (*(uint16*)(g_ram+0x1858)) +#define solid_enemy_collision_type (*(uint16*)(g_ram+0x185A)) +#define debug_index (*(uint16*)(g_ram+0x185C)) +#define debug_time_frozen_for_enemies (*(uint16*)(g_ram+0x185E)) +#define debug_text_cursor_x (*(uint16*)(g_ram+0x1860)) +#define debug_text_cursor_y (*(uint16*)(g_ram+0x1862)) +#define debug_enemy_set_entry_index (*(uint16*)(g_ram+0x1864)) +#define debug_enemy_population_pointer (*(uint16*)(g_ram+0x1866)) +#define debug_enemy_spawn_x_pos (*(uint16*)(g_ram+0x1868)) +#define debug_enemy_spawn_y_pos (*(uint16*)(g_ram+0x186A)) +#define enemy_spritemap_entry_pointer (*(uint16*)(g_ram+0x186E)) +#define enemy_left_border_collision (*(uint16*)(g_ram+0x1870)) +#define enemy_bottom_border_collision (*(uint16*)(g_ram+0x1872)) +#define enemy_right_border_collision (*(uint16*)(g_ram+0x1874)) +#define enemy_top_border_collision (*(uint16*)(g_ram+0x1876)) +#define hitbox_ptr (*(uint16*)(g_ram+0x1878)) +#define enemy_spritemap_entry_coll_x_pos (*(uint16*)(g_ram+0x187A)) +#define num_projs_to_check (*(uint16*)(g_ram+0x187C)) +#define samus_right_border_coll (*(uint16*)(g_ram+0x187E)) +#define samus_left_border_coll (*(uint16*)(g_ram+0x1880)) +#define samus_bottom_border_coll (*(uint16*)(g_ram+0x1882)) +#define samus_top_border_coll (*(uint16*)(g_ram+0x1884)) +#define samus_target_x_pos (*(uint16*)(g_ram+0x189A)) +#define samus_target_x_subpos (*(uint16*)(g_ram+0x189C)) +#define samus_target_y_pos (*(uint16*)(g_ram+0x189E)) +#define samus_target_y_subpos (*(uint16*)(g_ram+0x18A0)) +#define samus_x_radius_mirror (*(uint16*)(g_ram+0x18A2)) +#define samus_y_radius_mirror (*(uint16*)(g_ram+0x18A4)) +#define collision_detection_index (*(uint16*)(g_ram+0x18A6)) +#define samus_invincibility_timer (*(uint16*)(g_ram+0x18A8)) +#define samus_knockback_timer (*(uint16*)(g_ram+0x18AA)) +#define projectile_invincibility_timer (*(uint16*)(g_ram+0x18AC)) +#define flag_disable_projectile_interaction (*(uint16*)(g_ram+0x18AE)) +#define hdma_objects_enable_flag (*(uint16*)(g_ram+0x18B0)) +#define hdma_object_index (*(uint16*)(g_ram+0x18B2)) +#define hdma_object_channels_bitmask ((uint16*)(g_ram+0x18B4)) +#define hdma_object_bank_slot ((uint16*)(g_ram+0x18C0)) +#define hdma_object_instruction_list_pointers ((uint16*)(g_ram+0x18CC)) +#define hdma_object_table_pointers ((uint16*)(g_ram+0x18D8)) +#define hdma_object_instruction_timers ((uint16*)(g_ram+0x18E4)) +#define hdma_object_pre_instructions ((uint16*)(g_ram+0x18F0)) +#define hdma_object_pre_instruction_bank ((uint16*)(g_ram+0x18FC)) +#define hdma_object_timers ((uint16*)(g_ram+0x1908)) +#define hdma_object_A ((uint16*)(g_ram+0x1914)) +#define hdma_object_B ((uint16*)(g_ram+0x1920)) +#define hdma_object_C ((uint16*)(g_ram+0x192C)) +#define hdma_object_D ((uint16*)(g_ram+0x1938)) +#define hdma_object_E ((uint16*)(g_ram+0x1944)) +#define hdma_object_F ((uint16*)(g_ram+0x1950)) +#define fx_y_subpos (*(uint16*)(g_ram+0x195C)) +#define fx_y_pos (*(uint16*)(g_ram+0x195E)) +#define lava_acid_y_subpos (*(uint16*)(g_ram+0x1960)) +#define lava_acid_y_pos (*(uint16*)(g_ram+0x1962)) +#define fx_tilemap_ptr (*(uint16*)(g_ram+0x1964)) +#define current_fx_entry_ptr (*(uint16*)(g_ram+0x1966)) +#define current_fx_entry_offset (*(uint16*)(g_ram+0x1968)) +#define current_fx_palette_fx_bitset (*(uint16*)(g_ram+0x196A)) +#define fx_rising_function_bank_88 (*(uint16*)(g_ram+0x196C)) +#define fx_type (*(uint16*)(g_ram+0x196E)) +#define fx_y_suboffset (*(uint16*)(g_ram+0x1970)) +#define fx_y_offset (*(uint16*)(g_ram+0x1972)) +#define tide_phase (*(uint16*)(g_ram+0x1974)) +#define fx_base_y_subpos (*(uint16*)(g_ram+0x1976)) +#define fx_base_y_pos (*(uint16*)(g_ram+0x1978)) +#define fx_target_y_pos (*(uint16*)(g_ram+0x197A)) +#define fx_y_vel (*(uint16*)(g_ram+0x197C)) +#define fx_liquid_options (*(uint16*)(g_ram+0x197E)) +#define fx_timer (*(uint16*)(g_ram+0x1980)) +#define fx_layer_blending_config_a (*(uint16*)(g_ram+0x1982)) +#define fx_layer_blending_config_b (*(uint16*)(g_ram+0x1984)) +#define fx_layer_blending_config_c (*(uint16*)(g_ram+0x1986)) +#define phantom_related_layer_flag (*(uint16*)(g_ram+0x1988)) +#define enemy_projectile_enable_flag (*(uint16*)(g_ram+0x198D)) +#define enemy_projectile_unk198F (*(uint16*)(g_ram+0x198F)) +#define enemy_projectile_index (*(uint16*)(g_ram+0x1991)) +#define enemy_projectile_init_param (*(uint16*)(g_ram+0x1993)) +#define enemy_projectile_unk1995 (*(uint16*)(g_ram+0x1995)) +#define enemy_projectile_id ((uint16*)(g_ram+0x1997)) +#define enemy_projectile_gfx_idx ((uint16*)(g_ram+0x19BB)) +#define enemy_projectile_timers ((uint16*)(g_ram+0x19DF)) +#define enemy_projectile_pre_instr ((uint16*)(g_ram+0x1A03)) +#define enemy_projectile_1A27 ((uint16*)(g_ram+0x1A27)) +#define enemy_projectile_x_pos ((uint16*)(g_ram+0x1A4B)) +#define enemy_projectile_y_subpos ((uint16*)(g_ram+0x1A6F)) +#define enemy_projectile_y_pos ((uint16*)(g_ram+0x1A93)) +#define enemy_projectile_x_vel ((uint16*)(g_ram+0x1AB7)) +#define enemy_projectile_y_vel ((uint16*)(g_ram+0x1ADB)) +#define enemy_projectile_E ((uint16*)(g_ram+0x1AFF)) +#define enemy_projectile_F ((uint16*)(g_ram+0x1B23)) +#define enemy_projectile_instr_list_ptr ((uint16*)(g_ram+0x1B47)) +#define enemy_projectile_spritemap_ptr ((uint16*)(g_ram+0x1B6B)) +#define enemy_projectile_instr_timers ((uint16*)(g_ram+0x1B8F)) +#define enemy_projectile_radius ((uint16*)(g_ram+0x1BB3)) +#define enemy_projectile_properties ((uint16*)(g_ram+0x1BD7)) +#define enemy_projectile_G ((uint16*)(g_ram+0x1BFB)) +#define message_box_index (*(uint16*)(g_ram+0x1C1F)) +#define plm_flag (*(uint16*)(g_ram+0x1C23)) +#define plm_draw_tilemap_index (*(uint16*)(g_ram+0x1C25)) +#define plm_id (*(uint16*)(g_ram+0x1C27)) +#define plm_x_block (*(uint16*)(g_ram+0x1C29)) +#define plm_y_block (*(uint16*)(g_ram+0x1C2B)) +#define plm_item_gfx_index (*(uint16*)(g_ram+0x1C2D)) +#define plm_item_gfx_ptrs ((uint16*)(g_ram+0x1C2F)) +#define plm_header_ptr ((uint16*)(g_ram+0x1C37)) +#define plm_block_indices ((uint16*)(g_ram+0x1C87)) +#define plm_pre_instrs ((uint16*)(g_ram+0x1CD7)) +#define plm_instr_list_ptrs ((uint16*)(g_ram+0x1D27)) +#define plm_timers ((uint16*)(g_ram+0x1D77)) +#define plm_room_arguments ((uint16*)(g_ram+0x1DC7)) +#define plm_variable ((uint16*)(g_ram+0x1E17)) +#define custom_draw_instr_num_blocks (*(uint16*)(g_ram+0x1E67)) +#define custom_draw_instr_plm_block (*(uint16*)(g_ram+0x1E69)) +#define custom_draw_instr_zero_terminator (*(uint16*)(g_ram+0x1E6B)) +#define tourian_entrance_statue_finished (*(uint16*)(g_ram+0x1E6D)) +#define tourian_entrance_statue_animstate (*(uint16*)(g_ram+0x1E6F)) +#define flag_samus_in_quicksand (*(uint16*)(g_ram+0x1E71)) +#define inside_block_reaction_samus_point (*(uint16*)(g_ram+0x1E73)) +#define save_station_lockout_flag (*(uint16*)(g_ram+0x1E75)) +#define current_slope_bts (*(uint16*)(g_ram+0x1E77)) +#define flag_for_palette_fx_objects (*(uint16*)(g_ram+0x1E79)) +#define palettefx_index (*(uint16*)(g_ram+0x1E7B)) +#define palettefx_ids ((uint16*)(g_ram+0x1E7D)) +#define palettefx_color_indexes ((uint16*)(g_ram+0x1E8D)) +#define palettefx_pre_instr ((uint16*)(g_ram+0x1EAD)) +#define palettefx_instr_list_ptrs ((uint16*)(g_ram+0x1EBD)) +#define palettefx_instr_timers ((uint16*)(g_ram+0x1ECD)) +#define palettefx_timers ((uint16*)(g_ram+0x1EDD)) +#define samus_in_heat_palfx_index (*(uint16*)(g_ram+0x1EED)) +#define samus_in_heat_palettefx_prev_index (*(uint16*)(g_ram+0x1EEF)) +#define animtiles_enable_flag (*(uint16*)(g_ram+0x1EF1)) +#define animtiles_object_index (*(uint16*)(g_ram+0x1EF3)) +#define animtiles_ids ((uint16*)(g_ram+0x1EF5)) +#define animtiles_timers ((uint16*)(g_ram+0x1F01)) +#define animtiles_instr_list_ptrs ((uint16*)(g_ram+0x1F0D)) +#define animtiles_instr_timers ((uint16*)(g_ram+0x1F19)) +#define animtiles_src_ptr ((uint16*)(g_ram+0x1F25)) +#define animtiles_sizes ((uint16*)(g_ram+0x1F31)) +#define animtiles_vram_ptr ((uint16*)(g_ram+0x1F3D)) +#define animtiles_instruction (*(uint16*)(g_ram+0x1F49)) +#define cinematic_function (*(uint16*)(g_ram+0x1F51)) +#define demo_timer (*(uint16*)(g_ram+0x1F53)) +#define demo_set (*(uint16*)(g_ram+0x1F55)) +#define demo_scene (*(uint16*)(g_ram+0x1F57)) +#define num_demo_sets (*(uint16*)(g_ram+0x1F59)) +#define STACK ((uint16*)(g_ram+0x1F5B)) +#define tilemap_stuff ((uint16*)(g_ram+0x2000)) +#define ram3000 (*(Ram3000*)(g_ram+0x3000)) +#define ram3800 (*(Ram3800*)(g_ram+0x3800)) +#define ram4000 (*(Ram4000*)(g_ram+0x4000)) +#define enemy_spawn_data ((EnemySpawnData*)(g_ram+0x7000)) +#define enemy_ram7800 ((ExtraEnemyRam7800*)(g_ram+0x7800)) +#define extra_enemy_ram8000 ((ExtraEnemyRam8000*)(g_ram+0x8000)) +#define extra_enemy_ram8800 ((ExtraEnemyRam8800*)(g_ram+0x8800)) +#define kraid_unk9000 (*(uint16*)(g_ram+0x9000)) +#define g_word_7E9002 (*(uint16*)(g_ram+0x9002)) +#define g_word_7E9004 (*(uint16*)(g_ram+0x9004)) +#define g_word_7E9006 (*(uint16*)(g_ram+0x9006)) +#define g_word_7E9008 (*(uint16*)(g_ram+0x9008)) +#define g_word_7E900A (*(uint16*)(g_ram+0x900A)) +#define g_word_7E900C (*(uint16*)(g_ram+0x900C)) +#define g_word_7E900F (*(uint16*)(g_ram+0x900F)) +#define g_word_7E9012 (*(uint16*)(g_ram+0x9012)) +#define g_word_7E9015 (*(uint16*)(g_ram+0x9015)) +#define g_word_7E9018 (*(uint16*)(g_ram+0x9018)) +#define g_word_7E9020 (*(uint16*)(g_ram+0x9020)) +#define g_word_7E9022 (*(uint16*)(g_ram+0x9022)) +#define g_word_7E9030 (*(uint16*)(g_ram+0x9030)) +#define g_word_7E9032 (*(uint16*)(g_ram+0x9032)) +#define g_word_7E9040 (*(uint16*)(g_ram+0x9040)) +#define g_word_7E9042 (*(uint16*)(g_ram+0x9042)) +#define g_word_7E9050 (*(uint16*)(g_ram+0x9050)) +#define g_word_7E9052 (*(uint16*)(g_ram+0x9052)) +#define g_word_7E9060 (*(uint16*)(g_ram+0x9060)) +#define g_word_7E9062 (*(uint16*)(g_ram+0x9062)) +#define g_word_7E9070 (*(uint16*)(g_ram+0x9070)) +#define g_word_7E9072 (*(uint16*)(g_ram+0x9072)) +#define g_word_7E9080 (*(uint16*)(g_ram+0x9080)) +#define g_word_7E9082 (*(uint16*)(g_ram+0x9082)) +#define g_word_7E9090 (*(uint16*)(g_ram+0x9090)) +#define g_word_7E9092 (*(uint16*)(g_ram+0x9092)) +#define g_word_7E90A0 (*(uint16*)(g_ram+0x90A0)) +#define g_word_7E90A2 (*(uint16*)(g_ram+0x90A2)) +#define g_word_7E90B0 (*(uint16*)(g_ram+0x90B0)) +#define g_word_7E90B2 (*(uint16*)(g_ram+0x90B2)) +#define g_word_7E90C0 (*(uint16*)(g_ram+0x90C0)) +#define g_word_7E90C2 (*(uint16*)(g_ram+0x90C2)) +#define g_word_7E90D0 (*(uint16*)(g_ram+0x90D0)) +#define g_word_7E90D2 (*(uint16*)(g_ram+0x90D2)) +#define g_word_7E9100 (*(uint16*)(g_ram+0x9100)) +#define g_word_7E9140 (*(uint16*)(g_ram+0x9140)) +#define g_word_7E9180 (*(uint16*)(g_ram+0x9180)) +#define g_byte_7E9500 (*(uint8*)(g_ram+0x9500)) +#define g_byte_7E9510 (*(uint8*)(g_ram+0x9510)) +#define g_byte_7E9520 (*(uint8*)(g_ram+0x9520)) +#define g_byte_7E9530 (*(uint8*)(g_ram+0x9530)) +#define g_byte_7E9540 (*(uint8*)(g_ram+0x9540)) +#define g_byte_7E9550 (*(uint8*)(g_ram+0x9550)) +#define g_byte_7E9560 (*(uint8*)(g_ram+0x9560)) +#define g_byte_7E9570 (*(uint8*)(g_ram+0x9570)) +#define g_byte_7E9580 (*(uint8*)(g_ram+0x9580)) +#define g_byte_7E9590 (*(uint8*)(g_ram+0x9590)) +#define g_byte_7E95A0 (*(uint8*)(g_ram+0x95A0)) +#define g_byte_7E95B0 (*(uint8*)(g_ram+0x95B0)) +#define g_byte_7E95C0 (*(uint8*)(g_ram+0x95C0)) +#define g_byte_7E95D0 (*(uint8*)(g_ram+0x95D0)) +#define g_byte_7E95E0 (*(uint8*)(g_ram+0x95E0)) +#define g_byte_7E95F0 (*(uint8*)(g_ram+0x95F0)) +#define g_byte_7E9600 (*(uint8*)(g_ram+0x9600)) +#define g_byte_7E9610 (*(uint8*)(g_ram+0x9610)) +#define g_word_7E97DC ((uint16*)(g_ram+0x97DC)) +#define hdma_table_1 ((uint16*)(g_ram+0x9800)) +#define mother_brain_indirect_hdma ((uint8*)(g_ram+0x9C00)) +#define g_word_7E9C44 (*(uint16*)(g_ram+0x9C44)) +#define g_word_7E9C46 ((uint16*)(g_ram+0x9C46)) +#define hdma_table_2 ((uint16*)(g_ram+0x9D00)) +#define hdma_window_1_left_pos ((ExpandingSquareTransitionHdma*)(g_ram+0x9E00)) +#define hdma_window_1_right_pos ((ExpandingSquareTransitionHdma*)(g_ram+0x9E10)) +#define expanding_square_topbottom_margin_right_pos (*(uint16*)(g_ram+0x9E20)) +#define expanding_square_topbottom_margin_left_pos (*(uint16*)(g_ram+0x9E22)) +#define expanding_square_left_subpos (*(uint16*)(g_ram+0x9E30)) +#define expanding_square_left_pos (*(uint16*)(g_ram+0x9E32)) +#define expanding_square_right_subpos (*(uint16*)(g_ram+0x9E34)) +#define expanding_square_right_pos (*(uint16*)(g_ram+0x9E36)) +#define expanding_square_top_subpos (*(uint16*)(g_ram+0x9E38)) +#define expanding_square_top_pos (*(uint16*)(g_ram+0x9E3A)) +#define expanding_square_bottom_subpos (*(uint16*)(g_ram+0x9E3C)) +#define expanding_square_bottom_pos (*(uint16*)(g_ram+0x9E3E)) +#define expanding_square_left_subvel (*(uint16*)(g_ram+0x9E40)) +#define expanding_square_left_vel (*(uint16*)(g_ram+0x9E42)) +#define expanding_square_right_subvel (*(uint16*)(g_ram+0x9E44)) +#define expanding_square_right_vel (*(uint16*)(g_ram+0x9E46)) +#define expanding_square_top_subvel (*(uint16*)(g_ram+0x9E48)) +#define expanding_square_top_vel (*(uint16*)(g_ram+0x9E4A)) +#define expanding_square_bottom_subvel (*(uint16*)(g_ram+0x9E4C)) +#define expanding_square_bottom_vel (*(uint16*)(g_ram+0x9E4E)) +#define expanding_square_timer (*(uint16*)(g_ram+0x9E50)) +#define g_word_7E9E80 ((uint16*)(g_ram+0x9E80)) +#define scrolling_sky_bg2_indirect_hdma ((uint8*)(g_ram+0x9F00)) +#define scrolling_sky_bg2_hdma_data ((uint16*)(g_ram+0x9F80)) +#define tile_table (*(TileTables*)(g_ram+0xA000)) +#define palette_buffer ((uint16*)(g_ram+0xC000)) +#define target_palettes ((uint16*)(g_ram+0xC200)) +#define palette_change_num (*(uint16*)(g_ram+0xC400)) +#define palette_change_denom (*(uint16*)(g_ram+0xC402)) +#define g_word_7EC404 (*(uint16*)(g_ram+0xC404)) +#define power_bomb_explosion_left_hdma ((uint8*)(g_ram+0xC406)) +#define power_bomb_explosion_right_hdma ((uint8*)(g_ram+0xC506)) +#define offscreen_power_bomb_left_hdma (*(uint8*)(g_ram+0xC606)) +#define offscreen_power_bomb_right_hdma (*(uint8*)(g_ram+0xC607)) +#define hud_tilemap ((uint16*)(g_ram+0xC608)) +#define plm_draw_tilemap ((uint16*)(g_ram+0xC6C8)) +#define bg1_column_update_tilemap_left_halves ((uint16*)(g_ram+0xC8C8)) +#define bg1_column_update_tilemap_right_halves ((uint16*)(g_ram+0xC908)) +#define bg1_column_update_tilemap_top_halves ((uint16*)(g_ram+0xC948)) +#define bg1_column_update_tilemap_bottom_halves ((uint16*)(g_ram+0xC98C)) +#define bg2_column_update_tilemap_left_halves ((uint8*)(g_ram+0xC9D0)) +#define bg2_column_update_tilemap_right_halves ((uint16*)(g_ram+0xCA10)) +#define bg2_column_update_tilemap_top_halves ((uint8*)(g_ram+0xCA50)) +#define bg2_column_update_tilemap_bottom_halves ((uint8*)(g_ram+0xCA94)) +#define hud_bg3_xpos (*(uint16*)(g_ram+0xCAD8)) +#define hud_bg3_ypos (*(uint16*)(g_ram+0xCADA)) +#define bg3_xpos (*(uint16*)(g_ram+0xCADC)) +#define bg3_ypos (*(uint16*)(g_ram+0xCADE)) +#define crocomire_bg2_scroll_hdma_indirect ((uint8*)(g_ram+0xCAE0)) +#define crocomire_bg2_scroll_hdma_data ((uint16*)(g_ram+0xCAF0)) +#define scrolls ((uint8*)(g_ram+0xCD20)) +#define explored_map_tiles_saved ((uint16*)(g_ram+0xCD52)) +#define debug_enemy_set_name ((uint8*)(g_ram+0xD552)) +#define debug_enemy_set_data ((uint8*)(g_ram+0xD55A)) +#define wrecked_ship_robot_palanim_palindex (*(uint16*)(g_ram+0xD652)) +#define wrecked_ship_robot_palanim_timer (*(uint16*)(g_ram+0xD654)) +#define wrecked_ship_robot_palanim_table_index (*(uint8*)(g_ram+0xD656)) +#define projectiletrail_left_instr_timer ((uint16*)(g_ram+0xD658)) +#define projectiletrail_right_instr_timer ((uint16*)(g_ram+0xD67C)) +#define projectiletrail_left_instr_list_ptr ((uint16*)(g_ram+0xD6A0)) +#define projectiletrail_right_instr_list_ptr ((uint16*)(g_ram+0xD6C4)) +#define projectiletrail_left_tile_and_attribs ((uint16*)(g_ram+0xD6E8)) +#define projectiletrail_right_tile_and_attribs ((uint16*)(g_ram+0xD70C)) +#define projectiletrail_left_x_pos ((uint16*)(g_ram+0xD730)) +#define projectiletrail_right_x_pos ((uint16*)(g_ram+0xD754)) +#define projectiletrail_left_y_pos ((uint16*)(g_ram+0xD778)) +#define projectiletrail_right_y_pos ((uint16*)(g_ram+0xD79C)) +#define player_data_saved ((uint16*)(g_ram+0xD7C0)) +#define events_that_happened ((uint8*)(g_ram+0xD820)) +#define boss_bits_for_area ((uint8*)(g_ram+0xD828)) +#define room_chozo_bits ((uint8*)(g_ram+0xD830)) +#define item_bit_array ((uint8*)(g_ram+0xD870)) +#define opened_door_bit_array ((uint8*)(g_ram+0xD8B0)) +#define UNUSED_word_7ED8F0 ((uint16*)(g_ram+0xD8F0)) +#define used_save_stations_and_elevators ((uint8*)(g_ram+0xD8F8)) +#define map_station_byte_array ((uint8*)(g_ram+0xD908)) +#define loading_game_state (*(uint16*)(g_ram+0xD914)) +#define sram_save_station_index (*(uint16*)(g_ram+0xD916)) +#define sram_area_index (*(uint16*)(g_ram+0xD918)) +#define global_number_of_items_loaded_ctr (*(uint16*)(g_ram+0xD91A)) +#define compressed_map_data ((uint8*)(g_ram+0xD91C)) +#define plm_instruction_timer ((uint16*)(g_ram+0xDE1C)) +#define plm_instruction_draw_ptr ((uint16*)(g_ram+0xDE6C)) +#define plm_instruction_list_link_reg ((uint16*)(g_ram+0xDEBC)) +#define plm_variables ((uint16*)(g_ram+0xDF0C)) +#define backup_of_bg2_during_pause ((uint16*)(g_ram+0xDF5C)) +#define enemy_def_ptr ((uint16*)(g_ram+0xEF5C)) +#define enemy_gfxdata_tiles_index ((uint16*)(g_ram+0xEF64)) +#define enemy_gfxdata_vram_ptr ((uint16*)(g_ram+0xEF6C)) +#define enemy_gfx_data_write_ptr (*(uint16*)(g_ram+0xEF74)) +#define next_enemy_tiles_index (*(uint16*)(g_ram+0xEF76)) +#define sprite_instr_list_ptrs ((uint16*)(g_ram+0xEF78)) +#define sprite_instr_timer ((uint16*)(g_ram+0xEFF8)) +#define sprite_palettes ((uint16*)(g_ram+0xF078)) +#define sprite_x_pos ((uint16*)(g_ram+0xF0F8)) +#define sprite_x_subpos ((uint16*)(g_ram+0xF178)) +#define sprite_y_pos ((uint16*)(g_ram+0xF1F8)) +#define sprite_y_subpos ((uint16*)(g_ram+0xF278)) +#define sprite_disable_flag ((uint16*)(g_ram+0xF2F8)) +#define enemy_processing_stage (*(uint16*)(g_ram+0xF378)) +#define g_word_7EF37A (*(uint16*)(g_ram+0xF37A)) +#define g_word_7EF37C (*(uint16*)(g_ram+0xF37C)) +#define g_word_7EF37E (*(uint16*)(g_ram+0xF37E)) +#define enemy_projectile_flags ((uint16*)(g_ram+0xF380)) +#define enemy_projectile_enemy_header_ptr ((uint16*)(g_ram+0xF3C8)) +#define enemy_projectile_killed_enemy_index ((uint16*)(g_ram+0xF410)) +#define special_death_item_drop_x_origin_pos (*(uint16*)(g_ram+0xF434)) +#define special_death_item_drop_y_origin_pos (*(uint16*)(g_ram+0xF436)) +#define ram7F_start (*(uint16*)(g_ram+0x10000)) +#define level_data ((uint16*)(g_ram+0x10002)) +#define g_word_7F1902 (*(uint16*)(g_ram+0x11902)) +#define g_word_7F3202 (*(uint16*)(g_ram+0x13202)) +#define g_word_7F4000 (*(uint16*)(g_ram+0x14000)) +#define g_word_7F4B02 (*(uint16*)(g_ram+0x14B02)) +#define BTS ((uint8*)(g_ram+0x16402)) +#define custom_background ((uint16*)(g_ram+0x19602)) +#define unused_1fa02 ((uint8*)(g_ram+0x1FA02)) +#define kSramChecksum ((uint16*)(g_sram+0x0)) +#define kSramChecksumInverted ((uint16*)(g_sram+0x8)) +#define sram_save_slot_selected (*(uint16*)(g_sram+0x1FEC)) +#define sram_save_slot_selected_complement (*(uint16*)(g_sram+0x1FEE)) +#define kSramChecksumUpper ((uint16*)(g_sram+0x1FF0)) +#define kSramChecksumInvertedUpper ((uint16*)(g_sram+0x1FF8)) + + + +#include "variables_extra.h" + +#define ADDR16_OF_RAM(x) ((uint8*)&(x) - g_ram) diff --git a/src/variables_extra.h b/src/variables_extra.h new file mode 100644 index 0000000..9e706eb --- /dev/null +++ b/src/variables_extra.h @@ -0,0 +1,74 @@ + +// Cinematic stuff +#define cinematic_var5 (*(uint16*)(g_ram+0x198D)) +#define cinematic_var6 (*(uint16*)(g_ram+0x198F)) +#define cinematic_var7 (*(uint16*)(g_ram+0x1991)) +#define cinematic_var8 (*(uint16*)(g_ram+0x1993)) +#define cinematic_var9 (*(uint16*)(g_ram+0x1995)) +#define cinematic_var10 (*(uint16*)(g_ram+0x1997)) + +#define g_word_7E1999 (*(uint16*)(g_ram+0x1999)) +#define g_word_7E199B (*(uint16*)(g_ram+0x199B)) +#define g_word_7E199D (*(uint16*)(g_ram+0x199D)) +#define g_word_7E199F (*(uint16*)(g_ram+0x199F)) +#define mode7_obj_instr_ptr ((uint16*)(g_ram+0x19A1)) +#define mode7_obj_preinstr_func ((uint16*)(g_ram+0x19A5)) +#define mode7_obj_instr_timer ((uint16*)(g_ram+0x19A9)) +#define mode7_obj_goto_timer ((uint16*)(g_ram+0x19AD)) +#define mode7_cur_index (*(uint16*)(g_ram+0x19B1)) +#define mode7_spawn_param (*(uint16*)(g_ram+0x19B3)) +#define cinematicbg_arr1 ((uint16*)(g_ram+0x19B5)) +#define cinematicbg_instr_ptr ((uint16*)(g_ram+0x19CD)) +#define cinematicbg_preinstr ((uint16*)(g_ram+0x19D5)) +#define cinematicbg_instr_timer ((uint16*)(g_ram+0x19DD)) +#define cinematicbg_arr6 ((uint16*)(g_ram+0x19E5)) +#define cinematicbg_var2 (*(uint16*)(g_ram+0x19ED)) +#define cinematic_enable_objs (*(uint16*)(g_ram+0x19F1)) +#define cinematic_enable_bg_tilemap (*(uint16*)(g_ram+0x19F3)) +#define cinematicbg_var3 (*(uint16*)(g_ram+0x19F5)) +#define cinematic_var21 (*(uint16*)(g_ram+0x19F7)) +#define cinematic_var22 (*(uint16*)(g_ram+0x19F9)) +#define cinematic_var23 (*(uint16*)(g_ram+0x19FB)) +#define cinematic_var24 (*(uint16*)(g_ram+0x19FD)) +#define cinematic_var25 (*(uint16*)(g_ram+0x19FF)) +#define cinematic_var26 (*(uint16*)(g_ram+0x1A01)) +#define enemy_projectile_pre_instr ((uint16*)(g_ram+0x1A03)) +#define cinematic_var20 (*(uint16*)(g_ram+0x1A37)) +#define cinematic_var19 (*(uint16*)(g_ram+0x1A47)) +#define cinematic_var4 (*(uint16*)(g_ram+0x1A49)) +#define cinematic_var13 (*(uint16*)(g_ram+0x1A4B)) +#define cinematic_var14 (*(uint16*)(g_ram+0x1A4D)) +#define cinematic_var17 (*(uint16*)(g_ram+0x1A4F)) +#define cinematic_var12 (*(uint16*)(g_ram+0x1A51)) +#define cinematic_var18 (*(uint16*)(g_ram+0x1A53)) +#define cinematic_var15 (*(uint16*)(g_ram+0x1A57)) +#define cinematic_obj_index (*(uint16*)(g_ram+0x1A59)) +#define cinematicspr_whattodraw ((uint16*)(g_ram+0x1A5D)) +#define cinematicbg_arr7 ((uint16*)(g_ram+0x1A7D)) +#define cinematicbg_arr8 ((uint16*)(g_ram+0x1A9D)) +#define cinematicbg_arr9 ((uint16*)(g_ram+0x1ABD)) +#define cinematicspr_arr6 ((uint16*)(g_ram+0x1ADD)) +#define cinematicspr_arr7 ((uint16*)(g_ram+0x1AFD)) +#define cinematicspr_instr_ptr ((uint16*)(g_ram+0x1B1D)) +#define cinematicspr_preinstr_func ((uint16*)(g_ram+0x1B3D)) +#define cinematicspr_instr_timer ((uint16*)(g_ram+0x1B5D)) +#define cinematicspr_goto_timer ((uint16*)(g_ram+0x1B7D)) +#define cinematic_spawn_param (*(uint16*)(g_ram+0x1B9D)) +#define cinematic_var11 (*(uint16*)(g_ram+0x1B9F)) +#define cinematicbg_var1 (*(uint16*)(g_ram+0x1BA1)) +#define cinematic_var16 (*(uint16*)(g_ram+0x1BA3)) + + +#define optionsmenu_index (*(uint16*)(g_ram+0x1A8F)) +#define options_menu_init_param (*(uint16*)(g_ram+0x1A93)) +#define optionsmenu_cur_data ((uint16*)(g_ram+0x1A9D)) +#define optionsmenu_arr8 ((uint16*)(g_ram+0x1AAD)) +#define optionsmenu_arr9 ((uint16*)(g_ram+0x1ABD)) +#define optionsmenu_arr10 ((uint16*)(g_ram+0x1ACD)) +#define optionsmenu_arr6 ((uint16*)(g_ram+0x1ADD)) +#define optionsmenu_arr7 ((uint16*)(g_ram+0x1AED)) +#define optionsmenu_instr_ptr ((uint16*)(g_ram+0x1AFD)) +#define optionsmenu_arr1 ((uint16*)(g_ram+0x1B0D)) +#define optionsmenu_instr_timer ((uint16*)(g_ram+0x1B1D)) +#define optionsmenu_arr5 ((uint16*)(g_ram+0x1B2D)) +#define optionsmenu_arr11 ((uint16*)(g_ram+0x1B3D)) diff --git a/third_party/.gitignore b/third_party/.gitignore new file mode 100644 index 0000000..1fbecd9 --- /dev/null +++ b/third_party/.gitignore @@ -0,0 +1,3 @@ +/tcc/ +/SDL2-2.24.1/ +/gl_core/*.o \ No newline at end of file diff --git a/third_party/gl_core/gl_core_3_1.c b/third_party/gl_core/gl_core_3_1.c new file mode 100644 index 0000000..1283172 --- /dev/null +++ b/third_party/gl_core/gl_core_3_1.c @@ -0,0 +1,3189 @@ +#include +#include +#include +#include "gl_core_3_1.h" + +#ifndef SDLCALL +#if (defined(__WIN32__) || defined(__WINRT__)) && !defined(__GNUC__) +#define SDLCALL __cdecl +#else +#define SDLCALL +#endif +#endif /* SDLCALL */ + +extern void *SDLCALL SDL_GL_GetProcAddress(const char *proc); + +#define IntGetProcAddress(name) SDL_GL_GetProcAddress(name) + +int ogl_ext_ARB_compressed_texture_pixel_storage = ogl_LOAD_FAILED; +int ogl_ext_ARB_conservative_depth = ogl_LOAD_FAILED; +int ogl_ext_ARB_ES2_compatibility = ogl_LOAD_FAILED; +int ogl_ext_ARB_get_program_binary = ogl_LOAD_FAILED; +int ogl_ext_ARB_explicit_uniform_location = ogl_LOAD_FAILED; +int ogl_ext_ARB_internalformat_query = ogl_LOAD_FAILED; +int ogl_ext_ARB_internalformat_query2 = ogl_LOAD_FAILED; +int ogl_ext_ARB_map_buffer_alignment = ogl_LOAD_FAILED; +int ogl_ext_ARB_program_interface_query = ogl_LOAD_FAILED; +int ogl_ext_ARB_separate_shader_objects = ogl_LOAD_FAILED; +int ogl_ext_ARB_shading_language_420pack = ogl_LOAD_FAILED; +int ogl_ext_ARB_shading_language_packing = ogl_LOAD_FAILED; +int ogl_ext_ARB_texture_buffer_range = ogl_LOAD_FAILED; +int ogl_ext_ARB_texture_storage = ogl_LOAD_FAILED; +int ogl_ext_ARB_texture_view = ogl_LOAD_FAILED; +int ogl_ext_ARB_vertex_attrib_binding = ogl_LOAD_FAILED; +int ogl_ext_ARB_viewport_array = ogl_LOAD_FAILED; +int ogl_ext_ARB_arrays_of_arrays = ogl_LOAD_FAILED; +int ogl_ext_ARB_clear_buffer_object = ogl_LOAD_FAILED; +int ogl_ext_ARB_copy_image = ogl_LOAD_FAILED; +int ogl_ext_ARB_ES3_compatibility = ogl_LOAD_FAILED; +int ogl_ext_ARB_fragment_layer_viewport = ogl_LOAD_FAILED; +int ogl_ext_ARB_framebuffer_no_attachments = ogl_LOAD_FAILED; +int ogl_ext_ARB_invalidate_subdata = ogl_LOAD_FAILED; +int ogl_ext_ARB_robust_buffer_access_behavior = ogl_LOAD_FAILED; +int ogl_ext_ARB_stencil_texturing = ogl_LOAD_FAILED; +int ogl_ext_ARB_texture_query_levels = ogl_LOAD_FAILED; +int ogl_ext_ARB_texture_storage_multisample = ogl_LOAD_FAILED; +int ogl_ext_KHR_debug = ogl_LOAD_FAILED; +int ogl_ext_ARB_buffer_storage = ogl_LOAD_FAILED; +int ogl_ext_ARB_clear_texture = ogl_LOAD_FAILED; +int ogl_ext_ARB_enhanced_layouts = ogl_LOAD_FAILED; +int ogl_ext_ARB_multi_bind = ogl_LOAD_FAILED; +int ogl_ext_ARB_query_buffer_object = ogl_LOAD_FAILED; +int ogl_ext_ARB_texture_mirror_clamp_to_edge = ogl_LOAD_FAILED; +int ogl_ext_ARB_texture_stencil8 = ogl_LOAD_FAILED; +int ogl_ext_ARB_vertex_type_10f_11f_11f_rev = ogl_LOAD_FAILED; +int ogl_ext_ARB_seamless_cubemap_per_texture = ogl_LOAD_FAILED; +int ogl_ext_ARB_clip_control = ogl_LOAD_FAILED; +int ogl_ext_ARB_conditional_render_inverted = ogl_LOAD_FAILED; +int ogl_ext_ARB_cull_distance = ogl_LOAD_FAILED; +int ogl_ext_ARB_derivative_control = ogl_LOAD_FAILED; +int ogl_ext_ARB_direct_state_access = ogl_LOAD_FAILED; +int ogl_ext_ARB_get_texture_sub_image = ogl_LOAD_FAILED; +int ogl_ext_ARB_shader_texture_image_samples = ogl_LOAD_FAILED; +int ogl_ext_ARB_texture_barrier = ogl_LOAD_FAILED; +int ogl_ext_KHR_context_flush_control = ogl_LOAD_FAILED; +int ogl_ext_KHR_robust_buffer_access_behavior = ogl_LOAD_FAILED; +int ogl_ext_KHR_robustness = ogl_LOAD_FAILED; +int ogl_ext_EXT_texture_compression_s3tc = ogl_LOAD_FAILED; +int ogl_ext_EXT_texture_sRGB = ogl_LOAD_FAILED; +int ogl_ext_EXT_texture_filter_anisotropic = ogl_LOAD_FAILED; + +void (CODEGEN_FUNCPTR *_ptrc_glClearDepthf)(GLfloat d) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDepthRangef)(GLfloat n, GLfloat f) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glReleaseShaderCompiler)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glShaderBinary)(GLsizei count, const GLuint * shaders, GLenum binaryformat, const void * binary, GLsizei length) = NULL; + +static int Load_ARB_ES2_compatibility(void) +{ + int numFailed = 0; + _ptrc_glClearDepthf = (void (CODEGEN_FUNCPTR *)(GLfloat))IntGetProcAddress("glClearDepthf"); + if(!_ptrc_glClearDepthf) numFailed++; + _ptrc_glDepthRangef = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat))IntGetProcAddress("glDepthRangef"); + if(!_ptrc_glDepthRangef) numFailed++; + _ptrc_glGetShaderPrecisionFormat = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *, GLint *))IntGetProcAddress("glGetShaderPrecisionFormat"); + if(!_ptrc_glGetShaderPrecisionFormat) numFailed++; + _ptrc_glReleaseShaderCompiler = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glReleaseShaderCompiler"); + if(!_ptrc_glReleaseShaderCompiler) numFailed++; + _ptrc_glShaderBinary = (void (CODEGEN_FUNCPTR *)(GLsizei, const GLuint *, GLenum, const void *, GLsizei))IntGetProcAddress("glShaderBinary"); + if(!_ptrc_glShaderBinary) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glGetProgramBinary)(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramBinary)(GLuint program, GLenum binaryFormat, const void * binary, GLsizei length) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramParameteri)(GLuint program, GLenum pname, GLint value) = NULL; + +static int Load_ARB_get_program_binary(void) +{ + int numFailed = 0; + _ptrc_glGetProgramBinary = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLsizei *, GLenum *, void *))IntGetProcAddress("glGetProgramBinary"); + if(!_ptrc_glGetProgramBinary) numFailed++; + _ptrc_glProgramBinary = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, const void *, GLsizei))IntGetProcAddress("glProgramBinary"); + if(!_ptrc_glProgramBinary) numFailed++; + _ptrc_glProgramParameteri = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint))IntGetProcAddress("glProgramParameteri"); + if(!_ptrc_glProgramParameteri) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glGetInternalformativ)(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint * params) = NULL; + +static int Load_ARB_internalformat_query(void) +{ + int numFailed = 0; + _ptrc_glGetInternalformativ = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLsizei, GLint *))IntGetProcAddress("glGetInternalformativ"); + if(!_ptrc_glGetInternalformativ) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glGetInternalformati64v)(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 * params) = NULL; + +static int Load_ARB_internalformat_query2(void) +{ + int numFailed = 0; + _ptrc_glGetInternalformati64v = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLsizei, GLint64 *))IntGetProcAddress("glGetInternalformati64v"); + if(!_ptrc_glGetInternalformati64v) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glGetProgramInterfaceiv)(GLuint program, GLenum programInterface, GLenum pname, GLint * params) = NULL; +GLuint (CODEGEN_FUNCPTR *_ptrc_glGetProgramResourceIndex)(GLuint program, GLenum programInterface, const GLchar * name) = NULL; +GLint (CODEGEN_FUNCPTR *_ptrc_glGetProgramResourceLocation)(GLuint program, GLenum programInterface, const GLchar * name) = NULL; +GLint (CODEGEN_FUNCPTR *_ptrc_glGetProgramResourceLocationIndex)(GLuint program, GLenum programInterface, const GLchar * name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetProgramResourceName)(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetProgramResourceiv)(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) = NULL; + +static int Load_ARB_program_interface_query(void) +{ + int numFailed = 0; + _ptrc_glGetProgramInterfaceiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLenum, GLint *))IntGetProcAddress("glGetProgramInterfaceiv"); + if(!_ptrc_glGetProgramInterfaceiv) numFailed++; + _ptrc_glGetProgramResourceIndex = (GLuint (CODEGEN_FUNCPTR *)(GLuint, GLenum, const GLchar *))IntGetProcAddress("glGetProgramResourceIndex"); + if(!_ptrc_glGetProgramResourceIndex) numFailed++; + _ptrc_glGetProgramResourceLocation = (GLint (CODEGEN_FUNCPTR *)(GLuint, GLenum, const GLchar *))IntGetProcAddress("glGetProgramResourceLocation"); + if(!_ptrc_glGetProgramResourceLocation) numFailed++; + _ptrc_glGetProgramResourceLocationIndex = (GLint (CODEGEN_FUNCPTR *)(GLuint, GLenum, const GLchar *))IntGetProcAddress("glGetProgramResourceLocationIndex"); + if(!_ptrc_glGetProgramResourceLocationIndex) numFailed++; + _ptrc_glGetProgramResourceName = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *))IntGetProcAddress("glGetProgramResourceName"); + if(!_ptrc_glGetProgramResourceName) numFailed++; + _ptrc_glGetProgramResourceiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint, GLsizei, const GLenum *, GLsizei, GLsizei *, GLint *))IntGetProcAddress("glGetProgramResourceiv"); + if(!_ptrc_glGetProgramResourceiv) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glActiveShaderProgram)(GLuint pipeline, GLuint program) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindProgramPipeline)(GLuint pipeline) = NULL; +GLuint (CODEGEN_FUNCPTR *_ptrc_glCreateShaderProgramv)(GLenum type, GLsizei count, const GLchar *const* strings) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDeleteProgramPipelines)(GLsizei n, const GLuint * pipelines) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGenProgramPipelines)(GLsizei n, GLuint * pipelines) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetProgramPipelineInfoLog)(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetProgramPipelineiv)(GLuint pipeline, GLenum pname, GLint * params) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsProgramPipeline)(GLuint pipeline) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1d)(GLuint program, GLint location, GLdouble v0) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1dv)(GLuint program, GLint location, GLsizei count, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1f)(GLuint program, GLint location, GLfloat v0) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1i)(GLuint program, GLint location, GLint v0) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1iv)(GLuint program, GLint location, GLsizei count, const GLint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1ui)(GLuint program, GLint location, GLuint v0) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2d)(GLuint program, GLint location, GLdouble v0, GLdouble v1) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2dv)(GLuint program, GLint location, GLsizei count, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2f)(GLuint program, GLint location, GLfloat v0, GLfloat v1) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2i)(GLuint program, GLint location, GLint v0, GLint v1) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2iv)(GLuint program, GLint location, GLsizei count, const GLint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2ui)(GLuint program, GLint location, GLuint v0, GLuint v1) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3d)(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3dv)(GLuint program, GLint location, GLsizei count, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3f)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3i)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3iv)(GLuint program, GLint location, GLsizei count, const GLint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3ui)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4d)(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4dv)(GLuint program, GLint location, GLsizei count, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4f)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4i)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4iv)(GLuint program, GLint location, GLsizei count, const GLint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4ui)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2x3dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2x3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2x4dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2x4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3x2dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3x2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3x4dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3x4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4x2dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4x2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4x3dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4x3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUseProgramStages)(GLuint pipeline, GLbitfield stages, GLuint program) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glValidateProgramPipeline)(GLuint pipeline) = NULL; + +static int Load_ARB_separate_shader_objects(void) +{ + int numFailed = 0; + _ptrc_glActiveShaderProgram = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint))IntGetProcAddress("glActiveShaderProgram"); + if(!_ptrc_glActiveShaderProgram) numFailed++; + _ptrc_glBindProgramPipeline = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glBindProgramPipeline"); + if(!_ptrc_glBindProgramPipeline) numFailed++; + _ptrc_glCreateShaderProgramv = (GLuint (CODEGEN_FUNCPTR *)(GLenum, GLsizei, const GLchar *const*))IntGetProcAddress("glCreateShaderProgramv"); + if(!_ptrc_glCreateShaderProgramv) numFailed++; + _ptrc_glDeleteProgramPipelines = (void (CODEGEN_FUNCPTR *)(GLsizei, const GLuint *))IntGetProcAddress("glDeleteProgramPipelines"); + if(!_ptrc_glDeleteProgramPipelines) numFailed++; + _ptrc_glGenProgramPipelines = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glGenProgramPipelines"); + if(!_ptrc_glGenProgramPipelines) numFailed++; + _ptrc_glGetProgramPipelineInfoLog = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLsizei *, GLchar *))IntGetProcAddress("glGetProgramPipelineInfoLog"); + if(!_ptrc_glGetProgramPipelineInfoLog) numFailed++; + _ptrc_glGetProgramPipelineiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetProgramPipelineiv"); + if(!_ptrc_glGetProgramPipelineiv) numFailed++; + _ptrc_glIsProgramPipeline = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIsProgramPipeline"); + if(!_ptrc_glIsProgramPipeline) numFailed++; + _ptrc_glProgramUniform1d = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLdouble))IntGetProcAddress("glProgramUniform1d"); + if(!_ptrc_glProgramUniform1d) numFailed++; + _ptrc_glProgramUniform1dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLdouble *))IntGetProcAddress("glProgramUniform1dv"); + if(!_ptrc_glProgramUniform1dv) numFailed++; + _ptrc_glProgramUniform1f = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLfloat))IntGetProcAddress("glProgramUniform1f"); + if(!_ptrc_glProgramUniform1f) numFailed++; + _ptrc_glProgramUniform1fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLfloat *))IntGetProcAddress("glProgramUniform1fv"); + if(!_ptrc_glProgramUniform1fv) numFailed++; + _ptrc_glProgramUniform1i = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint))IntGetProcAddress("glProgramUniform1i"); + if(!_ptrc_glProgramUniform1i) numFailed++; + _ptrc_glProgramUniform1iv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLint *))IntGetProcAddress("glProgramUniform1iv"); + if(!_ptrc_glProgramUniform1iv) numFailed++; + _ptrc_glProgramUniform1ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLuint))IntGetProcAddress("glProgramUniform1ui"); + if(!_ptrc_glProgramUniform1ui) numFailed++; + _ptrc_glProgramUniform1uiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLuint *))IntGetProcAddress("glProgramUniform1uiv"); + if(!_ptrc_glProgramUniform1uiv) numFailed++; + _ptrc_glProgramUniform2d = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLdouble, GLdouble))IntGetProcAddress("glProgramUniform2d"); + if(!_ptrc_glProgramUniform2d) numFailed++; + _ptrc_glProgramUniform2dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLdouble *))IntGetProcAddress("glProgramUniform2dv"); + if(!_ptrc_glProgramUniform2dv) numFailed++; + _ptrc_glProgramUniform2f = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLfloat, GLfloat))IntGetProcAddress("glProgramUniform2f"); + if(!_ptrc_glProgramUniform2f) numFailed++; + _ptrc_glProgramUniform2fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLfloat *))IntGetProcAddress("glProgramUniform2fv"); + if(!_ptrc_glProgramUniform2fv) numFailed++; + _ptrc_glProgramUniform2i = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint))IntGetProcAddress("glProgramUniform2i"); + if(!_ptrc_glProgramUniform2i) numFailed++; + _ptrc_glProgramUniform2iv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLint *))IntGetProcAddress("glProgramUniform2iv"); + if(!_ptrc_glProgramUniform2iv) numFailed++; + _ptrc_glProgramUniform2ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLuint, GLuint))IntGetProcAddress("glProgramUniform2ui"); + if(!_ptrc_glProgramUniform2ui) numFailed++; + _ptrc_glProgramUniform2uiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLuint *))IntGetProcAddress("glProgramUniform2uiv"); + if(!_ptrc_glProgramUniform2uiv) numFailed++; + _ptrc_glProgramUniform3d = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glProgramUniform3d"); + if(!_ptrc_glProgramUniform3d) numFailed++; + _ptrc_glProgramUniform3dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLdouble *))IntGetProcAddress("glProgramUniform3dv"); + if(!_ptrc_glProgramUniform3dv) numFailed++; + _ptrc_glProgramUniform3f = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glProgramUniform3f"); + if(!_ptrc_glProgramUniform3f) numFailed++; + _ptrc_glProgramUniform3fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLfloat *))IntGetProcAddress("glProgramUniform3fv"); + if(!_ptrc_glProgramUniform3fv) numFailed++; + _ptrc_glProgramUniform3i = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint))IntGetProcAddress("glProgramUniform3i"); + if(!_ptrc_glProgramUniform3i) numFailed++; + _ptrc_glProgramUniform3iv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLint *))IntGetProcAddress("glProgramUniform3iv"); + if(!_ptrc_glProgramUniform3iv) numFailed++; + _ptrc_glProgramUniform3ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLuint, GLuint, GLuint))IntGetProcAddress("glProgramUniform3ui"); + if(!_ptrc_glProgramUniform3ui) numFailed++; + _ptrc_glProgramUniform3uiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLuint *))IntGetProcAddress("glProgramUniform3uiv"); + if(!_ptrc_glProgramUniform3uiv) numFailed++; + _ptrc_glProgramUniform4d = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glProgramUniform4d"); + if(!_ptrc_glProgramUniform4d) numFailed++; + _ptrc_glProgramUniform4dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLdouble *))IntGetProcAddress("glProgramUniform4dv"); + if(!_ptrc_glProgramUniform4dv) numFailed++; + _ptrc_glProgramUniform4f = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glProgramUniform4f"); + if(!_ptrc_glProgramUniform4f) numFailed++; + _ptrc_glProgramUniform4fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLfloat *))IntGetProcAddress("glProgramUniform4fv"); + if(!_ptrc_glProgramUniform4fv) numFailed++; + _ptrc_glProgramUniform4i = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint, GLint))IntGetProcAddress("glProgramUniform4i"); + if(!_ptrc_glProgramUniform4i) numFailed++; + _ptrc_glProgramUniform4iv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLint *))IntGetProcAddress("glProgramUniform4iv"); + if(!_ptrc_glProgramUniform4iv) numFailed++; + _ptrc_glProgramUniform4ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLuint, GLuint, GLuint, GLuint))IntGetProcAddress("glProgramUniform4ui"); + if(!_ptrc_glProgramUniform4ui) numFailed++; + _ptrc_glProgramUniform4uiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, const GLuint *))IntGetProcAddress("glProgramUniform4uiv"); + if(!_ptrc_glProgramUniform4uiv) numFailed++; + _ptrc_glProgramUniformMatrix2dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *))IntGetProcAddress("glProgramUniformMatrix2dv"); + if(!_ptrc_glProgramUniformMatrix2dv) numFailed++; + _ptrc_glProgramUniformMatrix2fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glProgramUniformMatrix2fv"); + if(!_ptrc_glProgramUniformMatrix2fv) numFailed++; + _ptrc_glProgramUniformMatrix2x3dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *))IntGetProcAddress("glProgramUniformMatrix2x3dv"); + if(!_ptrc_glProgramUniformMatrix2x3dv) numFailed++; + _ptrc_glProgramUniformMatrix2x3fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glProgramUniformMatrix2x3fv"); + if(!_ptrc_glProgramUniformMatrix2x3fv) numFailed++; + _ptrc_glProgramUniformMatrix2x4dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *))IntGetProcAddress("glProgramUniformMatrix2x4dv"); + if(!_ptrc_glProgramUniformMatrix2x4dv) numFailed++; + _ptrc_glProgramUniformMatrix2x4fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glProgramUniformMatrix2x4fv"); + if(!_ptrc_glProgramUniformMatrix2x4fv) numFailed++; + _ptrc_glProgramUniformMatrix3dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *))IntGetProcAddress("glProgramUniformMatrix3dv"); + if(!_ptrc_glProgramUniformMatrix3dv) numFailed++; + _ptrc_glProgramUniformMatrix3fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glProgramUniformMatrix3fv"); + if(!_ptrc_glProgramUniformMatrix3fv) numFailed++; + _ptrc_glProgramUniformMatrix3x2dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *))IntGetProcAddress("glProgramUniformMatrix3x2dv"); + if(!_ptrc_glProgramUniformMatrix3x2dv) numFailed++; + _ptrc_glProgramUniformMatrix3x2fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glProgramUniformMatrix3x2fv"); + if(!_ptrc_glProgramUniformMatrix3x2fv) numFailed++; + _ptrc_glProgramUniformMatrix3x4dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *))IntGetProcAddress("glProgramUniformMatrix3x4dv"); + if(!_ptrc_glProgramUniformMatrix3x4dv) numFailed++; + _ptrc_glProgramUniformMatrix3x4fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glProgramUniformMatrix3x4fv"); + if(!_ptrc_glProgramUniformMatrix3x4fv) numFailed++; + _ptrc_glProgramUniformMatrix4dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *))IntGetProcAddress("glProgramUniformMatrix4dv"); + if(!_ptrc_glProgramUniformMatrix4dv) numFailed++; + _ptrc_glProgramUniformMatrix4fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glProgramUniformMatrix4fv"); + if(!_ptrc_glProgramUniformMatrix4fv) numFailed++; + _ptrc_glProgramUniformMatrix4x2dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *))IntGetProcAddress("glProgramUniformMatrix4x2dv"); + if(!_ptrc_glProgramUniformMatrix4x2dv) numFailed++; + _ptrc_glProgramUniformMatrix4x2fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glProgramUniformMatrix4x2fv"); + if(!_ptrc_glProgramUniformMatrix4x2fv) numFailed++; + _ptrc_glProgramUniformMatrix4x3dv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *))IntGetProcAddress("glProgramUniformMatrix4x3dv"); + if(!_ptrc_glProgramUniformMatrix4x3dv) numFailed++; + _ptrc_glProgramUniformMatrix4x3fv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glProgramUniformMatrix4x3fv"); + if(!_ptrc_glProgramUniformMatrix4x3fv) numFailed++; + _ptrc_glUseProgramStages = (void (CODEGEN_FUNCPTR *)(GLuint, GLbitfield, GLuint))IntGetProcAddress("glUseProgramStages"); + if(!_ptrc_glUseProgramStages) numFailed++; + _ptrc_glValidateProgramPipeline = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glValidateProgramPipeline"); + if(!_ptrc_glValidateProgramPipeline) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glTexBufferRange)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) = NULL; + +static int Load_ARB_texture_buffer_range(void) +{ + int numFailed = 0; + _ptrc_glTexBufferRange = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLuint, GLintptr, GLsizeiptr))IntGetProcAddress("glTexBufferRange"); + if(!_ptrc_glTexBufferRange) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glTexStorage1D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexStorage2D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexStorage3D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = NULL; + +static int Load_ARB_texture_storage(void) +{ + int numFailed = 0; + _ptrc_glTexStorage1D = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, GLenum, GLsizei))IntGetProcAddress("glTexStorage1D"); + if(!_ptrc_glTexStorage1D) numFailed++; + _ptrc_glTexStorage2D = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, GLenum, GLsizei, GLsizei))IntGetProcAddress("glTexStorage2D"); + if(!_ptrc_glTexStorage2D) numFailed++; + _ptrc_glTexStorage3D = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei))IntGetProcAddress("glTexStorage3D"); + if(!_ptrc_glTexStorage3D) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glTextureView)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) = NULL; + +static int Load_ARB_texture_view(void) +{ + int numFailed = 0; + _ptrc_glTextureView = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint, GLenum, GLuint, GLuint, GLuint, GLuint))IntGetProcAddress("glTextureView"); + if(!_ptrc_glTextureView) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glBindVertexBuffer)(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribBinding)(GLuint attribindex, GLuint bindingindex) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribFormat)(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribIFormat)(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribLFormat)(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexBindingDivisor)(GLuint bindingindex, GLuint divisor) = NULL; + +static int Load_ARB_vertex_attrib_binding(void) +{ + int numFailed = 0; + _ptrc_glBindVertexBuffer = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLintptr, GLsizei))IntGetProcAddress("glBindVertexBuffer"); + if(!_ptrc_glBindVertexBuffer) numFailed++; + _ptrc_glVertexAttribBinding = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint))IntGetProcAddress("glVertexAttribBinding"); + if(!_ptrc_glVertexAttribBinding) numFailed++; + _ptrc_glVertexAttribFormat = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLenum, GLboolean, GLuint))IntGetProcAddress("glVertexAttribFormat"); + if(!_ptrc_glVertexAttribFormat) numFailed++; + _ptrc_glVertexAttribIFormat = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLenum, GLuint))IntGetProcAddress("glVertexAttribIFormat"); + if(!_ptrc_glVertexAttribIFormat) numFailed++; + _ptrc_glVertexAttribLFormat = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLenum, GLuint))IntGetProcAddress("glVertexAttribLFormat"); + if(!_ptrc_glVertexAttribLFormat) numFailed++; + _ptrc_glVertexBindingDivisor = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint))IntGetProcAddress("glVertexBindingDivisor"); + if(!_ptrc_glVertexBindingDivisor) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glDepthRangeArrayv)(GLuint first, GLsizei count, const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDepthRangeIndexed)(GLuint index, GLdouble n, GLdouble f) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetDoublei_v)(GLenum target, GLuint index, GLdouble * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetFloati_v)(GLenum target, GLuint index, GLfloat * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glScissorArrayv)(GLuint first, GLsizei count, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glScissorIndexed)(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glScissorIndexedv)(GLuint index, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glViewportArrayv)(GLuint first, GLsizei count, const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glViewportIndexedf)(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glViewportIndexedfv)(GLuint index, const GLfloat * v) = NULL; + +static int Load_ARB_viewport_array(void) +{ + int numFailed = 0; + _ptrc_glDepthRangeArrayv = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLdouble *))IntGetProcAddress("glDepthRangeArrayv"); + if(!_ptrc_glDepthRangeArrayv) numFailed++; + _ptrc_glDepthRangeIndexed = (void (CODEGEN_FUNCPTR *)(GLuint, GLdouble, GLdouble))IntGetProcAddress("glDepthRangeIndexed"); + if(!_ptrc_glDepthRangeIndexed) numFailed++; + _ptrc_glGetDoublei_v = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLdouble *))IntGetProcAddress("glGetDoublei_v"); + if(!_ptrc_glGetDoublei_v) numFailed++; + _ptrc_glGetFloati_v = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLfloat *))IntGetProcAddress("glGetFloati_v"); + if(!_ptrc_glGetFloati_v) numFailed++; + _ptrc_glScissorArrayv = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLint *))IntGetProcAddress("glScissorArrayv"); + if(!_ptrc_glScissorArrayv) numFailed++; + _ptrc_glScissorIndexed = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLsizei, GLsizei))IntGetProcAddress("glScissorIndexed"); + if(!_ptrc_glScissorIndexed) numFailed++; + _ptrc_glScissorIndexedv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLint *))IntGetProcAddress("glScissorIndexedv"); + if(!_ptrc_glScissorIndexedv) numFailed++; + _ptrc_glViewportArrayv = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLfloat *))IntGetProcAddress("glViewportArrayv"); + if(!_ptrc_glViewportArrayv) numFailed++; + _ptrc_glViewportIndexedf = (void (CODEGEN_FUNCPTR *)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glViewportIndexedf"); + if(!_ptrc_glViewportIndexedf) numFailed++; + _ptrc_glViewportIndexedfv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLfloat *))IntGetProcAddress("glViewportIndexedfv"); + if(!_ptrc_glViewportIndexedfv) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glClearBufferData)(GLenum target, GLenum internalformat, GLenum format, GLenum type, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearBufferSubData)(GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data) = NULL; + +static int Load_ARB_clear_buffer_object(void) +{ + int numFailed = 0; + _ptrc_glClearBufferData = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLenum, const void *))IntGetProcAddress("glClearBufferData"); + if(!_ptrc_glClearBufferData) numFailed++; + _ptrc_glClearBufferSubData = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLintptr, GLsizeiptr, GLenum, GLenum, const void *))IntGetProcAddress("glClearBufferSubData"); + if(!_ptrc_glClearBufferSubData) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glCopyImageSubData)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) = NULL; + +static int Load_ARB_copy_image(void) +{ + int numFailed = 0; + _ptrc_glCopyImageSubData = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint, GLint, GLint, GLint, GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei))IntGetProcAddress("glCopyImageSubData"); + if(!_ptrc_glCopyImageSubData) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glFramebufferParameteri)(GLenum target, GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetFramebufferParameteriv)(GLenum target, GLenum pname, GLint * params) = NULL; + +static int Load_ARB_framebuffer_no_attachments(void) +{ + int numFailed = 0; + _ptrc_glFramebufferParameteri = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint))IntGetProcAddress("glFramebufferParameteri"); + if(!_ptrc_glFramebufferParameteri) numFailed++; + _ptrc_glGetFramebufferParameteriv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetFramebufferParameteriv"); + if(!_ptrc_glGetFramebufferParameteriv) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glInvalidateBufferData)(GLuint buffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glInvalidateBufferSubData)(GLuint buffer, GLintptr offset, GLsizeiptr length) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glInvalidateFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum * attachments) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glInvalidateSubFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glInvalidateTexImage)(GLuint texture, GLint level) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glInvalidateTexSubImage)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = NULL; + +static int Load_ARB_invalidate_subdata(void) +{ + int numFailed = 0; + _ptrc_glInvalidateBufferData = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glInvalidateBufferData"); + if(!_ptrc_glInvalidateBufferData) numFailed++; + _ptrc_glInvalidateBufferSubData = (void (CODEGEN_FUNCPTR *)(GLuint, GLintptr, GLsizeiptr))IntGetProcAddress("glInvalidateBufferSubData"); + if(!_ptrc_glInvalidateBufferSubData) numFailed++; + _ptrc_glInvalidateFramebuffer = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, const GLenum *))IntGetProcAddress("glInvalidateFramebuffer"); + if(!_ptrc_glInvalidateFramebuffer) numFailed++; + _ptrc_glInvalidateSubFramebuffer = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, const GLenum *, GLint, GLint, GLsizei, GLsizei))IntGetProcAddress("glInvalidateSubFramebuffer"); + if(!_ptrc_glInvalidateSubFramebuffer) numFailed++; + _ptrc_glInvalidateTexImage = (void (CODEGEN_FUNCPTR *)(GLuint, GLint))IntGetProcAddress("glInvalidateTexImage"); + if(!_ptrc_glInvalidateTexImage) numFailed++; + _ptrc_glInvalidateTexSubImage = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei))IntGetProcAddress("glInvalidateTexSubImage"); + if(!_ptrc_glInvalidateTexSubImage) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glTexStorage2DMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexStorage3DMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) = NULL; + +static int Load_ARB_texture_storage_multisample(void) +{ + int numFailed = 0; + _ptrc_glTexStorage2DMultisample = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean))IntGetProcAddress("glTexStorage2DMultisample"); + if(!_ptrc_glTexStorage2DMultisample) numFailed++; + _ptrc_glTexStorage3DMultisample = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean))IntGetProcAddress("glTexStorage3DMultisample"); + if(!_ptrc_glTexStorage3DMultisample) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glDebugMessageCallback)(GLDEBUGPROC callback, const void * userParam) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDebugMessageControl)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDebugMessageInsert)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf) = NULL; +GLuint (CODEGEN_FUNCPTR *_ptrc_glGetDebugMessageLog)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetObjectLabel)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetObjectPtrLabel)(const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetPointerv)(GLenum pname, void ** params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glObjectLabel)(GLenum identifier, GLuint name, GLsizei length, const GLchar * label) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glObjectPtrLabel)(const void * ptr, GLsizei length, const GLchar * label) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPopDebugGroup)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPushDebugGroup)(GLenum source, GLuint id, GLsizei length, const GLchar * message) = NULL; + +static int Load_KHR_debug(void) +{ + int numFailed = 0; + _ptrc_glDebugMessageCallback = (void (CODEGEN_FUNCPTR *)(GLDEBUGPROC, const void *))IntGetProcAddress("glDebugMessageCallback"); + if(!_ptrc_glDebugMessageCallback) numFailed++; + _ptrc_glDebugMessageControl = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLsizei, const GLuint *, GLboolean))IntGetProcAddress("glDebugMessageControl"); + if(!_ptrc_glDebugMessageControl) numFailed++; + _ptrc_glDebugMessageInsert = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *))IntGetProcAddress("glDebugMessageInsert"); + if(!_ptrc_glDebugMessageInsert) numFailed++; + _ptrc_glGetDebugMessageLog = (GLuint (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLenum *, GLenum *, GLuint *, GLenum *, GLsizei *, GLchar *))IntGetProcAddress("glGetDebugMessageLog"); + if(!_ptrc_glGetDebugMessageLog) numFailed++; + _ptrc_glGetObjectLabel = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *))IntGetProcAddress("glGetObjectLabel"); + if(!_ptrc_glGetObjectLabel) numFailed++; + _ptrc_glGetObjectPtrLabel = (void (CODEGEN_FUNCPTR *)(const void *, GLsizei, GLsizei *, GLchar *))IntGetProcAddress("glGetObjectPtrLabel"); + if(!_ptrc_glGetObjectPtrLabel) numFailed++; + _ptrc_glGetPointerv = (void (CODEGEN_FUNCPTR *)(GLenum, void **))IntGetProcAddress("glGetPointerv"); + if(!_ptrc_glGetPointerv) numFailed++; + _ptrc_glObjectLabel = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLsizei, const GLchar *))IntGetProcAddress("glObjectLabel"); + if(!_ptrc_glObjectLabel) numFailed++; + _ptrc_glObjectPtrLabel = (void (CODEGEN_FUNCPTR *)(const void *, GLsizei, const GLchar *))IntGetProcAddress("glObjectPtrLabel"); + if(!_ptrc_glObjectPtrLabel) numFailed++; + _ptrc_glPopDebugGroup = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glPopDebugGroup"); + if(!_ptrc_glPopDebugGroup) numFailed++; + _ptrc_glPushDebugGroup = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLsizei, const GLchar *))IntGetProcAddress("glPushDebugGroup"); + if(!_ptrc_glPushDebugGroup) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glBufferStorage)(GLenum target, GLsizeiptr size, const void * data, GLbitfield flags) = NULL; + +static int Load_ARB_buffer_storage(void) +{ + int numFailed = 0; + _ptrc_glBufferStorage = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizeiptr, const void *, GLbitfield))IntGetProcAddress("glBufferStorage"); + if(!_ptrc_glBufferStorage) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glClearTexImage)(GLuint texture, GLint level, GLenum format, GLenum type, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearTexSubImage)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * data) = NULL; + +static int Load_ARB_clear_texture(void) +{ + int numFailed = 0; + _ptrc_glClearTexImage = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLenum, GLenum, const void *))IntGetProcAddress("glClearTexImage"); + if(!_ptrc_glClearTexImage) numFailed++; + _ptrc_glClearTexSubImage = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *))IntGetProcAddress("glClearTexSubImage"); + if(!_ptrc_glClearTexSubImage) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glBindBuffersBase)(GLenum target, GLuint first, GLsizei count, const GLuint * buffers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindBuffersRange)(GLenum target, GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizeiptr * sizes) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindImageTextures)(GLuint first, GLsizei count, const GLuint * textures) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindSamplers)(GLuint first, GLsizei count, const GLuint * samplers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindTextures)(GLuint first, GLsizei count, const GLuint * textures) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindVertexBuffers)(GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizei * strides) = NULL; + +static int Load_ARB_multi_bind(void) +{ + int numFailed = 0; + _ptrc_glBindBuffersBase = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLsizei, const GLuint *))IntGetProcAddress("glBindBuffersBase"); + if(!_ptrc_glBindBuffersBase) numFailed++; + _ptrc_glBindBuffersRange = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizeiptr *))IntGetProcAddress("glBindBuffersRange"); + if(!_ptrc_glBindBuffersRange) numFailed++; + _ptrc_glBindImageTextures = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLuint *))IntGetProcAddress("glBindImageTextures"); + if(!_ptrc_glBindImageTextures) numFailed++; + _ptrc_glBindSamplers = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLuint *))IntGetProcAddress("glBindSamplers"); + if(!_ptrc_glBindSamplers) numFailed++; + _ptrc_glBindTextures = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLuint *))IntGetProcAddress("glBindTextures"); + if(!_ptrc_glBindTextures) numFailed++; + _ptrc_glBindVertexBuffers = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizei *))IntGetProcAddress("glBindVertexBuffers"); + if(!_ptrc_glBindVertexBuffers) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glClipControl)(GLenum origin, GLenum depth) = NULL; + +static int Load_ARB_clip_control(void) +{ + int numFailed = 0; + _ptrc_glClipControl = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum))IntGetProcAddress("glClipControl"); + if(!_ptrc_glClipControl) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glBindTextureUnit)(GLuint unit, GLuint texture) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBlitNamedFramebuffer)(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) = NULL; +GLenum (CODEGEN_FUNCPTR *_ptrc_glCheckNamedFramebufferStatus)(GLuint framebuffer, GLenum target) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearNamedBufferData)(GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearNamedBufferSubData)(GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearNamedFramebufferfi)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat depth, GLint stencil) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearNamedFramebufferfv)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearNamedFramebufferiv)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearNamedFramebufferuiv)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCompressedTextureSubImage1D)(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCompressedTextureSubImage2D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCompressedTextureSubImage3D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCopyNamedBufferSubData)(GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCopyTextureSubImage1D)(GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCopyTextureSubImage2D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCopyTextureSubImage3D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCreateBuffers)(GLsizei n, GLuint * buffers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCreateFramebuffers)(GLsizei n, GLuint * framebuffers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCreateProgramPipelines)(GLsizei n, GLuint * pipelines) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCreateQueries)(GLenum target, GLsizei n, GLuint * ids) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCreateRenderbuffers)(GLsizei n, GLuint * renderbuffers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCreateSamplers)(GLsizei n, GLuint * samplers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCreateTextures)(GLenum target, GLsizei n, GLuint * textures) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCreateTransformFeedbacks)(GLsizei n, GLuint * ids) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCreateVertexArrays)(GLsizei n, GLuint * arrays) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDisableVertexArrayAttrib)(GLuint vaobj, GLuint index) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEnableVertexArrayAttrib)(GLuint vaobj, GLuint index) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFlushMappedNamedBufferRange)(GLuint buffer, GLintptr offset, GLsizeiptr length) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGenerateTextureMipmap)(GLuint texture) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetCompressedTextureImage)(GLuint texture, GLint level, GLsizei bufSize, void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetNamedBufferParameteri64v)(GLuint buffer, GLenum pname, GLint64 * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetNamedBufferParameteriv)(GLuint buffer, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetNamedBufferPointerv)(GLuint buffer, GLenum pname, void ** params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetNamedBufferSubData)(GLuint buffer, GLintptr offset, GLsizeiptr size, void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetNamedFramebufferAttachmentParameteriv)(GLuint framebuffer, GLenum attachment, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetNamedFramebufferParameteriv)(GLuint framebuffer, GLenum pname, GLint * param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetNamedRenderbufferParameteriv)(GLuint renderbuffer, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetQueryBufferObjecti64v)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetQueryBufferObjectiv)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetQueryBufferObjectui64v)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetQueryBufferObjectuiv)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTextureImage)(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTextureLevelParameterfv)(GLuint texture, GLint level, GLenum pname, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTextureLevelParameteriv)(GLuint texture, GLint level, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTextureParameterIiv)(GLuint texture, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTextureParameterIuiv)(GLuint texture, GLenum pname, GLuint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTextureParameterfv)(GLuint texture, GLenum pname, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTextureParameteriv)(GLuint texture, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTransformFeedbacki64_v)(GLuint xfb, GLenum pname, GLuint index, GLint64 * param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTransformFeedbacki_v)(GLuint xfb, GLenum pname, GLuint index, GLint * param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTransformFeedbackiv)(GLuint xfb, GLenum pname, GLint * param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetVertexArrayIndexed64iv)(GLuint vaobj, GLuint index, GLenum pname, GLint64 * param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetVertexArrayIndexediv)(GLuint vaobj, GLuint index, GLenum pname, GLint * param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetVertexArrayiv)(GLuint vaobj, GLenum pname, GLint * param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glInvalidateNamedFramebufferData)(GLuint framebuffer, GLsizei numAttachments, const GLenum * attachments) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glInvalidateNamedFramebufferSubData)(GLuint framebuffer, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height) = NULL; +void * (CODEGEN_FUNCPTR *_ptrc_glMapNamedBuffer)(GLuint buffer, GLenum access) = NULL; +void * (CODEGEN_FUNCPTR *_ptrc_glMapNamedBufferRange)(GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedBufferData)(GLuint buffer, GLsizeiptr size, const void * data, GLenum usage) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedBufferStorage)(GLuint buffer, GLsizeiptr size, const void * data, GLbitfield flags) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedBufferSubData)(GLuint buffer, GLintptr offset, GLsizeiptr size, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferDrawBuffer)(GLuint framebuffer, GLenum buf) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferDrawBuffers)(GLuint framebuffer, GLsizei n, const GLenum * bufs) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferParameteri)(GLuint framebuffer, GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferReadBuffer)(GLuint framebuffer, GLenum src) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferRenderbuffer)(GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferTexture)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferTextureLayer)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedRenderbufferStorage)(GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNamedRenderbufferStorageMultisample)(GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureBuffer)(GLuint texture, GLenum internalformat, GLuint buffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureBufferRange)(GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureParameterIiv)(GLuint texture, GLenum pname, const GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureParameterIuiv)(GLuint texture, GLenum pname, const GLuint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureParameterf)(GLuint texture, GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureParameterfv)(GLuint texture, GLenum pname, const GLfloat * param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureParameteri)(GLuint texture, GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureParameteriv)(GLuint texture, GLenum pname, const GLint * param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureStorage1D)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureStorage2D)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureStorage2DMultisample)(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureStorage3D)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureStorage3DMultisample)(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureSubImage1D)(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureSubImage2D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTextureSubImage3D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTransformFeedbackBufferBase)(GLuint xfb, GLuint index, GLuint buffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTransformFeedbackBufferRange)(GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glUnmapNamedBuffer)(GLuint buffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayAttribBinding)(GLuint vaobj, GLuint attribindex, GLuint bindingindex) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayAttribFormat)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayAttribIFormat)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayAttribLFormat)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayBindingDivisor)(GLuint vaobj, GLuint bindingindex, GLuint divisor) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayElementBuffer)(GLuint vaobj, GLuint buffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayVertexBuffer)(GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayVertexBuffers)(GLuint vaobj, GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizei * strides) = NULL; + +static int Load_ARB_direct_state_access(void) +{ + int numFailed = 0; + _ptrc_glBindTextureUnit = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint))IntGetProcAddress("glBindTextureUnit"); + if(!_ptrc_glBindTextureUnit) numFailed++; + _ptrc_glBlitNamedFramebuffer = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum))IntGetProcAddress("glBlitNamedFramebuffer"); + if(!_ptrc_glBlitNamedFramebuffer) numFailed++; + _ptrc_glCheckNamedFramebufferStatus = (GLenum (CODEGEN_FUNCPTR *)(GLuint, GLenum))IntGetProcAddress("glCheckNamedFramebufferStatus"); + if(!_ptrc_glCheckNamedFramebufferStatus) numFailed++; + _ptrc_glClearNamedBufferData = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLenum, GLenum, const void *))IntGetProcAddress("glClearNamedBufferData"); + if(!_ptrc_glClearNamedBufferData) numFailed++; + _ptrc_glClearNamedBufferSubData = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLintptr, GLsizeiptr, GLenum, GLenum, const void *))IntGetProcAddress("glClearNamedBufferSubData"); + if(!_ptrc_glClearNamedBufferSubData) numFailed++; + _ptrc_glClearNamedFramebufferfi = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint, const GLfloat, GLint))IntGetProcAddress("glClearNamedFramebufferfi"); + if(!_ptrc_glClearNamedFramebufferfi) numFailed++; + _ptrc_glClearNamedFramebufferfv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint, const GLfloat *))IntGetProcAddress("glClearNamedFramebufferfv"); + if(!_ptrc_glClearNamedFramebufferfv) numFailed++; + _ptrc_glClearNamedFramebufferiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint, const GLint *))IntGetProcAddress("glClearNamedFramebufferiv"); + if(!_ptrc_glClearNamedFramebufferiv) numFailed++; + _ptrc_glClearNamedFramebufferuiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint, const GLuint *))IntGetProcAddress("glClearNamedFramebufferuiv"); + if(!_ptrc_glClearNamedFramebufferuiv) numFailed++; + _ptrc_glCompressedTextureSubImage1D = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLsizei, GLenum, GLsizei, const void *))IntGetProcAddress("glCompressedTextureSubImage1D"); + if(!_ptrc_glCompressedTextureSubImage1D) numFailed++; + _ptrc_glCompressedTextureSubImage2D = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *))IntGetProcAddress("glCompressedTextureSubImage2D"); + if(!_ptrc_glCompressedTextureSubImage2D) numFailed++; + _ptrc_glCompressedTextureSubImage3D = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void *))IntGetProcAddress("glCompressedTextureSubImage3D"); + if(!_ptrc_glCompressedTextureSubImage3D) numFailed++; + _ptrc_glCopyNamedBufferSubData = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLintptr, GLintptr, GLsizeiptr))IntGetProcAddress("glCopyNamedBufferSubData"); + if(!_ptrc_glCopyNamedBufferSubData) numFailed++; + _ptrc_glCopyTextureSubImage1D = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint, GLsizei))IntGetProcAddress("glCopyTextureSubImage1D"); + if(!_ptrc_glCopyTextureSubImage1D) numFailed++; + _ptrc_glCopyTextureSubImage2D = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))IntGetProcAddress("glCopyTextureSubImage2D"); + if(!_ptrc_glCopyTextureSubImage2D) numFailed++; + _ptrc_glCopyTextureSubImage3D = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))IntGetProcAddress("glCopyTextureSubImage3D"); + if(!_ptrc_glCopyTextureSubImage3D) numFailed++; + _ptrc_glCreateBuffers = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glCreateBuffers"); + if(!_ptrc_glCreateBuffers) numFailed++; + _ptrc_glCreateFramebuffers = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glCreateFramebuffers"); + if(!_ptrc_glCreateFramebuffers) numFailed++; + _ptrc_glCreateProgramPipelines = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glCreateProgramPipelines"); + if(!_ptrc_glCreateProgramPipelines) numFailed++; + _ptrc_glCreateQueries = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, GLuint *))IntGetProcAddress("glCreateQueries"); + if(!_ptrc_glCreateQueries) numFailed++; + _ptrc_glCreateRenderbuffers = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glCreateRenderbuffers"); + if(!_ptrc_glCreateRenderbuffers) numFailed++; + _ptrc_glCreateSamplers = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glCreateSamplers"); + if(!_ptrc_glCreateSamplers) numFailed++; + _ptrc_glCreateTextures = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, GLuint *))IntGetProcAddress("glCreateTextures"); + if(!_ptrc_glCreateTextures) numFailed++; + _ptrc_glCreateTransformFeedbacks = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glCreateTransformFeedbacks"); + if(!_ptrc_glCreateTransformFeedbacks) numFailed++; + _ptrc_glCreateVertexArrays = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glCreateVertexArrays"); + if(!_ptrc_glCreateVertexArrays) numFailed++; + _ptrc_glDisableVertexArrayAttrib = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint))IntGetProcAddress("glDisableVertexArrayAttrib"); + if(!_ptrc_glDisableVertexArrayAttrib) numFailed++; + _ptrc_glEnableVertexArrayAttrib = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint))IntGetProcAddress("glEnableVertexArrayAttrib"); + if(!_ptrc_glEnableVertexArrayAttrib) numFailed++; + _ptrc_glFlushMappedNamedBufferRange = (void (CODEGEN_FUNCPTR *)(GLuint, GLintptr, GLsizeiptr))IntGetProcAddress("glFlushMappedNamedBufferRange"); + if(!_ptrc_glFlushMappedNamedBufferRange) numFailed++; + _ptrc_glGenerateTextureMipmap = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glGenerateTextureMipmap"); + if(!_ptrc_glGenerateTextureMipmap) numFailed++; + _ptrc_glGetCompressedTextureImage = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, void *))IntGetProcAddress("glGetCompressedTextureImage"); + if(!_ptrc_glGetCompressedTextureImage) numFailed++; + _ptrc_glGetNamedBufferParameteri64v = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint64 *))IntGetProcAddress("glGetNamedBufferParameteri64v"); + if(!_ptrc_glGetNamedBufferParameteri64v) numFailed++; + _ptrc_glGetNamedBufferParameteriv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetNamedBufferParameteriv"); + if(!_ptrc_glGetNamedBufferParameteriv) numFailed++; + _ptrc_glGetNamedBufferPointerv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, void **))IntGetProcAddress("glGetNamedBufferPointerv"); + if(!_ptrc_glGetNamedBufferPointerv) numFailed++; + _ptrc_glGetNamedBufferSubData = (void (CODEGEN_FUNCPTR *)(GLuint, GLintptr, GLsizeiptr, void *))IntGetProcAddress("glGetNamedBufferSubData"); + if(!_ptrc_glGetNamedBufferSubData) numFailed++; + _ptrc_glGetNamedFramebufferAttachmentParameteriv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLenum, GLint *))IntGetProcAddress("glGetNamedFramebufferAttachmentParameteriv"); + if(!_ptrc_glGetNamedFramebufferAttachmentParameteriv) numFailed++; + _ptrc_glGetNamedFramebufferParameteriv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetNamedFramebufferParameteriv"); + if(!_ptrc_glGetNamedFramebufferParameteriv) numFailed++; + _ptrc_glGetNamedRenderbufferParameteriv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetNamedRenderbufferParameteriv"); + if(!_ptrc_glGetNamedRenderbufferParameteriv) numFailed++; + _ptrc_glGetQueryBufferObjecti64v = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLenum, GLintptr))IntGetProcAddress("glGetQueryBufferObjecti64v"); + if(!_ptrc_glGetQueryBufferObjecti64v) numFailed++; + _ptrc_glGetQueryBufferObjectiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLenum, GLintptr))IntGetProcAddress("glGetQueryBufferObjectiv"); + if(!_ptrc_glGetQueryBufferObjectiv) numFailed++; + _ptrc_glGetQueryBufferObjectui64v = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLenum, GLintptr))IntGetProcAddress("glGetQueryBufferObjectui64v"); + if(!_ptrc_glGetQueryBufferObjectui64v) numFailed++; + _ptrc_glGetQueryBufferObjectuiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLenum, GLintptr))IntGetProcAddress("glGetQueryBufferObjectuiv"); + if(!_ptrc_glGetQueryBufferObjectuiv) numFailed++; + _ptrc_glGetTextureImage = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLenum, GLenum, GLsizei, void *))IntGetProcAddress("glGetTextureImage"); + if(!_ptrc_glGetTextureImage) numFailed++; + _ptrc_glGetTextureLevelParameterfv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLenum, GLfloat *))IntGetProcAddress("glGetTextureLevelParameterfv"); + if(!_ptrc_glGetTextureLevelParameterfv) numFailed++; + _ptrc_glGetTextureLevelParameteriv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLenum, GLint *))IntGetProcAddress("glGetTextureLevelParameteriv"); + if(!_ptrc_glGetTextureLevelParameteriv) numFailed++; + _ptrc_glGetTextureParameterIiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetTextureParameterIiv"); + if(!_ptrc_glGetTextureParameterIiv) numFailed++; + _ptrc_glGetTextureParameterIuiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint *))IntGetProcAddress("glGetTextureParameterIuiv"); + if(!_ptrc_glGetTextureParameterIuiv) numFailed++; + _ptrc_glGetTextureParameterfv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLfloat *))IntGetProcAddress("glGetTextureParameterfv"); + if(!_ptrc_glGetTextureParameterfv) numFailed++; + _ptrc_glGetTextureParameteriv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetTextureParameteriv"); + if(!_ptrc_glGetTextureParameteriv) numFailed++; + _ptrc_glGetTransformFeedbacki64_v = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint, GLint64 *))IntGetProcAddress("glGetTransformFeedbacki64_v"); + if(!_ptrc_glGetTransformFeedbacki64_v) numFailed++; + _ptrc_glGetTransformFeedbacki_v = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint, GLint *))IntGetProcAddress("glGetTransformFeedbacki_v"); + if(!_ptrc_glGetTransformFeedbacki_v) numFailed++; + _ptrc_glGetTransformFeedbackiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetTransformFeedbackiv"); + if(!_ptrc_glGetTransformFeedbackiv) numFailed++; + _ptrc_glGetVertexArrayIndexed64iv = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLenum, GLint64 *))IntGetProcAddress("glGetVertexArrayIndexed64iv"); + if(!_ptrc_glGetVertexArrayIndexed64iv) numFailed++; + _ptrc_glGetVertexArrayIndexediv = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLenum, GLint *))IntGetProcAddress("glGetVertexArrayIndexediv"); + if(!_ptrc_glGetVertexArrayIndexediv) numFailed++; + _ptrc_glGetVertexArrayiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetVertexArrayiv"); + if(!_ptrc_glGetVertexArrayiv) numFailed++; + _ptrc_glInvalidateNamedFramebufferData = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLenum *))IntGetProcAddress("glInvalidateNamedFramebufferData"); + if(!_ptrc_glInvalidateNamedFramebufferData) numFailed++; + _ptrc_glInvalidateNamedFramebufferSubData = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLenum *, GLint, GLint, GLsizei, GLsizei))IntGetProcAddress("glInvalidateNamedFramebufferSubData"); + if(!_ptrc_glInvalidateNamedFramebufferSubData) numFailed++; + _ptrc_glMapNamedBuffer = (void * (CODEGEN_FUNCPTR *)(GLuint, GLenum))IntGetProcAddress("glMapNamedBuffer"); + if(!_ptrc_glMapNamedBuffer) numFailed++; + _ptrc_glMapNamedBufferRange = (void * (CODEGEN_FUNCPTR *)(GLuint, GLintptr, GLsizeiptr, GLbitfield))IntGetProcAddress("glMapNamedBufferRange"); + if(!_ptrc_glMapNamedBufferRange) numFailed++; + _ptrc_glNamedBufferData = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizeiptr, const void *, GLenum))IntGetProcAddress("glNamedBufferData"); + if(!_ptrc_glNamedBufferData) numFailed++; + _ptrc_glNamedBufferStorage = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizeiptr, const void *, GLbitfield))IntGetProcAddress("glNamedBufferStorage"); + if(!_ptrc_glNamedBufferStorage) numFailed++; + _ptrc_glNamedBufferSubData = (void (CODEGEN_FUNCPTR *)(GLuint, GLintptr, GLsizeiptr, const void *))IntGetProcAddress("glNamedBufferSubData"); + if(!_ptrc_glNamedBufferSubData) numFailed++; + _ptrc_glNamedFramebufferDrawBuffer = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum))IntGetProcAddress("glNamedFramebufferDrawBuffer"); + if(!_ptrc_glNamedFramebufferDrawBuffer) numFailed++; + _ptrc_glNamedFramebufferDrawBuffers = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLenum *))IntGetProcAddress("glNamedFramebufferDrawBuffers"); + if(!_ptrc_glNamedFramebufferDrawBuffers) numFailed++; + _ptrc_glNamedFramebufferParameteri = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint))IntGetProcAddress("glNamedFramebufferParameteri"); + if(!_ptrc_glNamedFramebufferParameteri) numFailed++; + _ptrc_glNamedFramebufferReadBuffer = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum))IntGetProcAddress("glNamedFramebufferReadBuffer"); + if(!_ptrc_glNamedFramebufferReadBuffer) numFailed++; + _ptrc_glNamedFramebufferRenderbuffer = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLenum, GLuint))IntGetProcAddress("glNamedFramebufferRenderbuffer"); + if(!_ptrc_glNamedFramebufferRenderbuffer) numFailed++; + _ptrc_glNamedFramebufferTexture = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint, GLint))IntGetProcAddress("glNamedFramebufferTexture"); + if(!_ptrc_glNamedFramebufferTexture) numFailed++; + _ptrc_glNamedFramebufferTextureLayer = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint, GLint, GLint))IntGetProcAddress("glNamedFramebufferTextureLayer"); + if(!_ptrc_glNamedFramebufferTextureLayer) numFailed++; + _ptrc_glNamedRenderbufferStorage = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLsizei, GLsizei))IntGetProcAddress("glNamedRenderbufferStorage"); + if(!_ptrc_glNamedRenderbufferStorage) numFailed++; + _ptrc_glNamedRenderbufferStorageMultisample = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLenum, GLsizei, GLsizei))IntGetProcAddress("glNamedRenderbufferStorageMultisample"); + if(!_ptrc_glNamedRenderbufferStorageMultisample) numFailed++; + _ptrc_glTextureBuffer = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint))IntGetProcAddress("glTextureBuffer"); + if(!_ptrc_glTextureBuffer) numFailed++; + _ptrc_glTextureBufferRange = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint, GLintptr, GLsizeiptr))IntGetProcAddress("glTextureBufferRange"); + if(!_ptrc_glTextureBufferRange) numFailed++; + _ptrc_glTextureParameterIiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, const GLint *))IntGetProcAddress("glTextureParameterIiv"); + if(!_ptrc_glTextureParameterIiv) numFailed++; + _ptrc_glTextureParameterIuiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, const GLuint *))IntGetProcAddress("glTextureParameterIuiv"); + if(!_ptrc_glTextureParameterIuiv) numFailed++; + _ptrc_glTextureParameterf = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLfloat))IntGetProcAddress("glTextureParameterf"); + if(!_ptrc_glTextureParameterf) numFailed++; + _ptrc_glTextureParameterfv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, const GLfloat *))IntGetProcAddress("glTextureParameterfv"); + if(!_ptrc_glTextureParameterfv) numFailed++; + _ptrc_glTextureParameteri = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint))IntGetProcAddress("glTextureParameteri"); + if(!_ptrc_glTextureParameteri) numFailed++; + _ptrc_glTextureParameteriv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, const GLint *))IntGetProcAddress("glTextureParameteriv"); + if(!_ptrc_glTextureParameteriv) numFailed++; + _ptrc_glTextureStorage1D = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLenum, GLsizei))IntGetProcAddress("glTextureStorage1D"); + if(!_ptrc_glTextureStorage1D) numFailed++; + _ptrc_glTextureStorage2D = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLenum, GLsizei, GLsizei))IntGetProcAddress("glTextureStorage2D"); + if(!_ptrc_glTextureStorage2D) numFailed++; + _ptrc_glTextureStorage2DMultisample = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLboolean))IntGetProcAddress("glTextureStorage2DMultisample"); + if(!_ptrc_glTextureStorage2DMultisample) numFailed++; + _ptrc_glTextureStorage3D = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLsizei))IntGetProcAddress("glTextureStorage3D"); + if(!_ptrc_glTextureStorage3D) numFailed++; + _ptrc_glTextureStorage3DMultisample = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean))IntGetProcAddress("glTextureStorage3DMultisample"); + if(!_ptrc_glTextureStorage3DMultisample) numFailed++; + _ptrc_glTextureSubImage1D = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLsizei, GLenum, GLenum, const void *))IntGetProcAddress("glTextureSubImage1D"); + if(!_ptrc_glTextureSubImage1D) numFailed++; + _ptrc_glTextureSubImage2D = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void *))IntGetProcAddress("glTextureSubImage2D"); + if(!_ptrc_glTextureSubImage2D) numFailed++; + _ptrc_glTextureSubImage3D = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *))IntGetProcAddress("glTextureSubImage3D"); + if(!_ptrc_glTextureSubImage3D) numFailed++; + _ptrc_glTransformFeedbackBufferBase = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint))IntGetProcAddress("glTransformFeedbackBufferBase"); + if(!_ptrc_glTransformFeedbackBufferBase) numFailed++; + _ptrc_glTransformFeedbackBufferRange = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint, GLintptr, GLsizeiptr))IntGetProcAddress("glTransformFeedbackBufferRange"); + if(!_ptrc_glTransformFeedbackBufferRange) numFailed++; + _ptrc_glUnmapNamedBuffer = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glUnmapNamedBuffer"); + if(!_ptrc_glUnmapNamedBuffer) numFailed++; + _ptrc_glVertexArrayAttribBinding = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint))IntGetProcAddress("glVertexArrayAttribBinding"); + if(!_ptrc_glVertexArrayAttribBinding) numFailed++; + _ptrc_glVertexArrayAttribFormat = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLint, GLenum, GLboolean, GLuint))IntGetProcAddress("glVertexArrayAttribFormat"); + if(!_ptrc_glVertexArrayAttribFormat) numFailed++; + _ptrc_glVertexArrayAttribIFormat = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLint, GLenum, GLuint))IntGetProcAddress("glVertexArrayAttribIFormat"); + if(!_ptrc_glVertexArrayAttribIFormat) numFailed++; + _ptrc_glVertexArrayAttribLFormat = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLint, GLenum, GLuint))IntGetProcAddress("glVertexArrayAttribLFormat"); + if(!_ptrc_glVertexArrayAttribLFormat) numFailed++; + _ptrc_glVertexArrayBindingDivisor = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint))IntGetProcAddress("glVertexArrayBindingDivisor"); + if(!_ptrc_glVertexArrayBindingDivisor) numFailed++; + _ptrc_glVertexArrayElementBuffer = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint))IntGetProcAddress("glVertexArrayElementBuffer"); + if(!_ptrc_glVertexArrayElementBuffer) numFailed++; + _ptrc_glVertexArrayVertexBuffer = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint, GLintptr, GLsizei))IntGetProcAddress("glVertexArrayVertexBuffer"); + if(!_ptrc_glVertexArrayVertexBuffer) numFailed++; + _ptrc_glVertexArrayVertexBuffers = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizei *))IntGetProcAddress("glVertexArrayVertexBuffers"); + if(!_ptrc_glVertexArrayVertexBuffers) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glGetCompressedTextureSubImage)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTextureSubImage)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void * pixels) = NULL; + +static int Load_ARB_get_texture_sub_image(void) +{ + int numFailed = 0; + _ptrc_glGetCompressedTextureSubImage = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, void *))IntGetProcAddress("glGetCompressedTextureSubImage"); + if(!_ptrc_glGetCompressedTextureSubImage) numFailed++; + _ptrc_glGetTextureSubImage = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *))IntGetProcAddress("glGetTextureSubImage"); + if(!_ptrc_glGetTextureSubImage) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glTextureBarrier)(void) = NULL; + +static int Load_ARB_texture_barrier(void) +{ + int numFailed = 0; + _ptrc_glTextureBarrier = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glTextureBarrier"); + if(!_ptrc_glTextureBarrier) numFailed++; + return numFailed; +} + +GLenum (CODEGEN_FUNCPTR *_ptrc_glGetGraphicsResetStatus)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetnUniformfv)(GLuint program, GLint location, GLsizei bufSize, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetnUniformiv)(GLuint program, GLint location, GLsizei bufSize, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetnUniformuiv)(GLuint program, GLint location, GLsizei bufSize, GLuint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glReadnPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data) = NULL; + +static int Load_KHR_robustness(void) +{ + int numFailed = 0; + _ptrc_glGetGraphicsResetStatus = (GLenum (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glGetGraphicsResetStatus"); + if(!_ptrc_glGetGraphicsResetStatus) numFailed++; + _ptrc_glGetnUniformfv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLfloat *))IntGetProcAddress("glGetnUniformfv"); + if(!_ptrc_glGetnUniformfv) numFailed++; + _ptrc_glGetnUniformiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLint *))IntGetProcAddress("glGetnUniformiv"); + if(!_ptrc_glGetnUniformiv) numFailed++; + _ptrc_glGetnUniformuiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLsizei, GLuint *))IntGetProcAddress("glGetnUniformuiv"); + if(!_ptrc_glGetnUniformuiv) numFailed++; + _ptrc_glReadnPixels = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *))IntGetProcAddress("glReadnPixels"); + if(!_ptrc_glReadnPixels) numFailed++; + return numFailed; +} + +void (CODEGEN_FUNCPTR *_ptrc_glAccum)(GLenum op, GLfloat value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glAlphaFunc)(GLenum func, GLfloat ref) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBegin)(GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBitmap)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte * bitmap) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBlendFunc)(GLenum sfactor, GLenum dfactor) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCallList)(GLuint list) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCallLists)(GLsizei n, GLenum type, const void * lists) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClear)(GLbitfield mask) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearAccum)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearDepth)(GLdouble depth) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearIndex)(GLfloat c ) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearStencil)(GLint s) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClipPlane)(GLenum plane, const GLdouble * equation) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3b)(GLbyte red, GLbyte green, GLbyte blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3bv)(const GLbyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3d)(GLdouble red, GLdouble green, GLdouble blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3f)(GLfloat red, GLfloat green, GLfloat blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3i)(GLint red, GLint green, GLint blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3s)(GLshort red, GLshort green, GLshort blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3ub)(GLubyte red, GLubyte green, GLubyte blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3ubv)(const GLubyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3ui)(GLuint red, GLuint green, GLuint blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3uiv)(const GLuint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3us)(GLushort red, GLushort green, GLushort blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor3usv)(const GLushort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4b)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4bv)(const GLbyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4d)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4i)(GLint red, GLint green, GLint blue, GLint alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4s)(GLshort red, GLshort green, GLshort blue, GLshort alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4ubv)(const GLubyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4ui)(GLuint red, GLuint green, GLuint blue, GLuint alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4uiv)(const GLuint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4us)(GLushort red, GLushort green, GLushort blue, GLushort alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColor4usv)(const GLushort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColorMaterial)(GLenum face, GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCullFace)(GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDeleteLists)(GLuint list, GLsizei range) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDepthFunc)(GLenum func) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDepthMask)(GLboolean flag) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDepthRange)(GLdouble ren_near, GLdouble ren_far) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDisable)(GLenum cap) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDrawBuffer)(GLenum buf) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDrawPixels)(GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEdgeFlag)(GLboolean flag) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEdgeFlagv)(const GLboolean * flag) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEnable)(GLenum cap) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEnd)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEndList)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord1d)(GLdouble u) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord1dv)(const GLdouble * u) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord1f)(GLfloat u) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord1fv)(const GLfloat * u) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord2d)(GLdouble u, GLdouble v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord2dv)(const GLdouble * u) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord2f)(GLfloat u, GLfloat v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord2fv)(const GLfloat * u) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalMesh1)(GLenum mode, GLint i1, GLint i2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalMesh2)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalPoint1)(GLint i) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEvalPoint2)(GLint i, GLint j) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFeedbackBuffer)(GLsizei size, GLenum type, GLfloat * buffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFinish)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFlush)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFogf)(GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFogfv)(GLenum pname, const GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFogi)(GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFogiv)(GLenum pname, const GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFrontFace)(GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFrustum)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) = NULL; +GLuint (CODEGEN_FUNCPTR *_ptrc_glGenLists)(GLsizei range) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetBooleanv)(GLenum pname, GLboolean * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetClipPlane)(GLenum plane, GLdouble * equation) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetDoublev)(GLenum pname, GLdouble * data) = NULL; +GLenum (CODEGEN_FUNCPTR *_ptrc_glGetError)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetFloatv)(GLenum pname, GLfloat * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetIntegerv)(GLenum pname, GLint * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetLightfv)(GLenum light, GLenum pname, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetLightiv)(GLenum light, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetMapdv)(GLenum target, GLenum query, GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetMapfv)(GLenum target, GLenum query, GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetMapiv)(GLenum target, GLenum query, GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetMaterialfv)(GLenum face, GLenum pname, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetMaterialiv)(GLenum face, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetPixelMapfv)(GLenum map, GLfloat * values) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetPixelMapuiv)(GLenum map, GLuint * values) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetPixelMapusv)(GLenum map, GLushort * values) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetPolygonStipple)(GLubyte * mask) = NULL; +const GLubyte * (CODEGEN_FUNCPTR *_ptrc_glGetString)(GLenum name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexEnvfv)(GLenum target, GLenum pname, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexEnviv)(GLenum target, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexGendv)(GLenum coord, GLenum pname, GLdouble * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexGenfv)(GLenum coord, GLenum pname, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexGeniv)(GLenum coord, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexImage)(GLenum target, GLint level, GLenum format, GLenum type, void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexLevelParameterfv)(GLenum target, GLint level, GLenum pname, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexParameteriv)(GLenum target, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glHint)(GLenum target, GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexMask)(GLuint mask) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexd)(GLdouble c) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexdv)(const GLdouble * c) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexf)(GLfloat c) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexfv)(const GLfloat * c) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexi)(GLint c) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexiv)(const GLint * c) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexs)(GLshort c) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexsv)(const GLshort * c) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glInitNames)(void) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsEnabled)(GLenum cap) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsList)(GLuint list) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLightModelf)(GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLightModelfv)(GLenum pname, const GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLightModeli)(GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLightModeliv)(GLenum pname, const GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLightf)(GLenum light, GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLightfv)(GLenum light, GLenum pname, const GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLighti)(GLenum light, GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLightiv)(GLenum light, GLenum pname, const GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLineStipple)(GLint factor, GLushort pattern) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLineWidth)(GLfloat width) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glListBase)(GLuint base) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLoadIdentity)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLoadMatrixd)(const GLdouble * m) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLoadMatrixf)(const GLfloat * m) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLoadName)(GLuint name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLogicOp)(GLenum opcode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMap1d)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble * points) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMap1f)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat * points) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMap2d)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble * points) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMap2f)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat * points) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMapGrid1d)(GLint un, GLdouble u1, GLdouble u2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMapGrid1f)(GLint un, GLfloat u1, GLfloat u2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMapGrid2d)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMapGrid2f)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMaterialf)(GLenum face, GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMaterialfv)(GLenum face, GLenum pname, const GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMateriali)(GLenum face, GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMaterialiv)(GLenum face, GLenum pname, const GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMatrixMode)(GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultMatrixd)(const GLdouble * m) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultMatrixf)(const GLfloat * m) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNewList)(GLuint list, GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormal3b)(GLbyte nx, GLbyte ny, GLbyte nz) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormal3bv)(const GLbyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormal3d)(GLdouble nx, GLdouble ny, GLdouble nz) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormal3dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormal3fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormal3i)(GLint nx, GLint ny, GLint nz) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormal3iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormal3s)(GLshort nx, GLshort ny, GLshort nz) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormal3sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glOrtho)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPassThrough)(GLfloat token) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPixelMapfv)(GLenum map, GLsizei mapsize, const GLfloat * values) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPixelMapuiv)(GLenum map, GLsizei mapsize, const GLuint * values) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPixelMapusv)(GLenum map, GLsizei mapsize, const GLushort * values) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPixelStoref)(GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPixelStorei)(GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPixelTransferf)(GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPixelTransferi)(GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPixelZoom)(GLfloat xfactor, GLfloat yfactor) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPointSize)(GLfloat size) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPolygonMode)(GLenum face, GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPolygonStipple)(const GLubyte * mask) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPopAttrib)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPopMatrix)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPopName)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPushAttrib)(GLbitfield mask) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPushMatrix)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPushName)(GLuint name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2d)(GLdouble x, GLdouble y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2f)(GLfloat x, GLfloat y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2i)(GLint x, GLint y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2s)(GLshort x, GLshort y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3d)(GLdouble x, GLdouble y, GLdouble z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3f)(GLfloat x, GLfloat y, GLfloat z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3i)(GLint x, GLint y, GLint z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3s)(GLshort x, GLshort y, GLshort z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4d)(GLdouble x, GLdouble y, GLdouble z, GLdouble w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4i)(GLint x, GLint y, GLint z, GLint w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4s)(GLshort x, GLshort y, GLshort z, GLshort w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glReadBuffer)(GLenum src) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRectd)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRectdv)(const GLdouble * v1, const GLdouble * v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRectf)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRectfv)(const GLfloat * v1, const GLfloat * v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRecti)(GLint x1, GLint y1, GLint x2, GLint y2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRectiv)(const GLint * v1, const GLint * v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRects)(GLshort x1, GLshort y1, GLshort x2, GLshort y2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRectsv)(const GLshort * v1, const GLshort * v2) = NULL; +GLint (CODEGEN_FUNCPTR *_ptrc_glRenderMode)(GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRotated)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glScaled)(GLdouble x, GLdouble y, GLdouble z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glScalef)(GLfloat x, GLfloat y, GLfloat z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSelectBuffer)(GLsizei size, GLuint * buffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glShadeModel)(GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glStencilFunc)(GLenum func, GLint ref, GLuint mask) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glStencilMask)(GLuint mask) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1d)(GLdouble s) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1f)(GLfloat s) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1i)(GLint s) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1s)(GLshort s) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2d)(GLdouble s, GLdouble t) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2f)(GLfloat s, GLfloat t) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2i)(GLint s, GLint t) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2s)(GLshort s, GLshort t) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3d)(GLdouble s, GLdouble t, GLdouble r) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3f)(GLfloat s, GLfloat t, GLfloat r) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3i)(GLint s, GLint t, GLint r) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3s)(GLshort s, GLshort t, GLshort r) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4d)(GLdouble s, GLdouble t, GLdouble r, GLdouble q) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4f)(GLfloat s, GLfloat t, GLfloat r, GLfloat q) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4i)(GLint s, GLint t, GLint r, GLint q) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4s)(GLshort s, GLshort t, GLshort r, GLshort q) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexEnvf)(GLenum target, GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexEnvfv)(GLenum target, GLenum pname, const GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexEnvi)(GLenum target, GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexEnviv)(GLenum target, GLenum pname, const GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexGend)(GLenum coord, GLenum pname, GLdouble param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexGendv)(GLenum coord, GLenum pname, const GLdouble * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexGenf)(GLenum coord, GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexGenfv)(GLenum coord, GLenum pname, const GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexGeni)(GLenum coord, GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexGeniv)(GLenum coord, GLenum pname, const GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexImage1D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexParameterf)(GLenum target, GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexParameterfv)(GLenum target, GLenum pname, const GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexParameteri)(GLenum target, GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexParameteriv)(GLenum target, GLenum pname, const GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTranslated)(GLdouble x, GLdouble y, GLdouble z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTranslatef)(GLfloat x, GLfloat y, GLfloat z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex2d)(GLdouble x, GLdouble y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex2dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex2f)(GLfloat x, GLfloat y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex2fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex2i)(GLint x, GLint y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex2iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex2s)(GLshort x, GLshort y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex2sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex3d)(GLdouble x, GLdouble y, GLdouble z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex3dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex3f)(GLfloat x, GLfloat y, GLfloat z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex3fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex3i)(GLint x, GLint y, GLint z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex3iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex3s)(GLshort x, GLshort y, GLshort z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex3sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex4d)(GLdouble x, GLdouble y, GLdouble z, GLdouble w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex4dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex4fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex4i)(GLint x, GLint y, GLint z, GLint w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex4iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex4s)(GLshort x, GLshort y, GLshort z, GLshort w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertex4sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) = NULL; + +GLboolean (CODEGEN_FUNCPTR *_ptrc_glAreTexturesResident)(GLsizei n, const GLuint * textures, GLboolean * residences) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glArrayElement)(GLint i) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindTexture)(GLenum target, GLuint texture) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColorPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCopyTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCopyTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDeleteTextures)(GLsizei n, const GLuint * textures) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDisableClientState)(GLenum ren_array) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDrawArrays)(GLenum mode, GLint first, GLsizei count) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void * indices) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEdgeFlagPointer)(GLsizei stride, const void * pointer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEnableClientState)(GLenum ren_array) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGenTextures)(GLsizei n, GLuint * textures) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexPointer)(GLenum type, GLsizei stride, const void * pointer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexub)(GLubyte c) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glIndexubv)(const GLubyte * c) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glInterleavedArrays)(GLenum format, GLsizei stride, const void * pointer) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsTexture)(GLuint texture) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glNormalPointer)(GLenum type, GLsizei stride, const void * pointer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPolygonOffset)(GLfloat factor, GLfloat units) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPopClientAttrib)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPrioritizeTextures)(GLsizei n, const GLuint * textures, const GLfloat * priorities) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPushClientAttrib)(GLbitfield mask) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer) = NULL; + +void (CODEGEN_FUNCPTR *_ptrc_glCopyTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels) = NULL; + +void (CODEGEN_FUNCPTR *_ptrc_glActiveTexture)(GLenum texture) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClientActiveTexture)(GLenum texture) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexImage3D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetCompressedTexImage)(GLenum target, GLint level, void * img) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLoadTransposeMatrixd)(const GLdouble * m) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLoadTransposeMatrixf)(const GLfloat * m) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultTransposeMatrixd)(const GLdouble * m) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultTransposeMatrixf)(const GLfloat * m) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1d)(GLenum target, GLdouble s) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1dv)(GLenum target, const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1f)(GLenum target, GLfloat s) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1fv)(GLenum target, const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1i)(GLenum target, GLint s) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1iv)(GLenum target, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1s)(GLenum target, GLshort s) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1sv)(GLenum target, const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2d)(GLenum target, GLdouble s, GLdouble t) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2dv)(GLenum target, const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2f)(GLenum target, GLfloat s, GLfloat t) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2fv)(GLenum target, const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2i)(GLenum target, GLint s, GLint t) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2iv)(GLenum target, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2s)(GLenum target, GLshort s, GLshort t) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2sv)(GLenum target, const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3d)(GLenum target, GLdouble s, GLdouble t, GLdouble r) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3dv)(GLenum target, const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3f)(GLenum target, GLfloat s, GLfloat t, GLfloat r) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3fv)(GLenum target, const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3i)(GLenum target, GLint s, GLint t, GLint r) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3iv)(GLenum target, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3s)(GLenum target, GLshort s, GLshort t, GLshort r) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3sv)(GLenum target, const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4d)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4dv)(GLenum target, const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4fv)(GLenum target, const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4i)(GLenum target, GLint s, GLint t, GLint r, GLint q) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4iv)(GLenum target, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4s)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4sv)(GLenum target, const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSampleCoverage)(GLfloat value, GLboolean invert) = NULL; + +void (CODEGEN_FUNCPTR *_ptrc_glBlendColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBlendEquation)(GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBlendFuncSeparate)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFogCoordPointer)(GLenum type, GLsizei stride, const void * pointer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFogCoordd)(GLdouble coord) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFogCoorddv)(const GLdouble * coord) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFogCoordf)(GLfloat coord) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFogCoordfv)(const GLfloat * coord) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiDrawArrays)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glMultiDrawElements)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPointParameterf)(GLenum pname, GLfloat param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPointParameterfv)(GLenum pname, const GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPointParameteri)(GLenum pname, GLint param) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPointParameteriv)(GLenum pname, const GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3b)(GLbyte red, GLbyte green, GLbyte blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3bv)(const GLbyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3d)(GLdouble red, GLdouble green, GLdouble blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3f)(GLfloat red, GLfloat green, GLfloat blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3i)(GLint red, GLint green, GLint blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3s)(GLshort red, GLshort green, GLshort blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3ub)(GLubyte red, GLubyte green, GLubyte blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3ubv)(const GLubyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3ui)(GLuint red, GLuint green, GLuint blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3uiv)(const GLuint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3us)(GLushort red, GLushort green, GLushort blue) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3usv)(const GLushort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColorPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2d)(GLdouble x, GLdouble y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2f)(GLfloat x, GLfloat y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2i)(GLint x, GLint y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2s)(GLshort x, GLshort y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2sv)(const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3d)(GLdouble x, GLdouble y, GLdouble z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3dv)(const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3f)(GLfloat x, GLfloat y, GLfloat z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3fv)(const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3i)(GLint x, GLint y, GLint z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3iv)(const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3s)(GLshort x, GLshort y, GLshort z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3sv)(const GLshort * v) = NULL; + +void (CODEGEN_FUNCPTR *_ptrc_glBeginQuery)(GLenum target, GLuint id) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindBuffer)(GLenum target, GLuint buffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBufferData)(GLenum target, GLsizeiptr size, const void * data, GLenum usage) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDeleteBuffers)(GLsizei n, const GLuint * buffers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDeleteQueries)(GLsizei n, const GLuint * ids) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEndQuery)(GLenum target) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGenBuffers)(GLsizei n, GLuint * buffers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGenQueries)(GLsizei n, GLuint * ids) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetBufferParameteriv)(GLenum target, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetBufferPointerv)(GLenum target, GLenum pname, void ** params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, void * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetQueryObjectiv)(GLuint id, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetQueryiv)(GLenum target, GLenum pname, GLint * params) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsBuffer)(GLuint buffer) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsQuery)(GLuint id) = NULL; +void * (CODEGEN_FUNCPTR *_ptrc_glMapBuffer)(GLenum target, GLenum access) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glUnmapBuffer)(GLenum target) = NULL; + +void (CODEGEN_FUNCPTR *_ptrc_glAttachShader)(GLuint program, GLuint shader) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindAttribLocation)(GLuint program, GLuint index, const GLchar * name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glCompileShader)(GLuint shader) = NULL; +GLuint (CODEGEN_FUNCPTR *_ptrc_glCreateProgram)(void) = NULL; +GLuint (CODEGEN_FUNCPTR *_ptrc_glCreateShader)(GLenum type) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDeleteProgram)(GLuint program) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDeleteShader)(GLuint shader) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDetachShader)(GLuint program, GLuint shader) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDisableVertexAttribArray)(GLuint index) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDrawBuffers)(GLsizei n, const GLenum * bufs) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEnableVertexAttribArray)(GLuint index) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetAttachedShaders)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders) = NULL; +GLint (CODEGEN_FUNCPTR *_ptrc_glGetAttribLocation)(GLuint program, const GLchar * name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetProgramiv)(GLuint program, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetShaderSource)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetShaderiv)(GLuint shader, GLenum pname, GLint * params) = NULL; +GLint (CODEGEN_FUNCPTR *_ptrc_glGetUniformLocation)(GLuint program, const GLchar * name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetUniformfv)(GLuint program, GLint location, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetUniformiv)(GLuint program, GLint location, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribPointerv)(GLuint index, GLenum pname, void ** pointer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribdv)(GLuint index, GLenum pname, GLdouble * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribiv)(GLuint index, GLenum pname, GLint * params) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsProgram)(GLuint program) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsShader)(GLuint shader) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glLinkProgram)(GLuint program) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glShaderSource)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glStencilMaskSeparate)(GLenum face, GLuint mask) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glStencilOpSeparate)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform1f)(GLint location, GLfloat v0) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform1fv)(GLint location, GLsizei count, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform1i)(GLint location, GLint v0) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform1iv)(GLint location, GLsizei count, const GLint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform2f)(GLint location, GLfloat v0, GLfloat v1) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform2fv)(GLint location, GLsizei count, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform2i)(GLint location, GLint v0, GLint v1) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform2iv)(GLint location, GLsizei count, const GLint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform3fv)(GLint location, GLsizei count, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform3i)(GLint location, GLint v0, GLint v1, GLint v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform3iv)(GLint location, GLsizei count, const GLint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform4f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform4fv)(GLint location, GLsizei count, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform4i)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform4iv)(GLint location, GLsizei count, const GLint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUseProgram)(GLuint program) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glValidateProgram)(GLuint program) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1d)(GLuint index, GLdouble x) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1dv)(GLuint index, const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1f)(GLuint index, GLfloat x) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1fv)(GLuint index, const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1s)(GLuint index, GLshort x) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1sv)(GLuint index, const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2d)(GLuint index, GLdouble x, GLdouble y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2dv)(GLuint index, const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2f)(GLuint index, GLfloat x, GLfloat y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2fv)(GLuint index, const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2s)(GLuint index, GLshort x, GLshort y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2sv)(GLuint index, const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3d)(GLuint index, GLdouble x, GLdouble y, GLdouble z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3dv)(GLuint index, const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3f)(GLuint index, GLfloat x, GLfloat y, GLfloat z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3fv)(GLuint index, const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3s)(GLuint index, GLshort x, GLshort y, GLshort z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3sv)(GLuint index, const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nbv)(GLuint index, const GLbyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Niv)(GLuint index, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nsv)(GLuint index, const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nub)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nubv)(GLuint index, const GLubyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nuiv)(GLuint index, const GLuint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nusv)(GLuint index, const GLushort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4bv)(GLuint index, const GLbyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4d)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4dv)(GLuint index, const GLdouble * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4f)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4fv)(GLuint index, const GLfloat * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4iv)(GLuint index, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4s)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4sv)(GLuint index, const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4ubv)(GLuint index, const GLubyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4uiv)(GLuint index, const GLuint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4usv)(GLuint index, const GLushort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer) = NULL; + +void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix2x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix2x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix3x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix3x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix4x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix4x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) = NULL; + +void (CODEGEN_FUNCPTR *_ptrc_glBeginConditionalRender)(GLuint id, GLenum mode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBeginTransformFeedback)(GLenum primitiveMode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindBufferBase)(GLenum target, GLuint index, GLuint buffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindBufferRange)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindFragDataLocation)(GLuint program, GLuint color, const GLchar * name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindFramebuffer)(GLenum target, GLuint framebuffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindRenderbuffer)(GLenum target, GLuint renderbuffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBindVertexArray)(GLuint ren_array) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glBlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) = NULL; +GLenum (CODEGEN_FUNCPTR *_ptrc_glCheckFramebufferStatus)(GLenum target) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClampColor)(GLenum target, GLenum clamp) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearBufferfi)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearBufferfv)(GLenum buffer, GLint drawbuffer, const GLfloat * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearBufferiv)(GLenum buffer, GLint drawbuffer, const GLint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glClearBufferuiv)(GLenum buffer, GLint drawbuffer, const GLuint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glColorMaski)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDeleteFramebuffers)(GLsizei n, const GLuint * framebuffers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDeleteRenderbuffers)(GLsizei n, const GLuint * renderbuffers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDeleteVertexArrays)(GLsizei n, const GLuint * arrays) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDisablei)(GLenum target, GLuint index) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEnablei)(GLenum target, GLuint index) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEndConditionalRender)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glEndTransformFeedback)(void) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFlushMappedBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFramebufferTexture1D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFramebufferTexture3D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glFramebufferTextureLayer)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGenFramebuffers)(GLsizei n, GLuint * framebuffers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGenRenderbuffers)(GLsizei n, GLuint * renderbuffers) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGenVertexArrays)(GLsizei n, GLuint * arrays) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGenerateMipmap)(GLenum target) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetBooleani_v)(GLenum target, GLuint index, GLboolean * data) = NULL; +GLint (CODEGEN_FUNCPTR *_ptrc_glGetFragDataLocation)(GLuint program, const GLchar * name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetIntegeri_v)(GLenum target, GLuint index, GLint * data) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint * params) = NULL; +const GLubyte * (CODEGEN_FUNCPTR *_ptrc_glGetStringi)(GLenum name, GLuint index) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexParameterIiv)(GLenum target, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTexParameterIuiv)(GLenum target, GLenum pname, GLuint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetTransformFeedbackVarying)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetUniformuiv)(GLuint program, GLint location, GLuint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribIiv)(GLuint index, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribIuiv)(GLuint index, GLenum pname, GLuint * params) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsEnabledi)(GLenum target, GLuint index) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsFramebuffer)(GLuint framebuffer) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsRenderbuffer)(GLuint renderbuffer) = NULL; +GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsVertexArray)(GLuint ren_array) = NULL; +void * (CODEGEN_FUNCPTR *_ptrc_glMapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glRenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexParameterIiv)(GLenum target, GLenum pname, const GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexParameterIuiv)(GLenum target, GLenum pname, const GLuint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTransformFeedbackVaryings)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform1ui)(GLint location, GLuint v0) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform1uiv)(GLint location, GLsizei count, const GLuint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform2ui)(GLint location, GLuint v0, GLuint v1) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform2uiv)(GLint location, GLsizei count, const GLuint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform3ui)(GLint location, GLuint v0, GLuint v1, GLuint v2) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform3uiv)(GLint location, GLsizei count, const GLuint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform4ui)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniform4uiv)(GLint location, GLsizei count, const GLuint * value) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI1i)(GLuint index, GLint x) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI1iv)(GLuint index, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI1ui)(GLuint index, GLuint x) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI1uiv)(GLuint index, const GLuint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI2i)(GLuint index, GLint x, GLint y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI2iv)(GLuint index, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI2ui)(GLuint index, GLuint x, GLuint y) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI2uiv)(GLuint index, const GLuint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI3i)(GLuint index, GLint x, GLint y, GLint z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI3iv)(GLuint index, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI3ui)(GLuint index, GLuint x, GLuint y, GLuint z) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI3uiv)(GLuint index, const GLuint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4bv)(GLuint index, const GLbyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4i)(GLuint index, GLint x, GLint y, GLint z, GLint w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4iv)(GLuint index, const GLint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4sv)(GLuint index, const GLshort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4ubv)(GLuint index, const GLubyte * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4ui)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4uiv)(GLuint index, const GLuint * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4usv)(GLuint index, const GLushort * v) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribIPointer)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer) = NULL; + +void (CODEGEN_FUNCPTR *_ptrc_glCopyBufferSubData)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDrawArraysInstanced)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glDrawElementsInstanced)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetActiveUniformBlockName)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetActiveUniformBlockiv)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetActiveUniformName)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetActiveUniformsiv)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params) = NULL; +GLuint (CODEGEN_FUNCPTR *_ptrc_glGetUniformBlockIndex)(GLuint program, const GLchar * uniformBlockName) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glGetUniformIndices)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glPrimitiveRestartIndex)(GLuint index) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glTexBuffer)(GLenum target, GLenum internalformat, GLuint buffer) = NULL; +void (CODEGEN_FUNCPTR *_ptrc_glUniformBlockBinding)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) = NULL; + +static int Load_Version_3_1(void) +{ + int numFailed = 0; + _ptrc_glAccum = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat))IntGetProcAddress("glAccum"); + if(!_ptrc_glAccum) numFailed++; + _ptrc_glAlphaFunc = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat))IntGetProcAddress("glAlphaFunc"); + if(!_ptrc_glAlphaFunc) numFailed++; + _ptrc_glBegin = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glBegin"); + if(!_ptrc_glBegin) numFailed++; + _ptrc_glBitmap = (void (CODEGEN_FUNCPTR *)(GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat, const GLubyte *))IntGetProcAddress("glBitmap"); + if(!_ptrc_glBitmap) numFailed++; + _ptrc_glBlendFunc = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum))IntGetProcAddress("glBlendFunc"); + if(!_ptrc_glBlendFunc) numFailed++; + _ptrc_glCallList = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glCallList"); + if(!_ptrc_glCallList) numFailed++; + _ptrc_glCallLists = (void (CODEGEN_FUNCPTR *)(GLsizei, GLenum, const void *))IntGetProcAddress("glCallLists"); + if(!_ptrc_glCallLists) numFailed++; + _ptrc_glClear = (void (CODEGEN_FUNCPTR *)(GLbitfield))IntGetProcAddress("glClear"); + if(!_ptrc_glClear) numFailed++; + _ptrc_glClearAccum = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glClearAccum"); + if(!_ptrc_glClearAccum) numFailed++; + _ptrc_glClearColor = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glClearColor"); + if(!_ptrc_glClearColor) numFailed++; + _ptrc_glClearDepth = (void (CODEGEN_FUNCPTR *)(GLdouble))IntGetProcAddress("glClearDepth"); + if(!_ptrc_glClearDepth) numFailed++; + _ptrc_glClearIndex = (void (CODEGEN_FUNCPTR *)(GLfloat))IntGetProcAddress("glClearIndex"); + if(!_ptrc_glClearIndex) numFailed++; + _ptrc_glClearStencil = (void (CODEGEN_FUNCPTR *)(GLint))IntGetProcAddress("glClearStencil"); + if(!_ptrc_glClearStencil) numFailed++; + _ptrc_glClipPlane = (void (CODEGEN_FUNCPTR *)(GLenum, const GLdouble *))IntGetProcAddress("glClipPlane"); + if(!_ptrc_glClipPlane) numFailed++; + _ptrc_glColor3b = (void (CODEGEN_FUNCPTR *)(GLbyte, GLbyte, GLbyte))IntGetProcAddress("glColor3b"); + if(!_ptrc_glColor3b) numFailed++; + _ptrc_glColor3bv = (void (CODEGEN_FUNCPTR *)(const GLbyte *))IntGetProcAddress("glColor3bv"); + if(!_ptrc_glColor3bv) numFailed++; + _ptrc_glColor3d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble))IntGetProcAddress("glColor3d"); + if(!_ptrc_glColor3d) numFailed++; + _ptrc_glColor3dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glColor3dv"); + if(!_ptrc_glColor3dv) numFailed++; + _ptrc_glColor3f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat))IntGetProcAddress("glColor3f"); + if(!_ptrc_glColor3f) numFailed++; + _ptrc_glColor3fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glColor3fv"); + if(!_ptrc_glColor3fv) numFailed++; + _ptrc_glColor3i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint))IntGetProcAddress("glColor3i"); + if(!_ptrc_glColor3i) numFailed++; + _ptrc_glColor3iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glColor3iv"); + if(!_ptrc_glColor3iv) numFailed++; + _ptrc_glColor3s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort))IntGetProcAddress("glColor3s"); + if(!_ptrc_glColor3s) numFailed++; + _ptrc_glColor3sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glColor3sv"); + if(!_ptrc_glColor3sv) numFailed++; + _ptrc_glColor3ub = (void (CODEGEN_FUNCPTR *)(GLubyte, GLubyte, GLubyte))IntGetProcAddress("glColor3ub"); + if(!_ptrc_glColor3ub) numFailed++; + _ptrc_glColor3ubv = (void (CODEGEN_FUNCPTR *)(const GLubyte *))IntGetProcAddress("glColor3ubv"); + if(!_ptrc_glColor3ubv) numFailed++; + _ptrc_glColor3ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint))IntGetProcAddress("glColor3ui"); + if(!_ptrc_glColor3ui) numFailed++; + _ptrc_glColor3uiv = (void (CODEGEN_FUNCPTR *)(const GLuint *))IntGetProcAddress("glColor3uiv"); + if(!_ptrc_glColor3uiv) numFailed++; + _ptrc_glColor3us = (void (CODEGEN_FUNCPTR *)(GLushort, GLushort, GLushort))IntGetProcAddress("glColor3us"); + if(!_ptrc_glColor3us) numFailed++; + _ptrc_glColor3usv = (void (CODEGEN_FUNCPTR *)(const GLushort *))IntGetProcAddress("glColor3usv"); + if(!_ptrc_glColor3usv) numFailed++; + _ptrc_glColor4b = (void (CODEGEN_FUNCPTR *)(GLbyte, GLbyte, GLbyte, GLbyte))IntGetProcAddress("glColor4b"); + if(!_ptrc_glColor4b) numFailed++; + _ptrc_glColor4bv = (void (CODEGEN_FUNCPTR *)(const GLbyte *))IntGetProcAddress("glColor4bv"); + if(!_ptrc_glColor4bv) numFailed++; + _ptrc_glColor4d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glColor4d"); + if(!_ptrc_glColor4d) numFailed++; + _ptrc_glColor4dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glColor4dv"); + if(!_ptrc_glColor4dv) numFailed++; + _ptrc_glColor4f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glColor4f"); + if(!_ptrc_glColor4f) numFailed++; + _ptrc_glColor4fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glColor4fv"); + if(!_ptrc_glColor4fv) numFailed++; + _ptrc_glColor4i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint, GLint))IntGetProcAddress("glColor4i"); + if(!_ptrc_glColor4i) numFailed++; + _ptrc_glColor4iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glColor4iv"); + if(!_ptrc_glColor4iv) numFailed++; + _ptrc_glColor4s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort, GLshort))IntGetProcAddress("glColor4s"); + if(!_ptrc_glColor4s) numFailed++; + _ptrc_glColor4sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glColor4sv"); + if(!_ptrc_glColor4sv) numFailed++; + _ptrc_glColor4ub = (void (CODEGEN_FUNCPTR *)(GLubyte, GLubyte, GLubyte, GLubyte))IntGetProcAddress("glColor4ub"); + if(!_ptrc_glColor4ub) numFailed++; + _ptrc_glColor4ubv = (void (CODEGEN_FUNCPTR *)(const GLubyte *))IntGetProcAddress("glColor4ubv"); + if(!_ptrc_glColor4ubv) numFailed++; + _ptrc_glColor4ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint, GLuint))IntGetProcAddress("glColor4ui"); + if(!_ptrc_glColor4ui) numFailed++; + _ptrc_glColor4uiv = (void (CODEGEN_FUNCPTR *)(const GLuint *))IntGetProcAddress("glColor4uiv"); + if(!_ptrc_glColor4uiv) numFailed++; + _ptrc_glColor4us = (void (CODEGEN_FUNCPTR *)(GLushort, GLushort, GLushort, GLushort))IntGetProcAddress("glColor4us"); + if(!_ptrc_glColor4us) numFailed++; + _ptrc_glColor4usv = (void (CODEGEN_FUNCPTR *)(const GLushort *))IntGetProcAddress("glColor4usv"); + if(!_ptrc_glColor4usv) numFailed++; + _ptrc_glColorMask = (void (CODEGEN_FUNCPTR *)(GLboolean, GLboolean, GLboolean, GLboolean))IntGetProcAddress("glColorMask"); + if(!_ptrc_glColorMask) numFailed++; + _ptrc_glColorMaterial = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum))IntGetProcAddress("glColorMaterial"); + if(!_ptrc_glColorMaterial) numFailed++; + _ptrc_glCopyPixels = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLsizei, GLsizei, GLenum))IntGetProcAddress("glCopyPixels"); + if(!_ptrc_glCopyPixels) numFailed++; + _ptrc_glCullFace = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glCullFace"); + if(!_ptrc_glCullFace) numFailed++; + _ptrc_glDeleteLists = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei))IntGetProcAddress("glDeleteLists"); + if(!_ptrc_glDeleteLists) numFailed++; + _ptrc_glDepthFunc = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glDepthFunc"); + if(!_ptrc_glDepthFunc) numFailed++; + _ptrc_glDepthMask = (void (CODEGEN_FUNCPTR *)(GLboolean))IntGetProcAddress("glDepthMask"); + if(!_ptrc_glDepthMask) numFailed++; + _ptrc_glDepthRange = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble))IntGetProcAddress("glDepthRange"); + if(!_ptrc_glDepthRange) numFailed++; + _ptrc_glDisable = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glDisable"); + if(!_ptrc_glDisable) numFailed++; + _ptrc_glDrawBuffer = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glDrawBuffer"); + if(!_ptrc_glDrawBuffer) numFailed++; + _ptrc_glDrawPixels = (void (CODEGEN_FUNCPTR *)(GLsizei, GLsizei, GLenum, GLenum, const void *))IntGetProcAddress("glDrawPixels"); + if(!_ptrc_glDrawPixels) numFailed++; + _ptrc_glEdgeFlag = (void (CODEGEN_FUNCPTR *)(GLboolean))IntGetProcAddress("glEdgeFlag"); + if(!_ptrc_glEdgeFlag) numFailed++; + _ptrc_glEdgeFlagv = (void (CODEGEN_FUNCPTR *)(const GLboolean *))IntGetProcAddress("glEdgeFlagv"); + if(!_ptrc_glEdgeFlagv) numFailed++; + _ptrc_glEnable = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glEnable"); + if(!_ptrc_glEnable) numFailed++; + _ptrc_glEnd = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glEnd"); + if(!_ptrc_glEnd) numFailed++; + _ptrc_glEndList = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glEndList"); + if(!_ptrc_glEndList) numFailed++; + _ptrc_glEvalCoord1d = (void (CODEGEN_FUNCPTR *)(GLdouble))IntGetProcAddress("glEvalCoord1d"); + if(!_ptrc_glEvalCoord1d) numFailed++; + _ptrc_glEvalCoord1dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glEvalCoord1dv"); + if(!_ptrc_glEvalCoord1dv) numFailed++; + _ptrc_glEvalCoord1f = (void (CODEGEN_FUNCPTR *)(GLfloat))IntGetProcAddress("glEvalCoord1f"); + if(!_ptrc_glEvalCoord1f) numFailed++; + _ptrc_glEvalCoord1fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glEvalCoord1fv"); + if(!_ptrc_glEvalCoord1fv) numFailed++; + _ptrc_glEvalCoord2d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble))IntGetProcAddress("glEvalCoord2d"); + if(!_ptrc_glEvalCoord2d) numFailed++; + _ptrc_glEvalCoord2dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glEvalCoord2dv"); + if(!_ptrc_glEvalCoord2dv) numFailed++; + _ptrc_glEvalCoord2f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat))IntGetProcAddress("glEvalCoord2f"); + if(!_ptrc_glEvalCoord2f) numFailed++; + _ptrc_glEvalCoord2fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glEvalCoord2fv"); + if(!_ptrc_glEvalCoord2fv) numFailed++; + _ptrc_glEvalMesh1 = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint))IntGetProcAddress("glEvalMesh1"); + if(!_ptrc_glEvalMesh1) numFailed++; + _ptrc_glEvalMesh2 = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLint, GLint))IntGetProcAddress("glEvalMesh2"); + if(!_ptrc_glEvalMesh2) numFailed++; + _ptrc_glEvalPoint1 = (void (CODEGEN_FUNCPTR *)(GLint))IntGetProcAddress("glEvalPoint1"); + if(!_ptrc_glEvalPoint1) numFailed++; + _ptrc_glEvalPoint2 = (void (CODEGEN_FUNCPTR *)(GLint, GLint))IntGetProcAddress("glEvalPoint2"); + if(!_ptrc_glEvalPoint2) numFailed++; + _ptrc_glFeedbackBuffer = (void (CODEGEN_FUNCPTR *)(GLsizei, GLenum, GLfloat *))IntGetProcAddress("glFeedbackBuffer"); + if(!_ptrc_glFeedbackBuffer) numFailed++; + _ptrc_glFinish = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glFinish"); + if(!_ptrc_glFinish) numFailed++; + _ptrc_glFlush = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glFlush"); + if(!_ptrc_glFlush) numFailed++; + _ptrc_glFogf = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat))IntGetProcAddress("glFogf"); + if(!_ptrc_glFogf) numFailed++; + _ptrc_glFogfv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLfloat *))IntGetProcAddress("glFogfv"); + if(!_ptrc_glFogfv) numFailed++; + _ptrc_glFogi = (void (CODEGEN_FUNCPTR *)(GLenum, GLint))IntGetProcAddress("glFogi"); + if(!_ptrc_glFogi) numFailed++; + _ptrc_glFogiv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLint *))IntGetProcAddress("glFogiv"); + if(!_ptrc_glFogiv) numFailed++; + _ptrc_glFrontFace = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glFrontFace"); + if(!_ptrc_glFrontFace) numFailed++; + _ptrc_glFrustum = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glFrustum"); + if(!_ptrc_glFrustum) numFailed++; + _ptrc_glGenLists = (GLuint (CODEGEN_FUNCPTR *)(GLsizei))IntGetProcAddress("glGenLists"); + if(!_ptrc_glGenLists) numFailed++; + _ptrc_glGetBooleanv = (void (CODEGEN_FUNCPTR *)(GLenum, GLboolean *))IntGetProcAddress("glGetBooleanv"); + if(!_ptrc_glGetBooleanv) numFailed++; + _ptrc_glGetClipPlane = (void (CODEGEN_FUNCPTR *)(GLenum, GLdouble *))IntGetProcAddress("glGetClipPlane"); + if(!_ptrc_glGetClipPlane) numFailed++; + _ptrc_glGetDoublev = (void (CODEGEN_FUNCPTR *)(GLenum, GLdouble *))IntGetProcAddress("glGetDoublev"); + if(!_ptrc_glGetDoublev) numFailed++; + _ptrc_glGetError = (GLenum (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glGetError"); + if(!_ptrc_glGetError) numFailed++; + _ptrc_glGetFloatv = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat *))IntGetProcAddress("glGetFloatv"); + if(!_ptrc_glGetFloatv) numFailed++; + _ptrc_glGetIntegerv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint *))IntGetProcAddress("glGetIntegerv"); + if(!_ptrc_glGetIntegerv) numFailed++; + _ptrc_glGetLightfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat *))IntGetProcAddress("glGetLightfv"); + if(!_ptrc_glGetLightfv) numFailed++; + _ptrc_glGetLightiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetLightiv"); + if(!_ptrc_glGetLightiv) numFailed++; + _ptrc_glGetMapdv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLdouble *))IntGetProcAddress("glGetMapdv"); + if(!_ptrc_glGetMapdv) numFailed++; + _ptrc_glGetMapfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat *))IntGetProcAddress("glGetMapfv"); + if(!_ptrc_glGetMapfv) numFailed++; + _ptrc_glGetMapiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetMapiv"); + if(!_ptrc_glGetMapiv) numFailed++; + _ptrc_glGetMaterialfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat *))IntGetProcAddress("glGetMaterialfv"); + if(!_ptrc_glGetMaterialfv) numFailed++; + _ptrc_glGetMaterialiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetMaterialiv"); + if(!_ptrc_glGetMaterialiv) numFailed++; + _ptrc_glGetPixelMapfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat *))IntGetProcAddress("glGetPixelMapfv"); + if(!_ptrc_glGetPixelMapfv) numFailed++; + _ptrc_glGetPixelMapuiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint *))IntGetProcAddress("glGetPixelMapuiv"); + if(!_ptrc_glGetPixelMapuiv) numFailed++; + _ptrc_glGetPixelMapusv = (void (CODEGEN_FUNCPTR *)(GLenum, GLushort *))IntGetProcAddress("glGetPixelMapusv"); + if(!_ptrc_glGetPixelMapusv) numFailed++; + _ptrc_glGetPolygonStipple = (void (CODEGEN_FUNCPTR *)(GLubyte *))IntGetProcAddress("glGetPolygonStipple"); + if(!_ptrc_glGetPolygonStipple) numFailed++; + _ptrc_glGetString = (const GLubyte * (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glGetString"); + if(!_ptrc_glGetString) numFailed++; + _ptrc_glGetTexEnvfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat *))IntGetProcAddress("glGetTexEnvfv"); + if(!_ptrc_glGetTexEnvfv) numFailed++; + _ptrc_glGetTexEnviv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetTexEnviv"); + if(!_ptrc_glGetTexEnviv) numFailed++; + _ptrc_glGetTexGendv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLdouble *))IntGetProcAddress("glGetTexGendv"); + if(!_ptrc_glGetTexGendv) numFailed++; + _ptrc_glGetTexGenfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat *))IntGetProcAddress("glGetTexGenfv"); + if(!_ptrc_glGetTexGenfv) numFailed++; + _ptrc_glGetTexGeniv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetTexGeniv"); + if(!_ptrc_glGetTexGeniv) numFailed++; + _ptrc_glGetTexImage = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLenum, GLenum, void *))IntGetProcAddress("glGetTexImage"); + if(!_ptrc_glGetTexImage) numFailed++; + _ptrc_glGetTexLevelParameterfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLenum, GLfloat *))IntGetProcAddress("glGetTexLevelParameterfv"); + if(!_ptrc_glGetTexLevelParameterfv) numFailed++; + _ptrc_glGetTexLevelParameteriv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLenum, GLint *))IntGetProcAddress("glGetTexLevelParameteriv"); + if(!_ptrc_glGetTexLevelParameteriv) numFailed++; + _ptrc_glGetTexParameterfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat *))IntGetProcAddress("glGetTexParameterfv"); + if(!_ptrc_glGetTexParameterfv) numFailed++; + _ptrc_glGetTexParameteriv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetTexParameteriv"); + if(!_ptrc_glGetTexParameteriv) numFailed++; + _ptrc_glHint = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum))IntGetProcAddress("glHint"); + if(!_ptrc_glHint) numFailed++; + _ptrc_glIndexMask = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIndexMask"); + if(!_ptrc_glIndexMask) numFailed++; + _ptrc_glIndexd = (void (CODEGEN_FUNCPTR *)(GLdouble))IntGetProcAddress("glIndexd"); + if(!_ptrc_glIndexd) numFailed++; + _ptrc_glIndexdv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glIndexdv"); + if(!_ptrc_glIndexdv) numFailed++; + _ptrc_glIndexf = (void (CODEGEN_FUNCPTR *)(GLfloat))IntGetProcAddress("glIndexf"); + if(!_ptrc_glIndexf) numFailed++; + _ptrc_glIndexfv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glIndexfv"); + if(!_ptrc_glIndexfv) numFailed++; + _ptrc_glIndexi = (void (CODEGEN_FUNCPTR *)(GLint))IntGetProcAddress("glIndexi"); + if(!_ptrc_glIndexi) numFailed++; + _ptrc_glIndexiv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glIndexiv"); + if(!_ptrc_glIndexiv) numFailed++; + _ptrc_glIndexs = (void (CODEGEN_FUNCPTR *)(GLshort))IntGetProcAddress("glIndexs"); + if(!_ptrc_glIndexs) numFailed++; + _ptrc_glIndexsv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glIndexsv"); + if(!_ptrc_glIndexsv) numFailed++; + _ptrc_glInitNames = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glInitNames"); + if(!_ptrc_glInitNames) numFailed++; + _ptrc_glIsEnabled = (GLboolean (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glIsEnabled"); + if(!_ptrc_glIsEnabled) numFailed++; + _ptrc_glIsList = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIsList"); + if(!_ptrc_glIsList) numFailed++; + _ptrc_glLightModelf = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat))IntGetProcAddress("glLightModelf"); + if(!_ptrc_glLightModelf) numFailed++; + _ptrc_glLightModelfv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLfloat *))IntGetProcAddress("glLightModelfv"); + if(!_ptrc_glLightModelfv) numFailed++; + _ptrc_glLightModeli = (void (CODEGEN_FUNCPTR *)(GLenum, GLint))IntGetProcAddress("glLightModeli"); + if(!_ptrc_glLightModeli) numFailed++; + _ptrc_glLightModeliv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLint *))IntGetProcAddress("glLightModeliv"); + if(!_ptrc_glLightModeliv) numFailed++; + _ptrc_glLightf = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat))IntGetProcAddress("glLightf"); + if(!_ptrc_glLightf) numFailed++; + _ptrc_glLightfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLfloat *))IntGetProcAddress("glLightfv"); + if(!_ptrc_glLightfv) numFailed++; + _ptrc_glLighti = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint))IntGetProcAddress("glLighti"); + if(!_ptrc_glLighti) numFailed++; + _ptrc_glLightiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLint *))IntGetProcAddress("glLightiv"); + if(!_ptrc_glLightiv) numFailed++; + _ptrc_glLineStipple = (void (CODEGEN_FUNCPTR *)(GLint, GLushort))IntGetProcAddress("glLineStipple"); + if(!_ptrc_glLineStipple) numFailed++; + _ptrc_glLineWidth = (void (CODEGEN_FUNCPTR *)(GLfloat))IntGetProcAddress("glLineWidth"); + if(!_ptrc_glLineWidth) numFailed++; + _ptrc_glListBase = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glListBase"); + if(!_ptrc_glListBase) numFailed++; + _ptrc_glLoadIdentity = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glLoadIdentity"); + if(!_ptrc_glLoadIdentity) numFailed++; + _ptrc_glLoadMatrixd = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glLoadMatrixd"); + if(!_ptrc_glLoadMatrixd) numFailed++; + _ptrc_glLoadMatrixf = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glLoadMatrixf"); + if(!_ptrc_glLoadMatrixf) numFailed++; + _ptrc_glLoadName = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glLoadName"); + if(!_ptrc_glLoadName) numFailed++; + _ptrc_glLogicOp = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glLogicOp"); + if(!_ptrc_glLogicOp) numFailed++; + _ptrc_glMap1d = (void (CODEGEN_FUNCPTR *)(GLenum, GLdouble, GLdouble, GLint, GLint, const GLdouble *))IntGetProcAddress("glMap1d"); + if(!_ptrc_glMap1d) numFailed++; + _ptrc_glMap1f = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat, GLfloat, GLint, GLint, const GLfloat *))IntGetProcAddress("glMap1f"); + if(!_ptrc_glMap1f) numFailed++; + _ptrc_glMap2d = (void (CODEGEN_FUNCPTR *)(GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *))IntGetProcAddress("glMap2d"); + if(!_ptrc_glMap2d) numFailed++; + _ptrc_glMap2f = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *))IntGetProcAddress("glMap2f"); + if(!_ptrc_glMap2f) numFailed++; + _ptrc_glMapGrid1d = (void (CODEGEN_FUNCPTR *)(GLint, GLdouble, GLdouble))IntGetProcAddress("glMapGrid1d"); + if(!_ptrc_glMapGrid1d) numFailed++; + _ptrc_glMapGrid1f = (void (CODEGEN_FUNCPTR *)(GLint, GLfloat, GLfloat))IntGetProcAddress("glMapGrid1f"); + if(!_ptrc_glMapGrid1f) numFailed++; + _ptrc_glMapGrid2d = (void (CODEGEN_FUNCPTR *)(GLint, GLdouble, GLdouble, GLint, GLdouble, GLdouble))IntGetProcAddress("glMapGrid2d"); + if(!_ptrc_glMapGrid2d) numFailed++; + _ptrc_glMapGrid2f = (void (CODEGEN_FUNCPTR *)(GLint, GLfloat, GLfloat, GLint, GLfloat, GLfloat))IntGetProcAddress("glMapGrid2f"); + if(!_ptrc_glMapGrid2f) numFailed++; + _ptrc_glMaterialf = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat))IntGetProcAddress("glMaterialf"); + if(!_ptrc_glMaterialf) numFailed++; + _ptrc_glMaterialfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLfloat *))IntGetProcAddress("glMaterialfv"); + if(!_ptrc_glMaterialfv) numFailed++; + _ptrc_glMateriali = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint))IntGetProcAddress("glMateriali"); + if(!_ptrc_glMateriali) numFailed++; + _ptrc_glMaterialiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLint *))IntGetProcAddress("glMaterialiv"); + if(!_ptrc_glMaterialiv) numFailed++; + _ptrc_glMatrixMode = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glMatrixMode"); + if(!_ptrc_glMatrixMode) numFailed++; + _ptrc_glMultMatrixd = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glMultMatrixd"); + if(!_ptrc_glMultMatrixd) numFailed++; + _ptrc_glMultMatrixf = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glMultMatrixf"); + if(!_ptrc_glMultMatrixf) numFailed++; + _ptrc_glNewList = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum))IntGetProcAddress("glNewList"); + if(!_ptrc_glNewList) numFailed++; + _ptrc_glNormal3b = (void (CODEGEN_FUNCPTR *)(GLbyte, GLbyte, GLbyte))IntGetProcAddress("glNormal3b"); + if(!_ptrc_glNormal3b) numFailed++; + _ptrc_glNormal3bv = (void (CODEGEN_FUNCPTR *)(const GLbyte *))IntGetProcAddress("glNormal3bv"); + if(!_ptrc_glNormal3bv) numFailed++; + _ptrc_glNormal3d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble))IntGetProcAddress("glNormal3d"); + if(!_ptrc_glNormal3d) numFailed++; + _ptrc_glNormal3dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glNormal3dv"); + if(!_ptrc_glNormal3dv) numFailed++; + _ptrc_glNormal3f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat))IntGetProcAddress("glNormal3f"); + if(!_ptrc_glNormal3f) numFailed++; + _ptrc_glNormal3fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glNormal3fv"); + if(!_ptrc_glNormal3fv) numFailed++; + _ptrc_glNormal3i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint))IntGetProcAddress("glNormal3i"); + if(!_ptrc_glNormal3i) numFailed++; + _ptrc_glNormal3iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glNormal3iv"); + if(!_ptrc_glNormal3iv) numFailed++; + _ptrc_glNormal3s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort))IntGetProcAddress("glNormal3s"); + if(!_ptrc_glNormal3s) numFailed++; + _ptrc_glNormal3sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glNormal3sv"); + if(!_ptrc_glNormal3sv) numFailed++; + _ptrc_glOrtho = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glOrtho"); + if(!_ptrc_glOrtho) numFailed++; + _ptrc_glPassThrough = (void (CODEGEN_FUNCPTR *)(GLfloat))IntGetProcAddress("glPassThrough"); + if(!_ptrc_glPassThrough) numFailed++; + _ptrc_glPixelMapfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, const GLfloat *))IntGetProcAddress("glPixelMapfv"); + if(!_ptrc_glPixelMapfv) numFailed++; + _ptrc_glPixelMapuiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, const GLuint *))IntGetProcAddress("glPixelMapuiv"); + if(!_ptrc_glPixelMapuiv) numFailed++; + _ptrc_glPixelMapusv = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, const GLushort *))IntGetProcAddress("glPixelMapusv"); + if(!_ptrc_glPixelMapusv) numFailed++; + _ptrc_glPixelStoref = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat))IntGetProcAddress("glPixelStoref"); + if(!_ptrc_glPixelStoref) numFailed++; + _ptrc_glPixelStorei = (void (CODEGEN_FUNCPTR *)(GLenum, GLint))IntGetProcAddress("glPixelStorei"); + if(!_ptrc_glPixelStorei) numFailed++; + _ptrc_glPixelTransferf = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat))IntGetProcAddress("glPixelTransferf"); + if(!_ptrc_glPixelTransferf) numFailed++; + _ptrc_glPixelTransferi = (void (CODEGEN_FUNCPTR *)(GLenum, GLint))IntGetProcAddress("glPixelTransferi"); + if(!_ptrc_glPixelTransferi) numFailed++; + _ptrc_glPixelZoom = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat))IntGetProcAddress("glPixelZoom"); + if(!_ptrc_glPixelZoom) numFailed++; + _ptrc_glPointSize = (void (CODEGEN_FUNCPTR *)(GLfloat))IntGetProcAddress("glPointSize"); + if(!_ptrc_glPointSize) numFailed++; + _ptrc_glPolygonMode = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum))IntGetProcAddress("glPolygonMode"); + if(!_ptrc_glPolygonMode) numFailed++; + _ptrc_glPolygonStipple = (void (CODEGEN_FUNCPTR *)(const GLubyte *))IntGetProcAddress("glPolygonStipple"); + if(!_ptrc_glPolygonStipple) numFailed++; + _ptrc_glPopAttrib = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glPopAttrib"); + if(!_ptrc_glPopAttrib) numFailed++; + _ptrc_glPopMatrix = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glPopMatrix"); + if(!_ptrc_glPopMatrix) numFailed++; + _ptrc_glPopName = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glPopName"); + if(!_ptrc_glPopName) numFailed++; + _ptrc_glPushAttrib = (void (CODEGEN_FUNCPTR *)(GLbitfield))IntGetProcAddress("glPushAttrib"); + if(!_ptrc_glPushAttrib) numFailed++; + _ptrc_glPushMatrix = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glPushMatrix"); + if(!_ptrc_glPushMatrix) numFailed++; + _ptrc_glPushName = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glPushName"); + if(!_ptrc_glPushName) numFailed++; + _ptrc_glRasterPos2d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble))IntGetProcAddress("glRasterPos2d"); + if(!_ptrc_glRasterPos2d) numFailed++; + _ptrc_glRasterPos2dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glRasterPos2dv"); + if(!_ptrc_glRasterPos2dv) numFailed++; + _ptrc_glRasterPos2f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat))IntGetProcAddress("glRasterPos2f"); + if(!_ptrc_glRasterPos2f) numFailed++; + _ptrc_glRasterPos2fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glRasterPos2fv"); + if(!_ptrc_glRasterPos2fv) numFailed++; + _ptrc_glRasterPos2i = (void (CODEGEN_FUNCPTR *)(GLint, GLint))IntGetProcAddress("glRasterPos2i"); + if(!_ptrc_glRasterPos2i) numFailed++; + _ptrc_glRasterPos2iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glRasterPos2iv"); + if(!_ptrc_glRasterPos2iv) numFailed++; + _ptrc_glRasterPos2s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort))IntGetProcAddress("glRasterPos2s"); + if(!_ptrc_glRasterPos2s) numFailed++; + _ptrc_glRasterPos2sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glRasterPos2sv"); + if(!_ptrc_glRasterPos2sv) numFailed++; + _ptrc_glRasterPos3d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble))IntGetProcAddress("glRasterPos3d"); + if(!_ptrc_glRasterPos3d) numFailed++; + _ptrc_glRasterPos3dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glRasterPos3dv"); + if(!_ptrc_glRasterPos3dv) numFailed++; + _ptrc_glRasterPos3f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat))IntGetProcAddress("glRasterPos3f"); + if(!_ptrc_glRasterPos3f) numFailed++; + _ptrc_glRasterPos3fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glRasterPos3fv"); + if(!_ptrc_glRasterPos3fv) numFailed++; + _ptrc_glRasterPos3i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint))IntGetProcAddress("glRasterPos3i"); + if(!_ptrc_glRasterPos3i) numFailed++; + _ptrc_glRasterPos3iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glRasterPos3iv"); + if(!_ptrc_glRasterPos3iv) numFailed++; + _ptrc_glRasterPos3s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort))IntGetProcAddress("glRasterPos3s"); + if(!_ptrc_glRasterPos3s) numFailed++; + _ptrc_glRasterPos3sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glRasterPos3sv"); + if(!_ptrc_glRasterPos3sv) numFailed++; + _ptrc_glRasterPos4d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glRasterPos4d"); + if(!_ptrc_glRasterPos4d) numFailed++; + _ptrc_glRasterPos4dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glRasterPos4dv"); + if(!_ptrc_glRasterPos4dv) numFailed++; + _ptrc_glRasterPos4f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glRasterPos4f"); + if(!_ptrc_glRasterPos4f) numFailed++; + _ptrc_glRasterPos4fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glRasterPos4fv"); + if(!_ptrc_glRasterPos4fv) numFailed++; + _ptrc_glRasterPos4i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint, GLint))IntGetProcAddress("glRasterPos4i"); + if(!_ptrc_glRasterPos4i) numFailed++; + _ptrc_glRasterPos4iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glRasterPos4iv"); + if(!_ptrc_glRasterPos4iv) numFailed++; + _ptrc_glRasterPos4s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort, GLshort))IntGetProcAddress("glRasterPos4s"); + if(!_ptrc_glRasterPos4s) numFailed++; + _ptrc_glRasterPos4sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glRasterPos4sv"); + if(!_ptrc_glRasterPos4sv) numFailed++; + _ptrc_glReadBuffer = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glReadBuffer"); + if(!_ptrc_glReadBuffer) numFailed++; + _ptrc_glReadPixels = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, void *))IntGetProcAddress("glReadPixels"); + if(!_ptrc_glReadPixels) numFailed++; + _ptrc_glRectd = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glRectd"); + if(!_ptrc_glRectd) numFailed++; + _ptrc_glRectdv = (void (CODEGEN_FUNCPTR *)(const GLdouble *, const GLdouble *))IntGetProcAddress("glRectdv"); + if(!_ptrc_glRectdv) numFailed++; + _ptrc_glRectf = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glRectf"); + if(!_ptrc_glRectf) numFailed++; + _ptrc_glRectfv = (void (CODEGEN_FUNCPTR *)(const GLfloat *, const GLfloat *))IntGetProcAddress("glRectfv"); + if(!_ptrc_glRectfv) numFailed++; + _ptrc_glRecti = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint, GLint))IntGetProcAddress("glRecti"); + if(!_ptrc_glRecti) numFailed++; + _ptrc_glRectiv = (void (CODEGEN_FUNCPTR *)(const GLint *, const GLint *))IntGetProcAddress("glRectiv"); + if(!_ptrc_glRectiv) numFailed++; + _ptrc_glRects = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort, GLshort))IntGetProcAddress("glRects"); + if(!_ptrc_glRects) numFailed++; + _ptrc_glRectsv = (void (CODEGEN_FUNCPTR *)(const GLshort *, const GLshort *))IntGetProcAddress("glRectsv"); + if(!_ptrc_glRectsv) numFailed++; + _ptrc_glRenderMode = (GLint (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glRenderMode"); + if(!_ptrc_glRenderMode) numFailed++; + _ptrc_glRotated = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glRotated"); + if(!_ptrc_glRotated) numFailed++; + _ptrc_glRotatef = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glRotatef"); + if(!_ptrc_glRotatef) numFailed++; + _ptrc_glScaled = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble))IntGetProcAddress("glScaled"); + if(!_ptrc_glScaled) numFailed++; + _ptrc_glScalef = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat))IntGetProcAddress("glScalef"); + if(!_ptrc_glScalef) numFailed++; + _ptrc_glScissor = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLsizei, GLsizei))IntGetProcAddress("glScissor"); + if(!_ptrc_glScissor) numFailed++; + _ptrc_glSelectBuffer = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glSelectBuffer"); + if(!_ptrc_glSelectBuffer) numFailed++; + _ptrc_glShadeModel = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glShadeModel"); + if(!_ptrc_glShadeModel) numFailed++; + _ptrc_glStencilFunc = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLuint))IntGetProcAddress("glStencilFunc"); + if(!_ptrc_glStencilFunc) numFailed++; + _ptrc_glStencilMask = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glStencilMask"); + if(!_ptrc_glStencilMask) numFailed++; + _ptrc_glStencilOp = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum))IntGetProcAddress("glStencilOp"); + if(!_ptrc_glStencilOp) numFailed++; + _ptrc_glTexCoord1d = (void (CODEGEN_FUNCPTR *)(GLdouble))IntGetProcAddress("glTexCoord1d"); + if(!_ptrc_glTexCoord1d) numFailed++; + _ptrc_glTexCoord1dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glTexCoord1dv"); + if(!_ptrc_glTexCoord1dv) numFailed++; + _ptrc_glTexCoord1f = (void (CODEGEN_FUNCPTR *)(GLfloat))IntGetProcAddress("glTexCoord1f"); + if(!_ptrc_glTexCoord1f) numFailed++; + _ptrc_glTexCoord1fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glTexCoord1fv"); + if(!_ptrc_glTexCoord1fv) numFailed++; + _ptrc_glTexCoord1i = (void (CODEGEN_FUNCPTR *)(GLint))IntGetProcAddress("glTexCoord1i"); + if(!_ptrc_glTexCoord1i) numFailed++; + _ptrc_glTexCoord1iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glTexCoord1iv"); + if(!_ptrc_glTexCoord1iv) numFailed++; + _ptrc_glTexCoord1s = (void (CODEGEN_FUNCPTR *)(GLshort))IntGetProcAddress("glTexCoord1s"); + if(!_ptrc_glTexCoord1s) numFailed++; + _ptrc_glTexCoord1sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glTexCoord1sv"); + if(!_ptrc_glTexCoord1sv) numFailed++; + _ptrc_glTexCoord2d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble))IntGetProcAddress("glTexCoord2d"); + if(!_ptrc_glTexCoord2d) numFailed++; + _ptrc_glTexCoord2dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glTexCoord2dv"); + if(!_ptrc_glTexCoord2dv) numFailed++; + _ptrc_glTexCoord2f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat))IntGetProcAddress("glTexCoord2f"); + if(!_ptrc_glTexCoord2f) numFailed++; + _ptrc_glTexCoord2fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glTexCoord2fv"); + if(!_ptrc_glTexCoord2fv) numFailed++; + _ptrc_glTexCoord2i = (void (CODEGEN_FUNCPTR *)(GLint, GLint))IntGetProcAddress("glTexCoord2i"); + if(!_ptrc_glTexCoord2i) numFailed++; + _ptrc_glTexCoord2iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glTexCoord2iv"); + if(!_ptrc_glTexCoord2iv) numFailed++; + _ptrc_glTexCoord2s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort))IntGetProcAddress("glTexCoord2s"); + if(!_ptrc_glTexCoord2s) numFailed++; + _ptrc_glTexCoord2sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glTexCoord2sv"); + if(!_ptrc_glTexCoord2sv) numFailed++; + _ptrc_glTexCoord3d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble))IntGetProcAddress("glTexCoord3d"); + if(!_ptrc_glTexCoord3d) numFailed++; + _ptrc_glTexCoord3dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glTexCoord3dv"); + if(!_ptrc_glTexCoord3dv) numFailed++; + _ptrc_glTexCoord3f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat))IntGetProcAddress("glTexCoord3f"); + if(!_ptrc_glTexCoord3f) numFailed++; + _ptrc_glTexCoord3fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glTexCoord3fv"); + if(!_ptrc_glTexCoord3fv) numFailed++; + _ptrc_glTexCoord3i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint))IntGetProcAddress("glTexCoord3i"); + if(!_ptrc_glTexCoord3i) numFailed++; + _ptrc_glTexCoord3iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glTexCoord3iv"); + if(!_ptrc_glTexCoord3iv) numFailed++; + _ptrc_glTexCoord3s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort))IntGetProcAddress("glTexCoord3s"); + if(!_ptrc_glTexCoord3s) numFailed++; + _ptrc_glTexCoord3sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glTexCoord3sv"); + if(!_ptrc_glTexCoord3sv) numFailed++; + _ptrc_glTexCoord4d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glTexCoord4d"); + if(!_ptrc_glTexCoord4d) numFailed++; + _ptrc_glTexCoord4dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glTexCoord4dv"); + if(!_ptrc_glTexCoord4dv) numFailed++; + _ptrc_glTexCoord4f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glTexCoord4f"); + if(!_ptrc_glTexCoord4f) numFailed++; + _ptrc_glTexCoord4fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glTexCoord4fv"); + if(!_ptrc_glTexCoord4fv) numFailed++; + _ptrc_glTexCoord4i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint, GLint))IntGetProcAddress("glTexCoord4i"); + if(!_ptrc_glTexCoord4i) numFailed++; + _ptrc_glTexCoord4iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glTexCoord4iv"); + if(!_ptrc_glTexCoord4iv) numFailed++; + _ptrc_glTexCoord4s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort, GLshort))IntGetProcAddress("glTexCoord4s"); + if(!_ptrc_glTexCoord4s) numFailed++; + _ptrc_glTexCoord4sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glTexCoord4sv"); + if(!_ptrc_glTexCoord4sv) numFailed++; + _ptrc_glTexEnvf = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat))IntGetProcAddress("glTexEnvf"); + if(!_ptrc_glTexEnvf) numFailed++; + _ptrc_glTexEnvfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLfloat *))IntGetProcAddress("glTexEnvfv"); + if(!_ptrc_glTexEnvfv) numFailed++; + _ptrc_glTexEnvi = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint))IntGetProcAddress("glTexEnvi"); + if(!_ptrc_glTexEnvi) numFailed++; + _ptrc_glTexEnviv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLint *))IntGetProcAddress("glTexEnviv"); + if(!_ptrc_glTexEnviv) numFailed++; + _ptrc_glTexGend = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLdouble))IntGetProcAddress("glTexGend"); + if(!_ptrc_glTexGend) numFailed++; + _ptrc_glTexGendv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLdouble *))IntGetProcAddress("glTexGendv"); + if(!_ptrc_glTexGendv) numFailed++; + _ptrc_glTexGenf = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat))IntGetProcAddress("glTexGenf"); + if(!_ptrc_glTexGenf) numFailed++; + _ptrc_glTexGenfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLfloat *))IntGetProcAddress("glTexGenfv"); + if(!_ptrc_glTexGenfv) numFailed++; + _ptrc_glTexGeni = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint))IntGetProcAddress("glTexGeni"); + if(!_ptrc_glTexGeni) numFailed++; + _ptrc_glTexGeniv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLint *))IntGetProcAddress("glTexGeniv"); + if(!_ptrc_glTexGeniv) numFailed++; + _ptrc_glTexImage1D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, const void *))IntGetProcAddress("glTexImage1D"); + if(!_ptrc_glTexImage1D) numFailed++; + _ptrc_glTexImage2D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *))IntGetProcAddress("glTexImage2D"); + if(!_ptrc_glTexImage2D) numFailed++; + _ptrc_glTexParameterf = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLfloat))IntGetProcAddress("glTexParameterf"); + if(!_ptrc_glTexParameterf) numFailed++; + _ptrc_glTexParameterfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLfloat *))IntGetProcAddress("glTexParameterfv"); + if(!_ptrc_glTexParameterfv) numFailed++; + _ptrc_glTexParameteri = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint))IntGetProcAddress("glTexParameteri"); + if(!_ptrc_glTexParameteri) numFailed++; + _ptrc_glTexParameteriv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLint *))IntGetProcAddress("glTexParameteriv"); + if(!_ptrc_glTexParameteriv) numFailed++; + _ptrc_glTranslated = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble))IntGetProcAddress("glTranslated"); + if(!_ptrc_glTranslated) numFailed++; + _ptrc_glTranslatef = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat))IntGetProcAddress("glTranslatef"); + if(!_ptrc_glTranslatef) numFailed++; + _ptrc_glVertex2d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble))IntGetProcAddress("glVertex2d"); + if(!_ptrc_glVertex2d) numFailed++; + _ptrc_glVertex2dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glVertex2dv"); + if(!_ptrc_glVertex2dv) numFailed++; + _ptrc_glVertex2f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat))IntGetProcAddress("glVertex2f"); + if(!_ptrc_glVertex2f) numFailed++; + _ptrc_glVertex2fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glVertex2fv"); + if(!_ptrc_glVertex2fv) numFailed++; + _ptrc_glVertex2i = (void (CODEGEN_FUNCPTR *)(GLint, GLint))IntGetProcAddress("glVertex2i"); + if(!_ptrc_glVertex2i) numFailed++; + _ptrc_glVertex2iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glVertex2iv"); + if(!_ptrc_glVertex2iv) numFailed++; + _ptrc_glVertex2s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort))IntGetProcAddress("glVertex2s"); + if(!_ptrc_glVertex2s) numFailed++; + _ptrc_glVertex2sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glVertex2sv"); + if(!_ptrc_glVertex2sv) numFailed++; + _ptrc_glVertex3d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble))IntGetProcAddress("glVertex3d"); + if(!_ptrc_glVertex3d) numFailed++; + _ptrc_glVertex3dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glVertex3dv"); + if(!_ptrc_glVertex3dv) numFailed++; + _ptrc_glVertex3f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat))IntGetProcAddress("glVertex3f"); + if(!_ptrc_glVertex3f) numFailed++; + _ptrc_glVertex3fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glVertex3fv"); + if(!_ptrc_glVertex3fv) numFailed++; + _ptrc_glVertex3i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint))IntGetProcAddress("glVertex3i"); + if(!_ptrc_glVertex3i) numFailed++; + _ptrc_glVertex3iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glVertex3iv"); + if(!_ptrc_glVertex3iv) numFailed++; + _ptrc_glVertex3s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort))IntGetProcAddress("glVertex3s"); + if(!_ptrc_glVertex3s) numFailed++; + _ptrc_glVertex3sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glVertex3sv"); + if(!_ptrc_glVertex3sv) numFailed++; + _ptrc_glVertex4d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glVertex4d"); + if(!_ptrc_glVertex4d) numFailed++; + _ptrc_glVertex4dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glVertex4dv"); + if(!_ptrc_glVertex4dv) numFailed++; + _ptrc_glVertex4f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glVertex4f"); + if(!_ptrc_glVertex4f) numFailed++; + _ptrc_glVertex4fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glVertex4fv"); + if(!_ptrc_glVertex4fv) numFailed++; + _ptrc_glVertex4i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint, GLint))IntGetProcAddress("glVertex4i"); + if(!_ptrc_glVertex4i) numFailed++; + _ptrc_glVertex4iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glVertex4iv"); + if(!_ptrc_glVertex4iv) numFailed++; + _ptrc_glVertex4s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort, GLshort))IntGetProcAddress("glVertex4s"); + if(!_ptrc_glVertex4s) numFailed++; + _ptrc_glVertex4sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glVertex4sv"); + if(!_ptrc_glVertex4sv) numFailed++; + _ptrc_glViewport = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLsizei, GLsizei))IntGetProcAddress("glViewport"); + if(!_ptrc_glViewport) numFailed++; + _ptrc_glAreTexturesResident = (GLboolean (CODEGEN_FUNCPTR *)(GLsizei, const GLuint *, GLboolean *))IntGetProcAddress("glAreTexturesResident"); + if(!_ptrc_glAreTexturesResident) numFailed++; + _ptrc_glArrayElement = (void (CODEGEN_FUNCPTR *)(GLint))IntGetProcAddress("glArrayElement"); + if(!_ptrc_glArrayElement) numFailed++; + _ptrc_glBindTexture = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glBindTexture"); + if(!_ptrc_glBindTexture) numFailed++; + _ptrc_glColorPointer = (void (CODEGEN_FUNCPTR *)(GLint, GLenum, GLsizei, const void *))IntGetProcAddress("glColorPointer"); + if(!_ptrc_glColorPointer) numFailed++; + _ptrc_glCopyTexImage1D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint))IntGetProcAddress("glCopyTexImage1D"); + if(!_ptrc_glCopyTexImage1D) numFailed++; + _ptrc_glCopyTexImage2D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint))IntGetProcAddress("glCopyTexImage2D"); + if(!_ptrc_glCopyTexImage2D) numFailed++; + _ptrc_glCopyTexSubImage1D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLint, GLint, GLsizei))IntGetProcAddress("glCopyTexSubImage1D"); + if(!_ptrc_glCopyTexSubImage1D) numFailed++; + _ptrc_glCopyTexSubImage2D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))IntGetProcAddress("glCopyTexSubImage2D"); + if(!_ptrc_glCopyTexSubImage2D) numFailed++; + _ptrc_glDeleteTextures = (void (CODEGEN_FUNCPTR *)(GLsizei, const GLuint *))IntGetProcAddress("glDeleteTextures"); + if(!_ptrc_glDeleteTextures) numFailed++; + _ptrc_glDisableClientState = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glDisableClientState"); + if(!_ptrc_glDisableClientState) numFailed++; + _ptrc_glDrawArrays = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLsizei))IntGetProcAddress("glDrawArrays"); + if(!_ptrc_glDrawArrays) numFailed++; + _ptrc_glDrawElements = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, GLenum, const void *))IntGetProcAddress("glDrawElements"); + if(!_ptrc_glDrawElements) numFailed++; + _ptrc_glEdgeFlagPointer = (void (CODEGEN_FUNCPTR *)(GLsizei, const void *))IntGetProcAddress("glEdgeFlagPointer"); + if(!_ptrc_glEdgeFlagPointer) numFailed++; + _ptrc_glEnableClientState = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glEnableClientState"); + if(!_ptrc_glEnableClientState) numFailed++; + _ptrc_glGenTextures = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glGenTextures"); + if(!_ptrc_glGenTextures) numFailed++; + _ptrc_glGetPointerv = (void (CODEGEN_FUNCPTR *)(GLenum, void **))IntGetProcAddress("glGetPointerv"); + if(!_ptrc_glGetPointerv) numFailed++; + _ptrc_glIndexPointer = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, const void *))IntGetProcAddress("glIndexPointer"); + if(!_ptrc_glIndexPointer) numFailed++; + _ptrc_glIndexub = (void (CODEGEN_FUNCPTR *)(GLubyte))IntGetProcAddress("glIndexub"); + if(!_ptrc_glIndexub) numFailed++; + _ptrc_glIndexubv = (void (CODEGEN_FUNCPTR *)(const GLubyte *))IntGetProcAddress("glIndexubv"); + if(!_ptrc_glIndexubv) numFailed++; + _ptrc_glInterleavedArrays = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, const void *))IntGetProcAddress("glInterleavedArrays"); + if(!_ptrc_glInterleavedArrays) numFailed++; + _ptrc_glIsTexture = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIsTexture"); + if(!_ptrc_glIsTexture) numFailed++; + _ptrc_glNormalPointer = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, const void *))IntGetProcAddress("glNormalPointer"); + if(!_ptrc_glNormalPointer) numFailed++; + _ptrc_glPolygonOffset = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat))IntGetProcAddress("glPolygonOffset"); + if(!_ptrc_glPolygonOffset) numFailed++; + _ptrc_glPopClientAttrib = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glPopClientAttrib"); + if(!_ptrc_glPopClientAttrib) numFailed++; + _ptrc_glPrioritizeTextures = (void (CODEGEN_FUNCPTR *)(GLsizei, const GLuint *, const GLfloat *))IntGetProcAddress("glPrioritizeTextures"); + if(!_ptrc_glPrioritizeTextures) numFailed++; + _ptrc_glPushClientAttrib = (void (CODEGEN_FUNCPTR *)(GLbitfield))IntGetProcAddress("glPushClientAttrib"); + if(!_ptrc_glPushClientAttrib) numFailed++; + _ptrc_glTexCoordPointer = (void (CODEGEN_FUNCPTR *)(GLint, GLenum, GLsizei, const void *))IntGetProcAddress("glTexCoordPointer"); + if(!_ptrc_glTexCoordPointer) numFailed++; + _ptrc_glTexSubImage1D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const void *))IntGetProcAddress("glTexSubImage1D"); + if(!_ptrc_glTexSubImage1D) numFailed++; + _ptrc_glTexSubImage2D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void *))IntGetProcAddress("glTexSubImage2D"); + if(!_ptrc_glTexSubImage2D) numFailed++; + _ptrc_glVertexPointer = (void (CODEGEN_FUNCPTR *)(GLint, GLenum, GLsizei, const void *))IntGetProcAddress("glVertexPointer"); + if(!_ptrc_glVertexPointer) numFailed++; + _ptrc_glCopyTexSubImage3D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))IntGetProcAddress("glCopyTexSubImage3D"); + if(!_ptrc_glCopyTexSubImage3D) numFailed++; + _ptrc_glDrawRangeElements = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLuint, GLsizei, GLenum, const void *))IntGetProcAddress("glDrawRangeElements"); + if(!_ptrc_glDrawRangeElements) numFailed++; + _ptrc_glTexImage3D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *))IntGetProcAddress("glTexImage3D"); + if(!_ptrc_glTexImage3D) numFailed++; + _ptrc_glTexSubImage3D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *))IntGetProcAddress("glTexSubImage3D"); + if(!_ptrc_glTexSubImage3D) numFailed++; + _ptrc_glActiveTexture = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glActiveTexture"); + if(!_ptrc_glActiveTexture) numFailed++; + _ptrc_glClientActiveTexture = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glClientActiveTexture"); + if(!_ptrc_glClientActiveTexture) numFailed++; + _ptrc_glCompressedTexImage1D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const void *))IntGetProcAddress("glCompressedTexImage1D"); + if(!_ptrc_glCompressedTexImage1D) numFailed++; + _ptrc_glCompressedTexImage2D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const void *))IntGetProcAddress("glCompressedTexImage2D"); + if(!_ptrc_glCompressedTexImage2D) numFailed++; + _ptrc_glCompressedTexImage3D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const void *))IntGetProcAddress("glCompressedTexImage3D"); + if(!_ptrc_glCompressedTexImage3D) numFailed++; + _ptrc_glCompressedTexSubImage1D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const void *))IntGetProcAddress("glCompressedTexSubImage1D"); + if(!_ptrc_glCompressedTexSubImage1D) numFailed++; + _ptrc_glCompressedTexSubImage2D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *))IntGetProcAddress("glCompressedTexSubImage2D"); + if(!_ptrc_glCompressedTexSubImage2D) numFailed++; + _ptrc_glCompressedTexSubImage3D = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void *))IntGetProcAddress("glCompressedTexSubImage3D"); + if(!_ptrc_glCompressedTexSubImage3D) numFailed++; + _ptrc_glGetCompressedTexImage = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, void *))IntGetProcAddress("glGetCompressedTexImage"); + if(!_ptrc_glGetCompressedTexImage) numFailed++; + _ptrc_glLoadTransposeMatrixd = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glLoadTransposeMatrixd"); + if(!_ptrc_glLoadTransposeMatrixd) numFailed++; + _ptrc_glLoadTransposeMatrixf = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glLoadTransposeMatrixf"); + if(!_ptrc_glLoadTransposeMatrixf) numFailed++; + _ptrc_glMultTransposeMatrixd = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glMultTransposeMatrixd"); + if(!_ptrc_glMultTransposeMatrixd) numFailed++; + _ptrc_glMultTransposeMatrixf = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glMultTransposeMatrixf"); + if(!_ptrc_glMultTransposeMatrixf) numFailed++; + _ptrc_glMultiTexCoord1d = (void (CODEGEN_FUNCPTR *)(GLenum, GLdouble))IntGetProcAddress("glMultiTexCoord1d"); + if(!_ptrc_glMultiTexCoord1d) numFailed++; + _ptrc_glMultiTexCoord1dv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLdouble *))IntGetProcAddress("glMultiTexCoord1dv"); + if(!_ptrc_glMultiTexCoord1dv) numFailed++; + _ptrc_glMultiTexCoord1f = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat))IntGetProcAddress("glMultiTexCoord1f"); + if(!_ptrc_glMultiTexCoord1f) numFailed++; + _ptrc_glMultiTexCoord1fv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLfloat *))IntGetProcAddress("glMultiTexCoord1fv"); + if(!_ptrc_glMultiTexCoord1fv) numFailed++; + _ptrc_glMultiTexCoord1i = (void (CODEGEN_FUNCPTR *)(GLenum, GLint))IntGetProcAddress("glMultiTexCoord1i"); + if(!_ptrc_glMultiTexCoord1i) numFailed++; + _ptrc_glMultiTexCoord1iv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLint *))IntGetProcAddress("glMultiTexCoord1iv"); + if(!_ptrc_glMultiTexCoord1iv) numFailed++; + _ptrc_glMultiTexCoord1s = (void (CODEGEN_FUNCPTR *)(GLenum, GLshort))IntGetProcAddress("glMultiTexCoord1s"); + if(!_ptrc_glMultiTexCoord1s) numFailed++; + _ptrc_glMultiTexCoord1sv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLshort *))IntGetProcAddress("glMultiTexCoord1sv"); + if(!_ptrc_glMultiTexCoord1sv) numFailed++; + _ptrc_glMultiTexCoord2d = (void (CODEGEN_FUNCPTR *)(GLenum, GLdouble, GLdouble))IntGetProcAddress("glMultiTexCoord2d"); + if(!_ptrc_glMultiTexCoord2d) numFailed++; + _ptrc_glMultiTexCoord2dv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLdouble *))IntGetProcAddress("glMultiTexCoord2dv"); + if(!_ptrc_glMultiTexCoord2dv) numFailed++; + _ptrc_glMultiTexCoord2f = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat, GLfloat))IntGetProcAddress("glMultiTexCoord2f"); + if(!_ptrc_glMultiTexCoord2f) numFailed++; + _ptrc_glMultiTexCoord2fv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLfloat *))IntGetProcAddress("glMultiTexCoord2fv"); + if(!_ptrc_glMultiTexCoord2fv) numFailed++; + _ptrc_glMultiTexCoord2i = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint))IntGetProcAddress("glMultiTexCoord2i"); + if(!_ptrc_glMultiTexCoord2i) numFailed++; + _ptrc_glMultiTexCoord2iv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLint *))IntGetProcAddress("glMultiTexCoord2iv"); + if(!_ptrc_glMultiTexCoord2iv) numFailed++; + _ptrc_glMultiTexCoord2s = (void (CODEGEN_FUNCPTR *)(GLenum, GLshort, GLshort))IntGetProcAddress("glMultiTexCoord2s"); + if(!_ptrc_glMultiTexCoord2s) numFailed++; + _ptrc_glMultiTexCoord2sv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLshort *))IntGetProcAddress("glMultiTexCoord2sv"); + if(!_ptrc_glMultiTexCoord2sv) numFailed++; + _ptrc_glMultiTexCoord3d = (void (CODEGEN_FUNCPTR *)(GLenum, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glMultiTexCoord3d"); + if(!_ptrc_glMultiTexCoord3d) numFailed++; + _ptrc_glMultiTexCoord3dv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLdouble *))IntGetProcAddress("glMultiTexCoord3dv"); + if(!_ptrc_glMultiTexCoord3dv) numFailed++; + _ptrc_glMultiTexCoord3f = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glMultiTexCoord3f"); + if(!_ptrc_glMultiTexCoord3f) numFailed++; + _ptrc_glMultiTexCoord3fv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLfloat *))IntGetProcAddress("glMultiTexCoord3fv"); + if(!_ptrc_glMultiTexCoord3fv) numFailed++; + _ptrc_glMultiTexCoord3i = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLint))IntGetProcAddress("glMultiTexCoord3i"); + if(!_ptrc_glMultiTexCoord3i) numFailed++; + _ptrc_glMultiTexCoord3iv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLint *))IntGetProcAddress("glMultiTexCoord3iv"); + if(!_ptrc_glMultiTexCoord3iv) numFailed++; + _ptrc_glMultiTexCoord3s = (void (CODEGEN_FUNCPTR *)(GLenum, GLshort, GLshort, GLshort))IntGetProcAddress("glMultiTexCoord3s"); + if(!_ptrc_glMultiTexCoord3s) numFailed++; + _ptrc_glMultiTexCoord3sv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLshort *))IntGetProcAddress("glMultiTexCoord3sv"); + if(!_ptrc_glMultiTexCoord3sv) numFailed++; + _ptrc_glMultiTexCoord4d = (void (CODEGEN_FUNCPTR *)(GLenum, GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glMultiTexCoord4d"); + if(!_ptrc_glMultiTexCoord4d) numFailed++; + _ptrc_glMultiTexCoord4dv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLdouble *))IntGetProcAddress("glMultiTexCoord4dv"); + if(!_ptrc_glMultiTexCoord4dv) numFailed++; + _ptrc_glMultiTexCoord4f = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glMultiTexCoord4f"); + if(!_ptrc_glMultiTexCoord4f) numFailed++; + _ptrc_glMultiTexCoord4fv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLfloat *))IntGetProcAddress("glMultiTexCoord4fv"); + if(!_ptrc_glMultiTexCoord4fv) numFailed++; + _ptrc_glMultiTexCoord4i = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLint, GLint, GLint))IntGetProcAddress("glMultiTexCoord4i"); + if(!_ptrc_glMultiTexCoord4i) numFailed++; + _ptrc_glMultiTexCoord4iv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLint *))IntGetProcAddress("glMultiTexCoord4iv"); + if(!_ptrc_glMultiTexCoord4iv) numFailed++; + _ptrc_glMultiTexCoord4s = (void (CODEGEN_FUNCPTR *)(GLenum, GLshort, GLshort, GLshort, GLshort))IntGetProcAddress("glMultiTexCoord4s"); + if(!_ptrc_glMultiTexCoord4s) numFailed++; + _ptrc_glMultiTexCoord4sv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLshort *))IntGetProcAddress("glMultiTexCoord4sv"); + if(!_ptrc_glMultiTexCoord4sv) numFailed++; + _ptrc_glSampleCoverage = (void (CODEGEN_FUNCPTR *)(GLfloat, GLboolean))IntGetProcAddress("glSampleCoverage"); + if(!_ptrc_glSampleCoverage) numFailed++; + _ptrc_glBlendColor = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glBlendColor"); + if(!_ptrc_glBlendColor) numFailed++; + _ptrc_glBlendEquation = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glBlendEquation"); + if(!_ptrc_glBlendEquation) numFailed++; + _ptrc_glBlendFuncSeparate = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLenum))IntGetProcAddress("glBlendFuncSeparate"); + if(!_ptrc_glBlendFuncSeparate) numFailed++; + _ptrc_glFogCoordPointer = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, const void *))IntGetProcAddress("glFogCoordPointer"); + if(!_ptrc_glFogCoordPointer) numFailed++; + _ptrc_glFogCoordd = (void (CODEGEN_FUNCPTR *)(GLdouble))IntGetProcAddress("glFogCoordd"); + if(!_ptrc_glFogCoordd) numFailed++; + _ptrc_glFogCoorddv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glFogCoorddv"); + if(!_ptrc_glFogCoorddv) numFailed++; + _ptrc_glFogCoordf = (void (CODEGEN_FUNCPTR *)(GLfloat))IntGetProcAddress("glFogCoordf"); + if(!_ptrc_glFogCoordf) numFailed++; + _ptrc_glFogCoordfv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glFogCoordfv"); + if(!_ptrc_glFogCoordfv) numFailed++; + _ptrc_glMultiDrawArrays = (void (CODEGEN_FUNCPTR *)(GLenum, const GLint *, const GLsizei *, GLsizei))IntGetProcAddress("glMultiDrawArrays"); + if(!_ptrc_glMultiDrawArrays) numFailed++; + _ptrc_glMultiDrawElements = (void (CODEGEN_FUNCPTR *)(GLenum, const GLsizei *, GLenum, const void *const*, GLsizei))IntGetProcAddress("glMultiDrawElements"); + if(!_ptrc_glMultiDrawElements) numFailed++; + _ptrc_glPointParameterf = (void (CODEGEN_FUNCPTR *)(GLenum, GLfloat))IntGetProcAddress("glPointParameterf"); + if(!_ptrc_glPointParameterf) numFailed++; + _ptrc_glPointParameterfv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLfloat *))IntGetProcAddress("glPointParameterfv"); + if(!_ptrc_glPointParameterfv) numFailed++; + _ptrc_glPointParameteri = (void (CODEGEN_FUNCPTR *)(GLenum, GLint))IntGetProcAddress("glPointParameteri"); + if(!_ptrc_glPointParameteri) numFailed++; + _ptrc_glPointParameteriv = (void (CODEGEN_FUNCPTR *)(GLenum, const GLint *))IntGetProcAddress("glPointParameteriv"); + if(!_ptrc_glPointParameteriv) numFailed++; + _ptrc_glSecondaryColor3b = (void (CODEGEN_FUNCPTR *)(GLbyte, GLbyte, GLbyte))IntGetProcAddress("glSecondaryColor3b"); + if(!_ptrc_glSecondaryColor3b) numFailed++; + _ptrc_glSecondaryColor3bv = (void (CODEGEN_FUNCPTR *)(const GLbyte *))IntGetProcAddress("glSecondaryColor3bv"); + if(!_ptrc_glSecondaryColor3bv) numFailed++; + _ptrc_glSecondaryColor3d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble))IntGetProcAddress("glSecondaryColor3d"); + if(!_ptrc_glSecondaryColor3d) numFailed++; + _ptrc_glSecondaryColor3dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glSecondaryColor3dv"); + if(!_ptrc_glSecondaryColor3dv) numFailed++; + _ptrc_glSecondaryColor3f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat))IntGetProcAddress("glSecondaryColor3f"); + if(!_ptrc_glSecondaryColor3f) numFailed++; + _ptrc_glSecondaryColor3fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glSecondaryColor3fv"); + if(!_ptrc_glSecondaryColor3fv) numFailed++; + _ptrc_glSecondaryColor3i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint))IntGetProcAddress("glSecondaryColor3i"); + if(!_ptrc_glSecondaryColor3i) numFailed++; + _ptrc_glSecondaryColor3iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glSecondaryColor3iv"); + if(!_ptrc_glSecondaryColor3iv) numFailed++; + _ptrc_glSecondaryColor3s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort))IntGetProcAddress("glSecondaryColor3s"); + if(!_ptrc_glSecondaryColor3s) numFailed++; + _ptrc_glSecondaryColor3sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glSecondaryColor3sv"); + if(!_ptrc_glSecondaryColor3sv) numFailed++; + _ptrc_glSecondaryColor3ub = (void (CODEGEN_FUNCPTR *)(GLubyte, GLubyte, GLubyte))IntGetProcAddress("glSecondaryColor3ub"); + if(!_ptrc_glSecondaryColor3ub) numFailed++; + _ptrc_glSecondaryColor3ubv = (void (CODEGEN_FUNCPTR *)(const GLubyte *))IntGetProcAddress("glSecondaryColor3ubv"); + if(!_ptrc_glSecondaryColor3ubv) numFailed++; + _ptrc_glSecondaryColor3ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint))IntGetProcAddress("glSecondaryColor3ui"); + if(!_ptrc_glSecondaryColor3ui) numFailed++; + _ptrc_glSecondaryColor3uiv = (void (CODEGEN_FUNCPTR *)(const GLuint *))IntGetProcAddress("glSecondaryColor3uiv"); + if(!_ptrc_glSecondaryColor3uiv) numFailed++; + _ptrc_glSecondaryColor3us = (void (CODEGEN_FUNCPTR *)(GLushort, GLushort, GLushort))IntGetProcAddress("glSecondaryColor3us"); + if(!_ptrc_glSecondaryColor3us) numFailed++; + _ptrc_glSecondaryColor3usv = (void (CODEGEN_FUNCPTR *)(const GLushort *))IntGetProcAddress("glSecondaryColor3usv"); + if(!_ptrc_glSecondaryColor3usv) numFailed++; + _ptrc_glSecondaryColorPointer = (void (CODEGEN_FUNCPTR *)(GLint, GLenum, GLsizei, const void *))IntGetProcAddress("glSecondaryColorPointer"); + if(!_ptrc_glSecondaryColorPointer) numFailed++; + _ptrc_glWindowPos2d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble))IntGetProcAddress("glWindowPos2d"); + if(!_ptrc_glWindowPos2d) numFailed++; + _ptrc_glWindowPos2dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glWindowPos2dv"); + if(!_ptrc_glWindowPos2dv) numFailed++; + _ptrc_glWindowPos2f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat))IntGetProcAddress("glWindowPos2f"); + if(!_ptrc_glWindowPos2f) numFailed++; + _ptrc_glWindowPos2fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glWindowPos2fv"); + if(!_ptrc_glWindowPos2fv) numFailed++; + _ptrc_glWindowPos2i = (void (CODEGEN_FUNCPTR *)(GLint, GLint))IntGetProcAddress("glWindowPos2i"); + if(!_ptrc_glWindowPos2i) numFailed++; + _ptrc_glWindowPos2iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glWindowPos2iv"); + if(!_ptrc_glWindowPos2iv) numFailed++; + _ptrc_glWindowPos2s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort))IntGetProcAddress("glWindowPos2s"); + if(!_ptrc_glWindowPos2s) numFailed++; + _ptrc_glWindowPos2sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glWindowPos2sv"); + if(!_ptrc_glWindowPos2sv) numFailed++; + _ptrc_glWindowPos3d = (void (CODEGEN_FUNCPTR *)(GLdouble, GLdouble, GLdouble))IntGetProcAddress("glWindowPos3d"); + if(!_ptrc_glWindowPos3d) numFailed++; + _ptrc_glWindowPos3dv = (void (CODEGEN_FUNCPTR *)(const GLdouble *))IntGetProcAddress("glWindowPos3dv"); + if(!_ptrc_glWindowPos3dv) numFailed++; + _ptrc_glWindowPos3f = (void (CODEGEN_FUNCPTR *)(GLfloat, GLfloat, GLfloat))IntGetProcAddress("glWindowPos3f"); + if(!_ptrc_glWindowPos3f) numFailed++; + _ptrc_glWindowPos3fv = (void (CODEGEN_FUNCPTR *)(const GLfloat *))IntGetProcAddress("glWindowPos3fv"); + if(!_ptrc_glWindowPos3fv) numFailed++; + _ptrc_glWindowPos3i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint))IntGetProcAddress("glWindowPos3i"); + if(!_ptrc_glWindowPos3i) numFailed++; + _ptrc_glWindowPos3iv = (void (CODEGEN_FUNCPTR *)(const GLint *))IntGetProcAddress("glWindowPos3iv"); + if(!_ptrc_glWindowPos3iv) numFailed++; + _ptrc_glWindowPos3s = (void (CODEGEN_FUNCPTR *)(GLshort, GLshort, GLshort))IntGetProcAddress("glWindowPos3s"); + if(!_ptrc_glWindowPos3s) numFailed++; + _ptrc_glWindowPos3sv = (void (CODEGEN_FUNCPTR *)(const GLshort *))IntGetProcAddress("glWindowPos3sv"); + if(!_ptrc_glWindowPos3sv) numFailed++; + _ptrc_glBeginQuery = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glBeginQuery"); + if(!_ptrc_glBeginQuery) numFailed++; + _ptrc_glBindBuffer = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glBindBuffer"); + if(!_ptrc_glBindBuffer) numFailed++; + _ptrc_glBufferData = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizeiptr, const void *, GLenum))IntGetProcAddress("glBufferData"); + if(!_ptrc_glBufferData) numFailed++; + _ptrc_glBufferSubData = (void (CODEGEN_FUNCPTR *)(GLenum, GLintptr, GLsizeiptr, const void *))IntGetProcAddress("glBufferSubData"); + if(!_ptrc_glBufferSubData) numFailed++; + _ptrc_glDeleteBuffers = (void (CODEGEN_FUNCPTR *)(GLsizei, const GLuint *))IntGetProcAddress("glDeleteBuffers"); + if(!_ptrc_glDeleteBuffers) numFailed++; + _ptrc_glDeleteQueries = (void (CODEGEN_FUNCPTR *)(GLsizei, const GLuint *))IntGetProcAddress("glDeleteQueries"); + if(!_ptrc_glDeleteQueries) numFailed++; + _ptrc_glEndQuery = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glEndQuery"); + if(!_ptrc_glEndQuery) numFailed++; + _ptrc_glGenBuffers = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glGenBuffers"); + if(!_ptrc_glGenBuffers) numFailed++; + _ptrc_glGenQueries = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glGenQueries"); + if(!_ptrc_glGenQueries) numFailed++; + _ptrc_glGetBufferParameteriv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetBufferParameteriv"); + if(!_ptrc_glGetBufferParameteriv) numFailed++; + _ptrc_glGetBufferPointerv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, void **))IntGetProcAddress("glGetBufferPointerv"); + if(!_ptrc_glGetBufferPointerv) numFailed++; + _ptrc_glGetBufferSubData = (void (CODEGEN_FUNCPTR *)(GLenum, GLintptr, GLsizeiptr, void *))IntGetProcAddress("glGetBufferSubData"); + if(!_ptrc_glGetBufferSubData) numFailed++; + _ptrc_glGetQueryObjectiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetQueryObjectiv"); + if(!_ptrc_glGetQueryObjectiv) numFailed++; + _ptrc_glGetQueryObjectuiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint *))IntGetProcAddress("glGetQueryObjectuiv"); + if(!_ptrc_glGetQueryObjectuiv) numFailed++; + _ptrc_glGetQueryiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetQueryiv"); + if(!_ptrc_glGetQueryiv) numFailed++; + _ptrc_glIsBuffer = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIsBuffer"); + if(!_ptrc_glIsBuffer) numFailed++; + _ptrc_glIsQuery = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIsQuery"); + if(!_ptrc_glIsQuery) numFailed++; + _ptrc_glMapBuffer = (void * (CODEGEN_FUNCPTR *)(GLenum, GLenum))IntGetProcAddress("glMapBuffer"); + if(!_ptrc_glMapBuffer) numFailed++; + _ptrc_glUnmapBuffer = (GLboolean (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glUnmapBuffer"); + if(!_ptrc_glUnmapBuffer) numFailed++; + _ptrc_glAttachShader = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint))IntGetProcAddress("glAttachShader"); + if(!_ptrc_glAttachShader) numFailed++; + _ptrc_glBindAttribLocation = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, const GLchar *))IntGetProcAddress("glBindAttribLocation"); + if(!_ptrc_glBindAttribLocation) numFailed++; + _ptrc_glBlendEquationSeparate = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum))IntGetProcAddress("glBlendEquationSeparate"); + if(!_ptrc_glBlendEquationSeparate) numFailed++; + _ptrc_glCompileShader = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glCompileShader"); + if(!_ptrc_glCompileShader) numFailed++; + _ptrc_glCreateProgram = (GLuint (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glCreateProgram"); + if(!_ptrc_glCreateProgram) numFailed++; + _ptrc_glCreateShader = (GLuint (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glCreateShader"); + if(!_ptrc_glCreateShader) numFailed++; + _ptrc_glDeleteProgram = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glDeleteProgram"); + if(!_ptrc_glDeleteProgram) numFailed++; + _ptrc_glDeleteShader = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glDeleteShader"); + if(!_ptrc_glDeleteShader) numFailed++; + _ptrc_glDetachShader = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint))IntGetProcAddress("glDetachShader"); + if(!_ptrc_glDetachShader) numFailed++; + _ptrc_glDisableVertexAttribArray = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glDisableVertexAttribArray"); + if(!_ptrc_glDisableVertexAttribArray) numFailed++; + _ptrc_glDrawBuffers = (void (CODEGEN_FUNCPTR *)(GLsizei, const GLenum *))IntGetProcAddress("glDrawBuffers"); + if(!_ptrc_glDrawBuffers) numFailed++; + _ptrc_glEnableVertexAttribArray = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glEnableVertexAttribArray"); + if(!_ptrc_glEnableVertexAttribArray) numFailed++; + _ptrc_glGetActiveAttrib = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *))IntGetProcAddress("glGetActiveAttrib"); + if(!_ptrc_glGetActiveAttrib) numFailed++; + _ptrc_glGetActiveUniform = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *))IntGetProcAddress("glGetActiveUniform"); + if(!_ptrc_glGetActiveUniform) numFailed++; + _ptrc_glGetAttachedShaders = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLsizei *, GLuint *))IntGetProcAddress("glGetAttachedShaders"); + if(!_ptrc_glGetAttachedShaders) numFailed++; + _ptrc_glGetAttribLocation = (GLint (CODEGEN_FUNCPTR *)(GLuint, const GLchar *))IntGetProcAddress("glGetAttribLocation"); + if(!_ptrc_glGetAttribLocation) numFailed++; + _ptrc_glGetProgramInfoLog = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLsizei *, GLchar *))IntGetProcAddress("glGetProgramInfoLog"); + if(!_ptrc_glGetProgramInfoLog) numFailed++; + _ptrc_glGetProgramiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetProgramiv"); + if(!_ptrc_glGetProgramiv) numFailed++; + _ptrc_glGetShaderInfoLog = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLsizei *, GLchar *))IntGetProcAddress("glGetShaderInfoLog"); + if(!_ptrc_glGetShaderInfoLog) numFailed++; + _ptrc_glGetShaderSource = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, GLsizei *, GLchar *))IntGetProcAddress("glGetShaderSource"); + if(!_ptrc_glGetShaderSource) numFailed++; + _ptrc_glGetShaderiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetShaderiv"); + if(!_ptrc_glGetShaderiv) numFailed++; + _ptrc_glGetUniformLocation = (GLint (CODEGEN_FUNCPTR *)(GLuint, const GLchar *))IntGetProcAddress("glGetUniformLocation"); + if(!_ptrc_glGetUniformLocation) numFailed++; + _ptrc_glGetUniformfv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLfloat *))IntGetProcAddress("glGetUniformfv"); + if(!_ptrc_glGetUniformfv) numFailed++; + _ptrc_glGetUniformiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint *))IntGetProcAddress("glGetUniformiv"); + if(!_ptrc_glGetUniformiv) numFailed++; + _ptrc_glGetVertexAttribPointerv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, void **))IntGetProcAddress("glGetVertexAttribPointerv"); + if(!_ptrc_glGetVertexAttribPointerv) numFailed++; + _ptrc_glGetVertexAttribdv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLdouble *))IntGetProcAddress("glGetVertexAttribdv"); + if(!_ptrc_glGetVertexAttribdv) numFailed++; + _ptrc_glGetVertexAttribfv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLfloat *))IntGetProcAddress("glGetVertexAttribfv"); + if(!_ptrc_glGetVertexAttribfv) numFailed++; + _ptrc_glGetVertexAttribiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetVertexAttribiv"); + if(!_ptrc_glGetVertexAttribiv) numFailed++; + _ptrc_glIsProgram = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIsProgram"); + if(!_ptrc_glIsProgram) numFailed++; + _ptrc_glIsShader = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIsShader"); + if(!_ptrc_glIsShader) numFailed++; + _ptrc_glLinkProgram = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glLinkProgram"); + if(!_ptrc_glLinkProgram) numFailed++; + _ptrc_glShaderSource = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLchar *const*, const GLint *))IntGetProcAddress("glShaderSource"); + if(!_ptrc_glShaderSource) numFailed++; + _ptrc_glStencilFuncSeparate = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint, GLuint))IntGetProcAddress("glStencilFuncSeparate"); + if(!_ptrc_glStencilFuncSeparate) numFailed++; + _ptrc_glStencilMaskSeparate = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glStencilMaskSeparate"); + if(!_ptrc_glStencilMaskSeparate) numFailed++; + _ptrc_glStencilOpSeparate = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLenum))IntGetProcAddress("glStencilOpSeparate"); + if(!_ptrc_glStencilOpSeparate) numFailed++; + _ptrc_glUniform1f = (void (CODEGEN_FUNCPTR *)(GLint, GLfloat))IntGetProcAddress("glUniform1f"); + if(!_ptrc_glUniform1f) numFailed++; + _ptrc_glUniform1fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLfloat *))IntGetProcAddress("glUniform1fv"); + if(!_ptrc_glUniform1fv) numFailed++; + _ptrc_glUniform1i = (void (CODEGEN_FUNCPTR *)(GLint, GLint))IntGetProcAddress("glUniform1i"); + if(!_ptrc_glUniform1i) numFailed++; + _ptrc_glUniform1iv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLint *))IntGetProcAddress("glUniform1iv"); + if(!_ptrc_glUniform1iv) numFailed++; + _ptrc_glUniform2f = (void (CODEGEN_FUNCPTR *)(GLint, GLfloat, GLfloat))IntGetProcAddress("glUniform2f"); + if(!_ptrc_glUniform2f) numFailed++; + _ptrc_glUniform2fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLfloat *))IntGetProcAddress("glUniform2fv"); + if(!_ptrc_glUniform2fv) numFailed++; + _ptrc_glUniform2i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint))IntGetProcAddress("glUniform2i"); + if(!_ptrc_glUniform2i) numFailed++; + _ptrc_glUniform2iv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLint *))IntGetProcAddress("glUniform2iv"); + if(!_ptrc_glUniform2iv) numFailed++; + _ptrc_glUniform3f = (void (CODEGEN_FUNCPTR *)(GLint, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glUniform3f"); + if(!_ptrc_glUniform3f) numFailed++; + _ptrc_glUniform3fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLfloat *))IntGetProcAddress("glUniform3fv"); + if(!_ptrc_glUniform3fv) numFailed++; + _ptrc_glUniform3i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint, GLint))IntGetProcAddress("glUniform3i"); + if(!_ptrc_glUniform3i) numFailed++; + _ptrc_glUniform3iv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLint *))IntGetProcAddress("glUniform3iv"); + if(!_ptrc_glUniform3iv) numFailed++; + _ptrc_glUniform4f = (void (CODEGEN_FUNCPTR *)(GLint, GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glUniform4f"); + if(!_ptrc_glUniform4f) numFailed++; + _ptrc_glUniform4fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLfloat *))IntGetProcAddress("glUniform4fv"); + if(!_ptrc_glUniform4fv) numFailed++; + _ptrc_glUniform4i = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint, GLint, GLint))IntGetProcAddress("glUniform4i"); + if(!_ptrc_glUniform4i) numFailed++; + _ptrc_glUniform4iv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLint *))IntGetProcAddress("glUniform4iv"); + if(!_ptrc_glUniform4iv) numFailed++; + _ptrc_glUniformMatrix2fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glUniformMatrix2fv"); + if(!_ptrc_glUniformMatrix2fv) numFailed++; + _ptrc_glUniformMatrix3fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glUniformMatrix3fv"); + if(!_ptrc_glUniformMatrix3fv) numFailed++; + _ptrc_glUniformMatrix4fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glUniformMatrix4fv"); + if(!_ptrc_glUniformMatrix4fv) numFailed++; + _ptrc_glUseProgram = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glUseProgram"); + if(!_ptrc_glUseProgram) numFailed++; + _ptrc_glValidateProgram = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glValidateProgram"); + if(!_ptrc_glValidateProgram) numFailed++; + _ptrc_glVertexAttrib1d = (void (CODEGEN_FUNCPTR *)(GLuint, GLdouble))IntGetProcAddress("glVertexAttrib1d"); + if(!_ptrc_glVertexAttrib1d) numFailed++; + _ptrc_glVertexAttrib1dv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLdouble *))IntGetProcAddress("glVertexAttrib1dv"); + if(!_ptrc_glVertexAttrib1dv) numFailed++; + _ptrc_glVertexAttrib1f = (void (CODEGEN_FUNCPTR *)(GLuint, GLfloat))IntGetProcAddress("glVertexAttrib1f"); + if(!_ptrc_glVertexAttrib1f) numFailed++; + _ptrc_glVertexAttrib1fv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLfloat *))IntGetProcAddress("glVertexAttrib1fv"); + if(!_ptrc_glVertexAttrib1fv) numFailed++; + _ptrc_glVertexAttrib1s = (void (CODEGEN_FUNCPTR *)(GLuint, GLshort))IntGetProcAddress("glVertexAttrib1s"); + if(!_ptrc_glVertexAttrib1s) numFailed++; + _ptrc_glVertexAttrib1sv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLshort *))IntGetProcAddress("glVertexAttrib1sv"); + if(!_ptrc_glVertexAttrib1sv) numFailed++; + _ptrc_glVertexAttrib2d = (void (CODEGEN_FUNCPTR *)(GLuint, GLdouble, GLdouble))IntGetProcAddress("glVertexAttrib2d"); + if(!_ptrc_glVertexAttrib2d) numFailed++; + _ptrc_glVertexAttrib2dv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLdouble *))IntGetProcAddress("glVertexAttrib2dv"); + if(!_ptrc_glVertexAttrib2dv) numFailed++; + _ptrc_glVertexAttrib2f = (void (CODEGEN_FUNCPTR *)(GLuint, GLfloat, GLfloat))IntGetProcAddress("glVertexAttrib2f"); + if(!_ptrc_glVertexAttrib2f) numFailed++; + _ptrc_glVertexAttrib2fv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLfloat *))IntGetProcAddress("glVertexAttrib2fv"); + if(!_ptrc_glVertexAttrib2fv) numFailed++; + _ptrc_glVertexAttrib2s = (void (CODEGEN_FUNCPTR *)(GLuint, GLshort, GLshort))IntGetProcAddress("glVertexAttrib2s"); + if(!_ptrc_glVertexAttrib2s) numFailed++; + _ptrc_glVertexAttrib2sv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLshort *))IntGetProcAddress("glVertexAttrib2sv"); + if(!_ptrc_glVertexAttrib2sv) numFailed++; + _ptrc_glVertexAttrib3d = (void (CODEGEN_FUNCPTR *)(GLuint, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glVertexAttrib3d"); + if(!_ptrc_glVertexAttrib3d) numFailed++; + _ptrc_glVertexAttrib3dv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLdouble *))IntGetProcAddress("glVertexAttrib3dv"); + if(!_ptrc_glVertexAttrib3dv) numFailed++; + _ptrc_glVertexAttrib3f = (void (CODEGEN_FUNCPTR *)(GLuint, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glVertexAttrib3f"); + if(!_ptrc_glVertexAttrib3f) numFailed++; + _ptrc_glVertexAttrib3fv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLfloat *))IntGetProcAddress("glVertexAttrib3fv"); + if(!_ptrc_glVertexAttrib3fv) numFailed++; + _ptrc_glVertexAttrib3s = (void (CODEGEN_FUNCPTR *)(GLuint, GLshort, GLshort, GLshort))IntGetProcAddress("glVertexAttrib3s"); + if(!_ptrc_glVertexAttrib3s) numFailed++; + _ptrc_glVertexAttrib3sv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLshort *))IntGetProcAddress("glVertexAttrib3sv"); + if(!_ptrc_glVertexAttrib3sv) numFailed++; + _ptrc_glVertexAttrib4Nbv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLbyte *))IntGetProcAddress("glVertexAttrib4Nbv"); + if(!_ptrc_glVertexAttrib4Nbv) numFailed++; + _ptrc_glVertexAttrib4Niv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLint *))IntGetProcAddress("glVertexAttrib4Niv"); + if(!_ptrc_glVertexAttrib4Niv) numFailed++; + _ptrc_glVertexAttrib4Nsv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLshort *))IntGetProcAddress("glVertexAttrib4Nsv"); + if(!_ptrc_glVertexAttrib4Nsv) numFailed++; + _ptrc_glVertexAttrib4Nub = (void (CODEGEN_FUNCPTR *)(GLuint, GLubyte, GLubyte, GLubyte, GLubyte))IntGetProcAddress("glVertexAttrib4Nub"); + if(!_ptrc_glVertexAttrib4Nub) numFailed++; + _ptrc_glVertexAttrib4Nubv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLubyte *))IntGetProcAddress("glVertexAttrib4Nubv"); + if(!_ptrc_glVertexAttrib4Nubv) numFailed++; + _ptrc_glVertexAttrib4Nuiv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLuint *))IntGetProcAddress("glVertexAttrib4Nuiv"); + if(!_ptrc_glVertexAttrib4Nuiv) numFailed++; + _ptrc_glVertexAttrib4Nusv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLushort *))IntGetProcAddress("glVertexAttrib4Nusv"); + if(!_ptrc_glVertexAttrib4Nusv) numFailed++; + _ptrc_glVertexAttrib4bv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLbyte *))IntGetProcAddress("glVertexAttrib4bv"); + if(!_ptrc_glVertexAttrib4bv) numFailed++; + _ptrc_glVertexAttrib4d = (void (CODEGEN_FUNCPTR *)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble))IntGetProcAddress("glVertexAttrib4d"); + if(!_ptrc_glVertexAttrib4d) numFailed++; + _ptrc_glVertexAttrib4dv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLdouble *))IntGetProcAddress("glVertexAttrib4dv"); + if(!_ptrc_glVertexAttrib4dv) numFailed++; + _ptrc_glVertexAttrib4f = (void (CODEGEN_FUNCPTR *)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat))IntGetProcAddress("glVertexAttrib4f"); + if(!_ptrc_glVertexAttrib4f) numFailed++; + _ptrc_glVertexAttrib4fv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLfloat *))IntGetProcAddress("glVertexAttrib4fv"); + if(!_ptrc_glVertexAttrib4fv) numFailed++; + _ptrc_glVertexAttrib4iv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLint *))IntGetProcAddress("glVertexAttrib4iv"); + if(!_ptrc_glVertexAttrib4iv) numFailed++; + _ptrc_glVertexAttrib4s = (void (CODEGEN_FUNCPTR *)(GLuint, GLshort, GLshort, GLshort, GLshort))IntGetProcAddress("glVertexAttrib4s"); + if(!_ptrc_glVertexAttrib4s) numFailed++; + _ptrc_glVertexAttrib4sv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLshort *))IntGetProcAddress("glVertexAttrib4sv"); + if(!_ptrc_glVertexAttrib4sv) numFailed++; + _ptrc_glVertexAttrib4ubv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLubyte *))IntGetProcAddress("glVertexAttrib4ubv"); + if(!_ptrc_glVertexAttrib4ubv) numFailed++; + _ptrc_glVertexAttrib4uiv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLuint *))IntGetProcAddress("glVertexAttrib4uiv"); + if(!_ptrc_glVertexAttrib4uiv) numFailed++; + _ptrc_glVertexAttrib4usv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLushort *))IntGetProcAddress("glVertexAttrib4usv"); + if(!_ptrc_glVertexAttrib4usv) numFailed++; + _ptrc_glVertexAttribPointer = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLenum, GLboolean, GLsizei, const void *))IntGetProcAddress("glVertexAttribPointer"); + if(!_ptrc_glVertexAttribPointer) numFailed++; + _ptrc_glUniformMatrix2x3fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glUniformMatrix2x3fv"); + if(!_ptrc_glUniformMatrix2x3fv) numFailed++; + _ptrc_glUniformMatrix2x4fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glUniformMatrix2x4fv"); + if(!_ptrc_glUniformMatrix2x4fv) numFailed++; + _ptrc_glUniformMatrix3x2fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glUniformMatrix3x2fv"); + if(!_ptrc_glUniformMatrix3x2fv) numFailed++; + _ptrc_glUniformMatrix3x4fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glUniformMatrix3x4fv"); + if(!_ptrc_glUniformMatrix3x4fv) numFailed++; + _ptrc_glUniformMatrix4x2fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glUniformMatrix4x2fv"); + if(!_ptrc_glUniformMatrix4x2fv) numFailed++; + _ptrc_glUniformMatrix4x3fv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, GLboolean, const GLfloat *))IntGetProcAddress("glUniformMatrix4x3fv"); + if(!_ptrc_glUniformMatrix4x3fv) numFailed++; + _ptrc_glBeginConditionalRender = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum))IntGetProcAddress("glBeginConditionalRender"); + if(!_ptrc_glBeginConditionalRender) numFailed++; + _ptrc_glBeginTransformFeedback = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glBeginTransformFeedback"); + if(!_ptrc_glBeginTransformFeedback) numFailed++; + _ptrc_glBindBufferBase = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLuint))IntGetProcAddress("glBindBufferBase"); + if(!_ptrc_glBindBufferBase) numFailed++; + _ptrc_glBindBufferRange = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLuint, GLintptr, GLsizeiptr))IntGetProcAddress("glBindBufferRange"); + if(!_ptrc_glBindBufferRange) numFailed++; + _ptrc_glBindFragDataLocation = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, const GLchar *))IntGetProcAddress("glBindFragDataLocation"); + if(!_ptrc_glBindFragDataLocation) numFailed++; + _ptrc_glBindFramebuffer = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glBindFramebuffer"); + if(!_ptrc_glBindFramebuffer) numFailed++; + _ptrc_glBindRenderbuffer = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glBindRenderbuffer"); + if(!_ptrc_glBindRenderbuffer) numFailed++; + _ptrc_glBindVertexArray = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glBindVertexArray"); + if(!_ptrc_glBindVertexArray) numFailed++; + _ptrc_glBlitFramebuffer = (void (CODEGEN_FUNCPTR *)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum))IntGetProcAddress("glBlitFramebuffer"); + if(!_ptrc_glBlitFramebuffer) numFailed++; + _ptrc_glCheckFramebufferStatus = (GLenum (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glCheckFramebufferStatus"); + if(!_ptrc_glCheckFramebufferStatus) numFailed++; + _ptrc_glClampColor = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum))IntGetProcAddress("glClampColor"); + if(!_ptrc_glClampColor) numFailed++; + _ptrc_glClearBufferfi = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLfloat, GLint))IntGetProcAddress("glClearBufferfi"); + if(!_ptrc_glClearBufferfi) numFailed++; + _ptrc_glClearBufferfv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, const GLfloat *))IntGetProcAddress("glClearBufferfv"); + if(!_ptrc_glClearBufferfv) numFailed++; + _ptrc_glClearBufferiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, const GLint *))IntGetProcAddress("glClearBufferiv"); + if(!_ptrc_glClearBufferiv) numFailed++; + _ptrc_glClearBufferuiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, const GLuint *))IntGetProcAddress("glClearBufferuiv"); + if(!_ptrc_glClearBufferuiv) numFailed++; + _ptrc_glColorMaski = (void (CODEGEN_FUNCPTR *)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean))IntGetProcAddress("glColorMaski"); + if(!_ptrc_glColorMaski) numFailed++; + _ptrc_glDeleteFramebuffers = (void (CODEGEN_FUNCPTR *)(GLsizei, const GLuint *))IntGetProcAddress("glDeleteFramebuffers"); + if(!_ptrc_glDeleteFramebuffers) numFailed++; + _ptrc_glDeleteRenderbuffers = (void (CODEGEN_FUNCPTR *)(GLsizei, const GLuint *))IntGetProcAddress("glDeleteRenderbuffers"); + if(!_ptrc_glDeleteRenderbuffers) numFailed++; + _ptrc_glDeleteVertexArrays = (void (CODEGEN_FUNCPTR *)(GLsizei, const GLuint *))IntGetProcAddress("glDeleteVertexArrays"); + if(!_ptrc_glDeleteVertexArrays) numFailed++; + _ptrc_glDisablei = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glDisablei"); + if(!_ptrc_glDisablei) numFailed++; + _ptrc_glEnablei = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glEnablei"); + if(!_ptrc_glEnablei) numFailed++; + _ptrc_glEndConditionalRender = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glEndConditionalRender"); + if(!_ptrc_glEndConditionalRender) numFailed++; + _ptrc_glEndTransformFeedback = (void (CODEGEN_FUNCPTR *)(void))IntGetProcAddress("glEndTransformFeedback"); + if(!_ptrc_glEndTransformFeedback) numFailed++; + _ptrc_glFlushMappedBufferRange = (void (CODEGEN_FUNCPTR *)(GLenum, GLintptr, GLsizeiptr))IntGetProcAddress("glFlushMappedBufferRange"); + if(!_ptrc_glFlushMappedBufferRange) numFailed++; + _ptrc_glFramebufferRenderbuffer = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLuint))IntGetProcAddress("glFramebufferRenderbuffer"); + if(!_ptrc_glFramebufferRenderbuffer) numFailed++; + _ptrc_glFramebufferTexture1D = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLuint, GLint))IntGetProcAddress("glFramebufferTexture1D"); + if(!_ptrc_glFramebufferTexture1D) numFailed++; + _ptrc_glFramebufferTexture2D = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLuint, GLint))IntGetProcAddress("glFramebufferTexture2D"); + if(!_ptrc_glFramebufferTexture2D) numFailed++; + _ptrc_glFramebufferTexture3D = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLuint, GLint, GLint))IntGetProcAddress("glFramebufferTexture3D"); + if(!_ptrc_glFramebufferTexture3D) numFailed++; + _ptrc_glFramebufferTextureLayer = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLuint, GLint, GLint))IntGetProcAddress("glFramebufferTextureLayer"); + if(!_ptrc_glFramebufferTextureLayer) numFailed++; + _ptrc_glGenFramebuffers = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glGenFramebuffers"); + if(!_ptrc_glGenFramebuffers) numFailed++; + _ptrc_glGenRenderbuffers = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glGenRenderbuffers"); + if(!_ptrc_glGenRenderbuffers) numFailed++; + _ptrc_glGenVertexArrays = (void (CODEGEN_FUNCPTR *)(GLsizei, GLuint *))IntGetProcAddress("glGenVertexArrays"); + if(!_ptrc_glGenVertexArrays) numFailed++; + _ptrc_glGenerateMipmap = (void (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glGenerateMipmap"); + if(!_ptrc_glGenerateMipmap) numFailed++; + _ptrc_glGetBooleani_v = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLboolean *))IntGetProcAddress("glGetBooleani_v"); + if(!_ptrc_glGetBooleani_v) numFailed++; + _ptrc_glGetFragDataLocation = (GLint (CODEGEN_FUNCPTR *)(GLuint, const GLchar *))IntGetProcAddress("glGetFragDataLocation"); + if(!_ptrc_glGetFragDataLocation) numFailed++; + _ptrc_glGetFramebufferAttachmentParameteriv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLenum, GLint *))IntGetProcAddress("glGetFramebufferAttachmentParameteriv"); + if(!_ptrc_glGetFramebufferAttachmentParameteriv) numFailed++; + _ptrc_glGetIntegeri_v = (void (CODEGEN_FUNCPTR *)(GLenum, GLuint, GLint *))IntGetProcAddress("glGetIntegeri_v"); + if(!_ptrc_glGetIntegeri_v) numFailed++; + _ptrc_glGetRenderbufferParameteriv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetRenderbufferParameteriv"); + if(!_ptrc_glGetRenderbufferParameteriv) numFailed++; + _ptrc_glGetStringi = (const GLubyte * (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glGetStringi"); + if(!_ptrc_glGetStringi) numFailed++; + _ptrc_glGetTexParameterIiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLint *))IntGetProcAddress("glGetTexParameterIiv"); + if(!_ptrc_glGetTexParameterIiv) numFailed++; + _ptrc_glGetTexParameterIuiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLuint *))IntGetProcAddress("glGetTexParameterIuiv"); + if(!_ptrc_glGetTexParameterIuiv) numFailed++; + _ptrc_glGetTransformFeedbackVarying = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *))IntGetProcAddress("glGetTransformFeedbackVarying"); + if(!_ptrc_glGetTransformFeedbackVarying) numFailed++; + _ptrc_glGetUniformuiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLuint *))IntGetProcAddress("glGetUniformuiv"); + if(!_ptrc_glGetUniformuiv) numFailed++; + _ptrc_glGetVertexAttribIiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLint *))IntGetProcAddress("glGetVertexAttribIiv"); + if(!_ptrc_glGetVertexAttribIiv) numFailed++; + _ptrc_glGetVertexAttribIuiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLenum, GLuint *))IntGetProcAddress("glGetVertexAttribIuiv"); + if(!_ptrc_glGetVertexAttribIuiv) numFailed++; + _ptrc_glIsEnabledi = (GLboolean (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glIsEnabledi"); + if(!_ptrc_glIsEnabledi) numFailed++; + _ptrc_glIsFramebuffer = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIsFramebuffer"); + if(!_ptrc_glIsFramebuffer) numFailed++; + _ptrc_glIsRenderbuffer = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIsRenderbuffer"); + if(!_ptrc_glIsRenderbuffer) numFailed++; + _ptrc_glIsVertexArray = (GLboolean (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glIsVertexArray"); + if(!_ptrc_glIsVertexArray) numFailed++; + _ptrc_glMapBufferRange = (void * (CODEGEN_FUNCPTR *)(GLenum, GLintptr, GLsizeiptr, GLbitfield))IntGetProcAddress("glMapBufferRange"); + if(!_ptrc_glMapBufferRange) numFailed++; + _ptrc_glRenderbufferStorage = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLsizei, GLsizei))IntGetProcAddress("glRenderbufferStorage"); + if(!_ptrc_glRenderbufferStorage) numFailed++; + _ptrc_glRenderbufferStorageMultisample = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, GLenum, GLsizei, GLsizei))IntGetProcAddress("glRenderbufferStorageMultisample"); + if(!_ptrc_glRenderbufferStorageMultisample) numFailed++; + _ptrc_glTexParameterIiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLint *))IntGetProcAddress("glTexParameterIiv"); + if(!_ptrc_glTexParameterIiv) numFailed++; + _ptrc_glTexParameterIuiv = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, const GLuint *))IntGetProcAddress("glTexParameterIuiv"); + if(!_ptrc_glTexParameterIuiv) numFailed++; + _ptrc_glTransformFeedbackVaryings = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLchar *const*, GLenum))IntGetProcAddress("glTransformFeedbackVaryings"); + if(!_ptrc_glTransformFeedbackVaryings) numFailed++; + _ptrc_glUniform1ui = (void (CODEGEN_FUNCPTR *)(GLint, GLuint))IntGetProcAddress("glUniform1ui"); + if(!_ptrc_glUniform1ui) numFailed++; + _ptrc_glUniform1uiv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLuint *))IntGetProcAddress("glUniform1uiv"); + if(!_ptrc_glUniform1uiv) numFailed++; + _ptrc_glUniform2ui = (void (CODEGEN_FUNCPTR *)(GLint, GLuint, GLuint))IntGetProcAddress("glUniform2ui"); + if(!_ptrc_glUniform2ui) numFailed++; + _ptrc_glUniform2uiv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLuint *))IntGetProcAddress("glUniform2uiv"); + if(!_ptrc_glUniform2uiv) numFailed++; + _ptrc_glUniform3ui = (void (CODEGEN_FUNCPTR *)(GLint, GLuint, GLuint, GLuint))IntGetProcAddress("glUniform3ui"); + if(!_ptrc_glUniform3ui) numFailed++; + _ptrc_glUniform3uiv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLuint *))IntGetProcAddress("glUniform3uiv"); + if(!_ptrc_glUniform3uiv) numFailed++; + _ptrc_glUniform4ui = (void (CODEGEN_FUNCPTR *)(GLint, GLuint, GLuint, GLuint, GLuint))IntGetProcAddress("glUniform4ui"); + if(!_ptrc_glUniform4ui) numFailed++; + _ptrc_glUniform4uiv = (void (CODEGEN_FUNCPTR *)(GLint, GLsizei, const GLuint *))IntGetProcAddress("glUniform4uiv"); + if(!_ptrc_glUniform4uiv) numFailed++; + _ptrc_glVertexAttribI1i = (void (CODEGEN_FUNCPTR *)(GLuint, GLint))IntGetProcAddress("glVertexAttribI1i"); + if(!_ptrc_glVertexAttribI1i) numFailed++; + _ptrc_glVertexAttribI1iv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLint *))IntGetProcAddress("glVertexAttribI1iv"); + if(!_ptrc_glVertexAttribI1iv) numFailed++; + _ptrc_glVertexAttribI1ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint))IntGetProcAddress("glVertexAttribI1ui"); + if(!_ptrc_glVertexAttribI1ui) numFailed++; + _ptrc_glVertexAttribI1uiv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLuint *))IntGetProcAddress("glVertexAttribI1uiv"); + if(!_ptrc_glVertexAttribI1uiv) numFailed++; + _ptrc_glVertexAttribI2i = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint))IntGetProcAddress("glVertexAttribI2i"); + if(!_ptrc_glVertexAttribI2i) numFailed++; + _ptrc_glVertexAttribI2iv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLint *))IntGetProcAddress("glVertexAttribI2iv"); + if(!_ptrc_glVertexAttribI2iv) numFailed++; + _ptrc_glVertexAttribI2ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint))IntGetProcAddress("glVertexAttribI2ui"); + if(!_ptrc_glVertexAttribI2ui) numFailed++; + _ptrc_glVertexAttribI2uiv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLuint *))IntGetProcAddress("glVertexAttribI2uiv"); + if(!_ptrc_glVertexAttribI2uiv) numFailed++; + _ptrc_glVertexAttribI3i = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint))IntGetProcAddress("glVertexAttribI3i"); + if(!_ptrc_glVertexAttribI3i) numFailed++; + _ptrc_glVertexAttribI3iv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLint *))IntGetProcAddress("glVertexAttribI3iv"); + if(!_ptrc_glVertexAttribI3iv) numFailed++; + _ptrc_glVertexAttribI3ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint, GLuint))IntGetProcAddress("glVertexAttribI3ui"); + if(!_ptrc_glVertexAttribI3ui) numFailed++; + _ptrc_glVertexAttribI3uiv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLuint *))IntGetProcAddress("glVertexAttribI3uiv"); + if(!_ptrc_glVertexAttribI3uiv) numFailed++; + _ptrc_glVertexAttribI4bv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLbyte *))IntGetProcAddress("glVertexAttribI4bv"); + if(!_ptrc_glVertexAttribI4bv) numFailed++; + _ptrc_glVertexAttribI4i = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLint, GLint, GLint))IntGetProcAddress("glVertexAttribI4i"); + if(!_ptrc_glVertexAttribI4i) numFailed++; + _ptrc_glVertexAttribI4iv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLint *))IntGetProcAddress("glVertexAttribI4iv"); + if(!_ptrc_glVertexAttribI4iv) numFailed++; + _ptrc_glVertexAttribI4sv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLshort *))IntGetProcAddress("glVertexAttribI4sv"); + if(!_ptrc_glVertexAttribI4sv) numFailed++; + _ptrc_glVertexAttribI4ubv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLubyte *))IntGetProcAddress("glVertexAttribI4ubv"); + if(!_ptrc_glVertexAttribI4ubv) numFailed++; + _ptrc_glVertexAttribI4ui = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint, GLuint, GLuint))IntGetProcAddress("glVertexAttribI4ui"); + if(!_ptrc_glVertexAttribI4ui) numFailed++; + _ptrc_glVertexAttribI4uiv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLuint *))IntGetProcAddress("glVertexAttribI4uiv"); + if(!_ptrc_glVertexAttribI4uiv) numFailed++; + _ptrc_glVertexAttribI4usv = (void (CODEGEN_FUNCPTR *)(GLuint, const GLushort *))IntGetProcAddress("glVertexAttribI4usv"); + if(!_ptrc_glVertexAttribI4usv) numFailed++; + _ptrc_glVertexAttribIPointer = (void (CODEGEN_FUNCPTR *)(GLuint, GLint, GLenum, GLsizei, const void *))IntGetProcAddress("glVertexAttribIPointer"); + if(!_ptrc_glVertexAttribIPointer) numFailed++; + _ptrc_glCopyBufferSubData = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr))IntGetProcAddress("glCopyBufferSubData"); + if(!_ptrc_glCopyBufferSubData) numFailed++; + _ptrc_glDrawArraysInstanced = (void (CODEGEN_FUNCPTR *)(GLenum, GLint, GLsizei, GLsizei))IntGetProcAddress("glDrawArraysInstanced"); + if(!_ptrc_glDrawArraysInstanced) numFailed++; + _ptrc_glDrawElementsInstanced = (void (CODEGEN_FUNCPTR *)(GLenum, GLsizei, GLenum, const void *, GLsizei))IntGetProcAddress("glDrawElementsInstanced"); + if(!_ptrc_glDrawElementsInstanced) numFailed++; + _ptrc_glGetActiveUniformBlockName = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *))IntGetProcAddress("glGetActiveUniformBlockName"); + if(!_ptrc_glGetActiveUniformBlockName) numFailed++; + _ptrc_glGetActiveUniformBlockiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLenum, GLint *))IntGetProcAddress("glGetActiveUniformBlockiv"); + if(!_ptrc_glGetActiveUniformBlockiv) numFailed++; + _ptrc_glGetActiveUniformName = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *))IntGetProcAddress("glGetActiveUniformName"); + if(!_ptrc_glGetActiveUniformName) numFailed++; + _ptrc_glGetActiveUniformsiv = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLuint *, GLenum, GLint *))IntGetProcAddress("glGetActiveUniformsiv"); + if(!_ptrc_glGetActiveUniformsiv) numFailed++; + _ptrc_glGetUniformBlockIndex = (GLuint (CODEGEN_FUNCPTR *)(GLuint, const GLchar *))IntGetProcAddress("glGetUniformBlockIndex"); + if(!_ptrc_glGetUniformBlockIndex) numFailed++; + _ptrc_glGetUniformIndices = (void (CODEGEN_FUNCPTR *)(GLuint, GLsizei, const GLchar *const*, GLuint *))IntGetProcAddress("glGetUniformIndices"); + if(!_ptrc_glGetUniformIndices) numFailed++; + _ptrc_glPrimitiveRestartIndex = (void (CODEGEN_FUNCPTR *)(GLuint))IntGetProcAddress("glPrimitiveRestartIndex"); + if(!_ptrc_glPrimitiveRestartIndex) numFailed++; + _ptrc_glTexBuffer = (void (CODEGEN_FUNCPTR *)(GLenum, GLenum, GLuint))IntGetProcAddress("glTexBuffer"); + if(!_ptrc_glTexBuffer) numFailed++; + _ptrc_glUniformBlockBinding = (void (CODEGEN_FUNCPTR *)(GLuint, GLuint, GLuint))IntGetProcAddress("glUniformBlockBinding"); + if(!_ptrc_glUniformBlockBinding) numFailed++; + return numFailed; +} + +typedef int (*PFN_LOADFUNCPOINTERS)(void); +typedef struct ogl_StrToExtMap_s +{ + char *extensionName; + int *extensionVariable; + PFN_LOADFUNCPOINTERS LoadExtension; +} ogl_StrToExtMap; + +static ogl_StrToExtMap ExtensionMap[52] = { + {"GL_ARB_compressed_texture_pixel_storage", &ogl_ext_ARB_compressed_texture_pixel_storage, NULL}, + {"GL_ARB_conservative_depth", &ogl_ext_ARB_conservative_depth, NULL}, + {"GL_ARB_ES2_compatibility", &ogl_ext_ARB_ES2_compatibility, Load_ARB_ES2_compatibility}, + {"GL_ARB_get_program_binary", &ogl_ext_ARB_get_program_binary, Load_ARB_get_program_binary}, + {"GL_ARB_explicit_uniform_location", &ogl_ext_ARB_explicit_uniform_location, NULL}, + {"GL_ARB_internalformat_query", &ogl_ext_ARB_internalformat_query, Load_ARB_internalformat_query}, + {"GL_ARB_internalformat_query2", &ogl_ext_ARB_internalformat_query2, Load_ARB_internalformat_query2}, + {"GL_ARB_map_buffer_alignment", &ogl_ext_ARB_map_buffer_alignment, NULL}, + {"GL_ARB_program_interface_query", &ogl_ext_ARB_program_interface_query, Load_ARB_program_interface_query}, + {"GL_ARB_separate_shader_objects", &ogl_ext_ARB_separate_shader_objects, Load_ARB_separate_shader_objects}, + {"GL_ARB_shading_language_420pack", &ogl_ext_ARB_shading_language_420pack, NULL}, + {"GL_ARB_shading_language_packing", &ogl_ext_ARB_shading_language_packing, NULL}, + {"GL_ARB_texture_buffer_range", &ogl_ext_ARB_texture_buffer_range, Load_ARB_texture_buffer_range}, + {"GL_ARB_texture_storage", &ogl_ext_ARB_texture_storage, Load_ARB_texture_storage}, + {"GL_ARB_texture_view", &ogl_ext_ARB_texture_view, Load_ARB_texture_view}, + {"GL_ARB_vertex_attrib_binding", &ogl_ext_ARB_vertex_attrib_binding, Load_ARB_vertex_attrib_binding}, + {"GL_ARB_viewport_array", &ogl_ext_ARB_viewport_array, Load_ARB_viewport_array}, + {"GL_ARB_arrays_of_arrays", &ogl_ext_ARB_arrays_of_arrays, NULL}, + {"GL_ARB_clear_buffer_object", &ogl_ext_ARB_clear_buffer_object, Load_ARB_clear_buffer_object}, + {"GL_ARB_copy_image", &ogl_ext_ARB_copy_image, Load_ARB_copy_image}, + {"GL_ARB_ES3_compatibility", &ogl_ext_ARB_ES3_compatibility, NULL}, + {"GL_ARB_fragment_layer_viewport", &ogl_ext_ARB_fragment_layer_viewport, NULL}, + {"GL_ARB_framebuffer_no_attachments", &ogl_ext_ARB_framebuffer_no_attachments, Load_ARB_framebuffer_no_attachments}, + {"GL_ARB_invalidate_subdata", &ogl_ext_ARB_invalidate_subdata, Load_ARB_invalidate_subdata}, + {"GL_ARB_robust_buffer_access_behavior", &ogl_ext_ARB_robust_buffer_access_behavior, NULL}, + {"GL_ARB_stencil_texturing", &ogl_ext_ARB_stencil_texturing, NULL}, + {"GL_ARB_texture_query_levels", &ogl_ext_ARB_texture_query_levels, NULL}, + {"GL_ARB_texture_storage_multisample", &ogl_ext_ARB_texture_storage_multisample, Load_ARB_texture_storage_multisample}, + {"GL_KHR_debug", &ogl_ext_KHR_debug, Load_KHR_debug}, + {"GL_ARB_buffer_storage", &ogl_ext_ARB_buffer_storage, Load_ARB_buffer_storage}, + {"GL_ARB_clear_texture", &ogl_ext_ARB_clear_texture, Load_ARB_clear_texture}, + {"GL_ARB_enhanced_layouts", &ogl_ext_ARB_enhanced_layouts, NULL}, + {"GL_ARB_multi_bind", &ogl_ext_ARB_multi_bind, Load_ARB_multi_bind}, + {"GL_ARB_query_buffer_object", &ogl_ext_ARB_query_buffer_object, NULL}, + {"GL_ARB_texture_mirror_clamp_to_edge", &ogl_ext_ARB_texture_mirror_clamp_to_edge, NULL}, + {"GL_ARB_texture_stencil8", &ogl_ext_ARB_texture_stencil8, NULL}, + {"GL_ARB_vertex_type_10f_11f_11f_rev", &ogl_ext_ARB_vertex_type_10f_11f_11f_rev, NULL}, + {"GL_ARB_seamless_cubemap_per_texture", &ogl_ext_ARB_seamless_cubemap_per_texture, NULL}, + {"GL_ARB_clip_control", &ogl_ext_ARB_clip_control, Load_ARB_clip_control}, + {"GL_ARB_conditional_render_inverted", &ogl_ext_ARB_conditional_render_inverted, NULL}, + {"GL_ARB_cull_distance", &ogl_ext_ARB_cull_distance, NULL}, + {"GL_ARB_derivative_control", &ogl_ext_ARB_derivative_control, NULL}, + {"GL_ARB_direct_state_access", &ogl_ext_ARB_direct_state_access, Load_ARB_direct_state_access}, + {"GL_ARB_get_texture_sub_image", &ogl_ext_ARB_get_texture_sub_image, Load_ARB_get_texture_sub_image}, + {"GL_ARB_shader_texture_image_samples", &ogl_ext_ARB_shader_texture_image_samples, NULL}, + {"GL_ARB_texture_barrier", &ogl_ext_ARB_texture_barrier, Load_ARB_texture_barrier}, + {"GL_KHR_context_flush_control", &ogl_ext_KHR_context_flush_control, NULL}, + {"GL_KHR_robust_buffer_access_behavior", &ogl_ext_KHR_robust_buffer_access_behavior, NULL}, + {"GL_KHR_robustness", &ogl_ext_KHR_robustness, Load_KHR_robustness}, + {"GL_EXT_texture_compression_s3tc", &ogl_ext_EXT_texture_compression_s3tc, NULL}, + {"GL_EXT_texture_sRGB", &ogl_ext_EXT_texture_sRGB, NULL}, + {"GL_EXT_texture_filter_anisotropic", &ogl_ext_EXT_texture_filter_anisotropic, NULL}, +}; + +static int g_extensionMapSize = 52; + +static ogl_StrToExtMap *FindExtEntry(const char *extensionName) +{ + int loop; + ogl_StrToExtMap *currLoc = ExtensionMap; + for(loop = 0; loop < g_extensionMapSize; ++loop, ++currLoc) + { + if(strcmp(extensionName, currLoc->extensionName) == 0) + return currLoc; + } + + return NULL; +} + +static void ClearExtensionVars(void) +{ + ogl_ext_ARB_compressed_texture_pixel_storage = ogl_LOAD_FAILED; + ogl_ext_ARB_conservative_depth = ogl_LOAD_FAILED; + ogl_ext_ARB_ES2_compatibility = ogl_LOAD_FAILED; + ogl_ext_ARB_get_program_binary = ogl_LOAD_FAILED; + ogl_ext_ARB_explicit_uniform_location = ogl_LOAD_FAILED; + ogl_ext_ARB_internalformat_query = ogl_LOAD_FAILED; + ogl_ext_ARB_internalformat_query2 = ogl_LOAD_FAILED; + ogl_ext_ARB_map_buffer_alignment = ogl_LOAD_FAILED; + ogl_ext_ARB_program_interface_query = ogl_LOAD_FAILED; + ogl_ext_ARB_separate_shader_objects = ogl_LOAD_FAILED; + ogl_ext_ARB_shading_language_420pack = ogl_LOAD_FAILED; + ogl_ext_ARB_shading_language_packing = ogl_LOAD_FAILED; + ogl_ext_ARB_texture_buffer_range = ogl_LOAD_FAILED; + ogl_ext_ARB_texture_storage = ogl_LOAD_FAILED; + ogl_ext_ARB_texture_view = ogl_LOAD_FAILED; + ogl_ext_ARB_vertex_attrib_binding = ogl_LOAD_FAILED; + ogl_ext_ARB_viewport_array = ogl_LOAD_FAILED; + ogl_ext_ARB_arrays_of_arrays = ogl_LOAD_FAILED; + ogl_ext_ARB_clear_buffer_object = ogl_LOAD_FAILED; + ogl_ext_ARB_copy_image = ogl_LOAD_FAILED; + ogl_ext_ARB_ES3_compatibility = ogl_LOAD_FAILED; + ogl_ext_ARB_fragment_layer_viewport = ogl_LOAD_FAILED; + ogl_ext_ARB_framebuffer_no_attachments = ogl_LOAD_FAILED; + ogl_ext_ARB_invalidate_subdata = ogl_LOAD_FAILED; + ogl_ext_ARB_robust_buffer_access_behavior = ogl_LOAD_FAILED; + ogl_ext_ARB_stencil_texturing = ogl_LOAD_FAILED; + ogl_ext_ARB_texture_query_levels = ogl_LOAD_FAILED; + ogl_ext_ARB_texture_storage_multisample = ogl_LOAD_FAILED; + ogl_ext_KHR_debug = ogl_LOAD_FAILED; + ogl_ext_ARB_buffer_storage = ogl_LOAD_FAILED; + ogl_ext_ARB_clear_texture = ogl_LOAD_FAILED; + ogl_ext_ARB_enhanced_layouts = ogl_LOAD_FAILED; + ogl_ext_ARB_multi_bind = ogl_LOAD_FAILED; + ogl_ext_ARB_query_buffer_object = ogl_LOAD_FAILED; + ogl_ext_ARB_texture_mirror_clamp_to_edge = ogl_LOAD_FAILED; + ogl_ext_ARB_texture_stencil8 = ogl_LOAD_FAILED; + ogl_ext_ARB_vertex_type_10f_11f_11f_rev = ogl_LOAD_FAILED; + ogl_ext_ARB_seamless_cubemap_per_texture = ogl_LOAD_FAILED; + ogl_ext_ARB_clip_control = ogl_LOAD_FAILED; + ogl_ext_ARB_conditional_render_inverted = ogl_LOAD_FAILED; + ogl_ext_ARB_cull_distance = ogl_LOAD_FAILED; + ogl_ext_ARB_derivative_control = ogl_LOAD_FAILED; + ogl_ext_ARB_direct_state_access = ogl_LOAD_FAILED; + ogl_ext_ARB_get_texture_sub_image = ogl_LOAD_FAILED; + ogl_ext_ARB_shader_texture_image_samples = ogl_LOAD_FAILED; + ogl_ext_ARB_texture_barrier = ogl_LOAD_FAILED; + ogl_ext_KHR_context_flush_control = ogl_LOAD_FAILED; + ogl_ext_KHR_robust_buffer_access_behavior = ogl_LOAD_FAILED; + ogl_ext_KHR_robustness = ogl_LOAD_FAILED; + ogl_ext_EXT_texture_compression_s3tc = ogl_LOAD_FAILED; + ogl_ext_EXT_texture_sRGB = ogl_LOAD_FAILED; + ogl_ext_EXT_texture_filter_anisotropic = ogl_LOAD_FAILED; +} + +static void LoadExtByName(const char *extensionName) +{ + ogl_StrToExtMap *entry = NULL; + entry = FindExtEntry(extensionName); + if(entry) + { + if(entry->LoadExtension) + { + int numFailed = entry->LoadExtension(); + if(numFailed == 0) + { + *(entry->extensionVariable) = ogl_LOAD_SUCCEEDED; + } + else + { + *(entry->extensionVariable) = ogl_LOAD_SUCCEEDED + numFailed; + } + } + else + { + *(entry->extensionVariable) = ogl_LOAD_SUCCEEDED; + } + } +} + +static void ProcExtsFromExtString(const char *strExtList) +{ + size_t iExtListLen = strlen(strExtList); + const char *strExtListEnd = strExtList + iExtListLen; + const char *strCurrPos = strExtList; + char strWorkBuff[256]; + + while(*strCurrPos) + { + /*Get the extension at our position.*/ + int iStrLen = 0; + const char *strEndStr = strchr(strCurrPos, ' '); + int iStop = 0; + if(strEndStr == NULL) + { + strEndStr = strExtListEnd; + iStop = 1; + } + + iStrLen = (int)((ptrdiff_t)strEndStr - (ptrdiff_t)strCurrPos); + + if(iStrLen > 255) + return; + + strncpy(strWorkBuff, strCurrPos, iStrLen); + strWorkBuff[iStrLen] = '\0'; + + LoadExtByName(strWorkBuff); + + strCurrPos = strEndStr + 1; + if(iStop) break; + } +} + +static void ProcExtsFromExtList(void) +{ + GLint iLoop; + GLint iNumExtensions = 0; + _ptrc_glGetIntegerv(GL_NUM_EXTENSIONS, &iNumExtensions); + + for(iLoop = 0; iLoop < iNumExtensions; iLoop++) + { + const char *strExtensionName = (const char *)_ptrc_glGetStringi(GL_EXTENSIONS, iLoop); + LoadExtByName(strExtensionName); + } +} + +int ogl_LoadFunctions() +{ + int numFailed = 0; + ClearExtensionVars(); + _ptrc_glGetString = (const GLubyte * (CODEGEN_FUNCPTR *)(GLenum))IntGetProcAddress("glGetString"); + if(!_ptrc_glGetString) return ogl_LOAD_FAILED; + + if (ogl_GetMajorVersion() < 3) + { + ProcExtsFromExtString((const char *)_ptrc_glGetString(GL_EXTENSIONS)); + } + else + { + _ptrc_glGetIntegerv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint *))IntGetProcAddress("glGetIntegerv"); + if(!_ptrc_glGetIntegerv) return ogl_LOAD_FAILED; + _ptrc_glGetStringi = (const GLubyte * (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glGetStringi"); + if(!_ptrc_glGetStringi) return ogl_LOAD_FAILED; + ProcExtsFromExtList(); + } + + numFailed = Load_Version_3_1(); + + if(numFailed == 0) + return ogl_LOAD_SUCCEEDED; + else + return ogl_LOAD_SUCCEEDED + numFailed; +} + +static int g_major_version = 0; +static int g_minor_version = 0; + +static void ParseVersionFromString(int *pOutMajor, int *pOutMinor, const char *strVersion) +{ + const char *strDotPos = NULL; + *pOutMinor = 0; + *pOutMajor = 0; + + strDotPos = strchr(strVersion, '.'); + if(!strDotPos) + return; + + *pOutMajor = atoi(strVersion); + *pOutMinor = atoi(strDotPos + 1); +} + +static void GetGLVersion(void) +{ + ParseVersionFromString(&g_major_version, &g_minor_version, (const char*)glGetString(GL_VERSION)); +} + +int ogl_GetMajorVersion(void) +{ + if(g_major_version == 0) + GetGLVersion(); + return g_major_version; +} + +int ogl_GetMinorVersion(void) +{ + if(g_major_version == 0) /*Yes, check the major version to get the minor one.*/ + GetGLVersion(); + return g_minor_version; +} + +int ogl_IsVersionGEQ(int majorVersion, int minorVersion) +{ + if(g_major_version == 0) + GetGLVersion(); + + if(majorVersion < g_major_version) return 1; + if(majorVersion > g_major_version) return 0; + if(minorVersion <= g_minor_version) return 1; + return 0; +} diff --git a/third_party/gl_core/gl_core_3_1.h b/third_party/gl_core/gl_core_3_1.h new file mode 100644 index 0000000..b80ce65 --- /dev/null +++ b/third_party/gl_core/gl_core_3_1.h @@ -0,0 +1,3703 @@ +#ifndef POINTER_C_GENERATED_HEADER_OPENGL_H +#define POINTER_C_GENERATED_HEADER_OPENGL_H + +#if defined(__glew_h__) || defined(__GLEW_H__) +#error Attempt to include auto-generated header after including glew.h +#endif +#if defined(__gl_h_) || defined(__GL_H__) +#error Attempt to include auto-generated header after including gl.h +#endif +#if defined(__glext_h_) || defined(__GLEXT_H_) +#error Attempt to include auto-generated header after including glext.h +#endif +#if defined(__gltypes_h_) +#error Attempt to include auto-generated header after gltypes.h +#endif +#if defined(__gl_ATI_h_) +#error Attempt to include auto-generated header after including glATI.h +#endif + +#define __glew_h__ +#define __GLEW_H__ +#define __gl_h_ +#define __GL_H__ +#define __glext_h_ +#define __GLEXT_H_ +#define __gltypes_h_ +#define __gl_ATI_h_ + +#ifndef GL_APIENTRY +#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) +#define GL_APIENTRY __stdcall +#else +#define GL_APIENTRY +#endif +#endif // GL_APIENTRY + +#ifndef CODEGEN_FUNCPTR + #define CODEGEN_REMOVE_FUNCPTR + #if defined(_WIN32) + #define CODEGEN_FUNCPTR GL_APIENTRY + #else + #define CODEGEN_FUNCPTR + #endif +#endif /*CODEGEN_FUNCPTR*/ + +#ifndef GLAPI + #define GLAPI extern +#endif + +#ifndef GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS +#define GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS + + +#endif /*GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS*/ + + +#include +#ifndef GLEXT_64_TYPES_DEFINED +/* This code block is duplicated in glxext.h, so must be protected */ +#define GLEXT_64_TYPES_DEFINED +/* Define int32_t, int64_t, and uint64_t types for UST/MSC */ +/* (as used in the GL_EXT_timer_query extension). */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +#elif defined(__sun__) || defined(__digital__) +#include +#if defined(__STDC__) +#if defined(__arch64__) || defined(_LP64) +typedef long int int64_t; +typedef unsigned long int uint64_t; +#else +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#endif /* __arch64__ */ +#endif /* __STDC__ */ +#elif defined( __VMS ) || defined(__sgi) +#include +#elif defined(__SCO__) || defined(__USLC__) +#include +#elif defined(__UNIXOS2__) || defined(__SOL64__) +typedef long int int32_t; +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#elif defined(_WIN32) && defined(__GNUC__) +#include +#elif defined(_WIN32) +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* Fallback if nothing above works */ +#include +#endif +#endif + typedef unsigned int GLenum; + typedef unsigned char GLboolean; + typedef unsigned int GLbitfield; + typedef void GLvoid; + typedef signed char GLbyte; + typedef short GLshort; + typedef int GLint; + typedef unsigned char GLubyte; + typedef unsigned short GLushort; + typedef unsigned int GLuint; + typedef int GLsizei; + typedef float GLfloat; + typedef float GLclampf; + typedef double GLdouble; + typedef double GLclampd; + typedef char GLchar; + typedef char GLcharARB; + #ifdef __APPLE__ +typedef void *GLhandleARB; +#else +typedef unsigned int GLhandleARB; +#endif + typedef unsigned short GLhalfARB; + typedef unsigned short GLhalf; + typedef GLint GLfixed; + typedef ptrdiff_t GLintptr; + typedef ptrdiff_t GLsizeiptr; + typedef int64_t GLint64; + typedef uint64_t GLuint64; + typedef ptrdiff_t GLintptrARB; + typedef ptrdiff_t GLsizeiptrARB; + typedef int64_t GLint64EXT; + typedef uint64_t GLuint64EXT; + typedef struct __GLsync *GLsync; + struct _cl_context; + struct _cl_event; + typedef void (GL_APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); + typedef void (GL_APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); + typedef void (GL_APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam); + typedef unsigned short GLhalfNV; + typedef GLintptr GLvdpauSurfaceNV; + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus*/ + +extern int ogl_ext_ARB_compressed_texture_pixel_storage; +extern int ogl_ext_ARB_conservative_depth; +extern int ogl_ext_ARB_ES2_compatibility; +extern int ogl_ext_ARB_get_program_binary; +extern int ogl_ext_ARB_explicit_uniform_location; +extern int ogl_ext_ARB_internalformat_query; +extern int ogl_ext_ARB_internalformat_query2; +extern int ogl_ext_ARB_map_buffer_alignment; +extern int ogl_ext_ARB_program_interface_query; +extern int ogl_ext_ARB_separate_shader_objects; +extern int ogl_ext_ARB_shading_language_420pack; +extern int ogl_ext_ARB_shading_language_packing; +extern int ogl_ext_ARB_texture_buffer_range; +extern int ogl_ext_ARB_texture_storage; +extern int ogl_ext_ARB_texture_view; +extern int ogl_ext_ARB_vertex_attrib_binding; +extern int ogl_ext_ARB_viewport_array; +extern int ogl_ext_ARB_arrays_of_arrays; +extern int ogl_ext_ARB_clear_buffer_object; +extern int ogl_ext_ARB_copy_image; +extern int ogl_ext_ARB_ES3_compatibility; +extern int ogl_ext_ARB_fragment_layer_viewport; +extern int ogl_ext_ARB_framebuffer_no_attachments; +extern int ogl_ext_ARB_invalidate_subdata; +extern int ogl_ext_ARB_robust_buffer_access_behavior; +extern int ogl_ext_ARB_stencil_texturing; +extern int ogl_ext_ARB_texture_query_levels; +extern int ogl_ext_ARB_texture_storage_multisample; +extern int ogl_ext_KHR_debug; +extern int ogl_ext_ARB_buffer_storage; +extern int ogl_ext_ARB_clear_texture; +extern int ogl_ext_ARB_enhanced_layouts; +extern int ogl_ext_ARB_multi_bind; +extern int ogl_ext_ARB_query_buffer_object; +extern int ogl_ext_ARB_texture_mirror_clamp_to_edge; +extern int ogl_ext_ARB_texture_stencil8; +extern int ogl_ext_ARB_vertex_type_10f_11f_11f_rev; +extern int ogl_ext_ARB_seamless_cubemap_per_texture; +extern int ogl_ext_ARB_clip_control; +extern int ogl_ext_ARB_conditional_render_inverted; +extern int ogl_ext_ARB_cull_distance; +extern int ogl_ext_ARB_derivative_control; +extern int ogl_ext_ARB_direct_state_access; +extern int ogl_ext_ARB_get_texture_sub_image; +extern int ogl_ext_ARB_shader_texture_image_samples; +extern int ogl_ext_ARB_texture_barrier; +extern int ogl_ext_KHR_context_flush_control; +extern int ogl_ext_KHR_robust_buffer_access_behavior; +extern int ogl_ext_KHR_robustness; +extern int ogl_ext_EXT_texture_compression_s3tc; +extern int ogl_ext_EXT_texture_sRGB; +extern int ogl_ext_EXT_texture_filter_anisotropic; + +#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D +#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C +#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E +#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B +#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129 +#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128 +#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A +#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127 + +#define GL_FIXED 0x140C +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_HIGH_INT 0x8DF5 +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_LOW_FLOAT 0x8DF0 +#define GL_LOW_INT 0x8DF3 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_RGB565 0x8D62 +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_SHADER_COMPILER 0x8DFA + +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 + +#define GL_MAX_UNIFORM_LOCATIONS 0x826E + +#define GL_NUM_SAMPLE_COUNTS 0x9380 + +#define GL_AUTO_GENERATE_MIPMAP 0x8295 +#define GL_CAVEAT_SUPPORT 0x82B8 +#define GL_CLEAR_BUFFER 0x82B4 +#define GL_COLOR_COMPONENTS 0x8283 +#define GL_COLOR_ENCODING 0x8296 +#define GL_COLOR_RENDERABLE 0x8286 +#define GL_COMPUTE_TEXTURE 0x82A0 +#define GL_DEPTH_COMPONENTS 0x8284 +#define GL_DEPTH_RENDERABLE 0x8287 +#define GL_FILTER 0x829A +#define GL_FRAGMENT_TEXTURE 0x829F +#define GL_FRAMEBUFFER_BLEND 0x828B +#define GL_FRAMEBUFFER_RENDERABLE 0x8289 +#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A +#define GL_FULL_SUPPORT 0x82B7 +#define GL_GEOMETRY_TEXTURE 0x829E +#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291 +#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292 +#define GL_IMAGE_CLASS_10_10_10_2 0x82C3 +#define GL_IMAGE_CLASS_11_11_10 0x82C2 +#define GL_IMAGE_CLASS_1_X_16 0x82BE +#define GL_IMAGE_CLASS_1_X_32 0x82BB +#define GL_IMAGE_CLASS_1_X_8 0x82C1 +#define GL_IMAGE_CLASS_2_X_16 0x82BD +#define GL_IMAGE_CLASS_2_X_32 0x82BA +#define GL_IMAGE_CLASS_2_X_8 0x82C0 +#define GL_IMAGE_CLASS_4_X_16 0x82BC +#define GL_IMAGE_CLASS_4_X_32 0x82B9 +#define GL_IMAGE_CLASS_4_X_8 0x82BF +#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_IMAGE_PIXEL_FORMAT 0x82A9 +#define GL_IMAGE_PIXEL_TYPE 0x82AA +#define GL_IMAGE_TEXEL_SIZE 0x82A7 +#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274 +#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B +#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273 +#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A +#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275 +#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C +#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272 +#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279 +#define GL_INTERNALFORMAT_PREFERRED 0x8270 +#define GL_INTERNALFORMAT_RED_SIZE 0x8271 +#define GL_INTERNALFORMAT_RED_TYPE 0x8278 +#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277 +#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276 +#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D +#define GL_INTERNALFORMAT_SUPPORTED 0x826F +#define GL_MANUAL_GENERATE_MIPMAP 0x8294 +#define GL_MAX_COMBINED_DIMENSIONS 0x8282 +#define GL_MAX_DEPTH 0x8280 +#define GL_MAX_HEIGHT 0x827F +#define GL_MAX_LAYERS 0x8281 +#define GL_MAX_WIDTH 0x827E +#define GL_MIPMAP 0x8293 +/*Copied GL_NUM_SAMPLE_COUNTS From: ARB_internalformat_query*/ +#define GL_READ_PIXELS 0x828C +#define GL_READ_PIXELS_FORMAT 0x828D +#define GL_READ_PIXELS_TYPE 0x828E +#define GL_RENDERBUFFER 0x8D41 +#define GL_SAMPLES 0x80A9 +#define GL_SHADER_IMAGE_ATOMIC 0x82A6 +#define GL_SHADER_IMAGE_LOAD 0x82A4 +#define GL_SHADER_IMAGE_STORE 0x82A5 +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF +#define GL_SRGB_DECODE_ARB 0x8299 +#define GL_SRGB_READ 0x8297 +#define GL_SRGB_WRITE 0x8298 +#define GL_STENCIL_COMPONENTS 0x8285 +#define GL_STENCIL_RENDERABLE 0x8288 +#define GL_TESS_CONTROL_TEXTURE 0x829C +#define GL_TESS_EVALUATION_TEXTURE 0x829D +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2 +#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3 +#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_GATHER 0x82A2 +#define GL_TEXTURE_GATHER_SHADOW 0x82A3 +#define GL_TEXTURE_IMAGE_FORMAT 0x828F +#define GL_TEXTURE_IMAGE_TYPE 0x8290 +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_SHADOW 0x82A1 +#define GL_TEXTURE_VIEW 0x82B5 +#define GL_VERTEX_TEXTURE 0x829B +#define GL_VIEW_CLASS_128_BITS 0x82C4 +#define GL_VIEW_CLASS_16_BITS 0x82CA +#define GL_VIEW_CLASS_24_BITS 0x82C9 +#define GL_VIEW_CLASS_32_BITS 0x82C8 +#define GL_VIEW_CLASS_48_BITS 0x82C7 +#define GL_VIEW_CLASS_64_BITS 0x82C6 +#define GL_VIEW_CLASS_8_BITS 0x82CB +#define GL_VIEW_CLASS_96_BITS 0x82C5 +#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3 +#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2 +#define GL_VIEW_CLASS_RGTC1_RED 0x82D0 +#define GL_VIEW_CLASS_RGTC2_RG 0x82D1 +#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC +#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD +#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE +#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF +#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6 + +#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC + +#define GL_ACTIVE_RESOURCES 0x92F5 +#define GL_ACTIVE_VARIABLES 0x9305 +#define GL_ARRAY_SIZE 0x92FB +#define GL_ARRAY_STRIDE 0x92FE +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 +#define GL_BLOCK_INDEX 0x92FD +#define GL_BUFFER_BINDING 0x9302 +#define GL_BUFFER_DATA_SIZE 0x9303 +#define GL_BUFFER_VARIABLE 0x92E5 +#define GL_COMPATIBLE_SUBROUTINES 0x8E4B +#define GL_COMPUTE_SUBROUTINE 0x92ED +#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3 +#define GL_FRAGMENT_SUBROUTINE 0x92EC +#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2 +#define GL_GEOMETRY_SUBROUTINE 0x92EB +#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1 +#define GL_IS_PER_PATCH 0x92E7 +#define GL_IS_ROW_MAJOR 0x9300 +#define GL_LOCATION 0x930E +#define GL_LOCATION_INDEX 0x930F +#define GL_MATRIX_STRIDE 0x92FF +#define GL_MAX_NAME_LENGTH 0x92F6 +#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 +#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8 +#define GL_NAME_LENGTH 0x92F9 +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A +#define GL_OFFSET 0x92FC +#define GL_PROGRAM_INPUT 0x92E3 +#define GL_PROGRAM_OUTPUT 0x92E4 +#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B +#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A +#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308 +#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#define GL_TESS_CONTROL_SUBROUTINE 0x92E9 +#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF +#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA +#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0 +#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C +#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D +#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 +#define GL_TYPE 0x92FA +#define GL_UNIFORM 0x92E1 +#define GL_UNIFORM_BLOCK 0x92E2 +#define GL_VERTEX_SUBROUTINE 0x92E8 +#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE + +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_ALL_SHADER_BITS 0xFFFFFFFF +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_GEOMETRY_SHADER_BIT 0x00000004 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 +#define GL_VERTEX_SHADER_BIT 0x00000001 + +#define GL_TEXTURE_BUFFER_OFFSET 0x919D +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F +#define GL_TEXTURE_BUFFER_SIZE 0x919E + +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F + +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD +#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB +#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE +#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC + +#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA +#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 +#define GL_VERTEX_ATTRIB_BINDING 0x82D4 +#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 +#define GL_VERTEX_BINDING_DIVISOR 0x82D6 +#define GL_VERTEX_BINDING_OFFSET 0x82D7 +#define GL_VERTEX_BINDING_STRIDE 0x82D8 + +#define GL_DEPTH_RANGE 0x0B70 +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_LAYER_PROVOKING_VERTEX 0x825E +#define GL_MAX_VIEWPORTS 0x825B +#define GL_PROVOKING_VERTEX 0x8E4F +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_UNDEFINED_VERTEX 0x8260 +#define GL_VIEWPORT 0x0BA2 +#define GL_VIEWPORT_BOUNDS_RANGE 0x825D +#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F +#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C + +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 + +#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 +#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317 +#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 +#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 + +#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA + +#define GL_BUFFER 0x82E0 +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 +#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D +#define GL_DEBUG_LOGGED_MESSAGES 0x9145 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DISPLAY_LIST 0x82E7 +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C +#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 +#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 +#define GL_MAX_LABEL_LENGTH 0x82E8 +#define GL_PROGRAM 0x82E2 +#define GL_PROGRAM_PIPELINE 0x82E4 +#define GL_QUERY 0x82E3 +#define GL_SAMPLER 0x82E6 +#define GL_SHADER 0x82E1 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_VERTEX_ARRAY 0x8074 + +#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F +#define GL_BUFFER_STORAGE_FLAGS 0x8220 +#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000 +#define GL_CLIENT_STORAGE_BIT 0x0200 +#define GL_DYNAMIC_STORAGE_BIT 0x0100 +#define GL_MAP_COHERENT_BIT 0x0080 +#define GL_MAP_PERSISTENT_BIT 0x0040 +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 + +#define GL_CLEAR_TEXTURE 0x9365 + +#define GL_LOCATION_COMPONENT 0x934A +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B +#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C + +#define GL_QUERY_BUFFER 0x9192 +#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000 +#define GL_QUERY_BUFFER_BINDING 0x9193 +#define GL_QUERY_RESULT_NO_WAIT 0x9194 + +#define GL_MIRROR_CLAMP_TO_EDGE 0x8743 + +#define GL_STENCIL_INDEX 0x1901 +#define GL_STENCIL_INDEX8 0x8D48 + +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B + +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F + +#define GL_CLIP_DEPTH_MODE 0x935D +#define GL_CLIP_ORIGIN 0x935C +#define GL_LOWER_LEFT 0x8CA1 +#define GL_NEGATIVE_ONE_TO_ONE 0x935E +#define GL_UPPER_LEFT 0x8CA2 +#define GL_ZERO_TO_ONE 0x935F + +#define GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A +#define GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19 +#define GL_QUERY_NO_WAIT_INVERTED 0x8E18 +#define GL_QUERY_WAIT_INVERTED 0x8E17 + +#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA +#define GL_MAX_CULL_DISTANCES 0x82F9 + +#define GL_QUERY_TARGET 0x82EA +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_TEXTURE_TARGET 0x1006 + +#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB +#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC +#define GL_NONE 0 + +#define GL_CONTEXT_LOST 0x0507 +#define GL_CONTEXT_ROBUST_ACCESS 0x90F3 +#define GL_GUILTY_CONTEXT_RESET 0x8253 +#define GL_INNOCENT_CONTEXT_RESET 0x8254 +#define GL_LOSE_CONTEXT_ON_RESET 0x8252 +#define GL_NO_ERROR 0 +#define GL_NO_RESET_NOTIFICATION 0x8261 +#define GL_RESET_NOTIFICATION_STRATEGY 0x8256 +#define GL_UNKNOWN_CONTEXT_RESET 0x8255 + +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 + +#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B +#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A +#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F +#define GL_COMPRESSED_SRGB_EXT 0x8C48 +#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C +#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 +#define GL_SLUMINANCE8_EXT 0x8C47 +#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 +#define GL_SLUMINANCE_EXT 0x8C46 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_SRGB8_EXT 0x8C41 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB_EXT 0x8C40 + +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE + +#define GL_2D 0x0600 +#define GL_2_BYTES 0x1407 +#define GL_3D 0x0601 +#define GL_3D_COLOR 0x0602 +#define GL_3D_COLOR_TEXTURE 0x0603 +#define GL_3_BYTES 0x1408 +#define GL_4D_COLOR_TEXTURE 0x0604 +#define GL_4_BYTES 0x1409 +#define GL_ACCUM 0x0100 +#define GL_ACCUM_ALPHA_BITS 0x0D5B +#define GL_ACCUM_BLUE_BITS 0x0D5A +#define GL_ACCUM_BUFFER_BIT 0x00000200 +#define GL_ACCUM_CLEAR_VALUE 0x0B80 +#define GL_ACCUM_GREEN_BITS 0x0D59 +#define GL_ACCUM_RED_BITS 0x0D58 +#define GL_ADD 0x0104 +#define GL_ALL_ATTRIB_BITS 0xFFFFFFFF +#define GL_ALPHA 0x1906 +#define GL_ALPHA12 0x803D +#define GL_ALPHA16 0x803E +#define GL_ALPHA4 0x803B +#define GL_ALPHA8 0x803C +#define GL_ALPHA_BIAS 0x0D1D +#define GL_ALPHA_BITS 0x0D55 +#define GL_ALPHA_SCALE 0x0D1C +#define GL_ALPHA_TEST 0x0BC0 +#define GL_ALPHA_TEST_FUNC 0x0BC1 +#define GL_ALPHA_TEST_REF 0x0BC2 +#define GL_ALWAYS 0x0207 +#define GL_AMBIENT 0x1200 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_AND 0x1501 +#define GL_AND_INVERTED 0x1504 +#define GL_AND_REVERSE 0x1502 +#define GL_ATTRIB_STACK_DEPTH 0x0BB0 +#define GL_AUTO_NORMAL 0x0D80 +#define GL_AUX0 0x0409 +#define GL_AUX1 0x040A +#define GL_AUX2 0x040B +#define GL_AUX3 0x040C +#define GL_AUX_BUFFERS 0x0C00 +#define GL_BACK 0x0405 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_BITMAP 0x1A00 +#define GL_BITMAP_TOKEN 0x0704 +#define GL_BLEND 0x0BE2 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLUE 0x1905 +#define GL_BLUE_BIAS 0x0D1B +#define GL_BLUE_BITS 0x0D54 +#define GL_BLUE_SCALE 0x0D1A +#define GL_BYTE 0x1400 +#define GL_C3F_V3F 0x2A24 +#define GL_C4F_N3F_V3F 0x2A26 +#define GL_C4UB_V2F 0x2A22 +#define GL_C4UB_V3F 0x2A23 +#define GL_CCW 0x0901 +#define GL_CLAMP 0x2900 +#define GL_CLEAR 0x1500 +#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF +#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 +#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 +#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 +#define GL_COEFF 0x0A00 +#define GL_COLOR 0x1800 +#define GL_COLOR_ARRAY 0x8076 +#define GL_COLOR_ARRAY_POINTER 0x8090 +#define GL_COLOR_ARRAY_SIZE 0x8081 +#define GL_COLOR_ARRAY_STRIDE 0x8083 +#define GL_COLOR_ARRAY_TYPE 0x8082 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_INDEX 0x1900 +#define GL_COLOR_INDEXES 0x1603 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_COLOR_MATERIAL_FACE 0x0B55 +#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_COMPILE 0x1300 +#define GL_COMPILE_AND_EXECUTE 0x1301 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_COPY 0x1503 +#define GL_COPY_INVERTED 0x150C +#define GL_COPY_PIXEL_TOKEN 0x0706 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_CURRENT_BIT 0x00000001 +#define GL_CURRENT_COLOR 0x0B00 +#define GL_CURRENT_INDEX 0x0B01 +#define GL_CURRENT_NORMAL 0x0B02 +#define GL_CURRENT_RASTER_COLOR 0x0B04 +#define GL_CURRENT_RASTER_DISTANCE 0x0B09 +#define GL_CURRENT_RASTER_INDEX 0x0B05 +#define GL_CURRENT_RASTER_POSITION 0x0B07 +#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 +#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 +#define GL_CURRENT_TEXTURE_COORDS 0x0B03 +#define GL_CW 0x0900 +#define GL_DECAL 0x2101 +#define GL_DECR 0x1E03 +#define GL_DEPTH 0x1801 +#define GL_DEPTH_BIAS 0x0D1F +#define GL_DEPTH_BITS 0x0D56 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_FUNC 0x0B74 +/*Copied GL_DEPTH_RANGE From: ARB_viewport_array*/ +#define GL_DEPTH_SCALE 0x0D1E +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DIFFUSE 0x1201 +#define GL_DITHER 0x0BD0 +#define GL_DOMAIN 0x0A02 +#define GL_DONT_CARE 0x1100 +#define GL_DOUBLE 0x140A +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_DRAW_PIXEL_TOKEN 0x0705 +#define GL_DST_ALPHA 0x0304 +#define GL_DST_COLOR 0x0306 +#define GL_EDGE_FLAG 0x0B43 +#define GL_EDGE_FLAG_ARRAY 0x8079 +#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 +#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C +#define GL_EMISSION 0x1600 +#define GL_ENABLE_BIT 0x00002000 +#define GL_EQUAL 0x0202 +#define GL_EQUIV 0x1509 +#define GL_EVAL_BIT 0x00010000 +#define GL_EXP 0x0800 +#define GL_EXP2 0x0801 +#define GL_EXTENSIONS 0x1F03 +#define GL_EYE_LINEAR 0x2400 +#define GL_EYE_PLANE 0x2502 +#define GL_FALSE 0 +#define GL_FASTEST 0x1101 +#define GL_FEEDBACK 0x1C01 +#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 +#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 +#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 +#define GL_FILL 0x1B02 +#define GL_FLAT 0x1D00 +#define GL_FLOAT 0x1406 +#define GL_FOG 0x0B60 +#define GL_FOG_BIT 0x00000080 +#define GL_FOG_COLOR 0x0B66 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_END 0x0B64 +#define GL_FOG_HINT 0x0C54 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_START 0x0B63 +#define GL_FRONT 0x0404 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_FRONT_FACE 0x0B46 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_GEQUAL 0x0206 +#define GL_GREATER 0x0204 +#define GL_GREEN 0x1904 +#define GL_GREEN_BIAS 0x0D19 +#define GL_GREEN_BITS 0x0D53 +#define GL_GREEN_SCALE 0x0D18 +#define GL_HINT_BIT 0x00008000 +#define GL_INCR 0x1E02 +#define GL_INDEX_ARRAY 0x8077 +#define GL_INDEX_ARRAY_POINTER 0x8091 +#define GL_INDEX_ARRAY_STRIDE 0x8086 +#define GL_INDEX_ARRAY_TYPE 0x8085 +#define GL_INDEX_BITS 0x0D51 +#define GL_INDEX_CLEAR_VALUE 0x0C20 +#define GL_INDEX_LOGIC_OP 0x0BF1 +#define GL_INDEX_MODE 0x0C30 +#define GL_INDEX_OFFSET 0x0D13 +#define GL_INDEX_SHIFT 0x0D12 +#define GL_INDEX_WRITEMASK 0x0C21 +#define GL_INT 0x1404 +#define GL_INTENSITY 0x8049 +#define GL_INTENSITY12 0x804C +#define GL_INTENSITY16 0x804D +#define GL_INTENSITY4 0x804A +#define GL_INTENSITY8 0x804B +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_OPERATION 0x0502 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVERT 0x150A +#define GL_KEEP 0x1E00 +#define GL_LEFT 0x0406 +#define GL_LEQUAL 0x0203 +#define GL_LESS 0x0201 +#define GL_LIGHT0 0x4000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 +#define GL_LIGHTING 0x0B50 +#define GL_LIGHTING_BIT 0x00000040 +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GL_LINE 0x1B01 +#define GL_LINEAR 0x2601 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINES 0x0001 +#define GL_LINE_BIT 0x00000004 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_RESET_TOKEN 0x0707 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_LINE_STIPPLE 0x0B24 +#define GL_LINE_STIPPLE_PATTERN 0x0B25 +#define GL_LINE_STIPPLE_REPEAT 0x0B26 +#define GL_LINE_STRIP 0x0003 +#define GL_LINE_TOKEN 0x0702 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LIST_BASE 0x0B32 +#define GL_LIST_BIT 0x00020000 +#define GL_LIST_INDEX 0x0B33 +#define GL_LIST_MODE 0x0B30 +#define GL_LOAD 0x0101 +#define GL_LOGIC_OP 0x0BF1 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE12 0x8041 +#define GL_LUMINANCE12_ALPHA12 0x8047 +#define GL_LUMINANCE12_ALPHA4 0x8046 +#define GL_LUMINANCE16 0x8042 +#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_LUMINANCE4 0x803F +#define GL_LUMINANCE4_ALPHA4 0x8043 +#define GL_LUMINANCE6_ALPHA2 0x8044 +#define GL_LUMINANCE8 0x8040 +#define GL_LUMINANCE8_ALPHA8 0x8045 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_MAP1_COLOR_4 0x0D90 +#define GL_MAP1_GRID_DOMAIN 0x0DD0 +#define GL_MAP1_GRID_SEGMENTS 0x0DD1 +#define GL_MAP1_INDEX 0x0D91 +#define GL_MAP1_NORMAL 0x0D92 +#define GL_MAP1_TEXTURE_COORD_1 0x0D93 +#define GL_MAP1_TEXTURE_COORD_2 0x0D94 +#define GL_MAP1_TEXTURE_COORD_3 0x0D95 +#define GL_MAP1_TEXTURE_COORD_4 0x0D96 +#define GL_MAP1_VERTEX_3 0x0D97 +#define GL_MAP1_VERTEX_4 0x0D98 +#define GL_MAP2_COLOR_4 0x0DB0 +#define GL_MAP2_GRID_DOMAIN 0x0DD2 +#define GL_MAP2_GRID_SEGMENTS 0x0DD3 +#define GL_MAP2_INDEX 0x0DB1 +#define GL_MAP2_NORMAL 0x0DB2 +#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 +#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 +#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 +#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 +#define GL_MAP2_VERTEX_3 0x0DB7 +#define GL_MAP2_VERTEX_4 0x0DB8 +#define GL_MAP_COLOR 0x0D10 +#define GL_MAP_STENCIL 0x0D11 +#define GL_MATRIX_MODE 0x0BA0 +#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 +#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_MAX_EVAL_ORDER 0x0D30 +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_LIST_NESTING 0x0B31 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_NAME_STACK_DEPTH 0x0D37 +#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MODELVIEW 0x1700 +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 +#define GL_MODULATE 0x2100 +#define GL_MULT 0x0103 +#define GL_N3F_V3F 0x2A25 +#define GL_NAME_STACK_DEPTH 0x0D70 +#define GL_NAND 0x150E +#define GL_NEAREST 0x2600 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEVER 0x0200 +#define GL_NICEST 0x1102 +/*Copied GL_NONE From: KHR_context_flush_control*/ +#define GL_NOOP 0x1505 +#define GL_NOR 0x1508 +#define GL_NORMALIZE 0x0BA1 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_NORMAL_ARRAY_POINTER 0x808F +#define GL_NORMAL_ARRAY_STRIDE 0x807F +#define GL_NORMAL_ARRAY_TYPE 0x807E +#define GL_NOTEQUAL 0x0205 +/*Copied GL_NO_ERROR From: KHR_robustness*/ +#define GL_OBJECT_LINEAR 0x2401 +#define GL_OBJECT_PLANE 0x2501 +#define GL_ONE 1 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_OR 0x1507 +#define GL_ORDER 0x0A01 +#define GL_OR_INVERTED 0x150D +#define GL_OR_REVERSE 0x150B +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PASS_THROUGH_TOKEN 0x0700 +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_PIXEL_MAP_A_TO_A 0x0C79 +#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 +#define GL_PIXEL_MAP_B_TO_B 0x0C78 +#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 +#define GL_PIXEL_MAP_G_TO_G 0x0C77 +#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 +#define GL_PIXEL_MAP_I_TO_A 0x0C75 +#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 +#define GL_PIXEL_MAP_I_TO_B 0x0C74 +#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 +#define GL_PIXEL_MAP_I_TO_G 0x0C73 +#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 +#define GL_PIXEL_MAP_I_TO_I 0x0C70 +#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 +#define GL_PIXEL_MAP_I_TO_R 0x0C72 +#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 +#define GL_PIXEL_MAP_R_TO_R 0x0C76 +#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 +#define GL_PIXEL_MAP_S_TO_S 0x0C71 +#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 +#define GL_PIXEL_MODE_BIT 0x00000020 +#define GL_POINT 0x1B00 +#define GL_POINTS 0x0000 +#define GL_POINT_BIT 0x00000002 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SMOOTH 0x0B10 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_POINT_TOKEN 0x0701 +#define GL_POLYGON 0x0009 +#define GL_POLYGON_BIT 0x00000008 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_POLYGON_STIPPLE 0x0B42 +#define GL_POLYGON_STIPPLE_BIT 0x00000010 +#define GL_POLYGON_TOKEN 0x0703 +#define GL_POSITION 0x1203 +#define GL_PROJECTION 0x1701 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_PROJECTION_STACK_DEPTH 0x0BA4 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_Q 0x2003 +#define GL_QUADRATIC_ATTENUATION 0x1209 +#define GL_QUADS 0x0007 +#define GL_QUAD_STRIP 0x0008 +#define GL_R 0x2002 +#define GL_R3_G3_B2 0x2A10 +#define GL_READ_BUFFER 0x0C02 +#define GL_RED 0x1903 +#define GL_RED_BIAS 0x0D15 +#define GL_RED_BITS 0x0D52 +#define GL_RED_SCALE 0x0D14 +#define GL_RENDER 0x1C00 +#define GL_RENDERER 0x1F01 +#define GL_RENDER_MODE 0x0C40 +#define GL_REPEAT 0x2901 +#define GL_REPLACE 0x1E01 +#define GL_RETURN 0x0102 +#define GL_RGB 0x1907 +#define GL_RGB10 0x8052 +#define GL_RGB10_A2 0x8059 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB5_A1 0x8057 +#define GL_RGB8 0x8051 +#define GL_RGBA 0x1908 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGBA8 0x8058 +#define GL_RGBA_MODE 0x0C31 +#define GL_RIGHT 0x0407 +#define GL_S 0x2000 +#define GL_SCISSOR_BIT 0x00080000 +/*Copied GL_SCISSOR_BOX From: ARB_viewport_array*/ +/*Copied GL_SCISSOR_TEST From: ARB_viewport_array*/ +#define GL_SELECT 0x1C02 +#define GL_SELECTION_BUFFER_POINTER 0x0DF3 +#define GL_SELECTION_BUFFER_SIZE 0x0DF4 +#define GL_SET 0x150F +#define GL_SHADE_MODEL 0x0B54 +#define GL_SHININESS 0x1601 +#define GL_SHORT 0x1402 +#define GL_SMOOTH 0x1D01 +#define GL_SPECULAR 0x1202 +#define GL_SPHERE_MAP 0x2402 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SRC_ALPHA 0x0302 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_SRC_COLOR 0x0300 +/*Copied GL_STACK_OVERFLOW From: KHR_debug*/ +/*Copied GL_STACK_UNDERFLOW From: KHR_debug*/ +#define GL_STENCIL 0x1802 +#define GL_STENCIL_BITS 0x0D57 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_FUNC 0x0B92 +/*Copied GL_STENCIL_INDEX From: ARB_texture_stencil8*/ +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STEREO 0x0C33 +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_T 0x2001 +#define GL_T2F_C3F_V3F 0x2A2A +#define GL_T2F_C4F_N3F_V3F 0x2A2C +#define GL_T2F_C4UB_V3F 0x2A29 +#define GL_T2F_N3F_V3F 0x2A2B +#define GL_T2F_V3F 0x2A27 +#define GL_T4F_C4F_N3F_V4F 0x2A2D +#define GL_T4F_V4F 0x2A28 +#define GL_TEXTURE 0x1702 +/*Copied GL_TEXTURE_1D From: ARB_internalformat_query2*/ +/*Copied GL_TEXTURE_2D From: ARB_internalformat_query2*/ +#define GL_TEXTURE_ALPHA_SIZE 0x805F +/*Copied GL_TEXTURE_BINDING_1D From: ARB_direct_state_access*/ +/*Copied GL_TEXTURE_BINDING_2D From: ARB_direct_state_access*/ +#define GL_TEXTURE_BIT 0x00040000 +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_BORDER 0x1005 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_COMPONENTS 0x1003 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GL_TEXTURE_ENV 0x2300 +#define GL_TEXTURE_ENV_COLOR 0x2201 +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_GEN_MODE 0x2500 +#define GL_TEXTURE_GEN_Q 0x0C63 +#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTENSITY_SIZE 0x8061 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_PRIORITY 0x8066 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_RESIDENT 0x8067 +#define GL_TEXTURE_STACK_DEPTH 0x0BA5 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TRANSFORM_BIT 0x00001000 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRUE 1 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_V2F 0x2A20 +#define GL_V3F 0x2A21 +#define GL_VENDOR 0x1F00 +#define GL_VERSION 0x1F02 +/*Copied GL_VERTEX_ARRAY From: KHR_debug*/ +#define GL_VERTEX_ARRAY_POINTER 0x808E +#define GL_VERTEX_ARRAY_SIZE 0x807A +#define GL_VERTEX_ARRAY_STRIDE 0x807C +#define GL_VERTEX_ARRAY_TYPE 0x807B +/*Copied GL_VIEWPORT From: ARB_viewport_array*/ +#define GL_VIEWPORT_BIT 0x00000800 +#define GL_XOR 0x1506 +#define GL_ZERO 0 +#define GL_ZOOM_X 0x0D16 +#define GL_ZOOM_Y 0x0D17 + +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_RESCALE_NORMAL 0x803A +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +/*Copied GL_TEXTURE_3D From: ARB_internalformat_query2*/ +#define GL_TEXTURE_BASE_LEVEL 0x813C +/*Copied GL_TEXTURE_BINDING_3D From: ARB_direct_state_access*/ +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 + +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_ADD_SIGNED 0x8574 +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_COMBINE 0x8570 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CONSTANT 0x8576 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +#define GL_INTERPOLATE 0x8575 +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_MULTISAMPLE 0x809D +#define GL_MULTISAMPLE_BIT 0x20000000 +#define GL_NORMAL_MAP 0x8511 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_OPERAND2_RGB 0x8592 +#define GL_PREVIOUS 0x8578 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_REFLECTION_MAP 0x8512 +#define GL_RGB_SCALE 0x8573 +/*Copied GL_SAMPLES From: ARB_internalformat_query2*/ +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_SOURCE2_RGB 0x8582 +#define GL_SUBTRACT 0x84E7 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +/*Copied GL_TEXTURE_BINDING_CUBE_MAP From: ARB_direct_state_access*/ +/*Copied GL_TEXTURE_COMPRESSED From: ARB_internalformat_query2*/ +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +/*Copied GL_TEXTURE_CUBE_MAP From: ARB_internalformat_query2*/ +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 + +#define GL_BLEND_COLOR 0x8005 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_COLOR_SUM 0x8458 +#define GL_COMPARE_R_TO_TEXTURE 0x884E +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_DECR_WRAP 0x8508 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_DEPTH_TEXTURE_MODE 0x884B +#define GL_FOG_COORDINATE 0x8451 +#define GL_FOG_COORDINATE_ARRAY 0x8457 +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_FUNC_SUBTRACT 0x800A +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_INCR_WRAP 0x8507 +#define GL_MAX 0x8008 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_MIN 0x8007 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_SECONDARY_COLOR_ARRAY 0x845E +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_LOD_BIAS 0x8501 + +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_CURRENT_FOG_COORD 0x8453 +#define GL_CURRENT_QUERY 0x8865 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_FOG_COORD 0x8451 +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_FOG_COORD_ARRAY 0x8457 +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D +#define GL_FOG_COORD_ARRAY_POINTER 0x8456 +#define GL_FOG_COORD_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORD_ARRAY_TYPE 0x8454 +#define GL_FOG_COORD_SRC 0x8450 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_READ_ONLY 0x88B8 +#define GL_READ_WRITE 0x88BA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_SRC0_ALPHA 0x8588 +#define GL_SRC0_RGB 0x8580 +#define GL_SRC1_ALPHA 0x8589 +#define GL_SRC1_RGB 0x8581 +#define GL_SRC2_ALPHA 0x858A +#define GL_SRC2_RGB 0x8582 +#define GL_STATIC_COPY 0x88E6 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STREAM_COPY 0x88E2 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_WRITE_ONLY 0x88B9 + +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_COORD_REPLACE 0x8862 +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_DELETE_STATUS 0x8B80 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_LINK_STATUS 0x8B82 +/*Copied GL_LOWER_LEFT From: ARB_clip_control*/ +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_POINT_SPRITE 0x8861 +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_TYPE 0x8B4F +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +/*Copied GL_UPPER_LEFT From: ARB_clip_control*/ +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_VERTEX_SHADER 0x8B31 + +#define GL_COMPRESSED_SLUMINANCE 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_SLUMINANCE 0x8C46 +#define GL_SLUMINANCE8 0x8C47 +#define GL_SLUMINANCE8_ALPHA8 0x8C45 +#define GL_SLUMINANCE_ALPHA 0x8C44 +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SRGB_ALPHA 0x8C42 + +#define GL_ALPHA_INTEGER 0x8D97 +#define GL_BGRA_INTEGER 0x8D9B +#define GL_BGR_INTEGER 0x8D9A +#define GL_BLUE_INTEGER 0x8D96 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_CLAMP_FRAGMENT_COLOR 0x891B +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_CLAMP_VERTEX_COLOR 0x891A +#define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 +#define GL_CLIP_DISTANCE2 0x3002 +#define GL_CLIP_DISTANCE3 0x3003 +#define GL_CLIP_DISTANCE4 0x3004 +#define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_RG 0x8226 +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_CONTEXT_FLAGS 0x821E +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FIXED_ONLY 0x891D +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER 0x8D40 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_GREEN_INTEGER 0x8D95 +#define GL_HALF_FLOAT 0x140B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_MAJOR_VERSION 0x821B +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +/*Copied GL_MAP_READ_BIT From: ARB_buffer_storage*/ +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +/*Copied GL_MAP_WRITE_BIT From: ARB_buffer_storage*/ +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_MINOR_VERSION 0x821C +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_NUM_EXTENSIONS 0x821D +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_WAIT 0x8E13 +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_R16 0x822A +#define GL_R16F 0x822D +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32F 0x822E +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_R8 0x8229 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RED_INTEGER 0x8D94 +/*Copied GL_RENDERBUFFER From: ARB_internalformat_query2*/ +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RG 0x8227 +#define GL_RG16 0x822C +#define GL_RG16F 0x822F +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32F 0x8230 +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_RG8 0x822B +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RGB16F 0x881B +#define GL_RGB16I 0x8D89 +#define GL_RGB16UI 0x8D77 +#define GL_RGB32F 0x8815 +#define GL_RGB32I 0x8D83 +#define GL_RGB32UI 0x8D71 +#define GL_RGB8I 0x8D8F +#define GL_RGB8UI 0x8D7D +#define GL_RGB9_E5 0x8C3D +#define GL_RGBA16F 0x881A +#define GL_RGBA16I 0x8D88 +#define GL_RGBA16UI 0x8D76 +#define GL_RGBA32F 0x8814 +#define GL_RGBA32I 0x8D82 +#define GL_RGBA32UI 0x8D70 +#define GL_RGBA8I 0x8D8E +#define GL_RGBA8UI 0x8D7C +#define GL_RGBA_INTEGER 0x8D99 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RG_INTEGER 0x8228 +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_STENCIL_INDEX4 0x8D47 +/*Copied GL_STENCIL_INDEX8 From: ARB_texture_stencil8*/ +/*Copied GL_TEXTURE_1D_ARRAY From: ARB_internalformat_query2*/ +/*Copied GL_TEXTURE_2D_ARRAY From: ARB_internalformat_query2*/ +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +/*Copied GL_TEXTURE_BINDING_1D_ARRAY From: ARB_direct_state_access*/ +/*Copied GL_TEXTURE_BINDING_2D_ARRAY From: ARB_direct_state_access*/ +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +/*Copied GL_TRANSFORM_FEEDBACK_BUFFER From: ARB_enhanced_layouts*/ +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +/*Copied GL_UNSIGNED_INT_10F_11F_11F_REV From: ARB_vertex_type_10f_11f_11f_rev*/ +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD + +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INVALID_INDEX 0xFFFFFFFF +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_R16_SNORM 0x8F98 +#define GL_R8_SNORM 0x8F94 +#define GL_RG16_SNORM 0x8F99 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA16_SNORM 0x8F9B +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SIGNED_NORMALIZED 0x8F9C +/*Copied GL_TEXTURE_BINDING_BUFFER From: ARB_direct_state_access*/ +/*Copied GL_TEXTURE_BINDING_RECTANGLE From: ARB_direct_state_access*/ +/*Copied GL_TEXTURE_BUFFER From: ARB_internalformat_query2*/ +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +/*Copied GL_TEXTURE_RECTANGLE From: ARB_internalformat_query2*/ +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 + + + +#ifndef GL_ARB_ES2_compatibility +#define GL_ARB_ES2_compatibility 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glClearDepthf)(GLfloat d); +#define glClearDepthf _ptrc_glClearDepthf +extern void (CODEGEN_FUNCPTR *_ptrc_glDepthRangef)(GLfloat n, GLfloat f); +#define glDepthRangef _ptrc_glDepthRangef +extern void (CODEGEN_FUNCPTR *_ptrc_glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision); +#define glGetShaderPrecisionFormat _ptrc_glGetShaderPrecisionFormat +extern void (CODEGEN_FUNCPTR *_ptrc_glReleaseShaderCompiler)(void); +#define glReleaseShaderCompiler _ptrc_glReleaseShaderCompiler +extern void (CODEGEN_FUNCPTR *_ptrc_glShaderBinary)(GLsizei count, const GLuint * shaders, GLenum binaryformat, const void * binary, GLsizei length); +#define glShaderBinary _ptrc_glShaderBinary +#endif /*GL_ARB_ES2_compatibility*/ + +#ifndef GL_ARB_get_program_binary +#define GL_ARB_get_program_binary 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glGetProgramBinary)(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary); +#define glGetProgramBinary _ptrc_glGetProgramBinary +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramBinary)(GLuint program, GLenum binaryFormat, const void * binary, GLsizei length); +#define glProgramBinary _ptrc_glProgramBinary +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramParameteri)(GLuint program, GLenum pname, GLint value); +#define glProgramParameteri _ptrc_glProgramParameteri +#endif /*GL_ARB_get_program_binary*/ + + +#ifndef GL_ARB_internalformat_query +#define GL_ARB_internalformat_query 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glGetInternalformativ)(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint * params); +#define glGetInternalformativ _ptrc_glGetInternalformativ +#endif /*GL_ARB_internalformat_query*/ + +#ifndef GL_ARB_internalformat_query2 +#define GL_ARB_internalformat_query2 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glGetInternalformati64v)(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 * params); +#define glGetInternalformati64v _ptrc_glGetInternalformati64v +#endif /*GL_ARB_internalformat_query2*/ + + +#ifndef GL_ARB_program_interface_query +#define GL_ARB_program_interface_query 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glGetProgramInterfaceiv)(GLuint program, GLenum programInterface, GLenum pname, GLint * params); +#define glGetProgramInterfaceiv _ptrc_glGetProgramInterfaceiv +extern GLuint (CODEGEN_FUNCPTR *_ptrc_glGetProgramResourceIndex)(GLuint program, GLenum programInterface, const GLchar * name); +#define glGetProgramResourceIndex _ptrc_glGetProgramResourceIndex +extern GLint (CODEGEN_FUNCPTR *_ptrc_glGetProgramResourceLocation)(GLuint program, GLenum programInterface, const GLchar * name); +#define glGetProgramResourceLocation _ptrc_glGetProgramResourceLocation +extern GLint (CODEGEN_FUNCPTR *_ptrc_glGetProgramResourceLocationIndex)(GLuint program, GLenum programInterface, const GLchar * name); +#define glGetProgramResourceLocationIndex _ptrc_glGetProgramResourceLocationIndex +extern void (CODEGEN_FUNCPTR *_ptrc_glGetProgramResourceName)(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name); +#define glGetProgramResourceName _ptrc_glGetProgramResourceName +extern void (CODEGEN_FUNCPTR *_ptrc_glGetProgramResourceiv)(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params); +#define glGetProgramResourceiv _ptrc_glGetProgramResourceiv +#endif /*GL_ARB_program_interface_query*/ + +#ifndef GL_ARB_separate_shader_objects +#define GL_ARB_separate_shader_objects 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glActiveShaderProgram)(GLuint pipeline, GLuint program); +#define glActiveShaderProgram _ptrc_glActiveShaderProgram +extern void (CODEGEN_FUNCPTR *_ptrc_glBindProgramPipeline)(GLuint pipeline); +#define glBindProgramPipeline _ptrc_glBindProgramPipeline +extern GLuint (CODEGEN_FUNCPTR *_ptrc_glCreateShaderProgramv)(GLenum type, GLsizei count, const GLchar *const* strings); +#define glCreateShaderProgramv _ptrc_glCreateShaderProgramv +extern void (CODEGEN_FUNCPTR *_ptrc_glDeleteProgramPipelines)(GLsizei n, const GLuint * pipelines); +#define glDeleteProgramPipelines _ptrc_glDeleteProgramPipelines +extern void (CODEGEN_FUNCPTR *_ptrc_glGenProgramPipelines)(GLsizei n, GLuint * pipelines); +#define glGenProgramPipelines _ptrc_glGenProgramPipelines +extern void (CODEGEN_FUNCPTR *_ptrc_glGetProgramPipelineInfoLog)(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +#define glGetProgramPipelineInfoLog _ptrc_glGetProgramPipelineInfoLog +extern void (CODEGEN_FUNCPTR *_ptrc_glGetProgramPipelineiv)(GLuint pipeline, GLenum pname, GLint * params); +#define glGetProgramPipelineiv _ptrc_glGetProgramPipelineiv +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsProgramPipeline)(GLuint pipeline); +#define glIsProgramPipeline _ptrc_glIsProgramPipeline +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1d)(GLuint program, GLint location, GLdouble v0); +#define glProgramUniform1d _ptrc_glProgramUniform1d +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1dv)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +#define glProgramUniform1dv _ptrc_glProgramUniform1dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1f)(GLuint program, GLint location, GLfloat v0); +#define glProgramUniform1f _ptrc_glProgramUniform1f +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +#define glProgramUniform1fv _ptrc_glProgramUniform1fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1i)(GLuint program, GLint location, GLint v0); +#define glProgramUniform1i _ptrc_glProgramUniform1i +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1iv)(GLuint program, GLint location, GLsizei count, const GLint * value); +#define glProgramUniform1iv _ptrc_glProgramUniform1iv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1ui)(GLuint program, GLint location, GLuint v0); +#define glProgramUniform1ui _ptrc_glProgramUniform1ui +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform1uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value); +#define glProgramUniform1uiv _ptrc_glProgramUniform1uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2d)(GLuint program, GLint location, GLdouble v0, GLdouble v1); +#define glProgramUniform2d _ptrc_glProgramUniform2d +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2dv)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +#define glProgramUniform2dv _ptrc_glProgramUniform2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2f)(GLuint program, GLint location, GLfloat v0, GLfloat v1); +#define glProgramUniform2f _ptrc_glProgramUniform2f +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +#define glProgramUniform2fv _ptrc_glProgramUniform2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2i)(GLuint program, GLint location, GLint v0, GLint v1); +#define glProgramUniform2i _ptrc_glProgramUniform2i +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2iv)(GLuint program, GLint location, GLsizei count, const GLint * value); +#define glProgramUniform2iv _ptrc_glProgramUniform2iv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2ui)(GLuint program, GLint location, GLuint v0, GLuint v1); +#define glProgramUniform2ui _ptrc_glProgramUniform2ui +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform2uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value); +#define glProgramUniform2uiv _ptrc_glProgramUniform2uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3d)(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); +#define glProgramUniform3d _ptrc_glProgramUniform3d +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3dv)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +#define glProgramUniform3dv _ptrc_glProgramUniform3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3f)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +#define glProgramUniform3f _ptrc_glProgramUniform3f +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +#define glProgramUniform3fv _ptrc_glProgramUniform3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3i)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +#define glProgramUniform3i _ptrc_glProgramUniform3i +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3iv)(GLuint program, GLint location, GLsizei count, const GLint * value); +#define glProgramUniform3iv _ptrc_glProgramUniform3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3ui)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +#define glProgramUniform3ui _ptrc_glProgramUniform3ui +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform3uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value); +#define glProgramUniform3uiv _ptrc_glProgramUniform3uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4d)(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); +#define glProgramUniform4d _ptrc_glProgramUniform4d +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4dv)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +#define glProgramUniform4dv _ptrc_glProgramUniform4dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4f)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +#define glProgramUniform4f _ptrc_glProgramUniform4f +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +#define glProgramUniform4fv _ptrc_glProgramUniform4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4i)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +#define glProgramUniform4i _ptrc_glProgramUniform4i +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4iv)(GLuint program, GLint location, GLsizei count, const GLint * value); +#define glProgramUniform4iv _ptrc_glProgramUniform4iv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4ui)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +#define glProgramUniform4ui _ptrc_glProgramUniform4ui +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniform4uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value); +#define glProgramUniform4uiv _ptrc_glProgramUniform4uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +#define glProgramUniformMatrix2dv _ptrc_glProgramUniformMatrix2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glProgramUniformMatrix2fv _ptrc_glProgramUniformMatrix2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2x3dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +#define glProgramUniformMatrix2x3dv _ptrc_glProgramUniformMatrix2x3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2x3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glProgramUniformMatrix2x3fv _ptrc_glProgramUniformMatrix2x3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2x4dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +#define glProgramUniformMatrix2x4dv _ptrc_glProgramUniformMatrix2x4dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix2x4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glProgramUniformMatrix2x4fv _ptrc_glProgramUniformMatrix2x4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +#define glProgramUniformMatrix3dv _ptrc_glProgramUniformMatrix3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glProgramUniformMatrix3fv _ptrc_glProgramUniformMatrix3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3x2dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +#define glProgramUniformMatrix3x2dv _ptrc_glProgramUniformMatrix3x2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3x2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glProgramUniformMatrix3x2fv _ptrc_glProgramUniformMatrix3x2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3x4dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +#define glProgramUniformMatrix3x4dv _ptrc_glProgramUniformMatrix3x4dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix3x4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glProgramUniformMatrix3x4fv _ptrc_glProgramUniformMatrix3x4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +#define glProgramUniformMatrix4dv _ptrc_glProgramUniformMatrix4dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glProgramUniformMatrix4fv _ptrc_glProgramUniformMatrix4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4x2dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +#define glProgramUniformMatrix4x2dv _ptrc_glProgramUniformMatrix4x2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4x2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glProgramUniformMatrix4x2fv _ptrc_glProgramUniformMatrix4x2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4x3dv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +#define glProgramUniformMatrix4x3dv _ptrc_glProgramUniformMatrix4x3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glProgramUniformMatrix4x3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glProgramUniformMatrix4x3fv _ptrc_glProgramUniformMatrix4x3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUseProgramStages)(GLuint pipeline, GLbitfield stages, GLuint program); +#define glUseProgramStages _ptrc_glUseProgramStages +extern void (CODEGEN_FUNCPTR *_ptrc_glValidateProgramPipeline)(GLuint pipeline); +#define glValidateProgramPipeline _ptrc_glValidateProgramPipeline +#endif /*GL_ARB_separate_shader_objects*/ + + + +#ifndef GL_ARB_texture_buffer_range +#define GL_ARB_texture_buffer_range 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glTexBufferRange)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +#define glTexBufferRange _ptrc_glTexBufferRange +#endif /*GL_ARB_texture_buffer_range*/ + +#ifndef GL_ARB_texture_storage +#define GL_ARB_texture_storage 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glTexStorage1D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +#define glTexStorage1D _ptrc_glTexStorage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glTexStorage2D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +#define glTexStorage2D _ptrc_glTexStorage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glTexStorage3D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +#define glTexStorage3D _ptrc_glTexStorage3D +#endif /*GL_ARB_texture_storage*/ + +#ifndef GL_ARB_texture_view +#define GL_ARB_texture_view 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureView)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +#define glTextureView _ptrc_glTextureView +#endif /*GL_ARB_texture_view*/ + +#ifndef GL_ARB_vertex_attrib_binding +#define GL_ARB_vertex_attrib_binding 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glBindVertexBuffer)(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +#define glBindVertexBuffer _ptrc_glBindVertexBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribBinding)(GLuint attribindex, GLuint bindingindex); +#define glVertexAttribBinding _ptrc_glVertexAttribBinding +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribFormat)(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +#define glVertexAttribFormat _ptrc_glVertexAttribFormat +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribIFormat)(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +#define glVertexAttribIFormat _ptrc_glVertexAttribIFormat +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribLFormat)(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +#define glVertexAttribLFormat _ptrc_glVertexAttribLFormat +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexBindingDivisor)(GLuint bindingindex, GLuint divisor); +#define glVertexBindingDivisor _ptrc_glVertexBindingDivisor +#endif /*GL_ARB_vertex_attrib_binding*/ + +#ifndef GL_ARB_viewport_array +#define GL_ARB_viewport_array 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glDepthRangeArrayv)(GLuint first, GLsizei count, const GLdouble * v); +#define glDepthRangeArrayv _ptrc_glDepthRangeArrayv +extern void (CODEGEN_FUNCPTR *_ptrc_glDepthRangeIndexed)(GLuint index, GLdouble n, GLdouble f); +#define glDepthRangeIndexed _ptrc_glDepthRangeIndexed +extern void (CODEGEN_FUNCPTR *_ptrc_glGetDoublei_v)(GLenum target, GLuint index, GLdouble * data); +#define glGetDoublei_v _ptrc_glGetDoublei_v +extern void (CODEGEN_FUNCPTR *_ptrc_glGetFloati_v)(GLenum target, GLuint index, GLfloat * data); +#define glGetFloati_v _ptrc_glGetFloati_v +extern void (CODEGEN_FUNCPTR *_ptrc_glScissorArrayv)(GLuint first, GLsizei count, const GLint * v); +#define glScissorArrayv _ptrc_glScissorArrayv +extern void (CODEGEN_FUNCPTR *_ptrc_glScissorIndexed)(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +#define glScissorIndexed _ptrc_glScissorIndexed +extern void (CODEGEN_FUNCPTR *_ptrc_glScissorIndexedv)(GLuint index, const GLint * v); +#define glScissorIndexedv _ptrc_glScissorIndexedv +extern void (CODEGEN_FUNCPTR *_ptrc_glViewportArrayv)(GLuint first, GLsizei count, const GLfloat * v); +#define glViewportArrayv _ptrc_glViewportArrayv +extern void (CODEGEN_FUNCPTR *_ptrc_glViewportIndexedf)(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +#define glViewportIndexedf _ptrc_glViewportIndexedf +extern void (CODEGEN_FUNCPTR *_ptrc_glViewportIndexedfv)(GLuint index, const GLfloat * v); +#define glViewportIndexedfv _ptrc_glViewportIndexedfv +#endif /*GL_ARB_viewport_array*/ + + +#ifndef GL_ARB_clear_buffer_object +#define GL_ARB_clear_buffer_object 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glClearBufferData)(GLenum target, GLenum internalformat, GLenum format, GLenum type, const void * data); +#define glClearBufferData _ptrc_glClearBufferData +extern void (CODEGEN_FUNCPTR *_ptrc_glClearBufferSubData)(GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data); +#define glClearBufferSubData _ptrc_glClearBufferSubData +#endif /*GL_ARB_clear_buffer_object*/ + +#ifndef GL_ARB_copy_image +#define GL_ARB_copy_image 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyImageSubData)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +#define glCopyImageSubData _ptrc_glCopyImageSubData +#endif /*GL_ARB_copy_image*/ + + + +#ifndef GL_ARB_framebuffer_no_attachments +#define GL_ARB_framebuffer_no_attachments 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glFramebufferParameteri)(GLenum target, GLenum pname, GLint param); +#define glFramebufferParameteri _ptrc_glFramebufferParameteri +extern void (CODEGEN_FUNCPTR *_ptrc_glGetFramebufferParameteriv)(GLenum target, GLenum pname, GLint * params); +#define glGetFramebufferParameteriv _ptrc_glGetFramebufferParameteriv +#endif /*GL_ARB_framebuffer_no_attachments*/ + +#ifndef GL_ARB_invalidate_subdata +#define GL_ARB_invalidate_subdata 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glInvalidateBufferData)(GLuint buffer); +#define glInvalidateBufferData _ptrc_glInvalidateBufferData +extern void (CODEGEN_FUNCPTR *_ptrc_glInvalidateBufferSubData)(GLuint buffer, GLintptr offset, GLsizeiptr length); +#define glInvalidateBufferSubData _ptrc_glInvalidateBufferSubData +extern void (CODEGEN_FUNCPTR *_ptrc_glInvalidateFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum * attachments); +#define glInvalidateFramebuffer _ptrc_glInvalidateFramebuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glInvalidateSubFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height); +#define glInvalidateSubFramebuffer _ptrc_glInvalidateSubFramebuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glInvalidateTexImage)(GLuint texture, GLint level); +#define glInvalidateTexImage _ptrc_glInvalidateTexImage +extern void (CODEGEN_FUNCPTR *_ptrc_glInvalidateTexSubImage)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); +#define glInvalidateTexSubImage _ptrc_glInvalidateTexSubImage +#endif /*GL_ARB_invalidate_subdata*/ + + + + +#ifndef GL_ARB_texture_storage_multisample +#define GL_ARB_texture_storage_multisample 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glTexStorage2DMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +#define glTexStorage2DMultisample _ptrc_glTexStorage2DMultisample +extern void (CODEGEN_FUNCPTR *_ptrc_glTexStorage3DMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +#define glTexStorage3DMultisample _ptrc_glTexStorage3DMultisample +#endif /*GL_ARB_texture_storage_multisample*/ + +#ifndef GL_KHR_debug +#define GL_KHR_debug 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glDebugMessageCallback)(GLDEBUGPROC callback, const void * userParam); +#define glDebugMessageCallback _ptrc_glDebugMessageCallback +extern void (CODEGEN_FUNCPTR *_ptrc_glDebugMessageControl)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled); +#define glDebugMessageControl _ptrc_glDebugMessageControl +extern void (CODEGEN_FUNCPTR *_ptrc_glDebugMessageInsert)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf); +#define glDebugMessageInsert _ptrc_glDebugMessageInsert +extern GLuint (CODEGEN_FUNCPTR *_ptrc_glGetDebugMessageLog)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog); +#define glGetDebugMessageLog _ptrc_glGetDebugMessageLog +extern void (CODEGEN_FUNCPTR *_ptrc_glGetObjectLabel)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label); +#define glGetObjectLabel _ptrc_glGetObjectLabel +extern void (CODEGEN_FUNCPTR *_ptrc_glGetObjectPtrLabel)(const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label); +#define glGetObjectPtrLabel _ptrc_glGetObjectPtrLabel +extern void (CODEGEN_FUNCPTR *_ptrc_glGetPointerv)(GLenum pname, void ** params); +#define glGetPointerv _ptrc_glGetPointerv +extern void (CODEGEN_FUNCPTR *_ptrc_glObjectLabel)(GLenum identifier, GLuint name, GLsizei length, const GLchar * label); +#define glObjectLabel _ptrc_glObjectLabel +extern void (CODEGEN_FUNCPTR *_ptrc_glObjectPtrLabel)(const void * ptr, GLsizei length, const GLchar * label); +#define glObjectPtrLabel _ptrc_glObjectPtrLabel +extern void (CODEGEN_FUNCPTR *_ptrc_glPopDebugGroup)(void); +#define glPopDebugGroup _ptrc_glPopDebugGroup +extern void (CODEGEN_FUNCPTR *_ptrc_glPushDebugGroup)(GLenum source, GLuint id, GLsizei length, const GLchar * message); +#define glPushDebugGroup _ptrc_glPushDebugGroup +#endif /*GL_KHR_debug*/ + +#ifndef GL_ARB_buffer_storage +#define GL_ARB_buffer_storage 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glBufferStorage)(GLenum target, GLsizeiptr size, const void * data, GLbitfield flags); +#define glBufferStorage _ptrc_glBufferStorage +#endif /*GL_ARB_buffer_storage*/ + +#ifndef GL_ARB_clear_texture +#define GL_ARB_clear_texture 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glClearTexImage)(GLuint texture, GLint level, GLenum format, GLenum type, const void * data); +#define glClearTexImage _ptrc_glClearTexImage +extern void (CODEGEN_FUNCPTR *_ptrc_glClearTexSubImage)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * data); +#define glClearTexSubImage _ptrc_glClearTexSubImage +#endif /*GL_ARB_clear_texture*/ + + +#ifndef GL_ARB_multi_bind +#define GL_ARB_multi_bind 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glBindBuffersBase)(GLenum target, GLuint first, GLsizei count, const GLuint * buffers); +#define glBindBuffersBase _ptrc_glBindBuffersBase +extern void (CODEGEN_FUNCPTR *_ptrc_glBindBuffersRange)(GLenum target, GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizeiptr * sizes); +#define glBindBuffersRange _ptrc_glBindBuffersRange +extern void (CODEGEN_FUNCPTR *_ptrc_glBindImageTextures)(GLuint first, GLsizei count, const GLuint * textures); +#define glBindImageTextures _ptrc_glBindImageTextures +extern void (CODEGEN_FUNCPTR *_ptrc_glBindSamplers)(GLuint first, GLsizei count, const GLuint * samplers); +#define glBindSamplers _ptrc_glBindSamplers +extern void (CODEGEN_FUNCPTR *_ptrc_glBindTextures)(GLuint first, GLsizei count, const GLuint * textures); +#define glBindTextures _ptrc_glBindTextures +extern void (CODEGEN_FUNCPTR *_ptrc_glBindVertexBuffers)(GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizei * strides); +#define glBindVertexBuffers _ptrc_glBindVertexBuffers +#endif /*GL_ARB_multi_bind*/ + + + + + + +#ifndef GL_ARB_clip_control +#define GL_ARB_clip_control 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glClipControl)(GLenum origin, GLenum depth); +#define glClipControl _ptrc_glClipControl +#endif /*GL_ARB_clip_control*/ + + + + +#ifndef GL_ARB_direct_state_access +#define GL_ARB_direct_state_access 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glBindTextureUnit)(GLuint unit, GLuint texture); +#define glBindTextureUnit _ptrc_glBindTextureUnit +extern void (CODEGEN_FUNCPTR *_ptrc_glBlitNamedFramebuffer)(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#define glBlitNamedFramebuffer _ptrc_glBlitNamedFramebuffer +extern GLenum (CODEGEN_FUNCPTR *_ptrc_glCheckNamedFramebufferStatus)(GLuint framebuffer, GLenum target); +#define glCheckNamedFramebufferStatus _ptrc_glCheckNamedFramebufferStatus +extern void (CODEGEN_FUNCPTR *_ptrc_glClearNamedBufferData)(GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void * data); +#define glClearNamedBufferData _ptrc_glClearNamedBufferData +extern void (CODEGEN_FUNCPTR *_ptrc_glClearNamedBufferSubData)(GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data); +#define glClearNamedBufferSubData _ptrc_glClearNamedBufferSubData +extern void (CODEGEN_FUNCPTR *_ptrc_glClearNamedFramebufferfi)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat depth, GLint stencil); +#define glClearNamedFramebufferfi _ptrc_glClearNamedFramebufferfi +extern void (CODEGEN_FUNCPTR *_ptrc_glClearNamedFramebufferfv)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat * value); +#define glClearNamedFramebufferfv _ptrc_glClearNamedFramebufferfv +extern void (CODEGEN_FUNCPTR *_ptrc_glClearNamedFramebufferiv)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint * value); +#define glClearNamedFramebufferiv _ptrc_glClearNamedFramebufferiv +extern void (CODEGEN_FUNCPTR *_ptrc_glClearNamedFramebufferuiv)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint * value); +#define glClearNamedFramebufferuiv _ptrc_glClearNamedFramebufferuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glCompressedTextureSubImage1D)(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data); +#define glCompressedTextureSubImage1D _ptrc_glCompressedTextureSubImage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glCompressedTextureSubImage2D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data); +#define glCompressedTextureSubImage2D _ptrc_glCompressedTextureSubImage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glCompressedTextureSubImage3D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data); +#define glCompressedTextureSubImage3D _ptrc_glCompressedTextureSubImage3D +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyNamedBufferSubData)(GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +#define glCopyNamedBufferSubData _ptrc_glCopyNamedBufferSubData +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyTextureSubImage1D)(GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +#define glCopyTextureSubImage1D _ptrc_glCopyTextureSubImage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyTextureSubImage2D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#define glCopyTextureSubImage2D _ptrc_glCopyTextureSubImage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyTextureSubImage3D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#define glCopyTextureSubImage3D _ptrc_glCopyTextureSubImage3D +extern void (CODEGEN_FUNCPTR *_ptrc_glCreateBuffers)(GLsizei n, GLuint * buffers); +#define glCreateBuffers _ptrc_glCreateBuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glCreateFramebuffers)(GLsizei n, GLuint * framebuffers); +#define glCreateFramebuffers _ptrc_glCreateFramebuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glCreateProgramPipelines)(GLsizei n, GLuint * pipelines); +#define glCreateProgramPipelines _ptrc_glCreateProgramPipelines +extern void (CODEGEN_FUNCPTR *_ptrc_glCreateQueries)(GLenum target, GLsizei n, GLuint * ids); +#define glCreateQueries _ptrc_glCreateQueries +extern void (CODEGEN_FUNCPTR *_ptrc_glCreateRenderbuffers)(GLsizei n, GLuint * renderbuffers); +#define glCreateRenderbuffers _ptrc_glCreateRenderbuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glCreateSamplers)(GLsizei n, GLuint * samplers); +#define glCreateSamplers _ptrc_glCreateSamplers +extern void (CODEGEN_FUNCPTR *_ptrc_glCreateTextures)(GLenum target, GLsizei n, GLuint * textures); +#define glCreateTextures _ptrc_glCreateTextures +extern void (CODEGEN_FUNCPTR *_ptrc_glCreateTransformFeedbacks)(GLsizei n, GLuint * ids); +#define glCreateTransformFeedbacks _ptrc_glCreateTransformFeedbacks +extern void (CODEGEN_FUNCPTR *_ptrc_glCreateVertexArrays)(GLsizei n, GLuint * arrays); +#define glCreateVertexArrays _ptrc_glCreateVertexArrays +extern void (CODEGEN_FUNCPTR *_ptrc_glDisableVertexArrayAttrib)(GLuint vaobj, GLuint index); +#define glDisableVertexArrayAttrib _ptrc_glDisableVertexArrayAttrib +extern void (CODEGEN_FUNCPTR *_ptrc_glEnableVertexArrayAttrib)(GLuint vaobj, GLuint index); +#define glEnableVertexArrayAttrib _ptrc_glEnableVertexArrayAttrib +extern void (CODEGEN_FUNCPTR *_ptrc_glFlushMappedNamedBufferRange)(GLuint buffer, GLintptr offset, GLsizeiptr length); +#define glFlushMappedNamedBufferRange _ptrc_glFlushMappedNamedBufferRange +extern void (CODEGEN_FUNCPTR *_ptrc_glGenerateTextureMipmap)(GLuint texture); +#define glGenerateTextureMipmap _ptrc_glGenerateTextureMipmap +extern void (CODEGEN_FUNCPTR *_ptrc_glGetCompressedTextureImage)(GLuint texture, GLint level, GLsizei bufSize, void * pixels); +#define glGetCompressedTextureImage _ptrc_glGetCompressedTextureImage +extern void (CODEGEN_FUNCPTR *_ptrc_glGetNamedBufferParameteri64v)(GLuint buffer, GLenum pname, GLint64 * params); +#define glGetNamedBufferParameteri64v _ptrc_glGetNamedBufferParameteri64v +extern void (CODEGEN_FUNCPTR *_ptrc_glGetNamedBufferParameteriv)(GLuint buffer, GLenum pname, GLint * params); +#define glGetNamedBufferParameteriv _ptrc_glGetNamedBufferParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetNamedBufferPointerv)(GLuint buffer, GLenum pname, void ** params); +#define glGetNamedBufferPointerv _ptrc_glGetNamedBufferPointerv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetNamedBufferSubData)(GLuint buffer, GLintptr offset, GLsizeiptr size, void * data); +#define glGetNamedBufferSubData _ptrc_glGetNamedBufferSubData +extern void (CODEGEN_FUNCPTR *_ptrc_glGetNamedFramebufferAttachmentParameteriv)(GLuint framebuffer, GLenum attachment, GLenum pname, GLint * params); +#define glGetNamedFramebufferAttachmentParameteriv _ptrc_glGetNamedFramebufferAttachmentParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetNamedFramebufferParameteriv)(GLuint framebuffer, GLenum pname, GLint * param); +#define glGetNamedFramebufferParameteriv _ptrc_glGetNamedFramebufferParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetNamedRenderbufferParameteriv)(GLuint renderbuffer, GLenum pname, GLint * params); +#define glGetNamedRenderbufferParameteriv _ptrc_glGetNamedRenderbufferParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetQueryBufferObjecti64v)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +#define glGetQueryBufferObjecti64v _ptrc_glGetQueryBufferObjecti64v +extern void (CODEGEN_FUNCPTR *_ptrc_glGetQueryBufferObjectiv)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +#define glGetQueryBufferObjectiv _ptrc_glGetQueryBufferObjectiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetQueryBufferObjectui64v)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +#define glGetQueryBufferObjectui64v _ptrc_glGetQueryBufferObjectui64v +extern void (CODEGEN_FUNCPTR *_ptrc_glGetQueryBufferObjectuiv)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +#define glGetQueryBufferObjectuiv _ptrc_glGetQueryBufferObjectuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTextureImage)(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void * pixels); +#define glGetTextureImage _ptrc_glGetTextureImage +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTextureLevelParameterfv)(GLuint texture, GLint level, GLenum pname, GLfloat * params); +#define glGetTextureLevelParameterfv _ptrc_glGetTextureLevelParameterfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTextureLevelParameteriv)(GLuint texture, GLint level, GLenum pname, GLint * params); +#define glGetTextureLevelParameteriv _ptrc_glGetTextureLevelParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTextureParameterIiv)(GLuint texture, GLenum pname, GLint * params); +#define glGetTextureParameterIiv _ptrc_glGetTextureParameterIiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTextureParameterIuiv)(GLuint texture, GLenum pname, GLuint * params); +#define glGetTextureParameterIuiv _ptrc_glGetTextureParameterIuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTextureParameterfv)(GLuint texture, GLenum pname, GLfloat * params); +#define glGetTextureParameterfv _ptrc_glGetTextureParameterfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTextureParameteriv)(GLuint texture, GLenum pname, GLint * params); +#define glGetTextureParameteriv _ptrc_glGetTextureParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTransformFeedbacki64_v)(GLuint xfb, GLenum pname, GLuint index, GLint64 * param); +#define glGetTransformFeedbacki64_v _ptrc_glGetTransformFeedbacki64_v +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTransformFeedbacki_v)(GLuint xfb, GLenum pname, GLuint index, GLint * param); +#define glGetTransformFeedbacki_v _ptrc_glGetTransformFeedbacki_v +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTransformFeedbackiv)(GLuint xfb, GLenum pname, GLint * param); +#define glGetTransformFeedbackiv _ptrc_glGetTransformFeedbackiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetVertexArrayIndexed64iv)(GLuint vaobj, GLuint index, GLenum pname, GLint64 * param); +#define glGetVertexArrayIndexed64iv _ptrc_glGetVertexArrayIndexed64iv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetVertexArrayIndexediv)(GLuint vaobj, GLuint index, GLenum pname, GLint * param); +#define glGetVertexArrayIndexediv _ptrc_glGetVertexArrayIndexediv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetVertexArrayiv)(GLuint vaobj, GLenum pname, GLint * param); +#define glGetVertexArrayiv _ptrc_glGetVertexArrayiv +extern void (CODEGEN_FUNCPTR *_ptrc_glInvalidateNamedFramebufferData)(GLuint framebuffer, GLsizei numAttachments, const GLenum * attachments); +#define glInvalidateNamedFramebufferData _ptrc_glInvalidateNamedFramebufferData +extern void (CODEGEN_FUNCPTR *_ptrc_glInvalidateNamedFramebufferSubData)(GLuint framebuffer, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height); +#define glInvalidateNamedFramebufferSubData _ptrc_glInvalidateNamedFramebufferSubData +extern void * (CODEGEN_FUNCPTR *_ptrc_glMapNamedBuffer)(GLuint buffer, GLenum access); +#define glMapNamedBuffer _ptrc_glMapNamedBuffer +extern void * (CODEGEN_FUNCPTR *_ptrc_glMapNamedBufferRange)(GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +#define glMapNamedBufferRange _ptrc_glMapNamedBufferRange +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedBufferData)(GLuint buffer, GLsizeiptr size, const void * data, GLenum usage); +#define glNamedBufferData _ptrc_glNamedBufferData +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedBufferStorage)(GLuint buffer, GLsizeiptr size, const void * data, GLbitfield flags); +#define glNamedBufferStorage _ptrc_glNamedBufferStorage +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedBufferSubData)(GLuint buffer, GLintptr offset, GLsizeiptr size, const void * data); +#define glNamedBufferSubData _ptrc_glNamedBufferSubData +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferDrawBuffer)(GLuint framebuffer, GLenum buf); +#define glNamedFramebufferDrawBuffer _ptrc_glNamedFramebufferDrawBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferDrawBuffers)(GLuint framebuffer, GLsizei n, const GLenum * bufs); +#define glNamedFramebufferDrawBuffers _ptrc_glNamedFramebufferDrawBuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferParameteri)(GLuint framebuffer, GLenum pname, GLint param); +#define glNamedFramebufferParameteri _ptrc_glNamedFramebufferParameteri +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferReadBuffer)(GLuint framebuffer, GLenum src); +#define glNamedFramebufferReadBuffer _ptrc_glNamedFramebufferReadBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferRenderbuffer)(GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +#define glNamedFramebufferRenderbuffer _ptrc_glNamedFramebufferRenderbuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferTexture)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +#define glNamedFramebufferTexture _ptrc_glNamedFramebufferTexture +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedFramebufferTextureLayer)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +#define glNamedFramebufferTextureLayer _ptrc_glNamedFramebufferTextureLayer +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedRenderbufferStorage)(GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +#define glNamedRenderbufferStorage _ptrc_glNamedRenderbufferStorage +extern void (CODEGEN_FUNCPTR *_ptrc_glNamedRenderbufferStorageMultisample)(GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#define glNamedRenderbufferStorageMultisample _ptrc_glNamedRenderbufferStorageMultisample +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureBuffer)(GLuint texture, GLenum internalformat, GLuint buffer); +#define glTextureBuffer _ptrc_glTextureBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureBufferRange)(GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +#define glTextureBufferRange _ptrc_glTextureBufferRange +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureParameterIiv)(GLuint texture, GLenum pname, const GLint * params); +#define glTextureParameterIiv _ptrc_glTextureParameterIiv +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureParameterIuiv)(GLuint texture, GLenum pname, const GLuint * params); +#define glTextureParameterIuiv _ptrc_glTextureParameterIuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureParameterf)(GLuint texture, GLenum pname, GLfloat param); +#define glTextureParameterf _ptrc_glTextureParameterf +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureParameterfv)(GLuint texture, GLenum pname, const GLfloat * param); +#define glTextureParameterfv _ptrc_glTextureParameterfv +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureParameteri)(GLuint texture, GLenum pname, GLint param); +#define glTextureParameteri _ptrc_glTextureParameteri +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureParameteriv)(GLuint texture, GLenum pname, const GLint * param); +#define glTextureParameteriv _ptrc_glTextureParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureStorage1D)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width); +#define glTextureStorage1D _ptrc_glTextureStorage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureStorage2D)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +#define glTextureStorage2D _ptrc_glTextureStorage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureStorage2DMultisample)(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +#define glTextureStorage2DMultisample _ptrc_glTextureStorage2DMultisample +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureStorage3D)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +#define glTextureStorage3D _ptrc_glTextureStorage3D +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureStorage3DMultisample)(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +#define glTextureStorage3DMultisample _ptrc_glTextureStorage3DMultisample +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureSubImage1D)(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +#define glTextureSubImage1D _ptrc_glTextureSubImage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureSubImage2D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +#define glTextureSubImage2D _ptrc_glTextureSubImage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureSubImage3D)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +#define glTextureSubImage3D _ptrc_glTextureSubImage3D +extern void (CODEGEN_FUNCPTR *_ptrc_glTransformFeedbackBufferBase)(GLuint xfb, GLuint index, GLuint buffer); +#define glTransformFeedbackBufferBase _ptrc_glTransformFeedbackBufferBase +extern void (CODEGEN_FUNCPTR *_ptrc_glTransformFeedbackBufferRange)(GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +#define glTransformFeedbackBufferRange _ptrc_glTransformFeedbackBufferRange +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glUnmapNamedBuffer)(GLuint buffer); +#define glUnmapNamedBuffer _ptrc_glUnmapNamedBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayAttribBinding)(GLuint vaobj, GLuint attribindex, GLuint bindingindex); +#define glVertexArrayAttribBinding _ptrc_glVertexArrayAttribBinding +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayAttribFormat)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +#define glVertexArrayAttribFormat _ptrc_glVertexArrayAttribFormat +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayAttribIFormat)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +#define glVertexArrayAttribIFormat _ptrc_glVertexArrayAttribIFormat +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayAttribLFormat)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +#define glVertexArrayAttribLFormat _ptrc_glVertexArrayAttribLFormat +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayBindingDivisor)(GLuint vaobj, GLuint bindingindex, GLuint divisor); +#define glVertexArrayBindingDivisor _ptrc_glVertexArrayBindingDivisor +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayElementBuffer)(GLuint vaobj, GLuint buffer); +#define glVertexArrayElementBuffer _ptrc_glVertexArrayElementBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayVertexBuffer)(GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +#define glVertexArrayVertexBuffer _ptrc_glVertexArrayVertexBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexArrayVertexBuffers)(GLuint vaobj, GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizei * strides); +#define glVertexArrayVertexBuffers _ptrc_glVertexArrayVertexBuffers +#endif /*GL_ARB_direct_state_access*/ + +#ifndef GL_ARB_get_texture_sub_image +#define GL_ARB_get_texture_sub_image 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glGetCompressedTextureSubImage)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void * pixels); +#define glGetCompressedTextureSubImage _ptrc_glGetCompressedTextureSubImage +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTextureSubImage)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void * pixels); +#define glGetTextureSubImage _ptrc_glGetTextureSubImage +#endif /*GL_ARB_get_texture_sub_image*/ + + +#ifndef GL_ARB_texture_barrier +#define GL_ARB_texture_barrier 1 +extern void (CODEGEN_FUNCPTR *_ptrc_glTextureBarrier)(void); +#define glTextureBarrier _ptrc_glTextureBarrier +#endif /*GL_ARB_texture_barrier*/ + + + +#ifndef GL_KHR_robustness +#define GL_KHR_robustness 1 +extern GLenum (CODEGEN_FUNCPTR *_ptrc_glGetGraphicsResetStatus)(void); +#define glGetGraphicsResetStatus _ptrc_glGetGraphicsResetStatus +extern void (CODEGEN_FUNCPTR *_ptrc_glGetnUniformfv)(GLuint program, GLint location, GLsizei bufSize, GLfloat * params); +#define glGetnUniformfv _ptrc_glGetnUniformfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetnUniformiv)(GLuint program, GLint location, GLsizei bufSize, GLint * params); +#define glGetnUniformiv _ptrc_glGetnUniformiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetnUniformuiv)(GLuint program, GLint location, GLsizei bufSize, GLuint * params); +#define glGetnUniformuiv _ptrc_glGetnUniformuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glReadnPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data); +#define glReadnPixels _ptrc_glReadnPixels +#endif /*GL_KHR_robustness*/ + + + + +extern void (CODEGEN_FUNCPTR *_ptrc_glAccum)(GLenum op, GLfloat value); +#define glAccum _ptrc_glAccum +extern void (CODEGEN_FUNCPTR *_ptrc_glAlphaFunc)(GLenum func, GLfloat ref); +#define glAlphaFunc _ptrc_glAlphaFunc +extern void (CODEGEN_FUNCPTR *_ptrc_glBegin)(GLenum mode); +#define glBegin _ptrc_glBegin +extern void (CODEGEN_FUNCPTR *_ptrc_glBitmap)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte * bitmap); +#define glBitmap _ptrc_glBitmap +extern void (CODEGEN_FUNCPTR *_ptrc_glBlendFunc)(GLenum sfactor, GLenum dfactor); +#define glBlendFunc _ptrc_glBlendFunc +extern void (CODEGEN_FUNCPTR *_ptrc_glCallList)(GLuint list); +#define glCallList _ptrc_glCallList +extern void (CODEGEN_FUNCPTR *_ptrc_glCallLists)(GLsizei n, GLenum type, const void * lists); +#define glCallLists _ptrc_glCallLists +extern void (CODEGEN_FUNCPTR *_ptrc_glClear)(GLbitfield mask); +#define glClear _ptrc_glClear +extern void (CODEGEN_FUNCPTR *_ptrc_glClearAccum)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +#define glClearAccum _ptrc_glClearAccum +extern void (CODEGEN_FUNCPTR *_ptrc_glClearColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +#define glClearColor _ptrc_glClearColor +extern void (CODEGEN_FUNCPTR *_ptrc_glClearDepth)(GLdouble depth); +#define glClearDepth _ptrc_glClearDepth +extern void (CODEGEN_FUNCPTR *_ptrc_glClearIndex)(GLfloat c); +#define glClearIndex _ptrc_glClearIndex +extern void (CODEGEN_FUNCPTR *_ptrc_glClearStencil)(GLint s); +#define glClearStencil _ptrc_glClearStencil +extern void (CODEGEN_FUNCPTR *_ptrc_glClipPlane)(GLenum plane, const GLdouble * equation); +#define glClipPlane _ptrc_glClipPlane +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3b)(GLbyte red, GLbyte green, GLbyte blue); +#define glColor3b _ptrc_glColor3b +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3bv)(const GLbyte * v); +#define glColor3bv _ptrc_glColor3bv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3d)(GLdouble red, GLdouble green, GLdouble blue); +#define glColor3d _ptrc_glColor3d +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3dv)(const GLdouble * v); +#define glColor3dv _ptrc_glColor3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3f)(GLfloat red, GLfloat green, GLfloat blue); +#define glColor3f _ptrc_glColor3f +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3fv)(const GLfloat * v); +#define glColor3fv _ptrc_glColor3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3i)(GLint red, GLint green, GLint blue); +#define glColor3i _ptrc_glColor3i +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3iv)(const GLint * v); +#define glColor3iv _ptrc_glColor3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3s)(GLshort red, GLshort green, GLshort blue); +#define glColor3s _ptrc_glColor3s +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3sv)(const GLshort * v); +#define glColor3sv _ptrc_glColor3sv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3ub)(GLubyte red, GLubyte green, GLubyte blue); +#define glColor3ub _ptrc_glColor3ub +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3ubv)(const GLubyte * v); +#define glColor3ubv _ptrc_glColor3ubv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3ui)(GLuint red, GLuint green, GLuint blue); +#define glColor3ui _ptrc_glColor3ui +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3uiv)(const GLuint * v); +#define glColor3uiv _ptrc_glColor3uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3us)(GLushort red, GLushort green, GLushort blue); +#define glColor3us _ptrc_glColor3us +extern void (CODEGEN_FUNCPTR *_ptrc_glColor3usv)(const GLushort * v); +#define glColor3usv _ptrc_glColor3usv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4b)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +#define glColor4b _ptrc_glColor4b +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4bv)(const GLbyte * v); +#define glColor4bv _ptrc_glColor4bv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4d)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +#define glColor4d _ptrc_glColor4d +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4dv)(const GLdouble * v); +#define glColor4dv _ptrc_glColor4dv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +#define glColor4f _ptrc_glColor4f +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4fv)(const GLfloat * v); +#define glColor4fv _ptrc_glColor4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4i)(GLint red, GLint green, GLint blue, GLint alpha); +#define glColor4i _ptrc_glColor4i +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4iv)(const GLint * v); +#define glColor4iv _ptrc_glColor4iv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4s)(GLshort red, GLshort green, GLshort blue, GLshort alpha); +#define glColor4s _ptrc_glColor4s +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4sv)(const GLshort * v); +#define glColor4sv _ptrc_glColor4sv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +#define glColor4ub _ptrc_glColor4ub +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4ubv)(const GLubyte * v); +#define glColor4ubv _ptrc_glColor4ubv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4ui)(GLuint red, GLuint green, GLuint blue, GLuint alpha); +#define glColor4ui _ptrc_glColor4ui +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4uiv)(const GLuint * v); +#define glColor4uiv _ptrc_glColor4uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4us)(GLushort red, GLushort green, GLushort blue, GLushort alpha); +#define glColor4us _ptrc_glColor4us +extern void (CODEGEN_FUNCPTR *_ptrc_glColor4usv)(const GLushort * v); +#define glColor4usv _ptrc_glColor4usv +extern void (CODEGEN_FUNCPTR *_ptrc_glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +#define glColorMask _ptrc_glColorMask +extern void (CODEGEN_FUNCPTR *_ptrc_glColorMaterial)(GLenum face, GLenum mode); +#define glColorMaterial _ptrc_glColorMaterial +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +#define glCopyPixels _ptrc_glCopyPixels +extern void (CODEGEN_FUNCPTR *_ptrc_glCullFace)(GLenum mode); +#define glCullFace _ptrc_glCullFace +extern void (CODEGEN_FUNCPTR *_ptrc_glDeleteLists)(GLuint list, GLsizei range); +#define glDeleteLists _ptrc_glDeleteLists +extern void (CODEGEN_FUNCPTR *_ptrc_glDepthFunc)(GLenum func); +#define glDepthFunc _ptrc_glDepthFunc +extern void (CODEGEN_FUNCPTR *_ptrc_glDepthMask)(GLboolean flag); +#define glDepthMask _ptrc_glDepthMask +extern void (CODEGEN_FUNCPTR *_ptrc_glDepthRange)(GLdouble ren_near, GLdouble ren_far); +#define glDepthRange _ptrc_glDepthRange +extern void (CODEGEN_FUNCPTR *_ptrc_glDisable)(GLenum cap); +#define glDisable _ptrc_glDisable +extern void (CODEGEN_FUNCPTR *_ptrc_glDrawBuffer)(GLenum buf); +#define glDrawBuffer _ptrc_glDrawBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glDrawPixels)(GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +#define glDrawPixels _ptrc_glDrawPixels +extern void (CODEGEN_FUNCPTR *_ptrc_glEdgeFlag)(GLboolean flag); +#define glEdgeFlag _ptrc_glEdgeFlag +extern void (CODEGEN_FUNCPTR *_ptrc_glEdgeFlagv)(const GLboolean * flag); +#define glEdgeFlagv _ptrc_glEdgeFlagv +extern void (CODEGEN_FUNCPTR *_ptrc_glEnable)(GLenum cap); +#define glEnable _ptrc_glEnable +extern void (CODEGEN_FUNCPTR *_ptrc_glEnd)(void); +#define glEnd _ptrc_glEnd +extern void (CODEGEN_FUNCPTR *_ptrc_glEndList)(void); +#define glEndList _ptrc_glEndList +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord1d)(GLdouble u); +#define glEvalCoord1d _ptrc_glEvalCoord1d +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord1dv)(const GLdouble * u); +#define glEvalCoord1dv _ptrc_glEvalCoord1dv +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord1f)(GLfloat u); +#define glEvalCoord1f _ptrc_glEvalCoord1f +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord1fv)(const GLfloat * u); +#define glEvalCoord1fv _ptrc_glEvalCoord1fv +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord2d)(GLdouble u, GLdouble v); +#define glEvalCoord2d _ptrc_glEvalCoord2d +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord2dv)(const GLdouble * u); +#define glEvalCoord2dv _ptrc_glEvalCoord2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord2f)(GLfloat u, GLfloat v); +#define glEvalCoord2f _ptrc_glEvalCoord2f +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalCoord2fv)(const GLfloat * u); +#define glEvalCoord2fv _ptrc_glEvalCoord2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalMesh1)(GLenum mode, GLint i1, GLint i2); +#define glEvalMesh1 _ptrc_glEvalMesh1 +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalMesh2)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +#define glEvalMesh2 _ptrc_glEvalMesh2 +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalPoint1)(GLint i); +#define glEvalPoint1 _ptrc_glEvalPoint1 +extern void (CODEGEN_FUNCPTR *_ptrc_glEvalPoint2)(GLint i, GLint j); +#define glEvalPoint2 _ptrc_glEvalPoint2 +extern void (CODEGEN_FUNCPTR *_ptrc_glFeedbackBuffer)(GLsizei size, GLenum type, GLfloat * buffer); +#define glFeedbackBuffer _ptrc_glFeedbackBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glFinish)(void); +#define glFinish _ptrc_glFinish +extern void (CODEGEN_FUNCPTR *_ptrc_glFlush)(void); +#define glFlush _ptrc_glFlush +extern void (CODEGEN_FUNCPTR *_ptrc_glFogf)(GLenum pname, GLfloat param); +#define glFogf _ptrc_glFogf +extern void (CODEGEN_FUNCPTR *_ptrc_glFogfv)(GLenum pname, const GLfloat * params); +#define glFogfv _ptrc_glFogfv +extern void (CODEGEN_FUNCPTR *_ptrc_glFogi)(GLenum pname, GLint param); +#define glFogi _ptrc_glFogi +extern void (CODEGEN_FUNCPTR *_ptrc_glFogiv)(GLenum pname, const GLint * params); +#define glFogiv _ptrc_glFogiv +extern void (CODEGEN_FUNCPTR *_ptrc_glFrontFace)(GLenum mode); +#define glFrontFace _ptrc_glFrontFace +extern void (CODEGEN_FUNCPTR *_ptrc_glFrustum)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +#define glFrustum _ptrc_glFrustum +extern GLuint (CODEGEN_FUNCPTR *_ptrc_glGenLists)(GLsizei range); +#define glGenLists _ptrc_glGenLists +extern void (CODEGEN_FUNCPTR *_ptrc_glGetBooleanv)(GLenum pname, GLboolean * data); +#define glGetBooleanv _ptrc_glGetBooleanv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetClipPlane)(GLenum plane, GLdouble * equation); +#define glGetClipPlane _ptrc_glGetClipPlane +extern void (CODEGEN_FUNCPTR *_ptrc_glGetDoublev)(GLenum pname, GLdouble * data); +#define glGetDoublev _ptrc_glGetDoublev +extern GLenum (CODEGEN_FUNCPTR *_ptrc_glGetError)(void); +#define glGetError _ptrc_glGetError +extern void (CODEGEN_FUNCPTR *_ptrc_glGetFloatv)(GLenum pname, GLfloat * data); +#define glGetFloatv _ptrc_glGetFloatv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetIntegerv)(GLenum pname, GLint * data); +#define glGetIntegerv _ptrc_glGetIntegerv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetLightfv)(GLenum light, GLenum pname, GLfloat * params); +#define glGetLightfv _ptrc_glGetLightfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetLightiv)(GLenum light, GLenum pname, GLint * params); +#define glGetLightiv _ptrc_glGetLightiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetMapdv)(GLenum target, GLenum query, GLdouble * v); +#define glGetMapdv _ptrc_glGetMapdv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetMapfv)(GLenum target, GLenum query, GLfloat * v); +#define glGetMapfv _ptrc_glGetMapfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetMapiv)(GLenum target, GLenum query, GLint * v); +#define glGetMapiv _ptrc_glGetMapiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetMaterialfv)(GLenum face, GLenum pname, GLfloat * params); +#define glGetMaterialfv _ptrc_glGetMaterialfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetMaterialiv)(GLenum face, GLenum pname, GLint * params); +#define glGetMaterialiv _ptrc_glGetMaterialiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetPixelMapfv)(GLenum map, GLfloat * values); +#define glGetPixelMapfv _ptrc_glGetPixelMapfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetPixelMapuiv)(GLenum map, GLuint * values); +#define glGetPixelMapuiv _ptrc_glGetPixelMapuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetPixelMapusv)(GLenum map, GLushort * values); +#define glGetPixelMapusv _ptrc_glGetPixelMapusv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetPolygonStipple)(GLubyte * mask); +#define glGetPolygonStipple _ptrc_glGetPolygonStipple +extern const GLubyte * (CODEGEN_FUNCPTR *_ptrc_glGetString)(GLenum name); +#define glGetString _ptrc_glGetString +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexEnvfv)(GLenum target, GLenum pname, GLfloat * params); +#define glGetTexEnvfv _ptrc_glGetTexEnvfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexEnviv)(GLenum target, GLenum pname, GLint * params); +#define glGetTexEnviv _ptrc_glGetTexEnviv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexGendv)(GLenum coord, GLenum pname, GLdouble * params); +#define glGetTexGendv _ptrc_glGetTexGendv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexGenfv)(GLenum coord, GLenum pname, GLfloat * params); +#define glGetTexGenfv _ptrc_glGetTexGenfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexGeniv)(GLenum coord, GLenum pname, GLint * params); +#define glGetTexGeniv _ptrc_glGetTexGeniv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexImage)(GLenum target, GLint level, GLenum format, GLenum type, void * pixels); +#define glGetTexImage _ptrc_glGetTexImage +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexLevelParameterfv)(GLenum target, GLint level, GLenum pname, GLfloat * params); +#define glGetTexLevelParameterfv _ptrc_glGetTexLevelParameterfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint * params); +#define glGetTexLevelParameteriv _ptrc_glGetTexLevelParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat * params); +#define glGetTexParameterfv _ptrc_glGetTexParameterfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexParameteriv)(GLenum target, GLenum pname, GLint * params); +#define glGetTexParameteriv _ptrc_glGetTexParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glHint)(GLenum target, GLenum mode); +#define glHint _ptrc_glHint +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexMask)(GLuint mask); +#define glIndexMask _ptrc_glIndexMask +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexd)(GLdouble c); +#define glIndexd _ptrc_glIndexd +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexdv)(const GLdouble * c); +#define glIndexdv _ptrc_glIndexdv +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexf)(GLfloat c); +#define glIndexf _ptrc_glIndexf +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexfv)(const GLfloat * c); +#define glIndexfv _ptrc_glIndexfv +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexi)(GLint c); +#define glIndexi _ptrc_glIndexi +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexiv)(const GLint * c); +#define glIndexiv _ptrc_glIndexiv +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexs)(GLshort c); +#define glIndexs _ptrc_glIndexs +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexsv)(const GLshort * c); +#define glIndexsv _ptrc_glIndexsv +extern void (CODEGEN_FUNCPTR *_ptrc_glInitNames)(void); +#define glInitNames _ptrc_glInitNames +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsEnabled)(GLenum cap); +#define glIsEnabled _ptrc_glIsEnabled +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsList)(GLuint list); +#define glIsList _ptrc_glIsList +extern void (CODEGEN_FUNCPTR *_ptrc_glLightModelf)(GLenum pname, GLfloat param); +#define glLightModelf _ptrc_glLightModelf +extern void (CODEGEN_FUNCPTR *_ptrc_glLightModelfv)(GLenum pname, const GLfloat * params); +#define glLightModelfv _ptrc_glLightModelfv +extern void (CODEGEN_FUNCPTR *_ptrc_glLightModeli)(GLenum pname, GLint param); +#define glLightModeli _ptrc_glLightModeli +extern void (CODEGEN_FUNCPTR *_ptrc_glLightModeliv)(GLenum pname, const GLint * params); +#define glLightModeliv _ptrc_glLightModeliv +extern void (CODEGEN_FUNCPTR *_ptrc_glLightf)(GLenum light, GLenum pname, GLfloat param); +#define glLightf _ptrc_glLightf +extern void (CODEGEN_FUNCPTR *_ptrc_glLightfv)(GLenum light, GLenum pname, const GLfloat * params); +#define glLightfv _ptrc_glLightfv +extern void (CODEGEN_FUNCPTR *_ptrc_glLighti)(GLenum light, GLenum pname, GLint param); +#define glLighti _ptrc_glLighti +extern void (CODEGEN_FUNCPTR *_ptrc_glLightiv)(GLenum light, GLenum pname, const GLint * params); +#define glLightiv _ptrc_glLightiv +extern void (CODEGEN_FUNCPTR *_ptrc_glLineStipple)(GLint factor, GLushort pattern); +#define glLineStipple _ptrc_glLineStipple +extern void (CODEGEN_FUNCPTR *_ptrc_glLineWidth)(GLfloat width); +#define glLineWidth _ptrc_glLineWidth +extern void (CODEGEN_FUNCPTR *_ptrc_glListBase)(GLuint base); +#define glListBase _ptrc_glListBase +extern void (CODEGEN_FUNCPTR *_ptrc_glLoadIdentity)(void); +#define glLoadIdentity _ptrc_glLoadIdentity +extern void (CODEGEN_FUNCPTR *_ptrc_glLoadMatrixd)(const GLdouble * m); +#define glLoadMatrixd _ptrc_glLoadMatrixd +extern void (CODEGEN_FUNCPTR *_ptrc_glLoadMatrixf)(const GLfloat * m); +#define glLoadMatrixf _ptrc_glLoadMatrixf +extern void (CODEGEN_FUNCPTR *_ptrc_glLoadName)(GLuint name); +#define glLoadName _ptrc_glLoadName +extern void (CODEGEN_FUNCPTR *_ptrc_glLogicOp)(GLenum opcode); +#define glLogicOp _ptrc_glLogicOp +extern void (CODEGEN_FUNCPTR *_ptrc_glMap1d)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble * points); +#define glMap1d _ptrc_glMap1d +extern void (CODEGEN_FUNCPTR *_ptrc_glMap1f)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat * points); +#define glMap1f _ptrc_glMap1f +extern void (CODEGEN_FUNCPTR *_ptrc_glMap2d)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble * points); +#define glMap2d _ptrc_glMap2d +extern void (CODEGEN_FUNCPTR *_ptrc_glMap2f)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat * points); +#define glMap2f _ptrc_glMap2f +extern void (CODEGEN_FUNCPTR *_ptrc_glMapGrid1d)(GLint un, GLdouble u1, GLdouble u2); +#define glMapGrid1d _ptrc_glMapGrid1d +extern void (CODEGEN_FUNCPTR *_ptrc_glMapGrid1f)(GLint un, GLfloat u1, GLfloat u2); +#define glMapGrid1f _ptrc_glMapGrid1f +extern void (CODEGEN_FUNCPTR *_ptrc_glMapGrid2d)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +#define glMapGrid2d _ptrc_glMapGrid2d +extern void (CODEGEN_FUNCPTR *_ptrc_glMapGrid2f)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +#define glMapGrid2f _ptrc_glMapGrid2f +extern void (CODEGEN_FUNCPTR *_ptrc_glMaterialf)(GLenum face, GLenum pname, GLfloat param); +#define glMaterialf _ptrc_glMaterialf +extern void (CODEGEN_FUNCPTR *_ptrc_glMaterialfv)(GLenum face, GLenum pname, const GLfloat * params); +#define glMaterialfv _ptrc_glMaterialfv +extern void (CODEGEN_FUNCPTR *_ptrc_glMateriali)(GLenum face, GLenum pname, GLint param); +#define glMateriali _ptrc_glMateriali +extern void (CODEGEN_FUNCPTR *_ptrc_glMaterialiv)(GLenum face, GLenum pname, const GLint * params); +#define glMaterialiv _ptrc_glMaterialiv +extern void (CODEGEN_FUNCPTR *_ptrc_glMatrixMode)(GLenum mode); +#define glMatrixMode _ptrc_glMatrixMode +extern void (CODEGEN_FUNCPTR *_ptrc_glMultMatrixd)(const GLdouble * m); +#define glMultMatrixd _ptrc_glMultMatrixd +extern void (CODEGEN_FUNCPTR *_ptrc_glMultMatrixf)(const GLfloat * m); +#define glMultMatrixf _ptrc_glMultMatrixf +extern void (CODEGEN_FUNCPTR *_ptrc_glNewList)(GLuint list, GLenum mode); +#define glNewList _ptrc_glNewList +extern void (CODEGEN_FUNCPTR *_ptrc_glNormal3b)(GLbyte nx, GLbyte ny, GLbyte nz); +#define glNormal3b _ptrc_glNormal3b +extern void (CODEGEN_FUNCPTR *_ptrc_glNormal3bv)(const GLbyte * v); +#define glNormal3bv _ptrc_glNormal3bv +extern void (CODEGEN_FUNCPTR *_ptrc_glNormal3d)(GLdouble nx, GLdouble ny, GLdouble nz); +#define glNormal3d _ptrc_glNormal3d +extern void (CODEGEN_FUNCPTR *_ptrc_glNormal3dv)(const GLdouble * v); +#define glNormal3dv _ptrc_glNormal3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz); +#define glNormal3f _ptrc_glNormal3f +extern void (CODEGEN_FUNCPTR *_ptrc_glNormal3fv)(const GLfloat * v); +#define glNormal3fv _ptrc_glNormal3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glNormal3i)(GLint nx, GLint ny, GLint nz); +#define glNormal3i _ptrc_glNormal3i +extern void (CODEGEN_FUNCPTR *_ptrc_glNormal3iv)(const GLint * v); +#define glNormal3iv _ptrc_glNormal3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glNormal3s)(GLshort nx, GLshort ny, GLshort nz); +#define glNormal3s _ptrc_glNormal3s +extern void (CODEGEN_FUNCPTR *_ptrc_glNormal3sv)(const GLshort * v); +#define glNormal3sv _ptrc_glNormal3sv +extern void (CODEGEN_FUNCPTR *_ptrc_glOrtho)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +#define glOrtho _ptrc_glOrtho +extern void (CODEGEN_FUNCPTR *_ptrc_glPassThrough)(GLfloat token); +#define glPassThrough _ptrc_glPassThrough +extern void (CODEGEN_FUNCPTR *_ptrc_glPixelMapfv)(GLenum map, GLsizei mapsize, const GLfloat * values); +#define glPixelMapfv _ptrc_glPixelMapfv +extern void (CODEGEN_FUNCPTR *_ptrc_glPixelMapuiv)(GLenum map, GLsizei mapsize, const GLuint * values); +#define glPixelMapuiv _ptrc_glPixelMapuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glPixelMapusv)(GLenum map, GLsizei mapsize, const GLushort * values); +#define glPixelMapusv _ptrc_glPixelMapusv +extern void (CODEGEN_FUNCPTR *_ptrc_glPixelStoref)(GLenum pname, GLfloat param); +#define glPixelStoref _ptrc_glPixelStoref +extern void (CODEGEN_FUNCPTR *_ptrc_glPixelStorei)(GLenum pname, GLint param); +#define glPixelStorei _ptrc_glPixelStorei +extern void (CODEGEN_FUNCPTR *_ptrc_glPixelTransferf)(GLenum pname, GLfloat param); +#define glPixelTransferf _ptrc_glPixelTransferf +extern void (CODEGEN_FUNCPTR *_ptrc_glPixelTransferi)(GLenum pname, GLint param); +#define glPixelTransferi _ptrc_glPixelTransferi +extern void (CODEGEN_FUNCPTR *_ptrc_glPixelZoom)(GLfloat xfactor, GLfloat yfactor); +#define glPixelZoom _ptrc_glPixelZoom +extern void (CODEGEN_FUNCPTR *_ptrc_glPointSize)(GLfloat size); +#define glPointSize _ptrc_glPointSize +extern void (CODEGEN_FUNCPTR *_ptrc_glPolygonMode)(GLenum face, GLenum mode); +#define glPolygonMode _ptrc_glPolygonMode +extern void (CODEGEN_FUNCPTR *_ptrc_glPolygonStipple)(const GLubyte * mask); +#define glPolygonStipple _ptrc_glPolygonStipple +extern void (CODEGEN_FUNCPTR *_ptrc_glPopAttrib)(void); +#define glPopAttrib _ptrc_glPopAttrib +extern void (CODEGEN_FUNCPTR *_ptrc_glPopMatrix)(void); +#define glPopMatrix _ptrc_glPopMatrix +extern void (CODEGEN_FUNCPTR *_ptrc_glPopName)(void); +#define glPopName _ptrc_glPopName +extern void (CODEGEN_FUNCPTR *_ptrc_glPushAttrib)(GLbitfield mask); +#define glPushAttrib _ptrc_glPushAttrib +extern void (CODEGEN_FUNCPTR *_ptrc_glPushMatrix)(void); +#define glPushMatrix _ptrc_glPushMatrix +extern void (CODEGEN_FUNCPTR *_ptrc_glPushName)(GLuint name); +#define glPushName _ptrc_glPushName +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2d)(GLdouble x, GLdouble y); +#define glRasterPos2d _ptrc_glRasterPos2d +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2dv)(const GLdouble * v); +#define glRasterPos2dv _ptrc_glRasterPos2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2f)(GLfloat x, GLfloat y); +#define glRasterPos2f _ptrc_glRasterPos2f +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2fv)(const GLfloat * v); +#define glRasterPos2fv _ptrc_glRasterPos2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2i)(GLint x, GLint y); +#define glRasterPos2i _ptrc_glRasterPos2i +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2iv)(const GLint * v); +#define glRasterPos2iv _ptrc_glRasterPos2iv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2s)(GLshort x, GLshort y); +#define glRasterPos2s _ptrc_glRasterPos2s +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos2sv)(const GLshort * v); +#define glRasterPos2sv _ptrc_glRasterPos2sv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3d)(GLdouble x, GLdouble y, GLdouble z); +#define glRasterPos3d _ptrc_glRasterPos3d +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3dv)(const GLdouble * v); +#define glRasterPos3dv _ptrc_glRasterPos3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3f)(GLfloat x, GLfloat y, GLfloat z); +#define glRasterPos3f _ptrc_glRasterPos3f +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3fv)(const GLfloat * v); +#define glRasterPos3fv _ptrc_glRasterPos3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3i)(GLint x, GLint y, GLint z); +#define glRasterPos3i _ptrc_glRasterPos3i +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3iv)(const GLint * v); +#define glRasterPos3iv _ptrc_glRasterPos3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3s)(GLshort x, GLshort y, GLshort z); +#define glRasterPos3s _ptrc_glRasterPos3s +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos3sv)(const GLshort * v); +#define glRasterPos3sv _ptrc_glRasterPos3sv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4d)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +#define glRasterPos4d _ptrc_glRasterPos4d +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4dv)(const GLdouble * v); +#define glRasterPos4dv _ptrc_glRasterPos4dv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +#define glRasterPos4f _ptrc_glRasterPos4f +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4fv)(const GLfloat * v); +#define glRasterPos4fv _ptrc_glRasterPos4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4i)(GLint x, GLint y, GLint z, GLint w); +#define glRasterPos4i _ptrc_glRasterPos4i +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4iv)(const GLint * v); +#define glRasterPos4iv _ptrc_glRasterPos4iv +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4s)(GLshort x, GLshort y, GLshort z, GLshort w); +#define glRasterPos4s _ptrc_glRasterPos4s +extern void (CODEGEN_FUNCPTR *_ptrc_glRasterPos4sv)(const GLshort * v); +#define glRasterPos4sv _ptrc_glRasterPos4sv +extern void (CODEGEN_FUNCPTR *_ptrc_glReadBuffer)(GLenum src); +#define glReadBuffer _ptrc_glReadBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels); +#define glReadPixels _ptrc_glReadPixels +extern void (CODEGEN_FUNCPTR *_ptrc_glRectd)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +#define glRectd _ptrc_glRectd +extern void (CODEGEN_FUNCPTR *_ptrc_glRectdv)(const GLdouble * v1, const GLdouble * v2); +#define glRectdv _ptrc_glRectdv +extern void (CODEGEN_FUNCPTR *_ptrc_glRectf)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +#define glRectf _ptrc_glRectf +extern void (CODEGEN_FUNCPTR *_ptrc_glRectfv)(const GLfloat * v1, const GLfloat * v2); +#define glRectfv _ptrc_glRectfv +extern void (CODEGEN_FUNCPTR *_ptrc_glRecti)(GLint x1, GLint y1, GLint x2, GLint y2); +#define glRecti _ptrc_glRecti +extern void (CODEGEN_FUNCPTR *_ptrc_glRectiv)(const GLint * v1, const GLint * v2); +#define glRectiv _ptrc_glRectiv +extern void (CODEGEN_FUNCPTR *_ptrc_glRects)(GLshort x1, GLshort y1, GLshort x2, GLshort y2); +#define glRects _ptrc_glRects +extern void (CODEGEN_FUNCPTR *_ptrc_glRectsv)(const GLshort * v1, const GLshort * v2); +#define glRectsv _ptrc_glRectsv +extern GLint (CODEGEN_FUNCPTR *_ptrc_glRenderMode)(GLenum mode); +#define glRenderMode _ptrc_glRenderMode +extern void (CODEGEN_FUNCPTR *_ptrc_glRotated)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +#define glRotated _ptrc_glRotated +extern void (CODEGEN_FUNCPTR *_ptrc_glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +#define glRotatef _ptrc_glRotatef +extern void (CODEGEN_FUNCPTR *_ptrc_glScaled)(GLdouble x, GLdouble y, GLdouble z); +#define glScaled _ptrc_glScaled +extern void (CODEGEN_FUNCPTR *_ptrc_glScalef)(GLfloat x, GLfloat y, GLfloat z); +#define glScalef _ptrc_glScalef +extern void (CODEGEN_FUNCPTR *_ptrc_glScissor)(GLint x, GLint y, GLsizei width, GLsizei height); +#define glScissor _ptrc_glScissor +extern void (CODEGEN_FUNCPTR *_ptrc_glSelectBuffer)(GLsizei size, GLuint * buffer); +#define glSelectBuffer _ptrc_glSelectBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glShadeModel)(GLenum mode); +#define glShadeModel _ptrc_glShadeModel +extern void (CODEGEN_FUNCPTR *_ptrc_glStencilFunc)(GLenum func, GLint ref, GLuint mask); +#define glStencilFunc _ptrc_glStencilFunc +extern void (CODEGEN_FUNCPTR *_ptrc_glStencilMask)(GLuint mask); +#define glStencilMask _ptrc_glStencilMask +extern void (CODEGEN_FUNCPTR *_ptrc_glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass); +#define glStencilOp _ptrc_glStencilOp +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1d)(GLdouble s); +#define glTexCoord1d _ptrc_glTexCoord1d +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1dv)(const GLdouble * v); +#define glTexCoord1dv _ptrc_glTexCoord1dv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1f)(GLfloat s); +#define glTexCoord1f _ptrc_glTexCoord1f +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1fv)(const GLfloat * v); +#define glTexCoord1fv _ptrc_glTexCoord1fv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1i)(GLint s); +#define glTexCoord1i _ptrc_glTexCoord1i +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1iv)(const GLint * v); +#define glTexCoord1iv _ptrc_glTexCoord1iv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1s)(GLshort s); +#define glTexCoord1s _ptrc_glTexCoord1s +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord1sv)(const GLshort * v); +#define glTexCoord1sv _ptrc_glTexCoord1sv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2d)(GLdouble s, GLdouble t); +#define glTexCoord2d _ptrc_glTexCoord2d +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2dv)(const GLdouble * v); +#define glTexCoord2dv _ptrc_glTexCoord2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2f)(GLfloat s, GLfloat t); +#define glTexCoord2f _ptrc_glTexCoord2f +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2fv)(const GLfloat * v); +#define glTexCoord2fv _ptrc_glTexCoord2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2i)(GLint s, GLint t); +#define glTexCoord2i _ptrc_glTexCoord2i +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2iv)(const GLint * v); +#define glTexCoord2iv _ptrc_glTexCoord2iv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2s)(GLshort s, GLshort t); +#define glTexCoord2s _ptrc_glTexCoord2s +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord2sv)(const GLshort * v); +#define glTexCoord2sv _ptrc_glTexCoord2sv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3d)(GLdouble s, GLdouble t, GLdouble r); +#define glTexCoord3d _ptrc_glTexCoord3d +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3dv)(const GLdouble * v); +#define glTexCoord3dv _ptrc_glTexCoord3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3f)(GLfloat s, GLfloat t, GLfloat r); +#define glTexCoord3f _ptrc_glTexCoord3f +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3fv)(const GLfloat * v); +#define glTexCoord3fv _ptrc_glTexCoord3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3i)(GLint s, GLint t, GLint r); +#define glTexCoord3i _ptrc_glTexCoord3i +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3iv)(const GLint * v); +#define glTexCoord3iv _ptrc_glTexCoord3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3s)(GLshort s, GLshort t, GLshort r); +#define glTexCoord3s _ptrc_glTexCoord3s +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord3sv)(const GLshort * v); +#define glTexCoord3sv _ptrc_glTexCoord3sv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4d)(GLdouble s, GLdouble t, GLdouble r, GLdouble q); +#define glTexCoord4d _ptrc_glTexCoord4d +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4dv)(const GLdouble * v); +#define glTexCoord4dv _ptrc_glTexCoord4dv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4f)(GLfloat s, GLfloat t, GLfloat r, GLfloat q); +#define glTexCoord4f _ptrc_glTexCoord4f +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4fv)(const GLfloat * v); +#define glTexCoord4fv _ptrc_glTexCoord4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4i)(GLint s, GLint t, GLint r, GLint q); +#define glTexCoord4i _ptrc_glTexCoord4i +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4iv)(const GLint * v); +#define glTexCoord4iv _ptrc_glTexCoord4iv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4s)(GLshort s, GLshort t, GLshort r, GLshort q); +#define glTexCoord4s _ptrc_glTexCoord4s +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoord4sv)(const GLshort * v); +#define glTexCoord4sv _ptrc_glTexCoord4sv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexEnvf)(GLenum target, GLenum pname, GLfloat param); +#define glTexEnvf _ptrc_glTexEnvf +extern void (CODEGEN_FUNCPTR *_ptrc_glTexEnvfv)(GLenum target, GLenum pname, const GLfloat * params); +#define glTexEnvfv _ptrc_glTexEnvfv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexEnvi)(GLenum target, GLenum pname, GLint param); +#define glTexEnvi _ptrc_glTexEnvi +extern void (CODEGEN_FUNCPTR *_ptrc_glTexEnviv)(GLenum target, GLenum pname, const GLint * params); +#define glTexEnviv _ptrc_glTexEnviv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexGend)(GLenum coord, GLenum pname, GLdouble param); +#define glTexGend _ptrc_glTexGend +extern void (CODEGEN_FUNCPTR *_ptrc_glTexGendv)(GLenum coord, GLenum pname, const GLdouble * params); +#define glTexGendv _ptrc_glTexGendv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexGenf)(GLenum coord, GLenum pname, GLfloat param); +#define glTexGenf _ptrc_glTexGenf +extern void (CODEGEN_FUNCPTR *_ptrc_glTexGenfv)(GLenum coord, GLenum pname, const GLfloat * params); +#define glTexGenfv _ptrc_glTexGenfv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexGeni)(GLenum coord, GLenum pname, GLint param); +#define glTexGeni _ptrc_glTexGeni +extern void (CODEGEN_FUNCPTR *_ptrc_glTexGeniv)(GLenum coord, GLenum pname, const GLint * params); +#define glTexGeniv _ptrc_glTexGeniv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexImage1D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); +#define glTexImage1D _ptrc_glTexImage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +#define glTexImage2D _ptrc_glTexImage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glTexParameterf)(GLenum target, GLenum pname, GLfloat param); +#define glTexParameterf _ptrc_glTexParameterf +extern void (CODEGEN_FUNCPTR *_ptrc_glTexParameterfv)(GLenum target, GLenum pname, const GLfloat * params); +#define glTexParameterfv _ptrc_glTexParameterfv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexParameteri)(GLenum target, GLenum pname, GLint param); +#define glTexParameteri _ptrc_glTexParameteri +extern void (CODEGEN_FUNCPTR *_ptrc_glTexParameteriv)(GLenum target, GLenum pname, const GLint * params); +#define glTexParameteriv _ptrc_glTexParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glTranslated)(GLdouble x, GLdouble y, GLdouble z); +#define glTranslated _ptrc_glTranslated +extern void (CODEGEN_FUNCPTR *_ptrc_glTranslatef)(GLfloat x, GLfloat y, GLfloat z); +#define glTranslatef _ptrc_glTranslatef +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex2d)(GLdouble x, GLdouble y); +#define glVertex2d _ptrc_glVertex2d +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex2dv)(const GLdouble * v); +#define glVertex2dv _ptrc_glVertex2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex2f)(GLfloat x, GLfloat y); +#define glVertex2f _ptrc_glVertex2f +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex2fv)(const GLfloat * v); +#define glVertex2fv _ptrc_glVertex2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex2i)(GLint x, GLint y); +#define glVertex2i _ptrc_glVertex2i +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex2iv)(const GLint * v); +#define glVertex2iv _ptrc_glVertex2iv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex2s)(GLshort x, GLshort y); +#define glVertex2s _ptrc_glVertex2s +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex2sv)(const GLshort * v); +#define glVertex2sv _ptrc_glVertex2sv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex3d)(GLdouble x, GLdouble y, GLdouble z); +#define glVertex3d _ptrc_glVertex3d +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex3dv)(const GLdouble * v); +#define glVertex3dv _ptrc_glVertex3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex3f)(GLfloat x, GLfloat y, GLfloat z); +#define glVertex3f _ptrc_glVertex3f +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex3fv)(const GLfloat * v); +#define glVertex3fv _ptrc_glVertex3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex3i)(GLint x, GLint y, GLint z); +#define glVertex3i _ptrc_glVertex3i +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex3iv)(const GLint * v); +#define glVertex3iv _ptrc_glVertex3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex3s)(GLshort x, GLshort y, GLshort z); +#define glVertex3s _ptrc_glVertex3s +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex3sv)(const GLshort * v); +#define glVertex3sv _ptrc_glVertex3sv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex4d)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +#define glVertex4d _ptrc_glVertex4d +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex4dv)(const GLdouble * v); +#define glVertex4dv _ptrc_glVertex4dv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +#define glVertex4f _ptrc_glVertex4f +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex4fv)(const GLfloat * v); +#define glVertex4fv _ptrc_glVertex4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex4i)(GLint x, GLint y, GLint z, GLint w); +#define glVertex4i _ptrc_glVertex4i +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex4iv)(const GLint * v); +#define glVertex4iv _ptrc_glVertex4iv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex4s)(GLshort x, GLshort y, GLshort z, GLshort w); +#define glVertex4s _ptrc_glVertex4s +extern void (CODEGEN_FUNCPTR *_ptrc_glVertex4sv)(const GLshort * v); +#define glVertex4sv _ptrc_glVertex4sv +extern void (CODEGEN_FUNCPTR *_ptrc_glViewport)(GLint x, GLint y, GLsizei width, GLsizei height); +#define glViewport _ptrc_glViewport + +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glAreTexturesResident)(GLsizei n, const GLuint * textures, GLboolean * residences); +#define glAreTexturesResident _ptrc_glAreTexturesResident +extern void (CODEGEN_FUNCPTR *_ptrc_glArrayElement)(GLint i); +#define glArrayElement _ptrc_glArrayElement +extern void (CODEGEN_FUNCPTR *_ptrc_glBindTexture)(GLenum target, GLuint texture); +#define glBindTexture _ptrc_glBindTexture +extern void (CODEGEN_FUNCPTR *_ptrc_glColorPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer); +#define glColorPointer _ptrc_glColorPointer +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +#define glCopyTexImage1D _ptrc_glCopyTexImage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +#define glCopyTexImage2D _ptrc_glCopyTexImage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +#define glCopyTexSubImage1D _ptrc_glCopyTexSubImage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#define glCopyTexSubImage2D _ptrc_glCopyTexSubImage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glDeleteTextures)(GLsizei n, const GLuint * textures); +#define glDeleteTextures _ptrc_glDeleteTextures +extern void (CODEGEN_FUNCPTR *_ptrc_glDisableClientState)(GLenum ren_array); +#define glDisableClientState _ptrc_glDisableClientState +extern void (CODEGEN_FUNCPTR *_ptrc_glDrawArrays)(GLenum mode, GLint first, GLsizei count); +#define glDrawArrays _ptrc_glDrawArrays +extern void (CODEGEN_FUNCPTR *_ptrc_glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void * indices); +#define glDrawElements _ptrc_glDrawElements +extern void (CODEGEN_FUNCPTR *_ptrc_glEdgeFlagPointer)(GLsizei stride, const void * pointer); +#define glEdgeFlagPointer _ptrc_glEdgeFlagPointer +extern void (CODEGEN_FUNCPTR *_ptrc_glEnableClientState)(GLenum ren_array); +#define glEnableClientState _ptrc_glEnableClientState +extern void (CODEGEN_FUNCPTR *_ptrc_glGenTextures)(GLsizei n, GLuint * textures); +#define glGenTextures _ptrc_glGenTextures +extern void (CODEGEN_FUNCPTR *_ptrc_glGetPointerv)(GLenum pname, void ** params); +#define glGetPointerv _ptrc_glGetPointerv +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexPointer)(GLenum type, GLsizei stride, const void * pointer); +#define glIndexPointer _ptrc_glIndexPointer +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexub)(GLubyte c); +#define glIndexub _ptrc_glIndexub +extern void (CODEGEN_FUNCPTR *_ptrc_glIndexubv)(const GLubyte * c); +#define glIndexubv _ptrc_glIndexubv +extern void (CODEGEN_FUNCPTR *_ptrc_glInterleavedArrays)(GLenum format, GLsizei stride, const void * pointer); +#define glInterleavedArrays _ptrc_glInterleavedArrays +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsTexture)(GLuint texture); +#define glIsTexture _ptrc_glIsTexture +extern void (CODEGEN_FUNCPTR *_ptrc_glNormalPointer)(GLenum type, GLsizei stride, const void * pointer); +#define glNormalPointer _ptrc_glNormalPointer +extern void (CODEGEN_FUNCPTR *_ptrc_glPolygonOffset)(GLfloat factor, GLfloat units); +#define glPolygonOffset _ptrc_glPolygonOffset +extern void (CODEGEN_FUNCPTR *_ptrc_glPopClientAttrib)(void); +#define glPopClientAttrib _ptrc_glPopClientAttrib +extern void (CODEGEN_FUNCPTR *_ptrc_glPrioritizeTextures)(GLsizei n, const GLuint * textures, const GLfloat * priorities); +#define glPrioritizeTextures _ptrc_glPrioritizeTextures +extern void (CODEGEN_FUNCPTR *_ptrc_glPushClientAttrib)(GLbitfield mask); +#define glPushClientAttrib _ptrc_glPushClientAttrib +extern void (CODEGEN_FUNCPTR *_ptrc_glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer); +#define glTexCoordPointer _ptrc_glTexCoordPointer +extern void (CODEGEN_FUNCPTR *_ptrc_glTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +#define glTexSubImage1D _ptrc_glTexSubImage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +#define glTexSubImage2D _ptrc_glTexSubImage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer); +#define glVertexPointer _ptrc_glVertexPointer + +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#define glCopyTexSubImage3D _ptrc_glCopyTexSubImage3D +extern void (CODEGEN_FUNCPTR *_ptrc_glDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices); +#define glDrawRangeElements _ptrc_glDrawRangeElements +extern void (CODEGEN_FUNCPTR *_ptrc_glTexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); +#define glTexImage3D _ptrc_glTexImage3D +extern void (CODEGEN_FUNCPTR *_ptrc_glTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +#define glTexSubImage3D _ptrc_glTexSubImage3D + +extern void (CODEGEN_FUNCPTR *_ptrc_glActiveTexture)(GLenum texture); +#define glActiveTexture _ptrc_glActiveTexture +extern void (CODEGEN_FUNCPTR *_ptrc_glClientActiveTexture)(GLenum texture); +#define glClientActiveTexture _ptrc_glClientActiveTexture +extern void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data); +#define glCompressedTexImage1D _ptrc_glCompressedTexImage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data); +#define glCompressedTexImage2D _ptrc_glCompressedTexImage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexImage3D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data); +#define glCompressedTexImage3D _ptrc_glCompressedTexImage3D +extern void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data); +#define glCompressedTexSubImage1D _ptrc_glCompressedTexSubImage1D +extern void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data); +#define glCompressedTexSubImage2D _ptrc_glCompressedTexSubImage2D +extern void (CODEGEN_FUNCPTR *_ptrc_glCompressedTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data); +#define glCompressedTexSubImage3D _ptrc_glCompressedTexSubImage3D +extern void (CODEGEN_FUNCPTR *_ptrc_glGetCompressedTexImage)(GLenum target, GLint level, void * img); +#define glGetCompressedTexImage _ptrc_glGetCompressedTexImage +extern void (CODEGEN_FUNCPTR *_ptrc_glLoadTransposeMatrixd)(const GLdouble * m); +#define glLoadTransposeMatrixd _ptrc_glLoadTransposeMatrixd +extern void (CODEGEN_FUNCPTR *_ptrc_glLoadTransposeMatrixf)(const GLfloat * m); +#define glLoadTransposeMatrixf _ptrc_glLoadTransposeMatrixf +extern void (CODEGEN_FUNCPTR *_ptrc_glMultTransposeMatrixd)(const GLdouble * m); +#define glMultTransposeMatrixd _ptrc_glMultTransposeMatrixd +extern void (CODEGEN_FUNCPTR *_ptrc_glMultTransposeMatrixf)(const GLfloat * m); +#define glMultTransposeMatrixf _ptrc_glMultTransposeMatrixf +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1d)(GLenum target, GLdouble s); +#define glMultiTexCoord1d _ptrc_glMultiTexCoord1d +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1dv)(GLenum target, const GLdouble * v); +#define glMultiTexCoord1dv _ptrc_glMultiTexCoord1dv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1f)(GLenum target, GLfloat s); +#define glMultiTexCoord1f _ptrc_glMultiTexCoord1f +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1fv)(GLenum target, const GLfloat * v); +#define glMultiTexCoord1fv _ptrc_glMultiTexCoord1fv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1i)(GLenum target, GLint s); +#define glMultiTexCoord1i _ptrc_glMultiTexCoord1i +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1iv)(GLenum target, const GLint * v); +#define glMultiTexCoord1iv _ptrc_glMultiTexCoord1iv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1s)(GLenum target, GLshort s); +#define glMultiTexCoord1s _ptrc_glMultiTexCoord1s +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord1sv)(GLenum target, const GLshort * v); +#define glMultiTexCoord1sv _ptrc_glMultiTexCoord1sv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2d)(GLenum target, GLdouble s, GLdouble t); +#define glMultiTexCoord2d _ptrc_glMultiTexCoord2d +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2dv)(GLenum target, const GLdouble * v); +#define glMultiTexCoord2dv _ptrc_glMultiTexCoord2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2f)(GLenum target, GLfloat s, GLfloat t); +#define glMultiTexCoord2f _ptrc_glMultiTexCoord2f +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2fv)(GLenum target, const GLfloat * v); +#define glMultiTexCoord2fv _ptrc_glMultiTexCoord2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2i)(GLenum target, GLint s, GLint t); +#define glMultiTexCoord2i _ptrc_glMultiTexCoord2i +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2iv)(GLenum target, const GLint * v); +#define glMultiTexCoord2iv _ptrc_glMultiTexCoord2iv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2s)(GLenum target, GLshort s, GLshort t); +#define glMultiTexCoord2s _ptrc_glMultiTexCoord2s +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord2sv)(GLenum target, const GLshort * v); +#define glMultiTexCoord2sv _ptrc_glMultiTexCoord2sv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3d)(GLenum target, GLdouble s, GLdouble t, GLdouble r); +#define glMultiTexCoord3d _ptrc_glMultiTexCoord3d +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3dv)(GLenum target, const GLdouble * v); +#define glMultiTexCoord3dv _ptrc_glMultiTexCoord3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3f)(GLenum target, GLfloat s, GLfloat t, GLfloat r); +#define glMultiTexCoord3f _ptrc_glMultiTexCoord3f +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3fv)(GLenum target, const GLfloat * v); +#define glMultiTexCoord3fv _ptrc_glMultiTexCoord3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3i)(GLenum target, GLint s, GLint t, GLint r); +#define glMultiTexCoord3i _ptrc_glMultiTexCoord3i +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3iv)(GLenum target, const GLint * v); +#define glMultiTexCoord3iv _ptrc_glMultiTexCoord3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3s)(GLenum target, GLshort s, GLshort t, GLshort r); +#define glMultiTexCoord3s _ptrc_glMultiTexCoord3s +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord3sv)(GLenum target, const GLshort * v); +#define glMultiTexCoord3sv _ptrc_glMultiTexCoord3sv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4d)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +#define glMultiTexCoord4d _ptrc_glMultiTexCoord4d +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4dv)(GLenum target, const GLdouble * v); +#define glMultiTexCoord4dv _ptrc_glMultiTexCoord4dv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +#define glMultiTexCoord4f _ptrc_glMultiTexCoord4f +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4fv)(GLenum target, const GLfloat * v); +#define glMultiTexCoord4fv _ptrc_glMultiTexCoord4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4i)(GLenum target, GLint s, GLint t, GLint r, GLint q); +#define glMultiTexCoord4i _ptrc_glMultiTexCoord4i +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4iv)(GLenum target, const GLint * v); +#define glMultiTexCoord4iv _ptrc_glMultiTexCoord4iv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4s)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +#define glMultiTexCoord4s _ptrc_glMultiTexCoord4s +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiTexCoord4sv)(GLenum target, const GLshort * v); +#define glMultiTexCoord4sv _ptrc_glMultiTexCoord4sv +extern void (CODEGEN_FUNCPTR *_ptrc_glSampleCoverage)(GLfloat value, GLboolean invert); +#define glSampleCoverage _ptrc_glSampleCoverage + +extern void (CODEGEN_FUNCPTR *_ptrc_glBlendColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +#define glBlendColor _ptrc_glBlendColor +extern void (CODEGEN_FUNCPTR *_ptrc_glBlendEquation)(GLenum mode); +#define glBlendEquation _ptrc_glBlendEquation +extern void (CODEGEN_FUNCPTR *_ptrc_glBlendFuncSeparate)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#define glBlendFuncSeparate _ptrc_glBlendFuncSeparate +extern void (CODEGEN_FUNCPTR *_ptrc_glFogCoordPointer)(GLenum type, GLsizei stride, const void * pointer); +#define glFogCoordPointer _ptrc_glFogCoordPointer +extern void (CODEGEN_FUNCPTR *_ptrc_glFogCoordd)(GLdouble coord); +#define glFogCoordd _ptrc_glFogCoordd +extern void (CODEGEN_FUNCPTR *_ptrc_glFogCoorddv)(const GLdouble * coord); +#define glFogCoorddv _ptrc_glFogCoorddv +extern void (CODEGEN_FUNCPTR *_ptrc_glFogCoordf)(GLfloat coord); +#define glFogCoordf _ptrc_glFogCoordf +extern void (CODEGEN_FUNCPTR *_ptrc_glFogCoordfv)(const GLfloat * coord); +#define glFogCoordfv _ptrc_glFogCoordfv +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiDrawArrays)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount); +#define glMultiDrawArrays _ptrc_glMultiDrawArrays +extern void (CODEGEN_FUNCPTR *_ptrc_glMultiDrawElements)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount); +#define glMultiDrawElements _ptrc_glMultiDrawElements +extern void (CODEGEN_FUNCPTR *_ptrc_glPointParameterf)(GLenum pname, GLfloat param); +#define glPointParameterf _ptrc_glPointParameterf +extern void (CODEGEN_FUNCPTR *_ptrc_glPointParameterfv)(GLenum pname, const GLfloat * params); +#define glPointParameterfv _ptrc_glPointParameterfv +extern void (CODEGEN_FUNCPTR *_ptrc_glPointParameteri)(GLenum pname, GLint param); +#define glPointParameteri _ptrc_glPointParameteri +extern void (CODEGEN_FUNCPTR *_ptrc_glPointParameteriv)(GLenum pname, const GLint * params); +#define glPointParameteriv _ptrc_glPointParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3b)(GLbyte red, GLbyte green, GLbyte blue); +#define glSecondaryColor3b _ptrc_glSecondaryColor3b +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3bv)(const GLbyte * v); +#define glSecondaryColor3bv _ptrc_glSecondaryColor3bv +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3d)(GLdouble red, GLdouble green, GLdouble blue); +#define glSecondaryColor3d _ptrc_glSecondaryColor3d +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3dv)(const GLdouble * v); +#define glSecondaryColor3dv _ptrc_glSecondaryColor3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3f)(GLfloat red, GLfloat green, GLfloat blue); +#define glSecondaryColor3f _ptrc_glSecondaryColor3f +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3fv)(const GLfloat * v); +#define glSecondaryColor3fv _ptrc_glSecondaryColor3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3i)(GLint red, GLint green, GLint blue); +#define glSecondaryColor3i _ptrc_glSecondaryColor3i +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3iv)(const GLint * v); +#define glSecondaryColor3iv _ptrc_glSecondaryColor3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3s)(GLshort red, GLshort green, GLshort blue); +#define glSecondaryColor3s _ptrc_glSecondaryColor3s +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3sv)(const GLshort * v); +#define glSecondaryColor3sv _ptrc_glSecondaryColor3sv +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3ub)(GLubyte red, GLubyte green, GLubyte blue); +#define glSecondaryColor3ub _ptrc_glSecondaryColor3ub +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3ubv)(const GLubyte * v); +#define glSecondaryColor3ubv _ptrc_glSecondaryColor3ubv +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3ui)(GLuint red, GLuint green, GLuint blue); +#define glSecondaryColor3ui _ptrc_glSecondaryColor3ui +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3uiv)(const GLuint * v); +#define glSecondaryColor3uiv _ptrc_glSecondaryColor3uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3us)(GLushort red, GLushort green, GLushort blue); +#define glSecondaryColor3us _ptrc_glSecondaryColor3us +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColor3usv)(const GLushort * v); +#define glSecondaryColor3usv _ptrc_glSecondaryColor3usv +extern void (CODEGEN_FUNCPTR *_ptrc_glSecondaryColorPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer); +#define glSecondaryColorPointer _ptrc_glSecondaryColorPointer +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2d)(GLdouble x, GLdouble y); +#define glWindowPos2d _ptrc_glWindowPos2d +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2dv)(const GLdouble * v); +#define glWindowPos2dv _ptrc_glWindowPos2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2f)(GLfloat x, GLfloat y); +#define glWindowPos2f _ptrc_glWindowPos2f +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2fv)(const GLfloat * v); +#define glWindowPos2fv _ptrc_glWindowPos2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2i)(GLint x, GLint y); +#define glWindowPos2i _ptrc_glWindowPos2i +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2iv)(const GLint * v); +#define glWindowPos2iv _ptrc_glWindowPos2iv +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2s)(GLshort x, GLshort y); +#define glWindowPos2s _ptrc_glWindowPos2s +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos2sv)(const GLshort * v); +#define glWindowPos2sv _ptrc_glWindowPos2sv +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3d)(GLdouble x, GLdouble y, GLdouble z); +#define glWindowPos3d _ptrc_glWindowPos3d +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3dv)(const GLdouble * v); +#define glWindowPos3dv _ptrc_glWindowPos3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3f)(GLfloat x, GLfloat y, GLfloat z); +#define glWindowPos3f _ptrc_glWindowPos3f +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3fv)(const GLfloat * v); +#define glWindowPos3fv _ptrc_glWindowPos3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3i)(GLint x, GLint y, GLint z); +#define glWindowPos3i _ptrc_glWindowPos3i +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3iv)(const GLint * v); +#define glWindowPos3iv _ptrc_glWindowPos3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3s)(GLshort x, GLshort y, GLshort z); +#define glWindowPos3s _ptrc_glWindowPos3s +extern void (CODEGEN_FUNCPTR *_ptrc_glWindowPos3sv)(const GLshort * v); +#define glWindowPos3sv _ptrc_glWindowPos3sv + +extern void (CODEGEN_FUNCPTR *_ptrc_glBeginQuery)(GLenum target, GLuint id); +#define glBeginQuery _ptrc_glBeginQuery +extern void (CODEGEN_FUNCPTR *_ptrc_glBindBuffer)(GLenum target, GLuint buffer); +#define glBindBuffer _ptrc_glBindBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glBufferData)(GLenum target, GLsizeiptr size, const void * data, GLenum usage); +#define glBufferData _ptrc_glBufferData +extern void (CODEGEN_FUNCPTR *_ptrc_glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data); +#define glBufferSubData _ptrc_glBufferSubData +extern void (CODEGEN_FUNCPTR *_ptrc_glDeleteBuffers)(GLsizei n, const GLuint * buffers); +#define glDeleteBuffers _ptrc_glDeleteBuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glDeleteQueries)(GLsizei n, const GLuint * ids); +#define glDeleteQueries _ptrc_glDeleteQueries +extern void (CODEGEN_FUNCPTR *_ptrc_glEndQuery)(GLenum target); +#define glEndQuery _ptrc_glEndQuery +extern void (CODEGEN_FUNCPTR *_ptrc_glGenBuffers)(GLsizei n, GLuint * buffers); +#define glGenBuffers _ptrc_glGenBuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glGenQueries)(GLsizei n, GLuint * ids); +#define glGenQueries _ptrc_glGenQueries +extern void (CODEGEN_FUNCPTR *_ptrc_glGetBufferParameteriv)(GLenum target, GLenum pname, GLint * params); +#define glGetBufferParameteriv _ptrc_glGetBufferParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetBufferPointerv)(GLenum target, GLenum pname, void ** params); +#define glGetBufferPointerv _ptrc_glGetBufferPointerv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, void * data); +#define glGetBufferSubData _ptrc_glGetBufferSubData +extern void (CODEGEN_FUNCPTR *_ptrc_glGetQueryObjectiv)(GLuint id, GLenum pname, GLint * params); +#define glGetQueryObjectiv _ptrc_glGetQueryObjectiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint * params); +#define glGetQueryObjectuiv _ptrc_glGetQueryObjectuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetQueryiv)(GLenum target, GLenum pname, GLint * params); +#define glGetQueryiv _ptrc_glGetQueryiv +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsBuffer)(GLuint buffer); +#define glIsBuffer _ptrc_glIsBuffer +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsQuery)(GLuint id); +#define glIsQuery _ptrc_glIsQuery +extern void * (CODEGEN_FUNCPTR *_ptrc_glMapBuffer)(GLenum target, GLenum access); +#define glMapBuffer _ptrc_glMapBuffer +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glUnmapBuffer)(GLenum target); +#define glUnmapBuffer _ptrc_glUnmapBuffer + +extern void (CODEGEN_FUNCPTR *_ptrc_glAttachShader)(GLuint program, GLuint shader); +#define glAttachShader _ptrc_glAttachShader +extern void (CODEGEN_FUNCPTR *_ptrc_glBindAttribLocation)(GLuint program, GLuint index, const GLchar * name); +#define glBindAttribLocation _ptrc_glBindAttribLocation +extern void (CODEGEN_FUNCPTR *_ptrc_glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha); +#define glBlendEquationSeparate _ptrc_glBlendEquationSeparate +extern void (CODEGEN_FUNCPTR *_ptrc_glCompileShader)(GLuint shader); +#define glCompileShader _ptrc_glCompileShader +extern GLuint (CODEGEN_FUNCPTR *_ptrc_glCreateProgram)(void); +#define glCreateProgram _ptrc_glCreateProgram +extern GLuint (CODEGEN_FUNCPTR *_ptrc_glCreateShader)(GLenum type); +#define glCreateShader _ptrc_glCreateShader +extern void (CODEGEN_FUNCPTR *_ptrc_glDeleteProgram)(GLuint program); +#define glDeleteProgram _ptrc_glDeleteProgram +extern void (CODEGEN_FUNCPTR *_ptrc_glDeleteShader)(GLuint shader); +#define glDeleteShader _ptrc_glDeleteShader +extern void (CODEGEN_FUNCPTR *_ptrc_glDetachShader)(GLuint program, GLuint shader); +#define glDetachShader _ptrc_glDetachShader +extern void (CODEGEN_FUNCPTR *_ptrc_glDisableVertexAttribArray)(GLuint index); +#define glDisableVertexAttribArray _ptrc_glDisableVertexAttribArray +extern void (CODEGEN_FUNCPTR *_ptrc_glDrawBuffers)(GLsizei n, const GLenum * bufs); +#define glDrawBuffers _ptrc_glDrawBuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glEnableVertexAttribArray)(GLuint index); +#define glEnableVertexAttribArray _ptrc_glEnableVertexAttribArray +extern void (CODEGEN_FUNCPTR *_ptrc_glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); +#define glGetActiveAttrib _ptrc_glGetActiveAttrib +extern void (CODEGEN_FUNCPTR *_ptrc_glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); +#define glGetActiveUniform _ptrc_glGetActiveUniform +extern void (CODEGEN_FUNCPTR *_ptrc_glGetAttachedShaders)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders); +#define glGetAttachedShaders _ptrc_glGetAttachedShaders +extern GLint (CODEGEN_FUNCPTR *_ptrc_glGetAttribLocation)(GLuint program, const GLchar * name); +#define glGetAttribLocation _ptrc_glGetAttribLocation +extern void (CODEGEN_FUNCPTR *_ptrc_glGetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +#define glGetProgramInfoLog _ptrc_glGetProgramInfoLog +extern void (CODEGEN_FUNCPTR *_ptrc_glGetProgramiv)(GLuint program, GLenum pname, GLint * params); +#define glGetProgramiv _ptrc_glGetProgramiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +#define glGetShaderInfoLog _ptrc_glGetShaderInfoLog +extern void (CODEGEN_FUNCPTR *_ptrc_glGetShaderSource)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source); +#define glGetShaderSource _ptrc_glGetShaderSource +extern void (CODEGEN_FUNCPTR *_ptrc_glGetShaderiv)(GLuint shader, GLenum pname, GLint * params); +#define glGetShaderiv _ptrc_glGetShaderiv +extern GLint (CODEGEN_FUNCPTR *_ptrc_glGetUniformLocation)(GLuint program, const GLchar * name); +#define glGetUniformLocation _ptrc_glGetUniformLocation +extern void (CODEGEN_FUNCPTR *_ptrc_glGetUniformfv)(GLuint program, GLint location, GLfloat * params); +#define glGetUniformfv _ptrc_glGetUniformfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetUniformiv)(GLuint program, GLint location, GLint * params); +#define glGetUniformiv _ptrc_glGetUniformiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribPointerv)(GLuint index, GLenum pname, void ** pointer); +#define glGetVertexAttribPointerv _ptrc_glGetVertexAttribPointerv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribdv)(GLuint index, GLenum pname, GLdouble * params); +#define glGetVertexAttribdv _ptrc_glGetVertexAttribdv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat * params); +#define glGetVertexAttribfv _ptrc_glGetVertexAttribfv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribiv)(GLuint index, GLenum pname, GLint * params); +#define glGetVertexAttribiv _ptrc_glGetVertexAttribiv +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsProgram)(GLuint program); +#define glIsProgram _ptrc_glIsProgram +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsShader)(GLuint shader); +#define glIsShader _ptrc_glIsShader +extern void (CODEGEN_FUNCPTR *_ptrc_glLinkProgram)(GLuint program); +#define glLinkProgram _ptrc_glLinkProgram +extern void (CODEGEN_FUNCPTR *_ptrc_glShaderSource)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length); +#define glShaderSource _ptrc_glShaderSource +extern void (CODEGEN_FUNCPTR *_ptrc_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask); +#define glStencilFuncSeparate _ptrc_glStencilFuncSeparate +extern void (CODEGEN_FUNCPTR *_ptrc_glStencilMaskSeparate)(GLenum face, GLuint mask); +#define glStencilMaskSeparate _ptrc_glStencilMaskSeparate +extern void (CODEGEN_FUNCPTR *_ptrc_glStencilOpSeparate)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +#define glStencilOpSeparate _ptrc_glStencilOpSeparate +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform1f)(GLint location, GLfloat v0); +#define glUniform1f _ptrc_glUniform1f +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform1fv)(GLint location, GLsizei count, const GLfloat * value); +#define glUniform1fv _ptrc_glUniform1fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform1i)(GLint location, GLint v0); +#define glUniform1i _ptrc_glUniform1i +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform1iv)(GLint location, GLsizei count, const GLint * value); +#define glUniform1iv _ptrc_glUniform1iv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform2f)(GLint location, GLfloat v0, GLfloat v1); +#define glUniform2f _ptrc_glUniform2f +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform2fv)(GLint location, GLsizei count, const GLfloat * value); +#define glUniform2fv _ptrc_glUniform2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform2i)(GLint location, GLint v0, GLint v1); +#define glUniform2i _ptrc_glUniform2i +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform2iv)(GLint location, GLsizei count, const GLint * value); +#define glUniform2iv _ptrc_glUniform2iv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +#define glUniform3f _ptrc_glUniform3f +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform3fv)(GLint location, GLsizei count, const GLfloat * value); +#define glUniform3fv _ptrc_glUniform3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform3i)(GLint location, GLint v0, GLint v1, GLint v2); +#define glUniform3i _ptrc_glUniform3i +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform3iv)(GLint location, GLsizei count, const GLint * value); +#define glUniform3iv _ptrc_glUniform3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform4f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +#define glUniform4f _ptrc_glUniform4f +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform4fv)(GLint location, GLsizei count, const GLfloat * value); +#define glUniform4fv _ptrc_glUniform4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform4i)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +#define glUniform4i _ptrc_glUniform4i +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform4iv)(GLint location, GLsizei count, const GLint * value); +#define glUniform4iv _ptrc_glUniform4iv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glUniformMatrix2fv _ptrc_glUniformMatrix2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glUniformMatrix3fv _ptrc_glUniformMatrix3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glUniformMatrix4fv _ptrc_glUniformMatrix4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUseProgram)(GLuint program); +#define glUseProgram _ptrc_glUseProgram +extern void (CODEGEN_FUNCPTR *_ptrc_glValidateProgram)(GLuint program); +#define glValidateProgram _ptrc_glValidateProgram +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1d)(GLuint index, GLdouble x); +#define glVertexAttrib1d _ptrc_glVertexAttrib1d +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1dv)(GLuint index, const GLdouble * v); +#define glVertexAttrib1dv _ptrc_glVertexAttrib1dv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1f)(GLuint index, GLfloat x); +#define glVertexAttrib1f _ptrc_glVertexAttrib1f +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1fv)(GLuint index, const GLfloat * v); +#define glVertexAttrib1fv _ptrc_glVertexAttrib1fv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1s)(GLuint index, GLshort x); +#define glVertexAttrib1s _ptrc_glVertexAttrib1s +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib1sv)(GLuint index, const GLshort * v); +#define glVertexAttrib1sv _ptrc_glVertexAttrib1sv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2d)(GLuint index, GLdouble x, GLdouble y); +#define glVertexAttrib2d _ptrc_glVertexAttrib2d +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2dv)(GLuint index, const GLdouble * v); +#define glVertexAttrib2dv _ptrc_glVertexAttrib2dv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2f)(GLuint index, GLfloat x, GLfloat y); +#define glVertexAttrib2f _ptrc_glVertexAttrib2f +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2fv)(GLuint index, const GLfloat * v); +#define glVertexAttrib2fv _ptrc_glVertexAttrib2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2s)(GLuint index, GLshort x, GLshort y); +#define glVertexAttrib2s _ptrc_glVertexAttrib2s +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib2sv)(GLuint index, const GLshort * v); +#define glVertexAttrib2sv _ptrc_glVertexAttrib2sv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3d)(GLuint index, GLdouble x, GLdouble y, GLdouble z); +#define glVertexAttrib3d _ptrc_glVertexAttrib3d +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3dv)(GLuint index, const GLdouble * v); +#define glVertexAttrib3dv _ptrc_glVertexAttrib3dv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3f)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +#define glVertexAttrib3f _ptrc_glVertexAttrib3f +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3fv)(GLuint index, const GLfloat * v); +#define glVertexAttrib3fv _ptrc_glVertexAttrib3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3s)(GLuint index, GLshort x, GLshort y, GLshort z); +#define glVertexAttrib3s _ptrc_glVertexAttrib3s +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib3sv)(GLuint index, const GLshort * v); +#define glVertexAttrib3sv _ptrc_glVertexAttrib3sv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nbv)(GLuint index, const GLbyte * v); +#define glVertexAttrib4Nbv _ptrc_glVertexAttrib4Nbv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Niv)(GLuint index, const GLint * v); +#define glVertexAttrib4Niv _ptrc_glVertexAttrib4Niv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nsv)(GLuint index, const GLshort * v); +#define glVertexAttrib4Nsv _ptrc_glVertexAttrib4Nsv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nub)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +#define glVertexAttrib4Nub _ptrc_glVertexAttrib4Nub +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nubv)(GLuint index, const GLubyte * v); +#define glVertexAttrib4Nubv _ptrc_glVertexAttrib4Nubv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nuiv)(GLuint index, const GLuint * v); +#define glVertexAttrib4Nuiv _ptrc_glVertexAttrib4Nuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4Nusv)(GLuint index, const GLushort * v); +#define glVertexAttrib4Nusv _ptrc_glVertexAttrib4Nusv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4bv)(GLuint index, const GLbyte * v); +#define glVertexAttrib4bv _ptrc_glVertexAttrib4bv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4d)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +#define glVertexAttrib4d _ptrc_glVertexAttrib4d +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4dv)(GLuint index, const GLdouble * v); +#define glVertexAttrib4dv _ptrc_glVertexAttrib4dv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4f)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +#define glVertexAttrib4f _ptrc_glVertexAttrib4f +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4fv)(GLuint index, const GLfloat * v); +#define glVertexAttrib4fv _ptrc_glVertexAttrib4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4iv)(GLuint index, const GLint * v); +#define glVertexAttrib4iv _ptrc_glVertexAttrib4iv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4s)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +#define glVertexAttrib4s _ptrc_glVertexAttrib4s +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4sv)(GLuint index, const GLshort * v); +#define glVertexAttrib4sv _ptrc_glVertexAttrib4sv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4ubv)(GLuint index, const GLubyte * v); +#define glVertexAttrib4ubv _ptrc_glVertexAttrib4ubv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4uiv)(GLuint index, const GLuint * v); +#define glVertexAttrib4uiv _ptrc_glVertexAttrib4uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttrib4usv)(GLuint index, const GLushort * v); +#define glVertexAttrib4usv _ptrc_glVertexAttrib4usv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer); +#define glVertexAttribPointer _ptrc_glVertexAttribPointer + +extern void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix2x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glUniformMatrix2x3fv _ptrc_glUniformMatrix2x3fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix2x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glUniformMatrix2x4fv _ptrc_glUniformMatrix2x4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix3x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glUniformMatrix3x2fv _ptrc_glUniformMatrix3x2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix3x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glUniformMatrix3x4fv _ptrc_glUniformMatrix3x4fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix4x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glUniformMatrix4x2fv _ptrc_glUniformMatrix4x2fv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniformMatrix4x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +#define glUniformMatrix4x3fv _ptrc_glUniformMatrix4x3fv + +extern void (CODEGEN_FUNCPTR *_ptrc_glBeginConditionalRender)(GLuint id, GLenum mode); +#define glBeginConditionalRender _ptrc_glBeginConditionalRender +extern void (CODEGEN_FUNCPTR *_ptrc_glBeginTransformFeedback)(GLenum primitiveMode); +#define glBeginTransformFeedback _ptrc_glBeginTransformFeedback +extern void (CODEGEN_FUNCPTR *_ptrc_glBindBufferBase)(GLenum target, GLuint index, GLuint buffer); +#define glBindBufferBase _ptrc_glBindBufferBase +extern void (CODEGEN_FUNCPTR *_ptrc_glBindBufferRange)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +#define glBindBufferRange _ptrc_glBindBufferRange +extern void (CODEGEN_FUNCPTR *_ptrc_glBindFragDataLocation)(GLuint program, GLuint color, const GLchar * name); +#define glBindFragDataLocation _ptrc_glBindFragDataLocation +extern void (CODEGEN_FUNCPTR *_ptrc_glBindFramebuffer)(GLenum target, GLuint framebuffer); +#define glBindFramebuffer _ptrc_glBindFramebuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glBindRenderbuffer)(GLenum target, GLuint renderbuffer); +#define glBindRenderbuffer _ptrc_glBindRenderbuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glBindVertexArray)(GLuint ren_array); +#define glBindVertexArray _ptrc_glBindVertexArray +extern void (CODEGEN_FUNCPTR *_ptrc_glBlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#define glBlitFramebuffer _ptrc_glBlitFramebuffer +extern GLenum (CODEGEN_FUNCPTR *_ptrc_glCheckFramebufferStatus)(GLenum target); +#define glCheckFramebufferStatus _ptrc_glCheckFramebufferStatus +extern void (CODEGEN_FUNCPTR *_ptrc_glClampColor)(GLenum target, GLenum clamp); +#define glClampColor _ptrc_glClampColor +extern void (CODEGEN_FUNCPTR *_ptrc_glClearBufferfi)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +#define glClearBufferfi _ptrc_glClearBufferfi +extern void (CODEGEN_FUNCPTR *_ptrc_glClearBufferfv)(GLenum buffer, GLint drawbuffer, const GLfloat * value); +#define glClearBufferfv _ptrc_glClearBufferfv +extern void (CODEGEN_FUNCPTR *_ptrc_glClearBufferiv)(GLenum buffer, GLint drawbuffer, const GLint * value); +#define glClearBufferiv _ptrc_glClearBufferiv +extern void (CODEGEN_FUNCPTR *_ptrc_glClearBufferuiv)(GLenum buffer, GLint drawbuffer, const GLuint * value); +#define glClearBufferuiv _ptrc_glClearBufferuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glColorMaski)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +#define glColorMaski _ptrc_glColorMaski +extern void (CODEGEN_FUNCPTR *_ptrc_glDeleteFramebuffers)(GLsizei n, const GLuint * framebuffers); +#define glDeleteFramebuffers _ptrc_glDeleteFramebuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glDeleteRenderbuffers)(GLsizei n, const GLuint * renderbuffers); +#define glDeleteRenderbuffers _ptrc_glDeleteRenderbuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glDeleteVertexArrays)(GLsizei n, const GLuint * arrays); +#define glDeleteVertexArrays _ptrc_glDeleteVertexArrays +extern void (CODEGEN_FUNCPTR *_ptrc_glDisablei)(GLenum target, GLuint index); +#define glDisablei _ptrc_glDisablei +extern void (CODEGEN_FUNCPTR *_ptrc_glEnablei)(GLenum target, GLuint index); +#define glEnablei _ptrc_glEnablei +extern void (CODEGEN_FUNCPTR *_ptrc_glEndConditionalRender)(void); +#define glEndConditionalRender _ptrc_glEndConditionalRender +extern void (CODEGEN_FUNCPTR *_ptrc_glEndTransformFeedback)(void); +#define glEndTransformFeedback _ptrc_glEndTransformFeedback +extern void (CODEGEN_FUNCPTR *_ptrc_glFlushMappedBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length); +#define glFlushMappedBufferRange _ptrc_glFlushMappedBufferRange +extern void (CODEGEN_FUNCPTR *_ptrc_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +#define glFramebufferRenderbuffer _ptrc_glFramebufferRenderbuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glFramebufferTexture1D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +#define glFramebufferTexture1D _ptrc_glFramebufferTexture1D +extern void (CODEGEN_FUNCPTR *_ptrc_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +#define glFramebufferTexture2D _ptrc_glFramebufferTexture2D +extern void (CODEGEN_FUNCPTR *_ptrc_glFramebufferTexture3D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +#define glFramebufferTexture3D _ptrc_glFramebufferTexture3D +extern void (CODEGEN_FUNCPTR *_ptrc_glFramebufferTextureLayer)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +#define glFramebufferTextureLayer _ptrc_glFramebufferTextureLayer +extern void (CODEGEN_FUNCPTR *_ptrc_glGenFramebuffers)(GLsizei n, GLuint * framebuffers); +#define glGenFramebuffers _ptrc_glGenFramebuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glGenRenderbuffers)(GLsizei n, GLuint * renderbuffers); +#define glGenRenderbuffers _ptrc_glGenRenderbuffers +extern void (CODEGEN_FUNCPTR *_ptrc_glGenVertexArrays)(GLsizei n, GLuint * arrays); +#define glGenVertexArrays _ptrc_glGenVertexArrays +extern void (CODEGEN_FUNCPTR *_ptrc_glGenerateMipmap)(GLenum target); +#define glGenerateMipmap _ptrc_glGenerateMipmap +extern void (CODEGEN_FUNCPTR *_ptrc_glGetBooleani_v)(GLenum target, GLuint index, GLboolean * data); +#define glGetBooleani_v _ptrc_glGetBooleani_v +extern GLint (CODEGEN_FUNCPTR *_ptrc_glGetFragDataLocation)(GLuint program, const GLchar * name); +#define glGetFragDataLocation _ptrc_glGetFragDataLocation +extern void (CODEGEN_FUNCPTR *_ptrc_glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint * params); +#define glGetFramebufferAttachmentParameteriv _ptrc_glGetFramebufferAttachmentParameteriv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetIntegeri_v)(GLenum target, GLuint index, GLint * data); +#define glGetIntegeri_v _ptrc_glGetIntegeri_v +extern void (CODEGEN_FUNCPTR *_ptrc_glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint * params); +#define glGetRenderbufferParameteriv _ptrc_glGetRenderbufferParameteriv +extern const GLubyte * (CODEGEN_FUNCPTR *_ptrc_glGetStringi)(GLenum name, GLuint index); +#define glGetStringi _ptrc_glGetStringi +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexParameterIiv)(GLenum target, GLenum pname, GLint * params); +#define glGetTexParameterIiv _ptrc_glGetTexParameterIiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTexParameterIuiv)(GLenum target, GLenum pname, GLuint * params); +#define glGetTexParameterIuiv _ptrc_glGetTexParameterIuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetTransformFeedbackVarying)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name); +#define glGetTransformFeedbackVarying _ptrc_glGetTransformFeedbackVarying +extern void (CODEGEN_FUNCPTR *_ptrc_glGetUniformuiv)(GLuint program, GLint location, GLuint * params); +#define glGetUniformuiv _ptrc_glGetUniformuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribIiv)(GLuint index, GLenum pname, GLint * params); +#define glGetVertexAttribIiv _ptrc_glGetVertexAttribIiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetVertexAttribIuiv)(GLuint index, GLenum pname, GLuint * params); +#define glGetVertexAttribIuiv _ptrc_glGetVertexAttribIuiv +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsEnabledi)(GLenum target, GLuint index); +#define glIsEnabledi _ptrc_glIsEnabledi +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsFramebuffer)(GLuint framebuffer); +#define glIsFramebuffer _ptrc_glIsFramebuffer +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsRenderbuffer)(GLuint renderbuffer); +#define glIsRenderbuffer _ptrc_glIsRenderbuffer +extern GLboolean (CODEGEN_FUNCPTR *_ptrc_glIsVertexArray)(GLuint ren_array); +#define glIsVertexArray _ptrc_glIsVertexArray +extern void * (CODEGEN_FUNCPTR *_ptrc_glMapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +#define glMapBufferRange _ptrc_glMapBufferRange +extern void (CODEGEN_FUNCPTR *_ptrc_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +#define glRenderbufferStorage _ptrc_glRenderbufferStorage +extern void (CODEGEN_FUNCPTR *_ptrc_glRenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#define glRenderbufferStorageMultisample _ptrc_glRenderbufferStorageMultisample +extern void (CODEGEN_FUNCPTR *_ptrc_glTexParameterIiv)(GLenum target, GLenum pname, const GLint * params); +#define glTexParameterIiv _ptrc_glTexParameterIiv +extern void (CODEGEN_FUNCPTR *_ptrc_glTexParameterIuiv)(GLenum target, GLenum pname, const GLuint * params); +#define glTexParameterIuiv _ptrc_glTexParameterIuiv +extern void (CODEGEN_FUNCPTR *_ptrc_glTransformFeedbackVaryings)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode); +#define glTransformFeedbackVaryings _ptrc_glTransformFeedbackVaryings +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform1ui)(GLint location, GLuint v0); +#define glUniform1ui _ptrc_glUniform1ui +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform1uiv)(GLint location, GLsizei count, const GLuint * value); +#define glUniform1uiv _ptrc_glUniform1uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform2ui)(GLint location, GLuint v0, GLuint v1); +#define glUniform2ui _ptrc_glUniform2ui +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform2uiv)(GLint location, GLsizei count, const GLuint * value); +#define glUniform2uiv _ptrc_glUniform2uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform3ui)(GLint location, GLuint v0, GLuint v1, GLuint v2); +#define glUniform3ui _ptrc_glUniform3ui +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform3uiv)(GLint location, GLsizei count, const GLuint * value); +#define glUniform3uiv _ptrc_glUniform3uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform4ui)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +#define glUniform4ui _ptrc_glUniform4ui +extern void (CODEGEN_FUNCPTR *_ptrc_glUniform4uiv)(GLint location, GLsizei count, const GLuint * value); +#define glUniform4uiv _ptrc_glUniform4uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI1i)(GLuint index, GLint x); +#define glVertexAttribI1i _ptrc_glVertexAttribI1i +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI1iv)(GLuint index, const GLint * v); +#define glVertexAttribI1iv _ptrc_glVertexAttribI1iv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI1ui)(GLuint index, GLuint x); +#define glVertexAttribI1ui _ptrc_glVertexAttribI1ui +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI1uiv)(GLuint index, const GLuint * v); +#define glVertexAttribI1uiv _ptrc_glVertexAttribI1uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI2i)(GLuint index, GLint x, GLint y); +#define glVertexAttribI2i _ptrc_glVertexAttribI2i +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI2iv)(GLuint index, const GLint * v); +#define glVertexAttribI2iv _ptrc_glVertexAttribI2iv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI2ui)(GLuint index, GLuint x, GLuint y); +#define glVertexAttribI2ui _ptrc_glVertexAttribI2ui +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI2uiv)(GLuint index, const GLuint * v); +#define glVertexAttribI2uiv _ptrc_glVertexAttribI2uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI3i)(GLuint index, GLint x, GLint y, GLint z); +#define glVertexAttribI3i _ptrc_glVertexAttribI3i +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI3iv)(GLuint index, const GLint * v); +#define glVertexAttribI3iv _ptrc_glVertexAttribI3iv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI3ui)(GLuint index, GLuint x, GLuint y, GLuint z); +#define glVertexAttribI3ui _ptrc_glVertexAttribI3ui +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI3uiv)(GLuint index, const GLuint * v); +#define glVertexAttribI3uiv _ptrc_glVertexAttribI3uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4bv)(GLuint index, const GLbyte * v); +#define glVertexAttribI4bv _ptrc_glVertexAttribI4bv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4i)(GLuint index, GLint x, GLint y, GLint z, GLint w); +#define glVertexAttribI4i _ptrc_glVertexAttribI4i +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4iv)(GLuint index, const GLint * v); +#define glVertexAttribI4iv _ptrc_glVertexAttribI4iv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4sv)(GLuint index, const GLshort * v); +#define glVertexAttribI4sv _ptrc_glVertexAttribI4sv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4ubv)(GLuint index, const GLubyte * v); +#define glVertexAttribI4ubv _ptrc_glVertexAttribI4ubv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4ui)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +#define glVertexAttribI4ui _ptrc_glVertexAttribI4ui +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4uiv)(GLuint index, const GLuint * v); +#define glVertexAttribI4uiv _ptrc_glVertexAttribI4uiv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribI4usv)(GLuint index, const GLushort * v); +#define glVertexAttribI4usv _ptrc_glVertexAttribI4usv +extern void (CODEGEN_FUNCPTR *_ptrc_glVertexAttribIPointer)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer); +#define glVertexAttribIPointer _ptrc_glVertexAttribIPointer + +extern void (CODEGEN_FUNCPTR *_ptrc_glCopyBufferSubData)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +#define glCopyBufferSubData _ptrc_glCopyBufferSubData +extern void (CODEGEN_FUNCPTR *_ptrc_glDrawArraysInstanced)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +#define glDrawArraysInstanced _ptrc_glDrawArraysInstanced +extern void (CODEGEN_FUNCPTR *_ptrc_glDrawElementsInstanced)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount); +#define glDrawElementsInstanced _ptrc_glDrawElementsInstanced +extern void (CODEGEN_FUNCPTR *_ptrc_glGetActiveUniformBlockName)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName); +#define glGetActiveUniformBlockName _ptrc_glGetActiveUniformBlockName +extern void (CODEGEN_FUNCPTR *_ptrc_glGetActiveUniformBlockiv)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params); +#define glGetActiveUniformBlockiv _ptrc_glGetActiveUniformBlockiv +extern void (CODEGEN_FUNCPTR *_ptrc_glGetActiveUniformName)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName); +#define glGetActiveUniformName _ptrc_glGetActiveUniformName +extern void (CODEGEN_FUNCPTR *_ptrc_glGetActiveUniformsiv)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params); +#define glGetActiveUniformsiv _ptrc_glGetActiveUniformsiv +extern GLuint (CODEGEN_FUNCPTR *_ptrc_glGetUniformBlockIndex)(GLuint program, const GLchar * uniformBlockName); +#define glGetUniformBlockIndex _ptrc_glGetUniformBlockIndex +extern void (CODEGEN_FUNCPTR *_ptrc_glGetUniformIndices)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices); +#define glGetUniformIndices _ptrc_glGetUniformIndices +extern void (CODEGEN_FUNCPTR *_ptrc_glPrimitiveRestartIndex)(GLuint index); +#define glPrimitiveRestartIndex _ptrc_glPrimitiveRestartIndex +extern void (CODEGEN_FUNCPTR *_ptrc_glTexBuffer)(GLenum target, GLenum internalformat, GLuint buffer); +#define glTexBuffer _ptrc_glTexBuffer +extern void (CODEGEN_FUNCPTR *_ptrc_glUniformBlockBinding)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +#define glUniformBlockBinding _ptrc_glUniformBlockBinding + +enum ogl_LoadStatus +{ + ogl_LOAD_FAILED = 0, + ogl_LOAD_SUCCEEDED = 1, +}; + +int ogl_LoadFunctions(); + +int ogl_GetMinorVersion(void); +int ogl_GetMajorVersion(void); +int ogl_IsVersionGEQ(int majorVersion, int minorVersion); + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*POINTER_C_GENERATED_HEADER_OPENGL_H*/ diff --git a/third_party/stb/stb_image.h b/third_party/stb/stb_image.h new file mode 100644 index 0000000..d60371b --- /dev/null +++ b/third_party/stb/stb_image.h @@ -0,0 +1,7897 @@ +/* stb_image - v2.27 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes + 2.26 (2020-07-13) many minor fixes + 2.25 (2020-02-02) fix warnings + 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically + 2.23 (2019-08-11) fix clang static analysis warning + 2.22 (2019-03-04) gif fixes, fix warnings + 2.21 (2019-02-25) fix typo in comment + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine Simon Breuss (16-bit PNM) + John-Mark Allen + Carmelo J Fdez-Aguera + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski + Phil Jordan Dave Moore Roy Eltham + Hayaki Saito Nathan Reed Won Chun + Luke Graham Johan Duparc Nick Verigakis the Horde3D community + Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Eugene Golushkov Laurent Gomila Cort Stratton github:snagar + Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex + Cass Everitt Ryamond Barbiero github:grim210 + Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw + Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus + Josh Tobin Matthew Gregan github:poppolopoppo + Julian Raschke Gregory Mullen Christian Floisand github:darealshinji + Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 + Brad Weinberger Matvey Cherevko github:mosra + Luca Sas Alexander Veselov Zack Middleton [reserved] + Ryan C. Gordon [reserved] [reserved] + DO NOT ADD YOUR NAME HERE + + Jacko Dirks + + To add your name to the credits, pick a random blank space in the middle and fill it. + 80% of merge conflicts on stb PRs are due to people adding their name at the end + of the credits. +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// To query the width, height and component count of an image without having to +// decode the full file, you can use the stbi_info family of functions: +// +// int x,y,n,ok; +// ok = stbi_info(filename, &x, &y, &n); +// // returns ok=1 and sets x, y, n if image is a supported format, +// // 0 otherwise. +// +// Note that stb_image pervasively uses ints in its public API for sizes, +// including sizes of memory buffers. This is now part of the API and thus +// hard to change without causing breakage. As a result, the various image +// loaders all have certain limits on image size; these differ somewhat +// by format but generally boil down to either just under 2GB or just under +// 1GB. When the decoded image would be larger than this, stb_image decoding +// will fail. +// +// Additionally, stb_image will reject image files that have any of their +// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, +// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, +// the only way to have an image with such dimensions load correctly +// is for it to have a rather extreme aspect ratio. Either way, the +// assumption here is that such larger images are likely to be malformed +// or malicious. If you do need to load an image with individual dimensions +// larger than that, and it still fits in the overall size limit, you can +// #define STBI_MAX_DIMENSIONS on your own to be something larger. +// +// =========================================================================== +// +// UNICODE: +// +// If compiling for Windows and you wish to use Unicode filenames, compile +// with +// #define STBI_WINDOWS_UTF8 +// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert +// Windows wchar_t filenames to utf8. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy-to-use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// provide more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image supports loading HDR images in general, and currently the Radiance +// .HDR file format specifically. You can still load any file through the existing +// interface; if you attempt to load an HDR file, it will be automatically remapped +// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// We optionally support converting iPhone-formatted PNGs (which store +// premultiplied BGRA) back to RGB, even though they're internally encoded +// differently. To enable this conversion, call +// stbi_convert_iphone_png_to_rgb(1). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// +// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater +// than that size (in either width or height) without further processing. +// This is to let programs in the wild set an upper bound to prevent +// denial-of-service attacks on untrusted data, as one could generate a +// valid image of gigantic dimensions and force stb_image to allocate a +// huge block of memory and spend disproportionate time decoding it. By +// default this is set to (1 << 24), which is 16777216, but that's still +// very big. + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + +#ifdef STBI_WINDOWS_UTF8 +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// on most compilers (and ALL modern mainstream compilers) this is threadsafe +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// as above, but only applies to images loaded on the thread that calls the function +// this function is only available if your compiler supports thread-local variables; +// calling it will fail to link if your compiler doesn't +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + +#ifdef __cplusplus +#define STBI_EXTERN extern "C" +#else +#define STBI_EXTERN extern +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + +#ifndef STBI_NO_THREAD_LOCALS + #if defined(__cplusplus) && __cplusplus >= 201103L + #define STBI_THREAD_LOCAL thread_local + #elif defined(__GNUC__) && __GNUC__ < 5 + #define STBI_THREAD_LOCAL __thread + #elif defined(_MSC_VER) + #define STBI_THREAD_LOCAL __declspec(thread) + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) + #define STBI_THREAD_LOCAL _Thread_local + #endif + + #ifndef STBI_THREAD_LOCAL + #if defined(__GNUC__) + #define STBI_THREAD_LOCAL __thread + #endif + #endif +#endif + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#endif + +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +#ifdef _MSC_VER +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name +#else +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +#ifndef STBI_MAX_DIMENSIONS +#define STBI_MAX_DIMENSIONS (1 << 24) +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + int callback_already_read; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + int ch; + fseek((FILE*) user, n, SEEK_CUR); + ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ + if (ch != EOF) { + ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ + } +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user) || ferror((FILE *) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__pnm_is16(stbi__context *s); +#endif + +static +#ifdef STBI_THREAD_LOCAL +STBI_THREAD_LOCAL +#endif +const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +#ifndef STBI_NO_FAILURE_STRINGS +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} +#endif + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} +#endif + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} +#endif + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load_global = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_global = flag_true_if_should_flip; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global +#else +static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; + +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_local = flag_true_if_should_flip; + stbi__vertically_flip_on_load_set = 1; +} + +#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \ + ? stbi__vertically_flip_on_load_local \ + : stbi__vertically_flip_on_load_global) +#endif // STBI_THREAD_LOCAL + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + // test the formats with a very explicit header first (at least a FOURCC + // or distinctive magic number first) + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #else + STBI_NOTUSED(bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + + // then the formats that can end up attempting to load with just 1 or 2 + // bytes matching expectations; these are prone to false positives, so + // try them later + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} +#endif + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 8) { + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 16) { + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); +#endif + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + return 0; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) +// nothing +#else +static void stbi__skip(stbi__context *s, int n) +{ + if (n == 0) return; // already there! + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) +// nothing +#else +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} +#endif + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + z += (stbi__uint32)stbi__get16le(s) << 16; + return z; +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + } + if (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + + sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & (sgn - 1)); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * (1 << j->succ_low)); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * (1 << shift)); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios + // and I've never seen a non-corrupted JPEG file actually use them + for (i=0; i < s->img_n; ++i) { + if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); + if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // nothing to do if no components requested; check this now to avoid + // accessing uninitialized coutput[0] later + if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__errpuc("outofmem", "Out of memory"); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__err("outofmem", "Out of memory"); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + if (!j) return stbi__err("outofmem", "Out of memory"); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) +#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[STBI__ZNSYMS]; + stbi__uint16 value[STBI__ZNSYMS]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static int stbi__zeof(stbi__zbuf *z) +{ + return (z->zbuffer >= z->zbuffer_end); +} + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + return stbi__zeof(z) ? 0 : *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + if (z->code_buffer >= (1U << z->num_bits)) { + z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ + return; + } + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s >= 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! + if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) { + if (stbi__zeof(a)) { + return -1; /* report error for unexpected end of data. */ + } + stbi__fill_bits(a); + } + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + unsigned int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (unsigned int) (z->zout - z->zout_start); + limit = old_limit = (unsigned) (z->zout_end - z->zout_start); + if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); + while (cur + n > limit) { + if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); + limit *= 2; + } + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + } else if (c == 18) { + c = stbi__zreceive(a,7)+11; + } else { + return stbi__err("bad codelengths", "Corrupt PNG"); + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior; + int filter = *raw++; + + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG"); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; // first pixel top byte + cur[filter_bytes+1] = 255; // first pixel bottom byte + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*filter_bytes; + #define STBI__CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; + } + #undef STBI__CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define STBI__CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) + switch (filter) { + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; + } + #undef STBI__CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + if (!final) return stbi__err("outofmem", "Out of memory"); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load_global = 0; +static int stbi__de_iphone_flag_global = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_global = flag_true_if_should_convert; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global +#define stbi__de_iphone_flag stbi__de_iphone_flag_global +#else +static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; +static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; + +STBIDEF void stbi__unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; + stbi__unpremultiply_on_load_set = 1; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_local = flag_true_if_should_convert; + stbi__de_iphone_flag_set = 1; +} + +#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ + ? stbi__unpremultiply_on_load_local \ + : stbi__unpremultiply_on_load_global) +#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ + ? stbi__de_iphone_flag_local \ + : stbi__de_iphone_flag_global) +#endif // STBI_THREAD_LOCAL + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); + s->img_y = stbi__get32be(s); + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth <= 8) + ri->bits_per_channel = 8; + else if (p->depth == 16) + ri->bits_per_channel = 16; + else + return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) { n += 16; z >>= 16; } + if (z >= 0x00100) { n += 8; z >>= 8; } + if (z >= 0x00010) { n += 4; z >>= 4; } + if (z >= 0x00004) { n += 2; z >>= 2; } + if (z >= 0x00002) { n += 1;/* >>= 1;*/ } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; + int extra_read; +} stbi__bmp_data; + +static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) +{ + // BI_BITFIELDS specifies masks explicitly, don't override + if (compress == 3) + return 1; + + if (compress == 0) { + if (info->bpp == 16) { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } else if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + // otherwise, use defaults, which is all-0 + info->mr = info->mg = info->mb = info->ma = 0; + } + return 1; + } + return 0; // error +} + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + info->extra_read = 14; + + if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes + if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + stbi__bmp_set_mask_defaults(info, compress); + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->extra_read += 12; + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + // V4/V5 header + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs + stbi__bmp_set_mask_defaults(info, compress); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - info.extra_read - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - info.extra_read - info.hsz) >> 2; + } + if (psize == 0) { + if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) { + return stbi__errpuc("bad offset", "Corrupt BMP"); + } + } + + if (info.bpp == 24 && ma == 0xff000000) + s->img_n = 3; + else + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - info.extra_read - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i]; p1[i] = p2[i]; p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + STBI_NOTUSED(tga_x_origin); // @TODO + STBI_NOTUSED(tga_y_origin); // @TODO + + if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + if (tga_palette_len == 0) { /* you have to have at least one entry! */ + STBI_FREE(tga_data); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + STBI_NOTUSED(tga_palette_start); + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + + if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + if (!result) return stbi__errpuc("outofmem", "Out of memory"); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!g) return stbi__err("outofmem", "Out of memory"); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) + return stbi__errpuc("too large", "GIF image is too large"); + pcount = g->w * g->h; + g->out = (stbi_uc *) stbi__malloc(4 * pcount); + g->background = (stbi_uc *) stbi__malloc(4 * pcount); + g->history = (stbi_uc *) stbi__malloc(pcount); + if (!g->out || !g->background || !g->history) + return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to the color that was there the previous frame. + memset(g->out, 0x00, 4 * pcount); + memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) + memset(g->history, 0x00, pcount); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispose of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + // if the width of the specified rectangle is 0, that means + // we may not see *any* pixels or the image is malformed; + // to make sure this is caught, move the current y down to + // max_y (which is what out_gif_code checks). + if (w == 0) + g->cur_y = g->max_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) +{ + STBI_FREE(g->out); + STBI_FREE(g->history); + STBI_FREE(g->background); + + if (out) STBI_FREE(out); + if (delays && *delays) STBI_FREE(*delays); + return stbi__errpuc("outofmem", "Out of memory"); +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + int out_size = 0; + int delays_size = 0; + + STBI_NOTUSED(out_size); + STBI_NOTUSED(delays_size); + + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); + if (!tmp) + return stbi__load_gif_main_outofmem(&g, out, delays); + else { + out = (stbi_uc*) tmp; + out_size = layers * stride; + } + + if (delays) { + int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); + if (!new_delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + *delays = new_delays; + delays_size = layers * sizeof(int); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (!out) + return stbi__load_gif_main_outofmem(&g, out, delays); + out_size = layers * stride; + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + if (!*delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + delays_size = layers * sizeof(int); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } else if (g.out) { + // if there was an error and we allocated an image buffer, free it! + STBI_FREE(g.out); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + if (p == NULL) { + stbi__rewind( s ); + return 0; + } + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) { + if (info.bpp == 24 && info.ma == 0xff000000) + *comp = 3; + else + *comp = info.ma ? 4 : 3; + } + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + STBI_NOTUSED(stbi__get32be(s)); + STBI_NOTUSED(stbi__get32be(s)); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); + if (ri->bits_per_channel == 0) + return 0; + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8)); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + if (maxv > 65535) + return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); + else if (maxv > 255) + return 16; + else + return 8; +} + +static int stbi__pnm_is16(stbi__context *s) +{ + if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) + return 1; + return 0; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_is16(s)) return 1; + #endif + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/