mirror of https://github.com/snesrev/smw.git
10302 lines
258 KiB
C
10302 lines
258 KiB
C
#include "smb1_consts.h"
|
|
#include "smb1_funcs.h"
|
|
#include "smb1_rtl.h"
|
|
#include "smb1_variables.h"
|
|
|
|
void (*funcs_11F7[4])(void) = {
|
|
&TitleScreen_0_InitializeGame,
|
|
&ScreenRoutines,
|
|
&TitleScreen_2_PrimaryGameSetup,
|
|
&TitleScreen_3_GameMenuRoutine,
|
|
}; // weak
|
|
void (*funcs_4FCB[47])(uint8 k) = {
|
|
&ExtObj07_VerticalPipe,
|
|
&ExtObj01_GrassyOrMushroomPlatform,
|
|
&ExtObj02_RowOfBricks,
|
|
&ExtObj03_RowOfSolidBlocks,
|
|
&ExtObj04_RowOfCoins,
|
|
&ExtObj05_ColumnOfBricks,
|
|
&ExtObj06_ColumnOfSolidBlocks,
|
|
&ExtObj07_VerticalPipe,
|
|
&ExtObj08_Hole,
|
|
&ExtObj09_PulleyRope,
|
|
&ExtObj0A_Bridge_High,
|
|
&ExtObj0B_Bridge_Middle,
|
|
&ExtObj0B_Bridge_Low,
|
|
&ExtObj0D_HoleWater,
|
|
&ExtObj0E_QuestionBlockHigh,
|
|
&ExtObj0E_QuestionBlockLow,
|
|
&nullsub_A85C,
|
|
&nullsub_A85C,
|
|
&nullsub_A85C,
|
|
&nullsub_A85C,
|
|
&nullsub_A85C,
|
|
&nullsub_A85C,
|
|
&ExtObj18_QuestionBlock,
|
|
&ExtObj18_QuestionBlock,
|
|
&ExtObj18_QuestionBlock,
|
|
&ExtObj19_Hidden1upBlock,
|
|
&BrickWithItem,
|
|
&BrickWithItem,
|
|
&BrickWithItem,
|
|
&ExtObj1D_BrickWith10Coins,
|
|
&BrickWithItem,
|
|
&ExtObj1F_WaterPipe,
|
|
&ExtObj20_EmptyBlock,
|
|
&ExtObj21_Jumpspring,
|
|
&ExtObj22_IntroPipe,
|
|
&ExtObj23_FlagpoleObject,
|
|
&ExtObj24_AxeObj,
|
|
&ExtObj25_ChainObj,
|
|
&ExtObj26_CastleBridge,
|
|
&ExtObj27_ScrollLockObject_Warp,
|
|
&ExtObj28_ScrollLockObject,
|
|
&ExtObj28_ScrollLockObject,
|
|
&ExtObj2C_AreaFrenzy,
|
|
&ExtObj2C_AreaFrenzy,
|
|
&ExtObj2C_AreaFrenzy,
|
|
&ExtObj2D_LoopCmdE,
|
|
&ExtObj2E_AlterAreaAttributes,
|
|
}; // weak
|
|
void (*funcs_A6DE[55])(uint8) = {
|
|
&NormalEnemy_Init, &NormalEnemy_Init, &NormalEnemy_Init, &RedKoopa_Init, &NoEnemyInit,
|
|
&HammerBro_Init, &Goomba_Init, &Blooper_Init, &BulletBill_Init, &NoEnemyInit,
|
|
&CheepCheep_Init, &CheepCheep_Init, &Podoboo_Init, &PiranhaPlant_Init, &JumpGPTroopa_Init,
|
|
&RedPTroopa_Init, &InitHorizFlySwimEnemy, &Lakitu_Init, &InitEnemyFrenzy, &NoEnemyInit,
|
|
&InitEnemyFrenzy, &InitEnemyFrenzy, &InitEnemyFrenzy, &InitEnemyFrenzy, &EndFrenzy,
|
|
&NoEnemyInit, &NoEnemyInit, &ShortFirebar_Init, &ShortFirebar_Init, &ShortFirebar_Init,
|
|
&ShortFirebar_Init, &LongFirebar_Init, &NoEnemyInit, &NoEnemyInit, &NoEnemyInit,
|
|
&NoEnemyInit, &BalPlatform_Init, &VertPlatform_Init, &LargeLiftUp_Init, &LargeLiftDown_Init,
|
|
&InitHoriPlatform_Init, &InitDropPlatform_Init, &InitHoriPlatform_Init, &PlatLiftUp_Init, &PlatLiftDown_Init,
|
|
&Bowser_Init, &Spr02E_Powerup_Init, &Spr02F_Vine_Init2, &NoEnemyInit, &NoEnemyInit,
|
|
&NoEnemyInit, &NoEnemyInit, &NoEnemyInit, &RetainerObj_Init, &EndOfEnemyInitCode,
|
|
}; // weak
|
|
void (*funcs_B851[6])(uint8) = {&LakituAndSpinyHandler, &NoFrenzyCode, &FlyingCheepCheep_Init,
|
|
&BowserFlame_Init, &InitFireworks, &BulletBillCheepCheep}; // weak
|
|
void (*funcs_BC01[34])(uint8) = {
|
|
&RunNormalEnemies, &RunBowserFlame, &RunFireworks, &NoRunCode, &NoRunCode, &NoRunCode, &NoRunCode,
|
|
&RunFirebarObj, &RunFirebarObj, &RunFirebarObj, &RunFirebarObj, &RunFirebarObj, &RunFirebarObj, &RunFirebarObj,
|
|
&RunFirebarObj, &NoRunCode, &RunLargePlatform, &RunLargePlatform, &RunLargePlatform, &RunLargePlatform, &RunLargePlatform,
|
|
&RunLargePlatform, &RunLargePlatform, &RunSmallPlatform, &RunSmallPlatform, &RunBowser, &PowerUpObjHandler, &VineObjectHandler,
|
|
&NoRunCode, &RunStarFlagObj, &JumpspringHandler, &NoRunCode, &WarpZoneObject, &RunRetainerObj}; // weak
|
|
void (*funcs_BDE8[21])(uint8) = {
|
|
&MoveNormalEnemy, &MoveNormalEnemy, &MoveNormalEnemy, &MoveNormalEnemy, &MoveNormalEnemy, &ProcHammerBro,
|
|
&MoveNormalEnemy, &MoveBloober, &MoveBulletBill, &NoMoveCode, &MoveSwimmingCheepCheep, &MoveSwimmingCheepCheep,
|
|
&MovePodoboo, &MovePiranhaPlant, &MoveJumpingEnemy, &ProcMoveRedPTroopa, &MoveFlyGreenPTroopa, &MoveLakitu,
|
|
&MoveNormalEnemy, &NoMoveCode, &MoveFlyingCheepCheep,
|
|
}; // weak
|
|
void (*funcs_BFB5[7])(uint8) = {&BalancePlatform, &YMovingPlatform, &MoveLargeLiftPlat, &MoveLargeLiftPlat,
|
|
&XMovingPlatform, &DropPlatform, &RightPlatform}; // weak
|
|
|
|
void Smb1VectorReset() {
|
|
WriteReg(NMITIMEN, 0);
|
|
WriteReg(MDMAEN, 0);
|
|
WriteReg(HDMAEN, 0);
|
|
WriteReg(INIDISP, 0x80u);
|
|
|
|
UploadSPCEngine();
|
|
InitializeRAMOnStartup();
|
|
VerifySaveDataIsValid();
|
|
UploadMainSampleData();
|
|
// LoadSplashScreen();
|
|
UploadSpuData();
|
|
vram_flag_028c = 1;
|
|
var0F0B = 3;
|
|
vram_flag_028e = 0;
|
|
var0E67 = 0;
|
|
WriteReg(OBSEL, 3u);
|
|
WriteReg(BG1SC, 1u);
|
|
WriteReg(BG2SC, 9u);
|
|
WriteReg(BG3SC, 0x59u);
|
|
WriteReg(BG4SC, 0);
|
|
WriteReg(BG12NBA, 0x11u);
|
|
WriteReg(BG34NBA, 5u);
|
|
WriteReg(SETINI, 0);
|
|
UNUSED_byte_7E1681 = 0;
|
|
game_mode = 0;
|
|
game_mode_task = 0;
|
|
g_byte_7FFFFF = 0;
|
|
ResetScrollRegs();
|
|
bgmode_mirror = 9;
|
|
mosaic_mirror = 0;
|
|
tm_mirror = 16;
|
|
ts_mirror = 0;
|
|
w12sel_mirror = 0;
|
|
w34sel_mirror = 0;
|
|
wobjsel_mirror = 0;
|
|
cgwsel_mirror = 0;
|
|
cgadsub_mirror = 32;
|
|
coldata1_mirror = 32;
|
|
coldata2_mirror = 64;
|
|
coldata3_mirror = 0x80;
|
|
hdmaenable_mirror = 0;
|
|
inidisp_mirror = 0x80;
|
|
wait_for_vblank = 0;
|
|
global_frame_advance_debug_active_flag = 0;
|
|
fade_direction = 0;
|
|
display_pause_menu_flag = 0;
|
|
sprite0_hit_detect_flag = 0x80;
|
|
var0E67 = 0;
|
|
obj_yspeed.bubble[0] = 0;
|
|
game_loop_toggler = 0;
|
|
vblank_upload_from_7f0000_flag = 0;
|
|
vblank_flag_0ED4 = 0;
|
|
update_entire_palette_flag = 0;
|
|
vram_buffer_addr_ctrl = 0;
|
|
vram_flag_028d = 0;
|
|
palette_mirror[0] = 0;
|
|
palette_mirror[128] = 0;
|
|
*(uint16 *)&vram_buffer1[1] = -1;
|
|
upload_buffer_3[1] = -1;
|
|
layer3_tilemap_upload_buf[1] = -1;
|
|
WriteReg(VMAIN, 0x80u);
|
|
WriteRegWord(VMADDL, 0x1000u);
|
|
WriteRegWord(DMAP0, 0x1801u);
|
|
WriteRegWord(A1T0L, 0x8000u);
|
|
WriteReg(A1B0, 3u);
|
|
WriteRegWord(DAS0L, 0x4000u);
|
|
WriteReg(MDMAEN, 1u);
|
|
WriteRegWord(VMADDL, 0x6000u);
|
|
WriteRegWord(A1T0L, 0x8000u);
|
|
WriteReg(A1B0, 4u);
|
|
WriteRegWord(DAS0L, 0x4000u);
|
|
WriteReg(MDMAEN, 1u);
|
|
WriteRegWord(VMADDL, 0x5000u);
|
|
WriteRegWord(A1T0L, 0xB000u);
|
|
WriteReg(A1B0, 9u);
|
|
WriteRegWord(DAS0L, 0x800u);
|
|
WriteReg(MDMAEN, 1u);
|
|
Dma_FillWith0x28();
|
|
UNUSED_byte_7E1608 = 0;
|
|
UNUSED_byte_7E1609 = 0;
|
|
apui03_upper_bit = 0;
|
|
UNUSED_byte_7E160E = 0;
|
|
apui00_delay = 0;
|
|
apui03_delay = 0x19;
|
|
apui02_var160C = 1;
|
|
frame_counter = -127;
|
|
WriteReg(NMITIMEN, 0x81u);
|
|
}
|
|
// 7E00BA: using guessed type int8;
|
|
|
|
void Smb1RunOneFrameOfGame_Internal() {
|
|
int8 v0; // r8
|
|
int8 v1; // cf
|
|
int8 v2; // r8
|
|
int8 v3; // r8
|
|
int8 v4; // r8
|
|
int8 v5; // r8
|
|
int8 v6; // r8
|
|
int8 v7; // r8
|
|
uint8 v8; // si
|
|
|
|
Smb1PollJoypadInputs();
|
|
random_lfsr_tmp = random_byte1 & 2;
|
|
v0 = 0;
|
|
if ((random_byte1 & 2) != (random_byte2 & 2))
|
|
v0 = 0x80;
|
|
v1 = random_byte1 & 1;
|
|
random_byte1 = (random_byte1 >> 1) + v0;
|
|
v2 = 0;
|
|
if (v1)
|
|
v2 = 0x80;
|
|
v1 = random_byte2 & 1;
|
|
random_byte2 = (random_byte2 >> 1) + v2;
|
|
v3 = 0;
|
|
if (v1)
|
|
v3 = 0x80;
|
|
v1 = random_byte3 & 1;
|
|
random_byte3 = (random_byte3 >> 1) + v3;
|
|
v4 = 0;
|
|
if (v1)
|
|
v4 = 0x80;
|
|
v1 = random_byte4 & 1;
|
|
random_byte4 = (random_byte4 >> 1) + v4;
|
|
v5 = 0;
|
|
if (v1)
|
|
v5 = 0x80;
|
|
v1 = random_byte5 & 1;
|
|
random_byte5 = (random_byte5 >> 1) + v5;
|
|
v6 = 0;
|
|
if (v1)
|
|
v6 = 0x80;
|
|
v1 = random_byte6 & 1;
|
|
random_byte6 = (random_byte6 >> 1) + v6;
|
|
v7 = 0;
|
|
if (v1)
|
|
v7 = 0x80;
|
|
random_byte7 = (random_byte7 >> 1) + v7;
|
|
HandleSfx();
|
|
if (!debug_flag)
|
|
goto LABEL_27;
|
|
if ((*(&controller_press2p1 + current_player_mirror) & 0x20) != 0)
|
|
++global_frame_advance_debug_active_flag;
|
|
if ((*(&controller_press2p1 + current_player_mirror) & 0x10) != 0 || (global_frame_advance_debug_active_flag & 1) == 0) {
|
|
LABEL_27:
|
|
Smb1HandleLevelTileAnimations();
|
|
HandlePauseMenu();
|
|
DoSomeDigitsStuff();
|
|
if (!area_type)
|
|
HandleLayersScroll();
|
|
if ((int8)game_loop_toggler > 0 && screen_timer &&
|
|
((*(&controller_press2p1 + current_player) & 0x80u) != 0 || (*(&controller_press1p1 + current_player) & 0x90) != 0)) {
|
|
screen_timer = 0;
|
|
game_loop_toggler = 0;
|
|
}
|
|
if (fade_direction) {
|
|
HandleScreenTransition();
|
|
} else {
|
|
if (display_pause_menu_flag & 1)
|
|
goto LABEL_52;
|
|
if (!timer_control || (--timer_control, !timer_control)) {
|
|
v8 = 24;
|
|
if ((--interval_timer_control & 0x80u) != 0) {
|
|
interval_timer_control = 20;
|
|
v8 = 43;
|
|
}
|
|
do {
|
|
if (*(&all_timers + v8))
|
|
--*(&all_timers + v8);
|
|
--v8;
|
|
} while ((v8 & 0x80u) == 0);
|
|
}
|
|
if (!screen_timer)
|
|
game_loop_toggler &= 0x80u;
|
|
++frame_counter;
|
|
if ((++podoboo_animation_frame_counter & 0x18) == 24)
|
|
podoboo_animation_frame_counter = 0;
|
|
CheckIfBowserTouchedLava();
|
|
if (sprite0_hit_detect_flag) {
|
|
if (!(disable_sprite_oamreset_flag & 1))
|
|
ResetMiscSpriteOamId();
|
|
}
|
|
ProcessGameMode();
|
|
if ((cutscene_var1680 & 0x80u) != 0) {
|
|
LABEL_52:
|
|
DrawLevelPreviewSprites_Sub_New();
|
|
MaybePauseMenuHandler();
|
|
}
|
|
}
|
|
}
|
|
CompressOAMTileSizeBuffer();
|
|
wait_for_vblank = 0;
|
|
}
|
|
|
|
void Smb1VectorNMI() {
|
|
uint8 v0; // al
|
|
uint16 v1; // si
|
|
int16 v2; // ax
|
|
uint16 v3; // si
|
|
int16 v4; // ax
|
|
uint8 v5; // di
|
|
uint16 v6; // si
|
|
uint8 v7; // si
|
|
int16 v8; // [rsp+3Fh] [rbp-9h]
|
|
|
|
v8 = *(uint16 *)&R0_;
|
|
ReadReg(RDNMI);
|
|
v0 = inidisp_mirror;
|
|
if (!inidisp_mirror)
|
|
v0 = 0x80;
|
|
WriteReg(INIDISP, v0);
|
|
WriteReg(HDMAEN, 0);
|
|
if (!wait_for_vblank) {
|
|
++wait_for_vblank;
|
|
R0_ = kDATA_0382DE[vram_buffer_addr_ctrl];
|
|
R1_ = kDATA_0382F1[vram_buffer_addr_ctrl];
|
|
R2_ = 0;
|
|
UploadStripeImage();
|
|
if (vram_buffer_addr_ctrl == 6) {
|
|
R0_ = kDATA_0382DE[0];
|
|
R1_ = kDATA_0382F1[0];
|
|
R2_ = 0;
|
|
UploadStripeImage();
|
|
}
|
|
WriteReg(VMAIN, 0x81u);
|
|
WriteRegWord(DMAP0, 0x1801u);
|
|
if (vblank_upload_from_7f0000_flag) {
|
|
WriteReg(A1B0, 0x7Fu);
|
|
v1 = 0;
|
|
v2 = upload_buffer_3[1];
|
|
do {
|
|
WriteRegWord(VMADDL, v2);
|
|
WriteRegWord(A1T0L, v1 + 4);
|
|
WriteRegWord(DAS0L, 0x40u);
|
|
v1 += 66;
|
|
WriteRegWord(MDMAEN, 1u);
|
|
v2 = upload_buffer_3[(v1 >> 1) + 1];
|
|
} while (v2 >= 0);
|
|
vblank_upload_from_7f0000_flag = 0;
|
|
}
|
|
if (vblank_flag_0ED4) {
|
|
WriteReg(A1B0, 0x7Fu);
|
|
v3 = 0;
|
|
v4 = layer3_tilemap_upload_buf[1];
|
|
do {
|
|
WriteRegWord(VMADDL, v4);
|
|
WriteRegWord(A1T0L, v3 + 8196);
|
|
WriteRegWord(DAS0L, 0x38u);
|
|
v3 += 58;
|
|
WriteRegWord(MDMAEN, 1u);
|
|
v4 = layer3_tilemap_upload_buf[(v3 >> 1) + 1];
|
|
} while (v4 >= 0);
|
|
*(uint16 *)&vblank_flag_0ED4 = 0;
|
|
}
|
|
WriteReg(VMAIN, 0x80u);
|
|
VramFunc_9B5C();
|
|
if (update_entire_palette_flag) {
|
|
if ((update_entire_palette_flag & 0x80u) != 0) {
|
|
update_entire_palette_flag = 1;
|
|
} else {
|
|
WriteReg(CGADD, 0);
|
|
WriteRegWord(DMAP0, 0x2200u);
|
|
WriteRegWord(A1T0L, 0x1000u);
|
|
WriteReg(A1B0, 0);
|
|
WriteRegWord(DAS0L, 0x200u);
|
|
WriteReg(MDMAEN, 1u);
|
|
update_entire_palette_flag = 0;
|
|
}
|
|
}
|
|
v5 = 0;
|
|
if (vram_buffer_addr_ctrl == 6)
|
|
v5 = 2;
|
|
v6 = kDATA_038304[v5 >> 1];
|
|
*(uint16 *)(&vram_buffer1_offset + v6) = 0;
|
|
*(uint16 *)&vram_buffer1[v6 + 1] = -1;
|
|
upload_buffer_3[0] = 0;
|
|
if (area_type)
|
|
layer3_tilemap_upload_buf[0] = 0;
|
|
vram_buffer_addr_ctrl = 0;
|
|
}
|
|
WriteReg(WH2, wh2_mirror);
|
|
WriteReg(WH3, wh3_mirror);
|
|
WriteReg(COLDATA, coldata_mirror);
|
|
WriteReg(CGWSEL, cgwsel_mirror);
|
|
WriteReg(CGADSUB, cgadsub_mirror);
|
|
WriteReg(W12SEL, w12sel_mirror);
|
|
WriteReg(W34SEL, w34sel_mirror);
|
|
WriteReg(WOBJSEL, wobjsel_mirror);
|
|
WriteReg(TM, tm_mirror);
|
|
WriteReg(TS, ts_mirror);
|
|
WriteReg(TMW, tmw_mirror);
|
|
WriteReg(TSW, tsw_mirror);
|
|
WriteReg(COLDATA, coldata1_mirror);
|
|
WriteReg(COLDATA, coldata2_mirror);
|
|
WriteReg(COLDATA, coldata3_mirror);
|
|
WriteReg(BGMODE, bgmode_mirror);
|
|
WriteReg(MOSAIC, mosaic_mirror);
|
|
WriteReg(BG3HOFS, 0);
|
|
WriteReg(BG3HOFS, 0);
|
|
if (vblank_which_layer2_scroll_flag) {
|
|
WriteReg(BG2HOFS, layer3_xpos);
|
|
WriteReg(BG2HOFS, HIBYTE(layer3_xpos));
|
|
}
|
|
if (!fade_direction) {
|
|
WriteReg(BG1HOFS, layer1_xpos_lo);
|
|
WriteReg(BG1HOFS, screen_left_xpos_hi);
|
|
if (!vblank_which_layer2_scroll_flag) {
|
|
WriteReg(BG2HOFS, layer2_xpos);
|
|
WriteReg(BG2HOFS, HIBYTE(layer2_xpos));
|
|
}
|
|
WriteReg(BG1VOFS, layer1_ypos_lo);
|
|
WriteReg(BG1VOFS, 0);
|
|
WriteReg(BG2VOFS, layer2_ypos);
|
|
WriteReg(BG2VOFS, HIBYTE(layer2_ypos));
|
|
}
|
|
WriteReg(HDMAEN, hdmaenable_mirror);
|
|
v7 = -127;
|
|
if (vblank_enable_vtimel_flag) {
|
|
ReadReg(TIMEUP);
|
|
WriteReg(VTIMEL, vtimel_mirror);
|
|
WriteReg(VTIMEH, 0);
|
|
WriteReg(HTIMEL, 0);
|
|
WriteReg(HTIMEH, 0);
|
|
v7 = -95;
|
|
}
|
|
WriteReg(NMITIMEN, v7);
|
|
*(uint16 *)&R0_ = v8;
|
|
}
|
|
|
|
void Smb1VectorIRQ() {
|
|
if ((ReadReg(TIMEUP) & 0x80u) != 0 && vblank_enable_vtimel_flag) {
|
|
if (vblank_which_layer2_scroll_flag) {
|
|
while ((ReadReg(HVBJOY) & 0x40) == 0)
|
|
;
|
|
WriteReg(BG2HOFS, layer2_xpos);
|
|
WriteReg(BG2HOFS, HIBYTE(layer2_xpos));
|
|
} else {
|
|
while ((ReadReg(HVBJOY) & 0x40) == 0)
|
|
;
|
|
WriteReg(BG3HOFS, layer3_xpos);
|
|
WriteReg(BG3HOFS, HIBYTE(layer3_xpos));
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProcessGameMode() {
|
|
int16 v0; // si
|
|
|
|
v0 = 2 * *(uint16 *)&game_mode;
|
|
if (2 * *(uint16 *)&game_mode) {
|
|
switch (v0) {
|
|
case 4: GameMode02_Cutscene(); break;
|
|
case 6: GameMode03_GameOverScreen(); break;
|
|
case 2: GameMode01_Level(); break;
|
|
default:
|
|
Unreachable();
|
|
while (1)
|
|
;
|
|
}
|
|
} else {
|
|
GameMode00_TitleScreen();
|
|
}
|
|
}
|
|
|
|
void HandlePauseMenu() {
|
|
if (game_mode != 2 && game_mode == 1 && game_mode_task == 3 && !var0E67 && inidisp_mirror == 15) {
|
|
if (pausemenu_delay) {
|
|
--pausemenu_delay;
|
|
} else if (game_engine_subroutine != 2 && game_engine_subroutine != 3 && !auto_control_player_var1 && pause_menu_idx < 2u) {
|
|
if (pausemenu_var2) {
|
|
--pausemenu_var2;
|
|
} else if (!pause_menu_idx && (*(&controller_press1p1 + current_player) & 0x10) != 0) {
|
|
pausemenu_delay = 17;
|
|
music_ch1 = -15;
|
|
sound_ch1 = 67;
|
|
PauseMenu_Func6();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ResetAllSpriteOams_Far() {
|
|
ResetAllSpriteOams();
|
|
}
|
|
|
|
void ResetMiscSpriteOamId() {
|
|
misc_spr_oam_id[0] = -112;
|
|
misc_spr_oam_id[1] = -108;
|
|
misc_spr_oam_id[2] = -104;
|
|
misc_spr_oam_id[3] = -100;
|
|
misc_spr_oam_id[4] = -96;
|
|
misc_spr_oam_id[5] = -92;
|
|
misc_spr_oam_id[6] = -88;
|
|
misc_spr_oam_id[7] = -84;
|
|
misc_spr_oam_id[8] = 88;
|
|
if (bowser_var0096)
|
|
ResetAlmostAllSpriteOams();
|
|
else
|
|
DrawLevelPreviewSprites_Sub_New();
|
|
}
|
|
|
|
void DrawLevelPreviewSprites_Sub_New() {
|
|
OamEnt *oam; // rbp
|
|
|
|
if (var0E67) {
|
|
oam = get_OamEnt(oam_buf, 0);
|
|
oam[20].ypos = -16;
|
|
oam[21].ypos = -16;
|
|
oam[44].ypos = -16;
|
|
oam[45].ypos = -16;
|
|
oam[46].ypos = -16;
|
|
oam[47].ypos = -16;
|
|
oam[48].ypos = -16;
|
|
oam[49].ypos = -16;
|
|
oam[50].ypos = -16;
|
|
oam[51].ypos = -16;
|
|
} else {
|
|
ResetAllSpriteOams();
|
|
}
|
|
}
|
|
|
|
void ResetAllSpriteOams() {
|
|
uint8 i; // si
|
|
OamEnt *oam; // rbp
|
|
|
|
for (i = 0; i != 64; i += 4) {
|
|
oam = get_OamEnt(oam_buf, i);
|
|
oam->ypos = -16;
|
|
oam[16].ypos = -16;
|
|
oam[32].ypos = -16;
|
|
oam[48].ypos = -16;
|
|
oam[64].ypos = -16;
|
|
oam[80].ypos = -16;
|
|
oam[96].ypos = -16;
|
|
oam[112].ypos = -16;
|
|
oam_tile_size_buffer[i] = 0;
|
|
oam_tile_size_buffer[i + 64] = 0;
|
|
oam_tile_size_buffer[i + 128] = 0;
|
|
oam_tile_size_buffer[i + 192] = 0;
|
|
oam_tile_size_buffer[i + 256] = 0;
|
|
oam_tile_size_buffer[i + 320] = 0;
|
|
oam_tile_size_buffer[i + 384] = 0;
|
|
oam_tile_size_buffer[i + 448] = 0;
|
|
}
|
|
}
|
|
|
|
void ResetAlmostAllSpriteOams() {
|
|
uint8 i; // si
|
|
OamEnt *oam; // rbp
|
|
|
|
for (i = 0; i != 64; i += 4) {
|
|
oam = get_OamEnt(oam_buf, i);
|
|
oam[16].ypos = -16;
|
|
oam[32].ypos = -16;
|
|
oam[48].ypos = -16;
|
|
oam[64].ypos = -16;
|
|
oam[80].ypos = -16;
|
|
oam[96].ypos = -16;
|
|
oam[112].ypos = -16;
|
|
oam_tile_size_buffer[i + 64] = 0;
|
|
oam_tile_size_buffer[i + 128] = 0;
|
|
oam_tile_size_buffer[i + 192] = 0;
|
|
oam_tile_size_buffer[i + 256] = 0;
|
|
oam_tile_size_buffer[i + 320] = 0;
|
|
oam_tile_size_buffer[i + 384] = 0;
|
|
oam_tile_size_buffer[i + 448] = 0;
|
|
}
|
|
}
|
|
|
|
void GameMode00_TitleScreen() {
|
|
funcs_11F7[(uint8)(2 * game_mode_task) >> 1]();
|
|
music_ch1 = 0;
|
|
}
|
|
// 11FF: using guessed type int (*funcs_11F7[4])();
|
|
|
|
void TitleScreen_3_GameMenuRoutine() {
|
|
int8 i; // si
|
|
int8 v1; // [rsp+47h] [rbp-1h]
|
|
uint8 v2; // [rsp+47h] [rbp-1h]
|
|
|
|
if (sram_controller1_plugged_in || !sram_controller2_plugged_in || (controller_press1p2 & 0x10) == 0) {
|
|
if (((controller_press1p2 | controller_press1p1) & 0x10) != 0)
|
|
goto LABEL_8;
|
|
if ((controller_hold2p1 != 0xB0 || saved_joypad_bits != 0x80) && (controller_hold2p2 != 0xB0 || controller_hold1p2 != 0x80)) {
|
|
if ((save_buffer_2_player_flag & 0x80u) == 0)
|
|
demo_timer = 64;
|
|
if (demo_timer)
|
|
DrawMushroomIcon();
|
|
if (((controller_press1p2 | controller_press1p1) & 0x2C) != 0) {
|
|
if (!demo_timer)
|
|
goto LABEL_33;
|
|
demo_timer = 24;
|
|
MoveTitleScreenMenuCursor_Main(controller_press1p2 | controller_press1p1);
|
|
} else if (!demo_timer) {
|
|
if (!(TitleScreen_Func1() & 1)) {
|
|
LABEL_31:
|
|
v2 = sound_ch3;
|
|
CODE_03AD74();
|
|
sound_ch1 = 0;
|
|
sound_ch2 = 0;
|
|
sound_ch3 = v2;
|
|
if (game_engine_subroutine != 6)
|
|
return;
|
|
UNUSED_byte_7E0EC8 = 0;
|
|
}
|
|
LABEL_33:
|
|
game_mode = 0;
|
|
game_mode_task = 0;
|
|
sprite0_hit_detect_flag = 0;
|
|
fade_direction = 1;
|
|
++disable_screen_flag;
|
|
return;
|
|
}
|
|
LABEL_24:
|
|
saved_joypad_bits = 0;
|
|
v1 = controller_press2p1 | controller_press1p1;
|
|
if (title_screen_erase_file_process | splash_screen_display_mario_coin_shine_flag) {
|
|
if ((v1 & 0x40) != 0) {
|
|
demo_timer = 24;
|
|
if (splash_screen_display_mario_coin_shine_flag) {
|
|
splash_screen_display_mario_coin_shine_flag = 0;
|
|
LoadFileSelectMenu_Main();
|
|
number_of_players = 0;
|
|
save_buffer_2_player_flag = -1;
|
|
}
|
|
}
|
|
} else if ((v1 & 0x83) != 0) {
|
|
ChangeSelectedWorld_Main(v1 & 0x83);
|
|
demo_timer = 24;
|
|
}
|
|
goto LABEL_31;
|
|
}
|
|
sram_top_score[0] = 0;
|
|
sram_top_score[1] = 0;
|
|
sram_top_score[2] = 0;
|
|
sram_top_score[3] = 0;
|
|
sram_top_score[4] = 0;
|
|
sram_top_score[5] = 0;
|
|
displayed_score[0] = 0;
|
|
displayed_score[1] = 0;
|
|
displayed_score[2] = 0;
|
|
displayed_score[3] = 0;
|
|
displayed_score[4] = 0;
|
|
displayed_score[5] = 0;
|
|
sound_ch1 = 8;
|
|
goto LABEL_33;
|
|
}
|
|
if (!number_of_players && demo_timer) {
|
|
sound_ch3 = 42;
|
|
goto LABEL_24;
|
|
}
|
|
LABEL_8:
|
|
CODE_03AD74();
|
|
if (!demo_timer)
|
|
goto LABEL_33;
|
|
sound_ch3 = 41;
|
|
demo_timer = 24;
|
|
if (splash_screen_display_mario_coin_shine_flag) {
|
|
if (number_of_players == 2) {
|
|
sram_controller_type_x = (sram_controller_type_x ^ 1) & 1;
|
|
sound_ch3 = 1;
|
|
LoadPlayerSelectMenu_Entry2();
|
|
} else {
|
|
GoContinue(sram_world_number);
|
|
var0E67 = 1;
|
|
PlayerGfxHandler();
|
|
LoadAreaPointer();
|
|
++hidden_1up_flag;
|
|
++offscr_hidden_1up_flag;
|
|
++fetch_new_game_timer_flag;
|
|
++game_mode;
|
|
primary_hard_mode = player_hard_mode_flag;
|
|
game_mode_task = 0;
|
|
demo_timer = 0;
|
|
for (i = 11; i >= 0; --i)
|
|
score_and_coin_display[(uint8)i] = 0;
|
|
tempE4 = 0;
|
|
score_and_coin_display[5] = ComputeDigitValue(player_coin_count);
|
|
score_and_coin_display[4] = tempE4;
|
|
tempE4 = 0;
|
|
score_and_coin_display[11] = ComputeDigitValue(g_byte_7E06BB);
|
|
score_and_coin_display[10] = tempE4;
|
|
unused_byte_7E0E1A = 1;
|
|
}
|
|
} else if (number_of_players == 3) {
|
|
title_screen_erase_file_process ^= 1u;
|
|
LoadFileSelectMenu_Entry2();
|
|
} else if (title_screen_erase_file_process) {
|
|
ClearSaveData_Main();
|
|
LoadFileSelectMenu_Entry2();
|
|
sound_ch3 = 5;
|
|
} else {
|
|
++splash_screen_display_mario_coin_shine_flag;
|
|
sram_world_number = *(&title_screen_file_aselected_world + number_of_players);
|
|
sram_initial_selected_level = 0;
|
|
LoadSaveFileData_Main();
|
|
if (splash_screen_display_mario_coin_shine_flag)
|
|
LoadPlayerSelectMenu_Main();
|
|
else
|
|
LoadFileSelectMenu_Main();
|
|
}
|
|
}
|
|
|
|
uint8 ComputeDigitValue(uint8 a) {
|
|
while (a >= 0xAu) {
|
|
++tempE4;
|
|
a -= 10;
|
|
}
|
|
return a;
|
|
}
|
|
|
|
void GoContinue(uint8 a) {
|
|
world_number = a;
|
|
offscreen_players_world = a;
|
|
CODE_05C95B();
|
|
}
|
|
|
|
void DrawMushroomIcon() {
|
|
uint8 i; // di
|
|
|
|
for (i = 20; (i & 0x80u) == 0; i -= 2)
|
|
*(uint16 *)(&vram_buffer1_offset + i) = kTitleScreenMenuCursorStripeImage[i >> 1];
|
|
*(uint16 *)&vram_buffer1[(uint8)(4 * number_of_players) + 5] = 4654;
|
|
--*(uint16 *)&vram_buffer1_offset;
|
|
--*(uint16 *)&vram_buffer1_offset;
|
|
}
|
|
|
|
uint8 TitleScreen_Func1() {
|
|
uint8 v0; // si
|
|
uint8 v1; // al
|
|
uint8 v2; // cf
|
|
uint8 v3; // al
|
|
bool rv = false;
|
|
|
|
v0 = title_screen_menu_var0717;
|
|
if (title_screen_menu_var0718 ||
|
|
((v0 = title_screen_menu_var0717 + 1, ++title_screen_menu_var0717, rv = true, !title_screen_hard_mode_flag) ? (v1 = kDATA_05EE45[v0])
|
|
: (v1 = kDATA_05EE72[v0]),
|
|
title_screen_menu_var0718 = v1, v2 = 0, v1)) {
|
|
if (title_screen_hard_mode_flag)
|
|
v3 = kDATA_05EE5B[v0];
|
|
else
|
|
v3 = kDATA_05EE30[v0];
|
|
saved_joypad_bits = v3;
|
|
--title_screen_menu_var0718;
|
|
rv = false;
|
|
}
|
|
return rv;
|
|
}
|
|
// 17E1: variable 'v2' is possibly undefined
|
|
|
|
void GameMode02_Cutscene() {
|
|
RunCutsceneTask();
|
|
if (game_mode_task) {
|
|
object_index = 0;
|
|
EnemiesAndLoopsCore(0);
|
|
}
|
|
RelativePlayerPosition();
|
|
PlayerGfxHandler();
|
|
}
|
|
|
|
void RunCutsceneTask() {
|
|
int8 v0; // si
|
|
int8 v1; // si
|
|
uint8 v2; // di
|
|
uint8 v3; // al
|
|
uint8 v4; // di
|
|
bool v5; // cf
|
|
|
|
if (cutscene_var1680 || world_number == 7) {
|
|
v1 = 2 * game_mode_task;
|
|
if (2 * game_mode_task == 6) {
|
|
if (player_size)
|
|
SpawnMushroomDuringPeachCutscene();
|
|
else
|
|
++game_mode_task;
|
|
++game_mode_task;
|
|
return;
|
|
}
|
|
switch (v1) {
|
|
case 8:
|
|
saved_joypad_bits = 0;
|
|
controller_press1p1 = 0;
|
|
controller_hold1p2 = 0;
|
|
controller_press1p2 = 0;
|
|
controller_hold2p1 = 0;
|
|
controller_hold2p2 = 0;
|
|
controller_press2p1 = 0;
|
|
controller_press2p2 = 0;
|
|
game_paused_timer = 2;
|
|
GameMode01_Level_GameCoreRoutine();
|
|
if (!player_size)
|
|
++game_mode_task;
|
|
return;
|
|
case 12:
|
|
++game_mode_task;
|
|
++cutscene_peach_current_state;
|
|
return;
|
|
case 14:
|
|
ProcessPeachMovement();
|
|
if (cutscene_peach_current_state >= 6u)
|
|
++game_mode_task;
|
|
return;
|
|
case 16:
|
|
music_ch1 = 14;
|
|
Ending_SetPaletteWriteText();
|
|
PauseMenu_Func5();
|
|
++game_mode_task;
|
|
return;
|
|
case 18: PeachCutscene_04DE8B(); return;
|
|
case 20: ++game_mode_task; return;
|
|
case 22: ++game_mode_task; return;
|
|
case 30:
|
|
if (!--inidisp_mirror)
|
|
game_mode_task = 12;
|
|
return;
|
|
case 26: CODE_04862A(); return;
|
|
case 28: WaitForMusicAndChangeTask(); return;
|
|
}
|
|
if (v1 != 10) {
|
|
if (v1 != 2) {
|
|
if (v1 != 4) {
|
|
if (v1 != 24) {
|
|
if (v1) {
|
|
Unreachable();
|
|
while (1)
|
|
;
|
|
}
|
|
goto LABEL_10;
|
|
}
|
|
goto LABEL_99;
|
|
}
|
|
LABEL_62:
|
|
if (bowser_var0096)
|
|
return;
|
|
if (cutscene_peach_var0F82)
|
|
Ending_SetGfxPtrToUpload();
|
|
v2 = 0;
|
|
enemy_data_a[1] = 0;
|
|
if (obj_xpos_hi.player == enemy_data_a[0]) {
|
|
if (world_number == 7) {
|
|
++enemy_data_a[1];
|
|
CODE_04DBDA();
|
|
goto LABEL_73;
|
|
}
|
|
if (world_number == 2) {
|
|
if (obj_xpos_lo.player >= 0x44u)
|
|
goto LABEL_73;
|
|
} else if (obj_xpos_lo.player >= 0x54u) {
|
|
goto LABEL_73;
|
|
}
|
|
}
|
|
++enemy_data_a[1];
|
|
v2 = 1;
|
|
LABEL_73:
|
|
AutoControlPlayer(v2);
|
|
if (screen_left_xpos_hi != enemy_data_a[0]) {
|
|
int t = cutscene_task_subpos + 0x180;
|
|
cutscene_task_subpos = t;
|
|
ScrollHandler(t >> 8);
|
|
CODE_03AE2C();
|
|
++enemy_data_a[1];
|
|
}
|
|
if (!enemy_data_a[1]) {
|
|
LABEL_97:
|
|
++game_mode_task;
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
CODE_04DE54();
|
|
LABEL_60:
|
|
enemy_data_a[0] = screen_right_xpos_hi + 1;
|
|
IncModeTask_B();
|
|
return;
|
|
}
|
|
LABEL_51:
|
|
if (event_music_buffer < 6u) {
|
|
if ((ReadReg(APUI03) & 0x7F) != 75)
|
|
sound_ch3 = 75;
|
|
CODE_03D809();
|
|
if (!(level_timer_ones | (uint8)(level_timer_tens | level_timer_hundreds))) {
|
|
sound_ch3 = 76;
|
|
unused_byte_7E0E1A = 76;
|
|
all_timers = 48;
|
|
event_music_buffer = 6;
|
|
++game_mode_task;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
v0 = 2 * game_mode_task;
|
|
if (2 * game_mode_task == 10)
|
|
goto LABEL_51;
|
|
if (v0 == 2) {
|
|
if (!pausemenu_var3) {
|
|
CutsceneBowserDefeat_04ECCA();
|
|
return;
|
|
}
|
|
CutsceneToad_04ED07();
|
|
goto LABEL_60;
|
|
}
|
|
if (v0 == 4)
|
|
goto LABEL_62;
|
|
if (v0 != 6) {
|
|
if (v0 != 8) {
|
|
if (v0 != 12) {
|
|
if (v0) {
|
|
Unreachable();
|
|
while (1)
|
|
;
|
|
}
|
|
LABEL_10:
|
|
BridgeCollapse();
|
|
return;
|
|
}
|
|
LABEL_99:
|
|
if (!event_music_buffer) {
|
|
if (cutscene_var1680 || world_number >= 7u) {
|
|
ContinueGame();
|
|
} else {
|
|
area_number = 0;
|
|
level_number = 0;
|
|
game_mode_task = 0;
|
|
++world_number;
|
|
cutscene_var0BA5 = 1;
|
|
TransposePlayers();
|
|
LoadAreaPointer();
|
|
++fetch_new_game_timer_flag;
|
|
game_mode = 1;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
if (cutscene_toad_text_timer)
|
|
goto LABEL_94;
|
|
v3 = cutscene_toad_line_to_display;
|
|
if (cutscene_toad_line_to_display) {
|
|
if (cutscene_toad_line_to_display >= 9u)
|
|
goto LABEL_94;
|
|
if (world_number == 7) {
|
|
if (cutscene_toad_line_to_display < 3u)
|
|
goto LABEL_94;
|
|
v3 = cutscene_toad_line_to_display - ((cutscene_toad_line_to_display < 3u) + 1);
|
|
} else if (cutscene_toad_line_to_display < 2u) {
|
|
goto LABEL_94;
|
|
}
|
|
}
|
|
v4 = v3;
|
|
if (!v3) {
|
|
if (current_player)
|
|
v4 = v3 + 1;
|
|
LABEL_93:
|
|
vram_buffer_addr_ctrl = v4 + 12;
|
|
goto LABEL_94;
|
|
}
|
|
v4 = v3 + 1;
|
|
if (world_number == 7)
|
|
goto LABEL_93;
|
|
v4 = v3;
|
|
if (v3 >= 4u) {
|
|
LABEL_95:
|
|
event_music_buffer = 6;
|
|
var0E67 = 6;
|
|
goto LABEL_97;
|
|
}
|
|
if (v3 < 3u)
|
|
goto LABEL_93;
|
|
LABEL_94:
|
|
v5 = __CFADD__(cutscene_toad_text_timer, 4);
|
|
cutscene_toad_text_timer += 4;
|
|
cutscene_toad_line_to_display += v5;
|
|
if (v5 < 7)
|
|
return;
|
|
goto LABEL_95;
|
|
}
|
|
if (++cutscene_wait_before_toad_breaks_out_of_bag == 112) {
|
|
cutscene_toad_popped_out_of_bag_flag = 1;
|
|
cutscene_wait_before_toad_breaks_out_of_bag = 0;
|
|
++game_mode_task;
|
|
}
|
|
}
|
|
// 1CFE: conditional instruction was optimized away because al.1==0
|
|
|
|
void FloateyNumbersRoutine(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
uint8 v3; // al
|
|
uint8 v4; // si
|
|
uint8 v5; // di
|
|
uint8 v6; // si
|
|
OamEnt *oam; // rbp
|
|
int v8; // edx
|
|
uint8 v9; // al
|
|
uint8 v10; // si
|
|
int8 v11; // al
|
|
|
|
v1 = floateynum_control[k];
|
|
if (v1) {
|
|
if (v1 >= 0xBu) {
|
|
v1 = 11;
|
|
floateynum_control[k] = 11;
|
|
if (k != 9)
|
|
stomp_chain_counter = 11;
|
|
}
|
|
v2 = v1;
|
|
v3 = floateynum_timer[k];
|
|
if (v3) {
|
|
--floateynum_timer[k];
|
|
if (v3 == 43) {
|
|
if (v2 == 11) {
|
|
GiveExtraLife();
|
|
sound_ch3 = 5;
|
|
}
|
|
digit_modifier[kDATA_038B31[v2] >> 4] = kDATA_038B31[v2] & 0xF;
|
|
AddToScore();
|
|
}
|
|
v4 = object_index;
|
|
v5 = floatey_numbers_oam_id;
|
|
while (get_OamEnt(oam_buf, v5)->ypos != 0xF0) {
|
|
v5 += 8;
|
|
if (v5 == 0x90) {
|
|
v5 = floatey_numbers_oam_id;
|
|
break;
|
|
}
|
|
}
|
|
if (score_spr_ypos_lo[object_index] >= 0x18u)
|
|
score_spr_ypos_lo[object_index] -= (score_spr_ypos_lo[object_index] < 0x18u) + 1;
|
|
DumpTwoSpr_(v5, score_spr_ypos_lo[v4]);
|
|
tempE0 = v4;
|
|
*(uint16 *)&tempE2 = floateynum_xpos_word[(uint8)(2 * v4) >> 1];
|
|
*(uint16 *)&tempDE = *(uint16 *)&tempE2 + 8;
|
|
v6 = tempE0;
|
|
tempDD = 0;
|
|
if (tempE3)
|
|
tempDD |= 1u;
|
|
oam_tile_size_buffer[v5] = tempDD;
|
|
if (floateynum_control[v6] < 6u || floateynum_control[v6] == 11)
|
|
tempDD = 0;
|
|
else
|
|
tempDD = 2;
|
|
if (tempDF)
|
|
tempDD |= 1u;
|
|
oam_tile_size_buffer[v5 + 4] = tempDD;
|
|
oam = get_OamEnt(oam_buf, v5);
|
|
oam->xpos = tempE2;
|
|
oam[1].xpos = tempDE;
|
|
v8 = (uint8)(2 * floateynum_control[v6]);
|
|
oam->charnum = kDATA_038B19[(uint8)(2 * floateynum_control[v6])];
|
|
v9 = kDATA_038B19[v8 + 1];
|
|
oam[1].charnum = v9;
|
|
v10 = v9;
|
|
v11 = 50;
|
|
oam->flags = 50;
|
|
if (v10 == 14)
|
|
v11 = 51;
|
|
oam[1].flags = v11;
|
|
} else {
|
|
floateynum_control[k] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScreenRoutines() {
|
|
int8 v0; // si
|
|
uint16 v1; // si
|
|
int v2; // edx
|
|
uint16 v3; // si
|
|
uint8 v4; // di
|
|
uint8 v5; // di
|
|
uint8 v6; // [rsp+46h] [rbp-2h]
|
|
uint8 v7; // [rsp+47h] [rbp-1h]
|
|
|
|
v0 = 2 * screen_routine_task;
|
|
if (!(2 * screen_routine_task)) {
|
|
if (game_mode) {
|
|
vram_buffer_addr_ctrl = 0;
|
|
update_entire_palette_flag = 1;
|
|
}
|
|
goto LABEL_53;
|
|
}
|
|
switch (v0) {
|
|
case 2:
|
|
v7 = background_color_ctrl;
|
|
v6 = player_status;
|
|
player_status = 0;
|
|
background_color_ctrl = 2;
|
|
GetPlayerColors();
|
|
player_status = v6;
|
|
background_color_ctrl = v7;
|
|
goto LABEL_53;
|
|
case 18:
|
|
SetLevelMusic();
|
|
CODE_04956B();
|
|
return;
|
|
case 20: GetBackgroundColor_0(); return;
|
|
case 22: ++screen_routine_task; return;
|
|
case 4: WriteGameText(0); goto LABEL_53;
|
|
case 6:
|
|
GetSBNibbles();
|
|
v1 = *(uint16 *)&vram_buffer1_offset;
|
|
v2 = *(uint16 *)&vram_buffer1_offset;
|
|
*(uint16 *)&vram_buffer1[*(uint16 *)&vram_buffer1_offset + 1] = 29272;
|
|
*(uint16 *)&vram_buffer1[v2 + 3] = 1792;
|
|
*(uint16 *)&vram_buffer1[v1 + 5] = 8232;
|
|
vram_buffer1[v1 + 7] = world_number + 1;
|
|
vram_buffer1[v1 + 8] = 32;
|
|
vram_buffer1[v1 + 10] = 32;
|
|
vram_buffer1[v1 + 12] = 32;
|
|
vram_buffer1[v1 + 9] = 36;
|
|
vram_buffer1[v1 + 11] = level_number + 1;
|
|
vram_buffer1[v1 + 13] = -1;
|
|
if (!game_mode && (save_buffer_2_player_flag & 0x80u) == 0)
|
|
vram_buffer1[v1 + 7] = save_buffer + 1;
|
|
*(uint16 *)&vram_buffer1_offset = v1 + 12;
|
|
v3 = v1 + 12;
|
|
if (player_hard_mode_flag)
|
|
vram_buffer1[v3 + 5 - 12] = 42;
|
|
goto LABEL_53;
|
|
case 8:
|
|
if (game_timer_expired_flag) {
|
|
game_timer_expired_flag = 0;
|
|
DrawLevelPreviewSprites_Sub_New();
|
|
v4 = CODE_0491DD();
|
|
game_loop_toggler = 1;
|
|
OutputInter(2u);
|
|
if (number_of_players) {
|
|
if ((other_player_num_lives & 0x80u) == 0) {
|
|
*(uint16 *)&vram_buffer1[v4 + 1] = 29272;
|
|
*(uint16 *)&vram_buffer1[v4 + 3] = 1792;
|
|
*(uint16 *)&vram_buffer1[v4 + 5] = 8232;
|
|
vram_buffer1[v4 + 7] = offscreen_players_world + 1;
|
|
vram_buffer1[v4 + 8] = 32;
|
|
vram_buffer1[v4 + 10] = 32;
|
|
vram_buffer1[v4 + 12] = 32;
|
|
vram_buffer1[v4 + 9] = 36;
|
|
vram_buffer1[v4 + 11] = player_other_players_level_number_display + 1;
|
|
vram_buffer1[v4 + 13] = -1;
|
|
*(uint16 *)&vram_buffer1_offset = v4 + 12;
|
|
v5 = v4 + 12;
|
|
if (other_player_hard_mode)
|
|
vram_buffer1[v5 + 5 - 12] = 42;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
++screen_routine_task;
|
|
LABEL_53:
|
|
++screen_routine_task;
|
|
return;
|
|
case 12:
|
|
if (!game_mode)
|
|
goto LABEL_51;
|
|
if (game_mode == 3) {
|
|
func_sub_8E50();
|
|
return;
|
|
}
|
|
if (!alt_entrance_ctrl && (area_type == 3 || !screen_routines_flag0769)) {
|
|
DrawLevelPreviewSprites();
|
|
CODE_0492E7();
|
|
OutputInter(1u);
|
|
} else {
|
|
LABEL_51:
|
|
NoInter();
|
|
}
|
|
break;
|
|
case 16: AreaParserTaskControl(); break;
|
|
case 24: DrawTitleScreen(); break;
|
|
case 26: ClearBuffersDrawIcon(); break;
|
|
case 28: WriteTopScore(); break;
|
|
case 10:
|
|
case 14: ResetSpritesAndScreenTimer(); break;
|
|
default:
|
|
Unreachable();
|
|
while (1)
|
|
;
|
|
}
|
|
}
|
|
// 7E16F6: using guessed type uint8 byte_7E16F6[10];
|
|
|
|
void OutputInter(uint8 a) {
|
|
WriteGameText(a);
|
|
ResetScreenTimer();
|
|
w12sel_mirror = 0;
|
|
w34sel_mirror = 0;
|
|
wobjsel_mirror = 0;
|
|
cgwsel_mirror = 0;
|
|
cgadsub_mirror = 32;
|
|
hdmaenable_mirror = 0;
|
|
fade_direction = 2;
|
|
enable_mosaic_fades_flag = 0;
|
|
inidisp_mirror = 0;
|
|
mosaic_mirror = 0;
|
|
disable_screen_flag = 0;
|
|
}
|
|
|
|
void NoInter() {
|
|
screen_routine_task = 8;
|
|
}
|
|
|
|
void func_sub_8E50() {
|
|
uint8 v0; // di
|
|
uint16 v1; // si
|
|
uint16 v2; // di
|
|
uint8 v3; // al
|
|
|
|
w12sel_mirror = 0;
|
|
w34sel_mirror = 0;
|
|
wobjsel_mirror = 0;
|
|
cgwsel_mirror = 0;
|
|
cgadsub_mirror = 32;
|
|
hdmaenable_mirror = 0;
|
|
if (disable_screen_flag) {
|
|
enable_mosaic_fades_flag = 0;
|
|
disable_screen_flag = 0;
|
|
inidisp_mirror = 0;
|
|
fade_direction = 2;
|
|
CODE_0491DD();
|
|
}
|
|
screen_timer = 9;
|
|
v0 = WriteGameText(3u);
|
|
if (number_of_players && (other_player_num_lives & 0x80u) == 0) {
|
|
CODE_0486DF(v0);
|
|
} else {
|
|
v1 = 0;
|
|
tempE5 = 0;
|
|
v2 = *(uint16 *)&tempE4;
|
|
do {
|
|
v3 = *((uint8 *)kDATA_03903D + v1);
|
|
vram_buffer1[v2 + 1] = v3;
|
|
++v1;
|
|
++v2;
|
|
} while (v3 != 0xFF);
|
|
*(uint16 *)&vram_buffer1_offset = v2;
|
|
}
|
|
current_player_mirror = 0;
|
|
IncModeTask_B();
|
|
}
|
|
// 262B: variable 'v0' is possibly undefined
|
|
|
|
void AreaParserTaskControl() {
|
|
if (disable_screen_flag) {
|
|
if (disable_screen_flag != 1)
|
|
++disable_screen_flag;
|
|
do
|
|
AreaParserTaskHandler();
|
|
while (area_parser_task_num);
|
|
if ((--column_sets & 0x80u) != 0)
|
|
++screen_routine_task;
|
|
vram_buffer_addr_ctrl = 6;
|
|
} else {
|
|
fade_direction = 1;
|
|
enable_mosaic_fades_flag = 0;
|
|
}
|
|
}
|
|
|
|
void DrawTitleScreen() {
|
|
uint16 v0; // si
|
|
uint16 i; // di
|
|
uint16 v2; // ax
|
|
|
|
if (game_mode) {
|
|
IncModeTask_B();
|
|
} else {
|
|
UNUSED_byte_7E0EC8 = 1;
|
|
v0 = *(uint16 *)&vram_buffer1_offset;
|
|
for (i = 0;; i += 2) {
|
|
v2 = kTitleScreenLogoAndMenuStripeImage[i >> 1];
|
|
*(uint16 *)&vram_buffer1[v0 + 1] = v2;
|
|
if (v2 == 0xFFFF)
|
|
break;
|
|
v0 += 2;
|
|
}
|
|
*(uint16 *)&vram_buffer1_offset = v0;
|
|
palette_anim0E20 = 0;
|
|
music_ch1 = 0x80;
|
|
game_loop_toggler = 0x80;
|
|
vram_buffer_addr_ctrl = 5;
|
|
LoadFileSelectMenu_Main();
|
|
++screen_routine_task;
|
|
}
|
|
}
|
|
|
|
void ClearBuffersDrawIcon() {
|
|
uint8 v0; // al
|
|
uint8 v1; // si
|
|
|
|
v0 = game_mode;
|
|
if (game_mode) {
|
|
IncModeTask_B();
|
|
} else {
|
|
v1 = 0;
|
|
do {
|
|
bridge_sprite_slot_exists_flag[v1] = v0;
|
|
*(&g_byte_7E0400 + v1--) = v0;
|
|
} while (v1);
|
|
if ((save_buffer_2_player_flag & 0x80u) == 0)
|
|
number_of_players = save_buffer_2_player_flag;
|
|
DrawMushroomIcon();
|
|
++screen_routine_task;
|
|
}
|
|
}
|
|
|
|
void WriteTopScore() {
|
|
UpdateNumber(0xFAu);
|
|
IncModeTask_B();
|
|
}
|
|
|
|
void IncModeTask_B() {
|
|
++game_mode_task;
|
|
}
|
|
|
|
uint8 WriteGameText(uint8 a) {
|
|
uint8 v1; // di
|
|
uint16 v2; // si
|
|
uint16 v3; // di
|
|
uint8 v4; // si
|
|
uint8 v5; // al
|
|
bool v6; // cf
|
|
uint8 v7; // al
|
|
uint8 v8; // di
|
|
uint8 v9; // si
|
|
uint8 v10; // di
|
|
|
|
v1 = 2 * a;
|
|
if ((uint8)(2 * a) >= 4u) {
|
|
if (v1 >= 8u)
|
|
v1 = 8;
|
|
if (!number_of_players)
|
|
++v1;
|
|
}
|
|
tempF3 = v1;
|
|
v2 = kGameTextOffsets[(uint8)(2 * v1) >> 1];
|
|
v3 = *(uint16 *)&vram_buffer1_offset;
|
|
while (kGameText[v2] != 0xFF)
|
|
vram_buffer1[++v3] = kGameText[v2++];
|
|
vram_buffer1[v3 + 1] = -1;
|
|
*(uint16 *)&tempE4 = v3;
|
|
if (a >= 4u) {
|
|
v9 = 4 * (a - ((a < 4u) + 4));
|
|
v10 = vram_buffer1_offset;
|
|
tempE6 = vram_buffer1_offset + 18;
|
|
do {
|
|
vram_buffer1[v10 + 51] = kWarpZoneNumbers[v9++];
|
|
v10 += 6;
|
|
} while (v10 < tempE6);
|
|
*(uint16 *)&vram_buffer1_offset += 64;
|
|
v3 = v10;
|
|
} else if (a == 1) {
|
|
CODE_048895(v3);
|
|
v4 = vram_buffer1_offset;
|
|
v5 = number_of_lives + 1;
|
|
if ((uint8)(number_of_lives + 1) >= 0xAu) {
|
|
tempE4 = 0;
|
|
tempE5 = 0;
|
|
while (1) {
|
|
v6 = v5 < 0x64u;
|
|
v5 -= 100;
|
|
if (v6)
|
|
break;
|
|
++tempE4;
|
|
}
|
|
v7 = v5 + 100;
|
|
while (1) {
|
|
v6 = v7 < 0xAu;
|
|
v7 -= 10;
|
|
if (v6)
|
|
break;
|
|
++tempE5;
|
|
}
|
|
tempE6 = v7 + 10;
|
|
if (tempE4)
|
|
vram_buffer1[vram_buffer1_offset + 13] = tempE4;
|
|
vram_buffer1[v4 + 15] = tempE5;
|
|
v5 = tempE6;
|
|
}
|
|
vram_buffer1[v4 + 17] = v5;
|
|
vram_buffer1[v4 + 45] = world_number + 1;
|
|
vram_buffer1[v4 + 49] = level_number + 1;
|
|
if (player_hard_mode_flag)
|
|
vram_buffer1[v4 + 43] = 42;
|
|
v3 = (uint8)(level_number + 1);
|
|
} else if (number_of_players && current_player_mirror) {
|
|
v8 = vram_buffer1_offset + 9;
|
|
if (tempF3 == 4 || tempF3 == 6) {
|
|
do {
|
|
vram_buffer1[v8 + 5] = *((uint8 *)kDATA_0390C7 + v8);
|
|
vram_buffer1[v8 + 19] = kDATA_0390D1[v8];
|
|
--v8;
|
|
} while ((v8 & 0x80u) == 0);
|
|
} else {
|
|
do {
|
|
vram_buffer1[v8 + 5] = *((uint8 *)kLuigiName + v8);
|
|
--v8;
|
|
} while ((v8 & 0x80u) == 0);
|
|
}
|
|
}
|
|
return v3;
|
|
}
|
|
|
|
void ResetSpritesAndScreenTimer() {
|
|
if (!screen_timer) {
|
|
if (game_mode != 3)
|
|
fade_direction = 1;
|
|
ResetScreenTimer();
|
|
}
|
|
}
|
|
|
|
void ResetScreenTimer() {
|
|
screen_timer = 7;
|
|
++screen_routine_task;
|
|
}
|
|
|
|
void RenderAreaGraphics() {
|
|
uint16 v0; // ax
|
|
int v1; // rbp
|
|
int8 v2; // t0
|
|
uint8 v3; // si
|
|
int8 v4; // al
|
|
bool v5; // cf
|
|
bool v6; // cl
|
|
int8 v7; // al
|
|
uint16 v8; // di
|
|
int v9; // rbp
|
|
int v10; // rbp
|
|
uint16 v11; // ax
|
|
uint16 v12; // di
|
|
int v13; // rbx
|
|
int16 v14; // ax
|
|
|
|
if (!render_graphics_var0EC9) {
|
|
*(uint16 *)&R0_ = vram_buffer2_offset;
|
|
v0 = render_graphics_var0720;
|
|
v1 = vram_buffer2_offset >> 1;
|
|
vram_buffer2[v1] = render_graphics_var0720;
|
|
v2 = v0;
|
|
LOBYTE(v0) = HIBYTE(v0);
|
|
HIBYTE(v0) = v2;
|
|
render_graphics_var0ecc = v0;
|
|
vram_buffer2[v1 + 1] = 15744;
|
|
vram_buffer2[v1 + 2] = 36;
|
|
vram_buffer2[v1 + 3] = 36;
|
|
vram_buffer2[v1 + 4] = 36;
|
|
vram_buffer2[v1 + 5] = 36;
|
|
v3 = 0;
|
|
if (render_graphics_var0EE7) {
|
|
render_graphics_var0EE6 = render_graphics_var0EE7;
|
|
UNUSED_render_graphics_var0EF5 = render_graphics_var0720;
|
|
render_graphics_var0EF4 = HIBYTE(render_graphics_var0720) + 1;
|
|
}
|
|
do {
|
|
R2_ = v3;
|
|
v4 = metatile_buffer[v3] & 0xC0;
|
|
v5 = __CFSHL__(v4, 1);
|
|
v4 *= 2;
|
|
v6 = v5;
|
|
v5 = __CFSHL__(v4, 1);
|
|
v7 = 2 * v4 + v6;
|
|
R6_ = kMetatileGraphics_Low[(uint8)(2 * v7 + v5)];
|
|
R7_ = kMetatileGraphics_High[(uint8)(2 * v7 + v5)];
|
|
*(uint16 *)&R3_ = 8 * (metatile_buffer[v3] & 0x3F);
|
|
v8 = *(uint16 *)&R3_ + __CFSHL__(2 * !(area_parser_task_num & 1), 1) + 4 * !(area_parser_task_num & 1);
|
|
v9 = *(uint16 *)&R0_ >> 1;
|
|
vram_buffer2[v9 + 6] = *(uint16 *)&RomPtr_00(*(uint16 *)&R6_)[v8];
|
|
vram_buffer2[v9 + 7] = *(uint16 *)&RomPtr_00(*(uint16 *)&R6_)[(uint16)(v8 + 2)];
|
|
++*(uint16 *)&R0_;
|
|
++*(uint16 *)&R0_;
|
|
++*(uint16 *)&R0_;
|
|
++*(uint16 *)&R0_;
|
|
v3 = R2_ + 1;
|
|
} while ((uint8)(R2_ + 1) < 0xDu);
|
|
v10 = vram_buffer2_offset >> 1;
|
|
v11 = vram_buffer2[v10 + 6];
|
|
if (v11 == 6306 || v11 == 6307) {
|
|
vram_buffer2[v10 + 2] = v11;
|
|
vram_buffer2[v10 + 3] = v11;
|
|
vram_buffer2[v10 + 4] = v11;
|
|
vram_buffer2[v10 + 5] = v11;
|
|
}
|
|
v12 = *(uint16 *)&R0_ + 14;
|
|
v13 = (uint16)(*(uint16 *)&R0_ + 14) >> 1;
|
|
vram_buffer2[v13] = -1;
|
|
vram_buffer2_offset = v12;
|
|
if (!cloud_type_override && area_type && area_type != 3) {
|
|
v14 = *(uint16 *)&vram_buffer1[2 * v13 + 759];
|
|
if (v14 == 36 || v14 == 4260) {
|
|
render_area_gfx_0ECE |= 0x100u;
|
|
} else if (v14 == 2568) {
|
|
render_area_gfx_0ECE &= 0xFF00u;
|
|
}
|
|
CODE_048D71();
|
|
}
|
|
if ((++HIBYTE(render_graphics_var0720) & 0x1F) == 0)
|
|
render_graphics_var0720 = (uint8)render_graphics_var0720 ^ 4;
|
|
vram_buffer_addr_ctrl = 6;
|
|
}
|
|
}
|
|
|
|
void nullsub_9390() {
|
|
;
|
|
}
|
|
|
|
void ColorRotation() {
|
|
;
|
|
}
|
|
|
|
void RemoveCoin_Axe() {
|
|
PutBlockMetatile(3u, vram_buffer1_offset + 1);
|
|
vram_buffer_addr_ctrl = 6;
|
|
MoveVOffset();
|
|
}
|
|
|
|
void ReplaceBlockMetatile(uint8 k, uint8 a) {
|
|
WriteBlockMetatile(a);
|
|
++block_residual_counter_unused;
|
|
--block_repflag[k];
|
|
}
|
|
|
|
void DestroyBlockMetatile() {
|
|
WriteBlockMetatile(0);
|
|
}
|
|
|
|
void WriteBlockMetatile(uint8 a) {
|
|
uint8 v1; // di
|
|
|
|
v1 = 3;
|
|
if (a) {
|
|
v1 = 0;
|
|
if (a != 91 && a != 81) {
|
|
v1 = 1;
|
|
if (a != 96 && a != 82)
|
|
v1 = 2;
|
|
}
|
|
}
|
|
PutBlockMetatile(v1, vram_buffer1_offset + 1);
|
|
MoveVOffset();
|
|
}
|
|
|
|
void MoveVOffset() {
|
|
*(uint16 *)&vram_buffer1_offset += 16;
|
|
}
|
|
|
|
void PutBlockMetatile(uint8 a, uint8 j) {
|
|
uint8 v2; // si
|
|
uint8 v3; // di
|
|
int8 v4; // al
|
|
bool v5; // cf
|
|
int8 v6; // al
|
|
|
|
R1_ = j;
|
|
v2 = 8 * a;
|
|
v3 = 0;
|
|
if (R6_ >= 0xD0u)
|
|
v3 = 4;
|
|
R3_ = v3;
|
|
R4_ = 2 * (R6_ & 0xF);
|
|
R5_ = __CFSHL__(R2_ + 32, 1);
|
|
v4 = 4 * (R2_ + 32);
|
|
v5 = __CFADD__(__CFSHL__(R5_, 1), v4);
|
|
v6 = __CFSHL__(R5_, 1) + v4;
|
|
v5 |= __CFADD__(R4_, v6);
|
|
R4_ += v6;
|
|
R5_ = v3 + v5 + 2 * R5_ + __CFSHL__(2 * (R2_ + 32), 1);
|
|
RemBridge(v2, R1_);
|
|
}
|
|
|
|
void RemBridge(uint8 k, uint8 j) {
|
|
int16 v2; // ax
|
|
int v3; // rbp
|
|
|
|
LOBYTE(v2) = R5_;
|
|
HIBYTE(v2) = R4_;
|
|
*(uint16 *)&vram_buffer1[j] = v2;
|
|
*(uint16 *)&vram_buffer1[j + 8] = v2 + 0x2000;
|
|
*(uint16 *)&vram_buffer1[j + 2] = 768;
|
|
*(uint16 *)&vram_buffer1[j + 10] = 768;
|
|
v3 = k >> 1;
|
|
*(uint16 *)&vram_buffer1[j + 4] = kBlockGfxData[v3];
|
|
*(uint16 *)&vram_buffer1[j + 6] = kBlockGfxData[v3 + 1];
|
|
*(uint16 *)&vram_buffer1[j + 12] = kBlockGfxData[v3 + 2];
|
|
*(uint16 *)&vram_buffer1[j + 14] = kBlockGfxData[v3 + 3];
|
|
*(uint16 *)&vram_buffer1[j + 16] = -1;
|
|
}
|
|
|
|
void VramFunc_9B5C() {
|
|
WriteReg(DMAP0, 0);
|
|
WriteRegWord(OAMADDL, 0);
|
|
WriteRegWord(BBAD0, 4u);
|
|
WriteRegWord(A1T0H, 8u);
|
|
WriteRegWord(DAS0L, 0x220u);
|
|
WriteReg(MDMAEN, 1u);
|
|
WriteReg(OAMADDH, 0x80u);
|
|
WriteReg(OAMADDL, 0);
|
|
if (pausemenu_var3 || (VramFunc_9BD4(1u), !vram_flag_028c) && vram_flag_028d) {
|
|
WriteRegWord(VMADDL, graphics_upload_vramaddress);
|
|
WriteRegWord(DMAP0, 0x1801u);
|
|
WriteRegWord(A1T0L, graphics_upload_ptr.addr);
|
|
WriteReg(A1B0, graphics_upload_ptr.bank);
|
|
WriteRegWord(DAS0L, graphics_upload_size);
|
|
WriteReg(MDMAEN, 1u);
|
|
if (pausemenu_var3) {
|
|
if (--pausemenu_var3) {
|
|
HIBYTE(graphics_upload_ptr.addr) += 8;
|
|
HIBYTE(graphics_upload_vramaddress) += 4;
|
|
}
|
|
}
|
|
}
|
|
vram_flag_028c = 0;
|
|
}
|
|
|
|
void VramFunc_9BD4(uint8 k) {
|
|
if (vram_flag_028e) {
|
|
WriteRegWord(VMADDL, player_vramaddress);
|
|
WriteRegWord(DMAP0, 0x1801u);
|
|
WriteRegWord(A1T0L, player_graphics_pointer.addr);
|
|
WriteReg(A1B0, player_graphics_pointer.bank);
|
|
WriteRegWord(DAS0L, player_graphics_upload_size);
|
|
WriteReg(MDMAEN, k);
|
|
}
|
|
}
|
|
|
|
void UploadStripeImage() {
|
|
uint16 v0; // di
|
|
int8 i; // al
|
|
uint16 v2; // di
|
|
int8 v3; // al
|
|
uint8 *v4; // rdx
|
|
int16 v5; // ax
|
|
uint16 v6; // si
|
|
int16 v7; // di
|
|
uint16 v8; // si
|
|
|
|
WriteReg(A1B1, 0);
|
|
R6_ = 0;
|
|
v0 = 0;
|
|
for (i = *IndirPtr(*(LongPtr *)&R0_, 0); i >= 0; i = *IndirPtr(*(LongPtr *)&R0_, v0)) {
|
|
R4_ = i;
|
|
v2 = v0 + 1;
|
|
R3_ = *IndirPtr(*(LongPtr *)&R0_, v2++);
|
|
v3 = *IndirPtr(*(LongPtr *)&R0_, v2) & 0x80;
|
|
R7_ = 4 * v3 + __CFSHL__(v3, 1);
|
|
R5_ = *IndirPtr(*(LongPtr *)&R0_, v2) & 0x40;
|
|
WriteReg(DMAP1, (R5_ >> 3) | 1);
|
|
WriteReg(BBAD1, 0x18u);
|
|
WriteRegWord(VMADDL, *(uint16 *)&R3_);
|
|
v4 = IndirPtr(*(LongPtr *)&R0_, v2);
|
|
LOBYTE(v5) = HIBYTE(*(uint16 *)v4);
|
|
HIBYTE(v5) = *(uint16 *)v4;
|
|
v6 = (v5 & 0x3FFF) + 1;
|
|
WriteRegWord(DAS1L, v6);
|
|
v7 = v2 + 2;
|
|
WriteRegWord(A1T1L, *(uint16 *)&R0_ + v7);
|
|
if (*(uint16 *)&R5_) {
|
|
v8 = (uint16)((v5 & 0x3FFF) + 2) >> 1;
|
|
WriteRegWord(DAS1L, v8);
|
|
WriteReg(DMAP1, R5_ >> 3);
|
|
WriteReg(VMAIN, R7_);
|
|
WriteReg(MDMAEN, 2u);
|
|
WriteReg(BBAD1, 0x19u);
|
|
WriteRegWord(A1T1L, *(uint16 *)&R0_ + v7 + 1);
|
|
WriteRegWord(VMADDL, *(uint16 *)&R3_);
|
|
WriteRegWord(DAS1L, v8);
|
|
v6 = 2;
|
|
}
|
|
*(uint16 *)&R3_ = v6;
|
|
v0 = v6 + v7;
|
|
WriteReg(VMAIN, R7_ | 0x80);
|
|
WriteReg(MDMAEN, 2u);
|
|
}
|
|
}
|
|
|
|
void PrintStatusBarNumbers(uint8 a) {
|
|
R0_ = a;
|
|
OutputNumbers(a);
|
|
OutputNumbers(R0_ >> 4);
|
|
}
|
|
|
|
void OutputNumbers(uint8 a) {
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
uint8 v3; // si
|
|
uint8 v4; // di
|
|
uint8 v5; // si
|
|
|
|
v1 = (a + 1) & 0xF;
|
|
if (v1 < 6u) {
|
|
v2 = 4 * v1;
|
|
if (4 * v1) {
|
|
tempF9 = 32;
|
|
v3 = vram_buffer1_offset;
|
|
vram_buffer1[vram_buffer1_offset + 1] = 88;
|
|
vram_buffer1[v3 + 2] = kStatusBarData[v2];
|
|
vram_buffer1[v3 + 3] = kStatusBarData[v2 + 1];
|
|
R3_ = kStatusBarData[v2 + 2];
|
|
vram_buffer1[v3 + 4] = 2 * R3_ - 1;
|
|
R2_ = v3;
|
|
v4 = kStatusBarOffset[v1] - kStatusBarData[v2 + 2];
|
|
v5 = R2_;
|
|
do {
|
|
vram_buffer1[v5 + 5] = displayed_score[v4];
|
|
vram_buffer1[v5 + 6] = tempF9;
|
|
v5 += 2;
|
|
++v4;
|
|
--R3_;
|
|
} while (R3_);
|
|
vram_buffer1[v5 + 5] = -1;
|
|
vram_buffer1_offset = v5 + 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintStatusBarNumbers_Far(uint8 a) {
|
|
PrintStatusBarNumbers(a);
|
|
}
|
|
|
|
void DigitsMathRoutine(uint8 j) {
|
|
uint8 i; // si
|
|
int8 v2; // al
|
|
int8 k; // si
|
|
bool v4; // zf
|
|
|
|
if (game_mode && (game_mode != 2 || game_mode_task == 5)) {
|
|
for (i = 5; (i & 0x80u) == 0; --i) {
|
|
v2 = displayed_score[j] + digit_modifier[i];
|
|
if (v2 < 0) {
|
|
v4 = digit_modifier[i - 1]-- == 1;
|
|
v2 = 9;
|
|
if (v4) {
|
|
LABEL_12:
|
|
if (!i) {
|
|
i = 5;
|
|
do
|
|
marios_score[i--] = 9;
|
|
while (i);
|
|
v2 = 19;
|
|
}
|
|
v2 -= 10;
|
|
++digit_modifier[i - 1];
|
|
}
|
|
} else if ((uint8)v2 >= 0xAu) {
|
|
goto LABEL_12;
|
|
}
|
|
displayed_score[j--] = v2;
|
|
}
|
|
}
|
|
for (k = 6; k >= 0; --k)
|
|
digit_modifier[k - 1] = 0;
|
|
}
|
|
|
|
void TitleScreen_0_InitializeGame() {
|
|
uint8 v0; // di
|
|
uint8 v1; // si
|
|
|
|
inidisp_mirror = 0x80;
|
|
palette_mirror[129] = 0x7FFF;
|
|
++update_entire_palette_flag;
|
|
vram_buffer1[1] = -1;
|
|
vram_buffer1[2] = -1;
|
|
bgmode_mirror = 9;
|
|
tm_mirror = 16;
|
|
cgadsub_mirror = 32;
|
|
coldata1_mirror = 32;
|
|
coldata2_mirror = 64;
|
|
coldata3_mirror = 0x80;
|
|
v0 = -2;
|
|
v1 = 5;
|
|
while (displayed_score[v1] < 0xAu) {
|
|
if ((--v1 & 0x80u) != 0) {
|
|
if (title_screen_var07FF == 0xA5)
|
|
v0 = -57;
|
|
break;
|
|
}
|
|
}
|
|
CODE_039F3E(v0);
|
|
title_screen_var07FF = -91;
|
|
random_byte1 = -91;
|
|
g_byte_7E0EF6 = 0;
|
|
vblank_upload_from_7f0000_flag = 0;
|
|
g_word_7E0EF7 = 0;
|
|
CODE_039F3E(0x6Fu);
|
|
demo_timer = 24;
|
|
LoadAreaPointer();
|
|
GameMode01_Level_InitializeArea();
|
|
fade_direction = 0;
|
|
}
|
|
|
|
void GameMode01_Level_InitializeArea() {
|
|
int8 i; // si
|
|
uint8 v2; // al
|
|
int16 v3; // ax
|
|
uint8 v4; // t0
|
|
uint8 v5; // di
|
|
int8 v6; // al
|
|
|
|
if (world_number >= 8u)
|
|
LoadAreaPointer();
|
|
CODE_039F3E(0x4Bu);
|
|
for (i = 41; i >= 0; --i)
|
|
*(&all_timers + (uint8)i) = 0;
|
|
v2 = halfway_page;
|
|
if (alt_entrance_ctrl)
|
|
v2 = entrance_page;
|
|
screen_left_xpos_hi = v2;
|
|
column_pos_hi = v2;
|
|
backloading_flag = v2;
|
|
v4 = v2;
|
|
LOBYTE(v3) = 0;
|
|
HIBYTE(v3) = v4;
|
|
screen_left_xpos16 = v3 & 0xFF00;
|
|
layer2_xpos = (uint16)(v3 & 0xFF00) >> 1;
|
|
layer3_xpos = (uint16)(v3 & 0xFF00) >> 2;
|
|
v5 = 0;
|
|
v6 = GetScreenPosition() & 1;
|
|
if (v6)
|
|
v5 = 4;
|
|
render_graphics_var0720 = v5;
|
|
block_buffer_column_pos = 16 * v6;
|
|
area_object_length[0] = -1;
|
|
area_object_length[1] = -1;
|
|
area_object_length[2] = -1;
|
|
area_object_length[3] = -1;
|
|
area_object_length[4] = -1;
|
|
column_sets = 11;
|
|
GetAreaDataAddrs();
|
|
if (primary_hard_mode || world_number >= 4u && (world_number != 4 || level_number >= 2u))
|
|
++secondary_hard_mode;
|
|
if (halfway_page)
|
|
player_entrance_ctrl = 2;
|
|
if (area_data_addr_index != 33 && area_data_addr_index != 2)
|
|
music_ch1 = 0x80;
|
|
fade_direction = 1;
|
|
++game_mode_task;
|
|
}
|
|
|
|
void TitleScreen_2_PrimaryGameSetup() {
|
|
if (ReadReg(APUI02) != 20) {
|
|
CheckWhichControllersArePluggedIn_Main();
|
|
WriteReg(APUI02, 0x14u);
|
|
apui02_var160C = 4;
|
|
}
|
|
fetch_new_game_timer_flag = 1;
|
|
player_size = 1;
|
|
other_player_size = 1;
|
|
level_free_movement_debug_flag = 0;
|
|
GameMode01_Level_SecondaryGameSetup();
|
|
}
|
|
|
|
void GameMode01_Level_SecondaryGameSetup() {
|
|
uint8 v0; // di
|
|
uint8 i; // si
|
|
|
|
fade_direction = 2;
|
|
inidisp_mirror = 0;
|
|
disable_screen_flag = 0;
|
|
v0 = 0;
|
|
do
|
|
bridge_sprite_slot_exists_flag[v0++] = 0;
|
|
while (v0);
|
|
game_timer_expired_flag = 0;
|
|
screen_routines_flag0769 = 0;
|
|
backloading_flag = 0;
|
|
bal_platform_alignment = -1;
|
|
vram_buffer1[1] = -1;
|
|
mirror_ppu_ctrl_reg1 >>= 1;
|
|
mirror_ppu_ctrl_reg1 = 2 * mirror_ppu_ctrl_reg1 + (screen_left_xpos_hi & 1);
|
|
unused_byte_7E0B43 = 56;
|
|
unused_byte_7E0B42 = 72;
|
|
unused_byte_7E0B41 = 88;
|
|
for (i = 28; (i & 0x80u) == 0; --i)
|
|
*(&spr_data_offset + i) = kDefaultSprOffsets[i];
|
|
nullsub_A2C9();
|
|
CODE_03A28F();
|
|
++sprite0_hit_detect_flag;
|
|
++game_mode_task;
|
|
}
|
|
|
|
void UNUSED_InitializeMemory(uint8 j, uint8 k) {
|
|
R6_ = 0;
|
|
R7_ = k;
|
|
do
|
|
RomPtr_RAM(*(uint16 *)&R6_)[j--] = 0;
|
|
while (j != 0xFF);
|
|
}
|
|
|
|
void CODE_039F3E(uint8 j) {
|
|
int8 v1; // si
|
|
uint8 v2; // si
|
|
|
|
if (area_data_addr_index == 33)
|
|
++fade_direction;
|
|
v1 = 7;
|
|
R6_ = 0;
|
|
do {
|
|
R7_ = v1;
|
|
do {
|
|
if (v1 != 1 || j < 0x50u)
|
|
RomPtr_RAM(*(uint16 *)&R6_)[j] = 0;
|
|
--j;
|
|
} while (j != 0xFF);
|
|
--v1;
|
|
} while (v1 >= 0);
|
|
vram_buffer1[1] = -1;
|
|
contact_sprite_arr1[0] = 0;
|
|
contact_sprite_arr1[1] = 0;
|
|
contact_sprite_arr1[2] = 0;
|
|
contact_sprite_arr1[3] = 0;
|
|
contact_sprite_arr1[4] = 0;
|
|
primary_hard_mode = player_hard_mode_flag;
|
|
v2 = 64;
|
|
do
|
|
*(&g_byte_7E0F00 + v2++) = 0;
|
|
while (v2);
|
|
if (var0F0B) {
|
|
if (!--var0F0B) {
|
|
title_screen_hard_mode_flag = save_buffer_hard_mode_active_flag;
|
|
primary_hard_mode = save_buffer_hard_mode_active_flag;
|
|
player_hard_mode_flag = save_buffer_hard_mode_active_flag;
|
|
LoadTopScoreFromSram();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Entrance_GameTimerSetup() {
|
|
uint8 v0; // di
|
|
uint8 v1; // si
|
|
uint8 v2; // si
|
|
|
|
obj_xpos_hi.player = screen_left_xpos_hi;
|
|
vertical_force_down = 40;
|
|
player_facing_dir = 1;
|
|
obj_ypos_hi.player = 1;
|
|
player_state = 0;
|
|
--player_collision_bits;
|
|
v0 = 0;
|
|
halfway_page = 0;
|
|
if (!area_type)
|
|
v0 = 1;
|
|
swimming_flag = v0;
|
|
v1 = player_entrance_ctrl;
|
|
if (alt_entrance_ctrl >= 2u)
|
|
v1 = kAltYPosOffset[alt_entrance_ctrl - 2];
|
|
obj_xpos_lo.player = kPlayerStarting_X_Pos[alt_entrance_ctrl];
|
|
obj_ypos_lo.player = kPlayerStarting_Y_Pos[v1];
|
|
player_sprattrib = kPlayerBgPriorityData[v1];
|
|
v2 = 0;
|
|
BoundingBoxCore(0, alt_entrance_ctrl);
|
|
GetPlayerColors();
|
|
if (game_timer_setting && fetch_new_game_timer_flag) {
|
|
level_timer_hundreds = kGameTimerData[game_timer_setting];
|
|
level_timer_ones = 1;
|
|
level_timer_tens = 0;
|
|
fetch_new_game_timer_flag = 0;
|
|
player_star_power_timer = 0;
|
|
}
|
|
if (vine_screen_exit_flag) {
|
|
player_state = 3;
|
|
InitBlock_XY_Pos(0);
|
|
unused_block_y_pos = -16;
|
|
v2 = 9;
|
|
Spr02F_Vine_Init(9u, 0);
|
|
}
|
|
if (!area_type)
|
|
SetupBubble(v2);
|
|
game_engine_subroutine = 7;
|
|
}
|
|
|
|
void PlayerLoseLife() {
|
|
uint8 v0; // si
|
|
uint8 v1; // al
|
|
uint8 v2; // al
|
|
|
|
fade_direction = 1;
|
|
var0E67 = 1;
|
|
sprite0_hit_detect_flag = 0;
|
|
if ((--number_of_lives & 0x80u) == 0) {
|
|
v0 = 2 * world_number;
|
|
if ((level_number & 2) != 0)
|
|
++v0;
|
|
v1 = kHalfwayPageNibbles[v0];
|
|
if (!(level_number & 1))
|
|
v1 >>= 4;
|
|
v2 = v1 & 0xF;
|
|
if (v2 != screen_left_xpos_hi && v2 >= screen_left_xpos_hi)
|
|
v2 = 0;
|
|
halfway_page = v2;
|
|
TransposePlayers();
|
|
ContinueGame();
|
|
} else {
|
|
game_mode_task = 0;
|
|
game_mode = 3;
|
|
}
|
|
}
|
|
|
|
void GameMode03_GameOverScreen() {
|
|
int8 v0; // si
|
|
|
|
v0 = 2 * game_mode_task;
|
|
if (2 * game_mode_task == 2) {
|
|
ScreenRoutines();
|
|
} else if (v0) {
|
|
if (v0 != 4) {
|
|
Unreachable();
|
|
while (1)
|
|
;
|
|
}
|
|
RunGameOver();
|
|
} else {
|
|
SetupGameOver();
|
|
}
|
|
}
|
|
|
|
void SetupGameOver() {
|
|
screen_routine_task = 0;
|
|
sprite0_hit_detect_flag = 0;
|
|
music_ch1 = 10;
|
|
++disable_screen_flag;
|
|
++game_mode_task;
|
|
}
|
|
|
|
void RunGameOver_() {
|
|
uint8 v0; // di
|
|
int8 i; // di
|
|
uint8 v2; // si
|
|
|
|
if (!number_of_players || (other_player_num_lives & 0x80u) != 0) {
|
|
controller_press1p1 |= controller_press1p2;
|
|
if ((controller_press1p1 & 0xC) == 0) {
|
|
LABEL_11:
|
|
if (!pausemenu_var2) {
|
|
if (((controller_press1p2 | controller_press1p1) & 0x10) == 0) {
|
|
if (((controller_press1p2 | controller_press1p1) & 0x20) != 0) {
|
|
sound_ch3 = 1;
|
|
if (++game_over_screen_blinking_cursor_pos == 3)
|
|
game_over_screen_blinking_cursor_pos = 0;
|
|
}
|
|
if (world_number != 8) {
|
|
if (sound_ch3)
|
|
blinking_cursor_frame_counter = 0;
|
|
CODE_03A142();
|
|
}
|
|
return;
|
|
}
|
|
pausemenu_var2 = 32;
|
|
sound_ch1 = 67;
|
|
music_ch1 = -13;
|
|
if (game_over_screen_blinking_cursor_pos)
|
|
sound_ch1 = 59;
|
|
}
|
|
CODE_03A142();
|
|
if (--pausemenu_var2)
|
|
return;
|
|
blinking_cursor_frame_counter = 0;
|
|
number_of_lives = 4;
|
|
some_flag_for_transpose_players = 0;
|
|
player_coin_count = 0;
|
|
player_other_players_coin_count = 0;
|
|
sram_world_number = world_number;
|
|
level_number = 0;
|
|
original_level = 0;
|
|
player_other_players_level_number_display = 0;
|
|
player_other_players_level = 0;
|
|
area_number = 0;
|
|
sram_initial_selected_level = 0;
|
|
for (i = 23; i >= 0; --i)
|
|
marios_score[(uint8)i] = 0;
|
|
++hidden_1up_flag;
|
|
if (game_over_screen_blinking_cursor_pos) {
|
|
SaveGame_Main();
|
|
if (game_over_screen_blinking_cursor_pos != 1) {
|
|
ResetGame_Main();
|
|
return;
|
|
}
|
|
}
|
|
LABEL_33:
|
|
if (TransposePlayers() & 1) {
|
|
continue_world = world_number;
|
|
game_mode_task = 0;
|
|
screen_timer = 0;
|
|
game_mode = 0;
|
|
} else {
|
|
ContinueGame();
|
|
}
|
|
return;
|
|
}
|
|
sound_ch3 = 1;
|
|
if ((controller_press1p1 & 8) != 0) {
|
|
v0 = game_over_screen_blinking_cursor_pos - 1;
|
|
if ((int8)(game_over_screen_blinking_cursor_pos - 1) < 0) {
|
|
v0 = game_over_screen_blinking_cursor_pos;
|
|
LABEL_9:
|
|
sound_ch3 = 0;
|
|
}
|
|
} else {
|
|
v0 = game_over_screen_blinking_cursor_pos + 1;
|
|
if (game_over_screen_blinking_cursor_pos == 2) {
|
|
v0 = 2;
|
|
goto LABEL_9;
|
|
}
|
|
}
|
|
game_over_screen_blinking_cursor_pos = v0;
|
|
goto LABEL_11;
|
|
}
|
|
v2 = RunGameOver_Sub();
|
|
if (v2 == 2)
|
|
goto LABEL_33;
|
|
if (v2) {
|
|
Unreachable();
|
|
while (1)
|
|
;
|
|
}
|
|
}
|
|
|
|
void CODE_03A142() {
|
|
uint8 i; // di
|
|
|
|
oam_tile_size_buffer[0] = ((uint8)(++blinking_cursor_frame_counter & 0x10) >> 4) | 2;
|
|
for (i = 3; (i & 0x80u) == 0; --i)
|
|
get_OamEnt(oam_buf, i)->xpos = kDATA_03A0C8[i];
|
|
get_OamEnt(oam_buf, 0)->ypos = kDATA_03A0CC[game_over_screen_blinking_cursor_pos];
|
|
}
|
|
|
|
void RunGameOver() {
|
|
RunGameOver_();
|
|
}
|
|
|
|
void ContinueGame() {
|
|
LoadAreaPointer();
|
|
if (!cutscene_var1680 && !number_of_players) {
|
|
player_size = 1;
|
|
player_status = 0;
|
|
}
|
|
++fetch_new_game_timer_flag;
|
|
timer_control = 0;
|
|
game_engine_subroutine = 0;
|
|
game_mode_task = 0;
|
|
game_mode = 1;
|
|
}
|
|
|
|
uint8 TransposePlayers() {
|
|
uint8 i; // si
|
|
uint8 v2; // [rsp+47h] [rbp-1h]
|
|
uint8 v3; // [rsp+47h] [rbp-1h]
|
|
uint8 v4; // [rsp+47h] [rbp-1h]
|
|
uint8 v5; // [rsp+47h] [rbp-1h]
|
|
|
|
if (number_of_players && (other_player_num_lives & 0x80u) == 0) {
|
|
v2 = player_size;
|
|
player_size = other_player_size;
|
|
other_player_size = v2;
|
|
v3 = player_status;
|
|
player_status = other_player_power_up;
|
|
other_player_power_up = v3;
|
|
v4 = player_hard_mode_flag;
|
|
player_hard_mode_flag = other_player_hard_mode;
|
|
other_player_hard_mode = v4;
|
|
current_player ^= 1u;
|
|
player_luigi_graphics = current_player;
|
|
for (i = 6; (i & 0x80u) == 0; --i) {
|
|
v5 = *(&number_of_lives + i);
|
|
*(&number_of_lives + i) = *(&other_player_num_lives + i);
|
|
*(&other_player_num_lives + i) = v5;
|
|
}
|
|
return 0;
|
|
}
|
|
if (some_flag_for_transpose_players)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
uint8 TransposePlayers_Far() {
|
|
return TransposePlayers() & 1;
|
|
}
|
|
|
|
void CODE_03A28F() {
|
|
unused_06C9 = -1;
|
|
}
|
|
|
|
void nullsub_A2C9() {
|
|
;
|
|
}
|
|
|
|
void AreaParserTaskHandler() {
|
|
uint8 v0; // di
|
|
|
|
v0 = area_parser_task_num;
|
|
if (!area_parser_task_num) {
|
|
v0 = 8;
|
|
area_parser_task_num = 8;
|
|
}
|
|
AreaParserTasks(v0 - 1);
|
|
if (!--area_parser_task_num) {
|
|
R0_ = 32;
|
|
if (obj_yspeed.bubble[0] == 3)
|
|
R0_ *= 2;
|
|
if (!vblank_which_layer2_scroll_flag) {
|
|
if ((R0_ & (uint8)layer2_xpos) != 0) {
|
|
if (area_parser_flag0EFC)
|
|
goto LABEL_14;
|
|
area_parser_flag0EFC = 1;
|
|
} else {
|
|
if (!area_parser_flag0EFC)
|
|
goto LABEL_14;
|
|
area_parser_flag0EFC = 0;
|
|
}
|
|
CODE_049B35();
|
|
nullsub_9390();
|
|
}
|
|
}
|
|
LABEL_14:
|
|
if ((layer3_xpos & 0x10) == 0) {
|
|
if (!area_parser_varEDD)
|
|
return;
|
|
area_parser_varEDD = 0;
|
|
goto LABEL_20;
|
|
}
|
|
if (!area_parser_varEDD) {
|
|
area_parser_varEDD = 1;
|
|
LABEL_20:
|
|
SMB3_BufferLayer3Tilemap();
|
|
}
|
|
}
|
|
|
|
void AreaParserTasks(uint8 a) {
|
|
int8 v1; // si
|
|
int8 i; // si
|
|
int8 v3; // al
|
|
uint8 v4; // al
|
|
uint8 v5; // si
|
|
uint8 v6; // di
|
|
uint8 v7; // di
|
|
uint8 v8; // si
|
|
uint8 v9; // al
|
|
uint8 v10; // al
|
|
uint8 v11; // si
|
|
uint8 v12; // di
|
|
uint8 v13; // di
|
|
uint8 v14; // al
|
|
uint8 v15; // al
|
|
int16 v16 = 0; // ax
|
|
uint8 v17; // si
|
|
uint8 v18; // di
|
|
bool v19; // cf
|
|
int16 v20; // cx
|
|
int16 v21; // ax
|
|
uint8 v22; // di
|
|
uint8 v23; // di
|
|
|
|
v1 = 2 * a;
|
|
if (2 * a == 2 || v1 == 4 || v1 == 10 || v1 == 12) {
|
|
RenderAreaGraphics();
|
|
return;
|
|
}
|
|
if (!v1 || v1 == 8) {
|
|
if ((++current_column_pos_lo & 0xF) == 0) {
|
|
current_column_pos_lo = 0;
|
|
++column_pos_hi;
|
|
}
|
|
++block_buffer_column_pos;
|
|
block_buffer_column_pos &= 0x1Fu;
|
|
} else {
|
|
if (v1 != 6 && v1 != 14) {
|
|
Unreachable();
|
|
while (1)
|
|
;
|
|
}
|
|
if (backloading_flag)
|
|
ProcessAreaData();
|
|
for (i = 12; i >= 0; --i)
|
|
metatile_buffer[(uint8)i] = 0;
|
|
if (background_scenery) {
|
|
v3 = column_pos_hi;
|
|
do {
|
|
if (sign8(v3 - 3))
|
|
break;
|
|
v3 -= 3;
|
|
} while (v3 >= 0);
|
|
v4 = kBackSceneryData[(uint8)(current_column_pos_lo + kBSceneDataOffsets[background_scenery - 1] + 16 * v3)];
|
|
if (v4) {
|
|
R0_ = (v4 & 0xF) - 1;
|
|
v5 = 3 * R0_;
|
|
v6 = v4 >> 4;
|
|
R0_ = 3;
|
|
do {
|
|
metatile_buffer[v6] = kBackSceneryMetatiles[v5++];
|
|
if (++v6 == 11)
|
|
break;
|
|
--R0_;
|
|
} while (R0_);
|
|
}
|
|
}
|
|
if (foreground_scenery) {
|
|
v7 = kFSceneDataOffsets[foreground_scenery - 1];
|
|
v8 = 0;
|
|
while (1) {
|
|
v9 = kForeSceneryData[v7];
|
|
if (v9)
|
|
break;
|
|
LABEL_39:
|
|
++v7;
|
|
if (++v8 == 13)
|
|
goto LABEL_40;
|
|
}
|
|
if (area_type) {
|
|
if (area_type != 3 || v9 != 0x86)
|
|
goto LABEL_38;
|
|
} else {
|
|
if (area_parser_ctr1) {
|
|
area_parser_ctr1 = 0;
|
|
LABEL_38:
|
|
metatile_buffer[v8] = v9;
|
|
goto LABEL_39;
|
|
}
|
|
++area_parser_ctr1;
|
|
++v9;
|
|
}
|
|
v9 += 2;
|
|
goto LABEL_38;
|
|
}
|
|
LABEL_40:
|
|
area_parser_var2 = 0;
|
|
tempF9 = 0;
|
|
area_parser_var4 = area_parser_var3++;
|
|
if (area_type || world_number != 7) {
|
|
v10 = kTerrainMetatiles[area_type];
|
|
if (cloud_type_override)
|
|
v10 = -116;
|
|
} else {
|
|
v10 = 101;
|
|
}
|
|
R7_ = v10;
|
|
v11 = 0;
|
|
v12 = 2 * terrain_control;
|
|
LABEL_46:
|
|
R0_ = kTerrainRenderBits[v12];
|
|
R1_ = v12 + 1;
|
|
if (cloud_type_override && v11)
|
|
R0_ &= 8u;
|
|
v13 = 0;
|
|
while (1) {
|
|
if ((R0_ & kBitmasks[v13]) != 0) {
|
|
if (obj_yspeed.bubble[0] == 3 && tempF9) {
|
|
v14 = 104;
|
|
R7_ = 104;
|
|
} else {
|
|
v14 = R7_;
|
|
}
|
|
metatile_buffer[v11] = v14;
|
|
if (tempF9 && obj_yspeed.bubble[0] == 3) {
|
|
v15 = tempF9++;
|
|
if (v15 == 0xFF) {
|
|
++metatile_buffer[v11];
|
|
++R7_;
|
|
}
|
|
} else if (obj_yspeed.bubble[0] == 3 && !area_parser_var2 && (area_parser_var4 & 1) == 0) {
|
|
++metatile_buffer[v11];
|
|
}
|
|
} else {
|
|
tempF9 = -2;
|
|
++area_parser_var2;
|
|
}
|
|
if (++v11 == 13)
|
|
break;
|
|
if (area_type == 2 && v11 == 11)
|
|
R7_ = 86;
|
|
++area_parser_var4;
|
|
if (++v13 == 8) {
|
|
v12 = R1_;
|
|
if (R1_)
|
|
goto LABEL_46;
|
|
break;
|
|
}
|
|
}
|
|
if (metatile_buffer[12] == 86 || metatile_buffer[12] == 114)
|
|
++metatile_buffer[12];
|
|
ProcessAreaData();
|
|
GetBlockBufferAddr(block_buffer_column_pos);
|
|
v17 = 0;
|
|
v18 = 0;
|
|
do {
|
|
R0_ = v18;
|
|
if (render_graphics_var0EC9)
|
|
break;
|
|
LOBYTE(v16) = metatile_buffer[v17] & 0xC0;
|
|
v19 = __CFSHL__(v16, 1);
|
|
LOBYTE(v16) = 2 * v16;
|
|
v20 = v19;
|
|
v19 = __CFSHL__(v16, 1);
|
|
LOBYTE(v16) = 2 * v16;
|
|
v21 = v16 + v20;
|
|
LOBYTE(v21) = 2 * v21;
|
|
v16 = v21 + v19;
|
|
v22 = v16;
|
|
LOBYTE(v16) = metatile_buffer[v17];
|
|
if ((uint8)v16 < kBlockBuffLowBounds[v22])
|
|
LOBYTE(v16) = 0;
|
|
v23 = R0_;
|
|
RomPtr_RAM(*(uint16 *)&R6_)[R0_] = v16;
|
|
v18 = v23 + 16;
|
|
++v17;
|
|
} while (v17 < 0xDu);
|
|
}
|
|
}
|
|
// 4978: variable 'v16' is possibly undefined
|
|
|
|
void ProcessAreaData() {
|
|
int16 i; // si
|
|
uint16 v1; // di
|
|
uint8 v2; // al
|
|
int8 v3; // al
|
|
uint8 *v4; // rdx
|
|
int16 v5; // si
|
|
|
|
do {
|
|
for (i = 4; i >= 0; i = v5 - 1) {
|
|
level_3_byte_object_flag = 0;
|
|
*(uint16 *)&object_index = i;
|
|
behind_area_parser_flag = 0;
|
|
v1 = area_data_offset;
|
|
v2 = *IndirPtr(area_data_ptr, area_data_offset);
|
|
if (v2 == 0xFD)
|
|
goto LABEL_20;
|
|
if ((v2 & 0xF) == 15)
|
|
++level_3_byte_object_flag;
|
|
if ((area_object_length[(uint16)i] & 0x80u) == 0) {
|
|
LABEL_20:
|
|
DecodeAreaData(i, v1);
|
|
goto LABEL_23;
|
|
}
|
|
if (level_3_byte_object_flag)
|
|
++v1;
|
|
if (__CFSHL__(*IndirPtr(area_data_ptr, v1 + 1), 1) && !area_object_page_sel) {
|
|
++area_object_page_sel;
|
|
++area_object_page_loc;
|
|
}
|
|
v1 = area_data_offset;
|
|
v3 = *IndirPtr(area_data_ptr, area_data_offset) & 0xF;
|
|
if (v3 == 13) {
|
|
v4 = IndirPtr(area_data_ptr, v1 + 1);
|
|
v1 = area_data_offset;
|
|
if ((*v4 & 0x40) == 0 && !area_object_page_sel) {
|
|
if (level_3_byte_object_flag)
|
|
v1 = area_data_offset + 1;
|
|
area_object_page_loc = *IndirPtr(area_data_ptr, v1 + 1) & 0x1F;
|
|
++area_object_page_sel;
|
|
goto LABEL_22;
|
|
}
|
|
} else if (v3 == 14 && backloading_flag) {
|
|
goto LABEL_20;
|
|
}
|
|
if (area_object_page_loc >= column_pos_hi)
|
|
goto LABEL_20;
|
|
++behind_area_parser_flag;
|
|
LABEL_22:
|
|
IncAreaObjOffset();
|
|
LABEL_23:
|
|
v5 = *(uint16 *)&object_index;
|
|
if ((area_object_length[*(uint16 *)&object_index] & 0x80u) == 0)
|
|
--area_object_length[*(uint16 *)&object_index];
|
|
}
|
|
} while (behind_area_parser_flag || backloading_flag);
|
|
}
|
|
|
|
void IncAreaObjOffset() {
|
|
++area_data_offset;
|
|
++area_data_offset;
|
|
if (level_3_byte_object_flag)
|
|
++area_data_offset;
|
|
area_object_page_sel = 0;
|
|
level_3_byte_object_flag = 0;
|
|
}
|
|
|
|
// local variable allocation has failed, the output may be wrong!
|
|
void DecodeAreaData(uint8 k, uint16 j) {
|
|
int16 v2; // di
|
|
int16 v3; // si
|
|
uint8 *v4; // rdx
|
|
uint8 v5; // al
|
|
uint16 v6; // si
|
|
uint8 v7; // al
|
|
uint16 v8; // di
|
|
int8 v9; // al
|
|
uint16 v10; // di
|
|
uint8 *v11; // rdx
|
|
int8 v12; // al
|
|
uint8 v13; // al
|
|
uint8 v14; // di
|
|
|
|
v2 = j;
|
|
if ((area_object_length[k] & 0x80u) == 0)
|
|
*(uint16 *)&j = area_obj_offset_buffer[(uint16)(2 * k) >> 1];
|
|
if (cutscene_peach_var0F82) {
|
|
DecodeAreaData_Sub_New();
|
|
cutscene_peach_var0F82 = 0;
|
|
return;
|
|
}
|
|
*(uint16 *)&tempF7 = j;
|
|
tempF6 = 0;
|
|
level_3_byte_object_flag = 0;
|
|
v3 = 16;
|
|
v4 = IndirPtr(area_data_ptr, j);
|
|
if (*v4 == 0xFD)
|
|
return;
|
|
v5 = *v4 & 0xF;
|
|
if (v5 == 15) {
|
|
++tempF6;
|
|
} else {
|
|
v3 = 8;
|
|
if (v5 != 12)
|
|
v3 = 0;
|
|
}
|
|
*(uint16 *)&R7_ = v3;
|
|
v6 = *(uint16 *)&object_index;
|
|
if (v5 != 14) {
|
|
if (v5 == 13) {
|
|
R7_ = 34;
|
|
if (tempF6)
|
|
*(uint16 *)&j = j + 1;
|
|
v8 = j + 1;
|
|
if ((*IndirPtr(area_data_ptr, v8) & 0x40) == 0)
|
|
return;
|
|
v9 = *IndirPtr(area_data_ptr, v8) & 0x7F;
|
|
if (v9 == 75)
|
|
++loop_command;
|
|
v7 = v9 & 0x3F;
|
|
goto LABEL_32;
|
|
}
|
|
if (v5 >= 0xCu) {
|
|
if (tempF6)
|
|
*(uint16 *)&j = j + 1;
|
|
v13 = *IndirPtr(area_data_ptr, j + 1) & 0x70;
|
|
} else {
|
|
if (tempF6)
|
|
*(uint16 *)&j = j + 1;
|
|
v10 = j + 1;
|
|
v11 = IndirPtr(area_data_ptr, v10);
|
|
v12 = *v11 & 0x70;
|
|
if (!v12) {
|
|
R7_ = 22;
|
|
v7 = *IndirPtr(area_data_ptr, v10) & 0xF;
|
|
goto LABEL_32;
|
|
}
|
|
R0_ = *v11 & 0x70;
|
|
if (v12 == 112 && (*IndirPtr(area_data_ptr, v10) & 8) != 0)
|
|
R0_ = 0;
|
|
v13 = R0_;
|
|
}
|
|
v7 = v13 >> 4;
|
|
goto LABEL_32;
|
|
}
|
|
R7_ = 0;
|
|
v7 = 46;
|
|
LABEL_32:
|
|
R0_ = v7;
|
|
if ((area_object_length[v6] & 0x80u) == 0) {
|
|
LABEL_43:
|
|
if (tempF6) {
|
|
DecodeAreaData_Sub2_New(WORD(tempF7));
|
|
} else {
|
|
v14 = R7_ + R0_;
|
|
R4_ = kDATA_03A7C9[v14];
|
|
R5_ = HIBYTE(kDATA_03A7C9[v14]);
|
|
((void (*)(uint8))funcs_4FCB[(unsigned int)(v14 * 2) >> 1])(v6);
|
|
}
|
|
return;
|
|
}
|
|
if (area_object_page_loc != column_pos_hi) {
|
|
if ((*IndirPtr(area_data_ptr, area_data_offset) & 0xF) != 14 || !backloading_flag)
|
|
return;
|
|
goto LABEL_40;
|
|
}
|
|
if (backloading_flag) {
|
|
backloading_flag = 0;
|
|
behind_area_parser_flag = 0;
|
|
object_index = 0;
|
|
object_index_upper_empty = 0;
|
|
return;
|
|
}
|
|
if ((uint8)(*IndirPtr(area_data_ptr, area_data_offset) & 0xF0) >> 4 == current_column_pos_lo) {
|
|
LABEL_40:
|
|
area_obj_offset_buffer[(uint8)(2 * v6) >> 1] = area_data_offset;
|
|
if (tempF6)
|
|
++level_3_byte_object_flag;
|
|
IncAreaObjOffset();
|
|
goto LABEL_43;
|
|
}
|
|
}
|
|
// 4C12: variables would overlap: di.1 and di.2
|
|
// 4FD3: using guessed type int (*funcs_4FCB[47])();
|
|
|
|
void ExtObj2D_LoopCmdE(uint8 k) {
|
|
;
|
|
}
|
|
|
|
void nullsub_A85C(uint8 k) {
|
|
;
|
|
}
|
|
|
|
void ExtObj2E_AlterAreaAttributes(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // [rsp+47h] [rbp-1h]
|
|
|
|
v2 = *IndirPtr(area_data_ptr, area_obj_offset_buffer[(uint16)(2 * k) >> 1] + 1);
|
|
if ((v2 & 0x40) != 0) {
|
|
v1 = v2 & 7;
|
|
if ((v2 & 7u) >= 4) {
|
|
background_color_ctrl = v2 & 4;
|
|
v1 = 0;
|
|
}
|
|
foreground_scenery = v1;
|
|
} else {
|
|
terrain_control = v2 & 0xF;
|
|
background_scenery = (uint8)(v2 & 0x30) >> 4;
|
|
}
|
|
}
|
|
|
|
void ExtObj27_ScrollLockObject_Warp(uint8 k) {
|
|
uint8 v1; // si
|
|
|
|
v1 = 4;
|
|
if (world_number) {
|
|
v1 = 5;
|
|
if (area_type == 1)
|
|
v1 = 6;
|
|
}
|
|
warp_zone_control = v1;
|
|
WriteGameText(v1);
|
|
KillEnemies(0xDu);
|
|
ExtObj28_ScrollLockObject(v1);
|
|
}
|
|
|
|
void ExtObj28_ScrollLockObject(uint8 k) {
|
|
scroll_lock ^= 1u;
|
|
}
|
|
|
|
void KillEnemies(uint8 a) {
|
|
uint8 i; // si
|
|
|
|
R0_ = a;
|
|
for (i = 8; (i & 0x80u) == 0; --i) {
|
|
if (enemy_id[i] == R0_)
|
|
enemy_flag[i] = 0;
|
|
}
|
|
}
|
|
|
|
void ExtObj2C_AreaFrenzy(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
|
|
v1 = kFrenzyIdData[R0_ - 8];
|
|
v2 = 9;
|
|
while ((--v2 & 0x80u) == 0) {
|
|
if (v1 == enemy_id[v2]) {
|
|
v1 = 0;
|
|
break;
|
|
}
|
|
}
|
|
enemy_frenzy_queue = v1;
|
|
}
|
|
|
|
void ExtObj01_GrassyOrMushroomPlatform(uint8 k) {
|
|
uint8 LrgObjAttrib; // di
|
|
int8 v2; // al
|
|
uint8 v3; // al
|
|
uint8 v4; // si
|
|
uint8 v5; // di
|
|
uint8 v6; // al
|
|
uint8 v7; // si
|
|
uint8 v8; // di
|
|
uint8 v9; // si
|
|
uint8 v10; // di
|
|
uint8 v11; // si
|
|
uint8 v12; // si
|
|
int8 v13; // di
|
|
uint8 v14; // si
|
|
int8 v15; // di
|
|
uint8 v16; // si
|
|
uint8 v17; // si
|
|
|
|
R4_ = *((uint8 *)kDATA_03A8C1 + (uint8)(2 * area_style));
|
|
R5_ = *((uint8 *)kDATA_03A8C1 + (uint8)(2 * area_style) + 1);
|
|
switch ((uint8)(2 * area_style) >> 1) {
|
|
case 0:
|
|
LrgObjAttrib = GetLrgObjAttrib(k);
|
|
tree_ledge_saved_x = k;
|
|
v2 = area_object_length[k];
|
|
if (!v2) {
|
|
v3 = 28;
|
|
goto LABEL_21;
|
|
}
|
|
if (v2 < 0) {
|
|
area_object_length[k] = LrgObjAttrib;
|
|
v2 = current_column_pos_lo | column_pos_hi;
|
|
if (__PAIR16__(current_column_pos_lo, column_pos_hi)) {
|
|
v3 = 26;
|
|
goto LABEL_21;
|
|
}
|
|
}
|
|
tree_ledge_countdown = v2;
|
|
v4 = R7_;
|
|
metatile_buffer[R7_] = 27;
|
|
v5 = v4 + 1;
|
|
if (--tree_ledge_countdown) {
|
|
if (tree_ledge_arr130F[tree_ledge_saved_x]) {
|
|
metatile_buffer[v5] = 70;
|
|
v6 = 74;
|
|
} else {
|
|
++tree_ledge_arr130F[tree_ledge_saved_x];
|
|
metatile_buffer[v5] = 69;
|
|
v6 = 73;
|
|
}
|
|
} else if (tree_ledge_arr130F[tree_ledge_saved_x]) {
|
|
tree_ledge_arr130F[tree_ledge_saved_x] = 0;
|
|
metatile_buffer[v5] = 71;
|
|
v6 = 75;
|
|
} else {
|
|
tree_ledge_arr130F[tree_ledge_saved_x] = 0;
|
|
metatile_buffer[v5] = 72;
|
|
v6 = 76;
|
|
}
|
|
v7 = v4 + 1;
|
|
goto LABEL_20;
|
|
case 1:;
|
|
uint16 t = ChkLrgObjLength(k);
|
|
R6_ = t;
|
|
if (t & 0x100) {
|
|
mushroom_ledge_half_len[k] = area_object_length[k] >> 1;
|
|
v3 = 29;
|
|
LABEL_21:
|
|
RenderUnderPart(R7_, 0, v3);
|
|
return;
|
|
}
|
|
v3 = 31;
|
|
v8 = area_object_length[k];
|
|
if (!v8)
|
|
goto LABEL_21;
|
|
R6_ = mushroom_ledge_half_len[k];
|
|
v9 = R7_;
|
|
metatile_buffer[R7_] = 30;
|
|
if (v8 == R6_) {
|
|
v7 = v9 + 1;
|
|
metatile_buffer[v7] = 79;
|
|
v6 = 80;
|
|
LABEL_20:
|
|
RenderUnderPart(v7 + 1, 0xFu, v6);
|
|
}
|
|
return;
|
|
case 2:
|
|
v10 = GetLrgObjAttrib(k);
|
|
v11 = R7_;
|
|
metatile_buffer[R7_] = 108;
|
|
v12 = v11 + 1;
|
|
v13 = v10 - 1;
|
|
if (v13 >= 0) {
|
|
metatile_buffer[v12] = 109;
|
|
v14 = v12 + 1;
|
|
v15 = v13 - 1;
|
|
if (v15 >= 0)
|
|
RenderUnderPart(v14, v15, 0x6Eu);
|
|
}
|
|
v16 = cannon_offset;
|
|
cannon_ypos_lo[v16] = GetAreaObjYPosition();
|
|
cannon_xpos_hi[v16] = column_pos_hi;
|
|
cannon_xpos_lo[v16] = GetAreaObjXPosition();
|
|
v17 = v16 + 1;
|
|
if (v17 >= 6u)
|
|
v17 = 0;
|
|
cannon_offset = v17;
|
|
return;
|
|
}
|
|
}
|
|
|
|
void ExtObj09_PulleyRope(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
uint8 v2 = ChkLrgObjLength(k) >> 8;
|
|
v1 = 0;
|
|
if (!v2) {
|
|
v1 = 1;
|
|
if (!area_object_length[k])
|
|
v1 = 2;
|
|
}
|
|
metatile_buffer[0] = kPulleyRopeMetatiles[v1];
|
|
}
|
|
|
|
void ExtObj1F_WaterPipe(uint8 k) {
|
|
int v1; // edx
|
|
|
|
GetLrgObjAttrib(k);
|
|
v1 = R7_;
|
|
metatile_buffer[R7_] = 117;
|
|
metatile_buffer[v1 + 1] = 118;
|
|
}
|
|
|
|
void ExtObj22_IntroPipe(uint8 k) {
|
|
uint8 v1; // si
|
|
uint8 v2; // di
|
|
int8 i; // si
|
|
|
|
ChkLrgObjFixedLength(k, 3u);
|
|
R5_ = 8;
|
|
R6_ = area_object_length[k];
|
|
v1 = 9;
|
|
bool flag = false;
|
|
if (kDATA_03A9E3[R6_]) {
|
|
v1 = RenderUnderPart(0, R5_, kDATA_03A9E3[R6_]);
|
|
flag = true;
|
|
}
|
|
v2 = R6_;
|
|
metatile_buffer[v1] = kDATA_03A9E7[R6_];
|
|
metatile_buffer[v1 + 1] = kDATA_03A9EB[v2];
|
|
if (flag) {
|
|
for (i = 6; i >= 0; --i)
|
|
metatile_buffer[(uint8)i] = 0;
|
|
metatile_buffer[7] = kDATA_03A9EF[v2];
|
|
}
|
|
}
|
|
|
|
void ExtObj07_VerticalPipe(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 slot; // si
|
|
uint8 AreaObjXPosition; // al
|
|
uint8 v4; // si
|
|
|
|
v1 = CODE_03AA4D(k);
|
|
if (R0_)
|
|
v1 += 4;
|
|
if (__PAIR16__(area_number, world_number)) {
|
|
if (area_object_length[k]) {
|
|
slot = FindEmptyEnemySlotRev();
|
|
if (slot != 0xff) {
|
|
AreaObjXPosition = GetAreaObjXPosition();
|
|
obj_xpos_lo.enemy[slot] = AreaObjXPosition + 8;
|
|
obj_xpos_hi.enemy[slot] = __CFADD__(AreaObjXPosition, 8) + column_pos_hi;
|
|
obj_ypos_hi.enemy[slot] = 1;
|
|
enemy_flag[slot] = 1;
|
|
obj_ypos_lo.enemy[slot] = GetAreaObjYPosition();
|
|
enemy_id[slot] = 13;
|
|
PiranhaPlant_Init(slot);
|
|
}
|
|
}
|
|
}
|
|
v4 = R7_;
|
|
metatile_buffer[R7_] = kDATA_03A9EF[v1];
|
|
RenderUnderPart(v4 + 1, R6_ - 1, kDATA_03A9F1[v1]);
|
|
}
|
|
|
|
uint8 CODE_03AA4D(uint8 k) {
|
|
ChkLrgObjFixedLength(k, 1u);
|
|
R6_ = GetLrgObjAttrib(k) & 7;
|
|
return area_object_length[k];
|
|
}
|
|
|
|
uint8 FindEmptyEnemySlot() {
|
|
uint8 result; // si
|
|
|
|
for (result = 0; result != 8; ++result) {
|
|
if (!enemy_flag[result])
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
uint8 FindEmptyEnemySlotRev() {
|
|
uint8 result; // si
|
|
|
|
for (result = 8; result != 0xFF; --result) {
|
|
if (!enemy_flag[result])
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void ExtObj0D_HoleWater(uint8 k) {
|
|
uint8 v1; // si
|
|
uint8 v2; // di
|
|
|
|
ChkLrgObjLength(k);
|
|
v1 = 10;
|
|
if (area_type == 3)
|
|
v1 = 11;
|
|
v2 = area_type;
|
|
metatile_buffer[v1] = kDATA_03AA78[area_type];
|
|
RenderUnderPart(v1 + 1, 1u, kDATA_03AA7C[v2 >> 1]);
|
|
}
|
|
|
|
void ExtObj0E_QuestionBlockHigh(uint8 k) {
|
|
CODE_03AAA4(k, 3u);
|
|
}
|
|
|
|
void ExtObj0E_QuestionBlockLow(uint8 k) {
|
|
CODE_03AAA4(k, 7u);
|
|
}
|
|
|
|
void CODE_03AAA4(uint8 k, uint8 a) {
|
|
ChkLrgObjLength(k);
|
|
metatile_buffer[a] = -25;
|
|
}
|
|
|
|
void ExtObj0A_Bridge_High(uint8 k) {
|
|
CODE_03AABA(k, 6u);
|
|
}
|
|
|
|
void ExtObj0B_Bridge_Middle(uint8 k) {
|
|
CODE_03AABA(k, 7u);
|
|
}
|
|
|
|
void ExtObj0B_Bridge_Low(uint8 k) {
|
|
CODE_03AABA(k, 9u);
|
|
}
|
|
|
|
void CODE_03AABA(uint8 k, uint8 a) {
|
|
uint8 v2; // al
|
|
|
|
ChkLrgObjLength(k);
|
|
if (area_object_length[k]) {
|
|
if (tree_ledge_arr130F[k]) {
|
|
v2 = 13;
|
|
} else {
|
|
++tree_ledge_arr130F[k];
|
|
v2 = 14;
|
|
}
|
|
} else {
|
|
tree_ledge_arr130F[k] = 0;
|
|
v2 = 15;
|
|
}
|
|
metatile_buffer[a] = v2;
|
|
RenderUnderPart(a + 1, 0, 0x6Bu);
|
|
}
|
|
|
|
void ExtObj23_FlagpoleObject(uint8 j) {
|
|
uint8 AreaObjXPosition; // al
|
|
|
|
metatile_buffer[0] = 40;
|
|
RenderUnderPart(1u, 8u, 0x29u);
|
|
metatile_buffer[10] = 100;
|
|
AreaObjXPosition = GetAreaObjXPosition();
|
|
obj_xpos_lo.enemy[5] = AreaObjXPosition - 8;
|
|
obj_xpos_hi.enemy[5] = column_pos_hi - (AreaObjXPosition < 8u);
|
|
obj_ypos_lo.enemy[5] = 48;
|
|
flagpole_score_ypos_lo = -80;
|
|
enemy_id[5] = 48;
|
|
++enemy_flag[5];
|
|
g_byte_7E0FB4 = -1;
|
|
g_byte_7E0FB5 = -1;
|
|
g_byte_7E0FB6 = -1;
|
|
g_byte_7E0FB7 = -1;
|
|
}
|
|
// 7E023D: using guessed type int8;
|
|
|
|
void ExtObj04_RowOfCoins(uint8 k) {
|
|
GetRow(k, kCoinMetatileData[area_type]);
|
|
}
|
|
|
|
void ExtObj26_CastleBridge(uint8 k) {
|
|
ChkLrgObjFixedLength(k, 0xCu);
|
|
ExtObj25_ChainObj(k);
|
|
}
|
|
|
|
void ExtObj24_AxeObj(uint8 k) {
|
|
vram_buffer_addr_ctrl = 8;
|
|
ExtObj25_ChainObj(k);
|
|
}
|
|
|
|
void ExtObj25_ChainObj(uint8 k) {
|
|
CODE_03AB55(kCObjectRow[R0_ - 2], kCObjectMetatile[R0_ - 2]);
|
|
}
|
|
|
|
void ExtObj20_EmptyBlock(uint8 k) {
|
|
GetLrgObjAttrib(k);
|
|
CODE_03AB55(R7_, 0xFCu);
|
|
}
|
|
|
|
void CODE_03AB55(uint8 k, uint8 a) {
|
|
RenderUnderPart(k, 0, a);
|
|
}
|
|
|
|
void ExtObj02_RowOfBricks(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
v1 = area_type;
|
|
if (cloud_type_override)
|
|
v1 = 4;
|
|
GetRow(k, kBrickMetatiles[v1]);
|
|
}
|
|
|
|
void ExtObj03_RowOfSolidBlocks(uint8 k) {
|
|
GetRow(k, kSolidBlockMetatiles[area_type]);
|
|
}
|
|
|
|
void GetRow(uint8 k, uint8 a) {
|
|
ChkLrgObjLength(k);
|
|
RenderUnderPart(R7_, 0, a);
|
|
}
|
|
|
|
void ExtObj05_ColumnOfBricks(uint8 k) {
|
|
uint8 LrgObjAttrib; // di
|
|
uint8 a; // [rsp+47h] [rbp-1h]
|
|
|
|
a = kBrickMetatiles[area_type];
|
|
LrgObjAttrib = GetLrgObjAttrib(k);
|
|
RenderUnderPart(R7_, LrgObjAttrib, a);
|
|
}
|
|
|
|
void ExtObj06_ColumnOfSolidBlocks(uint8 k) {
|
|
uint8 LrgObjAttrib; // di
|
|
uint8 a; // [rsp+47h] [rbp-1h]
|
|
|
|
a = kSolidBlockMetatiles[area_type];
|
|
LrgObjAttrib = GetLrgObjAttrib(k);
|
|
RenderUnderPart(R7_, LrgObjAttrib, a);
|
|
}
|
|
|
|
void ExtObj21_Jumpspring(uint8 k) {
|
|
uint8 EmptyEnemySlot; // si
|
|
uint8 AreaObjYPosition; // al
|
|
int v3; // edx
|
|
|
|
GetLrgObjAttrib(k);
|
|
EmptyEnemySlot = FindEmptyEnemySlot();
|
|
obj_xpos_lo.enemy[EmptyEnemySlot] = GetAreaObjXPosition();
|
|
obj_xpos_hi.enemy[EmptyEnemySlot] = column_pos_hi;
|
|
AreaObjYPosition = GetAreaObjYPosition();
|
|
obj_ypos_lo.enemy[EmptyEnemySlot] = AreaObjYPosition;
|
|
obj_xspeed.enemy[EmptyEnemySlot] = AreaObjYPosition;
|
|
enemy_id[EmptyEnemySlot] = 50;
|
|
obj_ypos_hi.enemy[EmptyEnemySlot] = 1;
|
|
++enemy_flag[EmptyEnemySlot];
|
|
v3 = R7_;
|
|
metatile_buffer[R7_] = 111;
|
|
metatile_buffer[v3 + 1] = 112;
|
|
}
|
|
|
|
void ExtObj19_Hidden1upBlock(uint8 k) {
|
|
if (hidden_1up_flag) {
|
|
hidden_1up_flag = 0;
|
|
BrickWithItem(k);
|
|
}
|
|
}
|
|
|
|
void ExtObj18_QuestionBlock(uint8 k) {
|
|
uint8 v1; // [rsp+47h] [rbp-1h]
|
|
|
|
v1 = kBrickQBlockMetatiles[GetAreaObjectID()];
|
|
GetLrgObjAttrib(k);
|
|
metatile_buffer[R7_] = v1;
|
|
}
|
|
|
|
void ExtObj1D_BrickWith10Coins(uint8 k) {
|
|
brick_coin_timer_flag = 0;
|
|
BrickWithItem(k);
|
|
}
|
|
|
|
void BrickWithItem(uint8 k) {
|
|
int8 v1; // al
|
|
uint8 v2; // [rsp+47h] [rbp-1h]
|
|
|
|
R7_ = GetAreaObjectID();
|
|
v1 = 0;
|
|
if (area_type != 1)
|
|
v1 = 5;
|
|
v2 = kBrickQBlockMetatiles[(uint8)(R7_ + v1)];
|
|
GetLrgObjAttrib(k);
|
|
metatile_buffer[R7_] = v2;
|
|
}
|
|
|
|
uint8 GetAreaObjectID() {
|
|
return R0_;
|
|
}
|
|
|
|
void ExtObj08_Hole(uint8 k) {
|
|
uint16 v1; // di
|
|
uint8 v2; // si
|
|
uint8 xpos; // al
|
|
uint8 v4; // si
|
|
|
|
v1 = ChkLrgObjLength(k);
|
|
if ((v1 & 0x100) && !area_type) {
|
|
v2 = cannon_offset;
|
|
xpos = GetAreaObjXPosition();
|
|
cannon_xpos_lo[v2] = xpos - 16;
|
|
cannon_xpos_hi[v2] = column_pos_hi - (xpos < 0x10u);
|
|
cannon_ypos_lo[v2] = 16 * (v1 + 2);
|
|
v4 = v2 + 1;
|
|
if (v4 >= 5u)
|
|
v4 = 0;
|
|
cannon_offset = v4;
|
|
}
|
|
RenderUnderPart(8u, 0xFu, 0);
|
|
}
|
|
|
|
uint8 RenderUnderPart(uint8 k, uint8 j, uint8 a) {
|
|
uint8 v3; // di
|
|
|
|
do {
|
|
area_object_height = j;
|
|
v3 = metatile_buffer[k];
|
|
if (!v3 || v3 != 27 && v3 != 30 && (v3 == 0xE7 || v3 != 70 && v3 != 74 && v3 < 0xE7u && (v3 != 87 && v3 != 86 || a != 80))) {
|
|
metatile_buffer[k] = a;
|
|
}
|
|
if (++k >= 0xDu)
|
|
break;
|
|
j = area_object_height - 1;
|
|
} while ((int8)(area_object_height - 1) >= 0);
|
|
return k;
|
|
}
|
|
|
|
uint16 ChkLrgObjLength(uint8 k) {
|
|
uint8 j; // di
|
|
|
|
j = GetLrgObjAttrib(k);
|
|
return ChkLrgObjFixedLength(k, j);
|
|
}
|
|
|
|
uint16 ChkLrgObjFixedLength(uint8 k, uint8 jin) {
|
|
uint16 j = jin;
|
|
if ((area_object_length[k] & 0x80u) != 0) {
|
|
area_object_length[k] = j;
|
|
j |= 0x100;
|
|
}
|
|
return j;
|
|
}
|
|
|
|
uint8 GetLrgObjAttrib(uint8 k) {
|
|
uint16 v1; // di
|
|
|
|
v1 = area_obj_offset_buffer[(uint16)(2 * k) >> 1];
|
|
R7_ = *IndirPtr(area_data_ptr, v1) & 0xF;
|
|
return *IndirPtr(area_data_ptr, v1 + 1) & 0xF;
|
|
}
|
|
|
|
uint8 GetAreaObjXPosition() {
|
|
return 16 * current_column_pos_lo;
|
|
}
|
|
|
|
uint8 GetAreaObjYPosition() {
|
|
return 16 * R7_ + 32;
|
|
}
|
|
|
|
void GetBlockBufferAddr(uint8 a) {
|
|
R7_ = kBlockBufferAddr[(a >> 4) + 2];
|
|
R6_ = kBlockBufferAddr[a >> 4] + (a & 0xF);
|
|
}
|
|
|
|
uint8 RenderUnderPart_Far(uint8 k, uint8 j, uint8 a) {
|
|
return RenderUnderPart(k, j, a);
|
|
}
|
|
|
|
uint16 ChkLrgObjFixedLength_Far(uint8 k, uint8 j) {
|
|
return ChkLrgObjFixedLength(k, j);
|
|
}
|
|
|
|
uint8 GetAreaObjXPosition_Far() {
|
|
return GetAreaObjXPosition();
|
|
}
|
|
|
|
uint8 FindEmptyEnemySlot_Far() {
|
|
return FindEmptyEnemySlot();
|
|
}
|
|
|
|
void GameMode01_Level() {
|
|
int8 v0; // si
|
|
|
|
v0 = 2 * game_mode_task;
|
|
if (2 * game_mode_task == 2) {
|
|
ScreenRoutines();
|
|
} else if (v0) {
|
|
if (v0 == 4) {
|
|
GameMode01_Level_SecondaryGameSetup();
|
|
} else {
|
|
if (v0 != 6) {
|
|
Unreachable();
|
|
while (1)
|
|
;
|
|
}
|
|
GameMode01_Level_GameCoreRoutine();
|
|
}
|
|
} else {
|
|
GameMode01_Level_InitializeArea();
|
|
}
|
|
}
|
|
|
|
void GameMode01_Level_GameCoreRoutine() {
|
|
ControllerStuff_05C860();
|
|
CODE_03AD74();
|
|
}
|
|
|
|
void CODE_03AD74() {
|
|
uint8 v0; // si
|
|
uint8 v1; // al
|
|
|
|
if (!player_state)
|
|
var0E67 = 0;
|
|
saved_joypad_bits = *(&saved_joypad_bits + current_player);
|
|
GameRoutines();
|
|
if (game_mode_task >= 3u) {
|
|
ProcFireball_Bubble();
|
|
v0 = 0;
|
|
while (1) {
|
|
object_index = v0;
|
|
if (var0E67 == 127)
|
|
break;
|
|
EnemiesAndLoopsCore(v0);
|
|
if (!var0E67)
|
|
FloateyNumbersRoutine(v0);
|
|
if (++v0 == 10) {
|
|
ProcessContactSprites();
|
|
if (var0E67)
|
|
var0E67 = 127;
|
|
break;
|
|
}
|
|
}
|
|
GetPlayerOffscreenBits();
|
|
RelativePlayerPosition();
|
|
PlayerGfxHandler();
|
|
object_index = 1;
|
|
BlockObjectsCore(1u);
|
|
object_index = 0;
|
|
BlockObjectsCore(0);
|
|
BlockObjMT_Updater();
|
|
MiscObjectsCore();
|
|
ProcessCannons();
|
|
ProcessWhirlpools();
|
|
FlagpoleRoutine();
|
|
RunGameTimer();
|
|
ColorRotation();
|
|
if (sign8(obj_ypos_hi.player - 2)) {
|
|
if (!player_star_power_timer) {
|
|
if (interval_timer_control == 1 && game_engine_subroutine != 12)
|
|
GetPlayerColors();
|
|
ResetPalStar();
|
|
goto LABEL_23;
|
|
}
|
|
if (player_star_power_timer == 4 && !interval_timer_control)
|
|
SetLevelMusic();
|
|
}
|
|
v1 = frame_counter;
|
|
if (player_star_power_timer < 8u)
|
|
v1 = frame_counter >> 2;
|
|
CyclePlayerPalette(v1);
|
|
LABEL_23:
|
|
buttons_a_b_previous = buttons_a_b;
|
|
buttons_left_right = 0;
|
|
CODE_03AE2C();
|
|
}
|
|
}
|
|
|
|
void CODE_03AE2C() {
|
|
if (vram_buffer_addr_ctrl != 6) {
|
|
if (!area_parser_task_num) {
|
|
if (sign8(scroll_thirty_two - 32))
|
|
return;
|
|
scroll_thirty_two -= 32;
|
|
LOBYTE(vram_buffer2_offset) = 0;
|
|
}
|
|
AreaParserTaskHandler();
|
|
}
|
|
}
|
|
|
|
void ScrollHandler(int scrollamt) {
|
|
uint8 v0; // di
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
bool v3; // cf
|
|
|
|
if (scrollamt >= 0) {
|
|
v0 = scrollamt;
|
|
goto LBL_ScrollScreen;
|
|
}
|
|
|
|
player_x_scroll += platform_x_scroll;
|
|
if (scroll_lock || player_pos_for_scroll < 0x50u || side_collision_timer || (int8)(player_x_scroll - 1) < 0) {
|
|
scroll_amount = 0;
|
|
} else {
|
|
v0 = player_x_scroll;
|
|
if (player_x_scroll >= 2u)
|
|
v0 = player_x_scroll - 1;
|
|
if (player_pos_for_scroll >= 0x70u)
|
|
v0 = player_x_scroll;
|
|
LBL_ScrollScreen:
|
|
scroll_amount = v0;
|
|
scroll_thirty_two += v0;
|
|
R0_ = screen_left_xpos_lo;
|
|
R1_ = screen_left_xpos_hi;
|
|
*(uint16 *)&R0_ += v0;
|
|
layer2_xpos = *(uint16 *)&R0_ >> 1;
|
|
layer3_xpos = *(uint16 *)&R0_ >> 2;
|
|
screen_left_xpos_lo = R0_;
|
|
layer1_xpos_lo = R0_;
|
|
screen_left_xpos16 = __PAIR16__(R1_, R0_);
|
|
screen_left_xpos_hi = R1_;
|
|
R0_ = R1_ & 1;
|
|
mirror_ppu_ctrl_reg1 = R1_ & 1 | mirror_ppu_ctrl_reg1 & 0xFE;
|
|
GetScreenPosition();
|
|
scroll_interval_timer = 8;
|
|
}
|
|
R0_ = GetXOffscreenBits(0);
|
|
v1 = 0;
|
|
if (__CFSHL__(R0_, 1) || (v1 = 1, (R0_ & 0x20) != 0)) {
|
|
v2 = *(&screen_left_xpos_lo + v1);
|
|
v3 = v2 < kSubtracterData_X[v1];
|
|
obj_xpos_lo.player = v2 - kSubtracterData_X[v1];
|
|
obj_xpos_hi.player = *(&screen_left_xpos_hi + v1) - v3;
|
|
if (buttons_left_right != kOffscrJoypadBitsData[v1])
|
|
obj_xspeed.player = 0;
|
|
}
|
|
platform_x_scroll = 0;
|
|
}
|
|
|
|
uint8 GetScreenPosition() {
|
|
uint8 result; // al
|
|
|
|
screen_right_xpos = screen_left_xpos_lo - 1;
|
|
result = (screen_left_xpos_lo != 0) + screen_left_xpos_hi;
|
|
screen_right_xpos_hi = result;
|
|
return result;
|
|
}
|
|
|
|
void GameRoutines() {
|
|
int8 v0; // si
|
|
|
|
v0 = 2 * game_engine_subroutine;
|
|
if (2 * game_engine_subroutine) {
|
|
switch (v0) {
|
|
case 12: PlayerLoseLife(); break;
|
|
case 14: PlayerEntrance(); break;
|
|
case 16: PlayerCtrlRoutine(); break;
|
|
case 2: Vine_AutoClimb(); break;
|
|
case 6: VerticalPipeEntry(); break;
|
|
case 4: SideExitPipeEntry(); break;
|
|
case 18: PlayerChangeSize(); break;
|
|
case 20: PlayerInjuryBlink(); break;
|
|
case 22: PlayerDeath(); break;
|
|
case 24: PlayerFireFlower(); break;
|
|
case 8: FlagpoleSlide(); break;
|
|
case 10: PlayerEndLevel(); break;
|
|
default:
|
|
Unreachable();
|
|
while (1)
|
|
;
|
|
}
|
|
} else {
|
|
Entrance_GameTimerSetup();
|
|
}
|
|
}
|
|
|
|
void PlayerEntrance() {
|
|
uint8 player; // al
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
|
|
if (alt_entrance_ctrl != 2) {
|
|
if (obj_ypos_lo.player < 0x30u) {
|
|
AutoControlPlayer(0);
|
|
return;
|
|
}
|
|
if (player_entrance_ctrl == 6 || player_entrance_ctrl == 7) {
|
|
if ((player_sprattrib & 0xF0) != 0) {
|
|
AutoControlPlayer(1u);
|
|
} else {
|
|
EnterSidePipe();
|
|
if (!--change_area_timer) {
|
|
fade_direction = 1;
|
|
enable_mosaic_fades_flag = 1;
|
|
++screen_routines_flag0769;
|
|
++area_number;
|
|
LoadAreaPointer();
|
|
++fetch_new_game_timer_flag;
|
|
ChgAreaMode();
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
LABEL_19:
|
|
player_gfx_processing_flag = 0;
|
|
game_engine_subroutine = 8;
|
|
player_facing_dir = 1;
|
|
alt_entrance_ctrl = 0;
|
|
disable_collision_detection = 0;
|
|
vine_screen_exit_flag = 0;
|
|
return;
|
|
}
|
|
if (vine_screen_exit_flag) {
|
|
if (vine_height == 96) {
|
|
v1 = 0;
|
|
v2 = 1;
|
|
if (obj_ypos_lo.player >= 0x99u) {
|
|
player_state = 3;
|
|
v1 = 1;
|
|
v2 = 8;
|
|
level_data_map16_lo[180] = 8;
|
|
}
|
|
disable_collision_detection = v1;
|
|
AutoControlPlayer(v2);
|
|
if (obj_xpos_lo.player >= 0x48u)
|
|
goto LABEL_19;
|
|
}
|
|
} else {
|
|
player = obj_ypos_lo.player;
|
|
if (obj_ypos_lo.player == 0xB0) {
|
|
player = 4;
|
|
sound_ch1 = 4;
|
|
}
|
|
player_gfx_processing_flag = player;
|
|
MovePlayerYAxis(0xFFu);
|
|
if (obj_ypos_lo.player < 0x91u)
|
|
goto LABEL_19;
|
|
}
|
|
}
|
|
|
|
void AutoControlPlayer(uint8 a) {
|
|
saved_joypad_bits = a;
|
|
auto_control_player_var1 = 1;
|
|
func_sub_B02C();
|
|
}
|
|
|
|
void PlayerCtrlRoutine() {
|
|
auto_control_player_var1 = 0;
|
|
func_sub_B02C();
|
|
}
|
|
|
|
void func_sub_B02C() {
|
|
uint8 v0; // al
|
|
bool v1; // cf
|
|
uint8 v2; // di
|
|
uint8 v3; // di
|
|
uint8 v4; // al
|
|
uint8 v6; // al
|
|
uint8 v7; // al
|
|
int8 v8; // si
|
|
|
|
if (game_engine_subroutine != 11) {
|
|
if (!area_type && (obj_ypos_hi.player != 1 || obj_ypos_lo.player >= 0xD0u))
|
|
saved_joypad_bits = 0;
|
|
buttons_a_b = saved_joypad_bits & 0xC0;
|
|
buttons_left_right = saved_joypad_bits & 3;
|
|
buttons_up_down = saved_joypad_bits & 0xC;
|
|
if ((saved_joypad_bits & 4) != 0 && !player_state && buttons_left_right) {
|
|
buttons_left_right = 0;
|
|
buttons_up_down = 0;
|
|
}
|
|
}
|
|
if (!debug_flag)
|
|
goto LABEL_36;
|
|
if ((*(&controller_hold2p1 + current_player_mirror) & 0xC0) != 0) {
|
|
if ((*(&controller_hold2p1 + current_player_mirror) & 0x80) != 0) {
|
|
player_size = 0;
|
|
player_status = 1;
|
|
} else {
|
|
player_size = 0;
|
|
player_status = 2;
|
|
}
|
|
}
|
|
if ((controller_press1p1 & 0x20) != 0) {
|
|
level_free_movement_debug_flag ^= controller_press1p1 & 0x20;
|
|
disable_collision_detection = level_free_movement_debug_flag >> 5;
|
|
}
|
|
if (level_free_movement_debug_flag) {
|
|
player_star_power_timer = 16;
|
|
if ((*(&controller_hold2p1 + current_player) & 0x10) == 0 || (frame_counter & 7) != 0) {
|
|
if ((frame_counter & 7) == 0 && (saved_joypad_bits & 0x80u) != 0) {
|
|
player_size ^= 1u;
|
|
player_status ^= 2u;
|
|
GetPlayerColors();
|
|
}
|
|
v0 = saved_joypad_bits & 3;
|
|
if ((saved_joypad_bits & 3) != 0) {
|
|
player_facing_dir = buttons_left_right;
|
|
v1 = __CFADD__(kDATA_03AFE6[v0 - 1], obj_xpos_lo.player);
|
|
obj_xpos_lo.player += kDATA_03AFE6[v0 - 1];
|
|
obj_xpos_hi.player += kDATA_03AFE8[v0 - 1] + v1;
|
|
}
|
|
if ((saved_joypad_bits & 0xC) != 0) {
|
|
v2 = (uint8)(saved_joypad_bits & 0xC) >> 2;
|
|
v1 = __CFADD__(kDATA_03AFE6[v2 - 1], obj_ypos_lo.player);
|
|
obj_ypos_lo.player += kDATA_03AFE6[v2 - 1];
|
|
obj_ypos_hi.player += kDATA_03AFE8[v2 - 1] + v1;
|
|
}
|
|
} else if (saved_joypad_bits & 1) {
|
|
level_timer_tens = 9;
|
|
level_timer_ones = 9;
|
|
level_timer_hundreds = 9;
|
|
} else if ((saved_joypad_bits & 2) != 0) {
|
|
level_timer_tens = 0;
|
|
level_timer_ones = 0;
|
|
level_timer_hundreds = 0;
|
|
level_free_movement_debug_flag = 0;
|
|
} else if ((saved_joypad_bits & 4) == 0 && (saved_joypad_bits & 8) != 0) {
|
|
GiveExtraLife();
|
|
}
|
|
} else {
|
|
LABEL_36:
|
|
PlayerMovementSubs();
|
|
}
|
|
v3 = 1;
|
|
if (!player_size) {
|
|
v3 = 0;
|
|
if (crouching_flag)
|
|
v3 = 2;
|
|
}
|
|
player_hitbox_ctrl = v3;
|
|
v4 = 1;
|
|
if (obj_xspeed.player) {
|
|
if ((obj_xspeed.player & 0x80u) != 0)
|
|
v4 = 2;
|
|
player_moving_dir = v4;
|
|
}
|
|
ScrollHandler(-1);
|
|
GetPlayerOffscreenBits();
|
|
RelativePlayerPosition();
|
|
BoundingBoxCore(0, 0);
|
|
PlayerBGCollision();
|
|
if (obj_ypos_lo.player >= 0x40u && game_engine_subroutine != 5 && game_engine_subroutine != 7 && game_engine_subroutine >= 4u) {
|
|
if (game_engine_subroutine == 11)
|
|
v6 = player_sprattrib & 0xCE | 0x30;
|
|
else
|
|
v6 = player_sprattrib & 0xCE | 0x20;
|
|
player_sprattrib = v6;
|
|
}
|
|
v7 = obj_ypos_hi.player;
|
|
if (!sign8(obj_ypos_hi.player - 2)) {
|
|
scroll_lock = 1;
|
|
R7_ = 4;
|
|
v8 = 0;
|
|
if (game_timer_expired_flag || !cloud_type_override) {
|
|
v8 = 1;
|
|
if (game_engine_subroutine != 11) {
|
|
if (!death_music_loaded) {
|
|
++death_music_loaded;
|
|
music_ch1 = 9;
|
|
var0E67 = obj_ypos_hi.player;
|
|
v7 = 1;
|
|
player_size = 1;
|
|
player_status = 0;
|
|
}
|
|
R7_ = 6;
|
|
}
|
|
}
|
|
if (!sign8(v7 - R7_)) {
|
|
if ((int8)(v8 - 1) < 0) {
|
|
vine_screen_exit_flag = 0;
|
|
SetEntr();
|
|
++alt_entrance_ctrl;
|
|
} else if (!event_music_buffer) {
|
|
game_engine_subroutine = 6;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Vine_AutoClimb() {
|
|
if (obj_ypos_hi.player || obj_ypos_lo.player >= 0xE4u) {
|
|
vine_screen_exit_flag = 8;
|
|
var0E67 = 8;
|
|
player_state = 3;
|
|
AutoControlPlayer(8u);
|
|
} else {
|
|
SetEntr();
|
|
}
|
|
}
|
|
|
|
void SetEntr() {
|
|
alt_entrance_ctrl = 2;
|
|
ChgAreaMode();
|
|
}
|
|
|
|
void VerticalPipeEntry() {
|
|
uint8 v0; // di
|
|
|
|
enable_mosaic_fades_flag = 1;
|
|
vertical_pipe_flag_var0218 = 1;
|
|
if (frame_counter & 1)
|
|
MovePlayerYAxis(1u);
|
|
ScrollHandler(-1);
|
|
v0 = 0;
|
|
if (!warp_zone_control) {
|
|
v0 = 1;
|
|
if (area_type == 3)
|
|
v0 = 2;
|
|
}
|
|
if (!--change_area_timer) {
|
|
alt_entrance_ctrl = v0;
|
|
ChgAreaMode();
|
|
}
|
|
}
|
|
|
|
void MovePlayerYAxis(uint8 a) {
|
|
obj_ypos_lo.player += a;
|
|
}
|
|
|
|
void SideExitPipeEntry() {
|
|
var0E67 = 1;
|
|
enable_mosaic_fades_flag = 1;
|
|
EnterSidePipe();
|
|
if (!--change_area_timer) {
|
|
alt_entrance_ctrl = 2;
|
|
ChgAreaMode();
|
|
}
|
|
}
|
|
|
|
void ChgAreaMode() {
|
|
fade_direction = 1;
|
|
var0E67 = 1;
|
|
game_mode_task = 0;
|
|
sprite0_hit_detect_flag = 0;
|
|
}
|
|
|
|
void EnterSidePipe() {
|
|
uint8 v0; // di
|
|
|
|
obj_xspeed.player = 8;
|
|
v0 = 1;
|
|
if ((obj_xpos_lo.player & 0xF) == 0) {
|
|
obj_xspeed.player = 0;
|
|
v0 = 0;
|
|
}
|
|
AutoControlPlayer(v0);
|
|
}
|
|
|
|
void PlayerChangeSize() {
|
|
if (timer_control == 0xF8) {
|
|
InitChangeSize();
|
|
} else if (timer_control == 0xC4) {
|
|
DonePlayerTask();
|
|
}
|
|
}
|
|
|
|
void PlayerInjuryBlink() {
|
|
if (timer_control >= 0xF0u) {
|
|
if (timer_control == 0xF0)
|
|
InitChangeSize();
|
|
} else if (timer_control == 0xC8) {
|
|
DonePlayerTask();
|
|
} else {
|
|
PlayerCtrlRoutine();
|
|
}
|
|
}
|
|
|
|
void InitChangeSize() {
|
|
if (!player_change_size_flag) {
|
|
player_anim_ctrl = player_change_size_flag++;
|
|
player_size ^= 1u;
|
|
}
|
|
}
|
|
|
|
void PlayerDeath() {
|
|
if (timer_control < 0xF0u)
|
|
PlayerCtrlRoutine();
|
|
}
|
|
|
|
void DonePlayerTask() {
|
|
timer_control = 0;
|
|
GetPlayerColors();
|
|
game_engine_subroutine = 8;
|
|
}
|
|
|
|
void PlayerFireFlower() {
|
|
if (timer_control == 0xC0) {
|
|
DonePlayerTask();
|
|
ResetPalStar();
|
|
} else {
|
|
CyclePlayerPalette(2 * ~timer_control);
|
|
}
|
|
}
|
|
|
|
void CyclePlayerPalette(uint8 a) {
|
|
uint16 v1; // si
|
|
uint16 i; // di
|
|
|
|
v1 = (8 * a) & 0x60;
|
|
if (current_player)
|
|
v1 += 32;
|
|
for (i = 480; i != 512; i += 2) {
|
|
palette_mirror[i >> 1] = kDATA_05ED91[v1 >> 1];
|
|
v1 += 2;
|
|
}
|
|
update_entire_palette_flag = 1;
|
|
}
|
|
|
|
void ResetPalStar() {
|
|
player_sprattrib = player_sprattrib & 0xF1 | 0xE;
|
|
}
|
|
|
|
void FlagpoleSlide() {
|
|
uint8 v0; // al
|
|
|
|
if (enemy_id[5] == 48) {
|
|
v0 = 0;
|
|
flagpole_sound_queue = 0;
|
|
if (obj_ypos_lo.player < 0x9Eu)
|
|
v0 = 4;
|
|
AutoControlPlayer(v0);
|
|
} else {
|
|
++game_engine_subroutine;
|
|
}
|
|
}
|
|
|
|
void PlayerEndLevel() {
|
|
if (HandleMarioGoalWalk()) {
|
|
AutoControlPlayer(1u);
|
|
if (obj_ypos_lo.player >= 0xAEu)
|
|
scroll_lock = 0;
|
|
}
|
|
if (star_flag_task_control == 5) {
|
|
if (++level_number == 3 && coin_tally_for_1ups >= kHidden1UpCoinAmts[world_number])
|
|
++hidden_1up_flag;
|
|
++area_number;
|
|
halfway_page = 0;
|
|
TransposePlayers();
|
|
LoadAreaPointer();
|
|
++fetch_new_game_timer_flag;
|
|
ChgAreaMode();
|
|
}
|
|
}
|
|
|
|
void PlayerMovementSubs() {
|
|
uint8 v0; // al
|
|
int8 v1; // si
|
|
bool v3; // cf
|
|
uint8 v4; // si
|
|
|
|
v0 = 0;
|
|
if (!player_size) {
|
|
if (player_state)
|
|
goto LABEL_5;
|
|
v0 = buttons_up_down & 4;
|
|
}
|
|
crouching_flag = v0;
|
|
LABEL_5:
|
|
PlayerPhysicsSub();
|
|
if (player_change_size_flag)
|
|
return;
|
|
if (player_state != 3)
|
|
climb_side_timer = 24;
|
|
v1 = 2 * player_state;
|
|
if (!(2 * player_state)) {
|
|
GetPlayerAnimSpeed();
|
|
if (buttons_left_right)
|
|
player_facing_dir = buttons_left_right;
|
|
ImposeFriction(buttons_left_right);
|
|
player_x_scroll = MovePlayerHoriz();
|
|
return;
|
|
}
|
|
if (v1 == 4) {
|
|
vertical_force = vertical_force_down;
|
|
LABEL_28:
|
|
if (buttons_left_right)
|
|
ImposeFriction(buttons_left_right);
|
|
player_x_scroll = MovePlayerHoriz();
|
|
if (game_engine_subroutine == 11)
|
|
vertical_force = 40;
|
|
MovePlayerVert();
|
|
return;
|
|
}
|
|
if (v1 == 2) {
|
|
if ((obj_yspeed.player & 0x80u) == 0 ||
|
|
(buttons_a_b_previous & buttons_a_b & 0x80) == 0 && (uint8)(jump_origin_y_pos_lo - obj_ypos_lo.player) >= diff_to_halt_jump) {
|
|
vertical_force = vertical_force_down;
|
|
}
|
|
if (swimming_flag) {
|
|
GetPlayerAnimSpeed();
|
|
if (obj_ypos_lo.player < 0x14u)
|
|
vertical_force = 24;
|
|
if (buttons_left_right)
|
|
player_facing_dir = buttons_left_right;
|
|
}
|
|
goto LABEL_28;
|
|
}
|
|
if (v1 != 6) {
|
|
Unreachable();
|
|
while (1)
|
|
;
|
|
}
|
|
uint16 t = obj_sub_ypos.player + obj_sub_yspeed.player;
|
|
obj_sub_ypos.player = t;
|
|
AddHiLo(&obj_ypos_hi.player, &obj_ypos_lo.player, (t >> 8) + (int8)obj_yspeed.player);
|
|
if ((player_collision_bits & buttons_left_right) == 0) {
|
|
climb_side_timer = 0;
|
|
return;
|
|
}
|
|
if (!climb_side_timer) {
|
|
climb_side_timer = 24;
|
|
v4 = 0;
|
|
if (!(player_collision_bits & buttons_left_right & 1)) {
|
|
if (rel_xpos_lo.player < 0x10u)
|
|
return;
|
|
v4 = 2;
|
|
}
|
|
if (player_facing_dir != 1)
|
|
++v4;
|
|
v3 = __CFADD__(kClimbAdderLow[v4], obj_xpos_lo.player);
|
|
obj_xpos_lo.player += kClimbAdderLow[v4];
|
|
obj_xpos_hi.player += kClimbAdderHigh[v4] + v3;
|
|
player_facing_dir = buttons_left_right ^ 3;
|
|
}
|
|
}
|
|
|
|
void PlayerPhysicsSub() {
|
|
uint8 v0; // di
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
uint8 v3; // di
|
|
bool v4; // cf
|
|
|
|
if (player_state == 3) {
|
|
v0 = 0;
|
|
if ((player_collision_bits & buttons_up_down) != 0) {
|
|
v0 = 1;
|
|
if ((player_collision_bits & buttons_up_down & 8) != 0) {
|
|
if ((frame_counter & 7) == 0)
|
|
sound_ch1 = 48;
|
|
} else {
|
|
v0 = 2;
|
|
}
|
|
}
|
|
obj_sub_yspeed.player = kClimb_Y_MForceData[v0];
|
|
v1 = 8;
|
|
obj_yspeed.player = kClimb_Y_SpeedData[v0];
|
|
if ((obj_yspeed.player & 0x80u) == 0)
|
|
v1 = 4;
|
|
player_anim_timer_set = v1;
|
|
return;
|
|
}
|
|
if (!jumpspring_anim_ctrl && (buttons_a_b & 0x80u) != 0 && (buttons_a_b_previous & buttons_a_b & 0x80) == 0 &&
|
|
(!player_state || swimming_flag && (jump_swim_timer || (obj_yspeed.player & 0x80u) == 0))) {
|
|
jump_swim_timer = 32;
|
|
v2 = 0;
|
|
obj_sub_ypos.player = 0;
|
|
obj_sub_yspeed.player = 0;
|
|
jump_origin_y_pos_hi = obj_ypos_hi.player;
|
|
jump_origin_y_pos_lo = obj_ypos_lo.player;
|
|
player_state = 1;
|
|
if (player_x_speed_absolute >= 9u) {
|
|
v2 = 1;
|
|
if (player_x_speed_absolute >= 0x10u) {
|
|
v2 = 2;
|
|
if (player_x_speed_absolute >= 0x19u) {
|
|
v2 = 3;
|
|
if (player_x_speed_absolute >= 0x1Cu)
|
|
v2 = 4;
|
|
}
|
|
}
|
|
}
|
|
diff_to_halt_jump = 1;
|
|
if (swimming_flag) {
|
|
v2 = 5;
|
|
if (cannon_timer[0])
|
|
v2 = 6;
|
|
}
|
|
vertical_force = kJumpMForceData[v2];
|
|
vertical_force_down = kFallMForceData[v2];
|
|
obj_sub_yspeed.player = kInitMForceData[v2];
|
|
obj_yspeed.player = kPlayerYSpdData[v2];
|
|
if (swimming_flag) {
|
|
sound_ch1 = 14;
|
|
if (obj_ypos_lo.player < 0x14u)
|
|
obj_yspeed.player = 0;
|
|
} else {
|
|
sound_ch2 = 1;
|
|
}
|
|
}
|
|
v3 = 0;
|
|
R0_ = 0;
|
|
if (player_state) {
|
|
if (player_x_speed_absolute < 0x19u)
|
|
goto LABEL_37;
|
|
} else {
|
|
v3 = 1;
|
|
if (!area_type)
|
|
goto LABEL_37;
|
|
v3 = 0;
|
|
if (buttons_left_right != player_moving_dir)
|
|
goto LABEL_37;
|
|
if ((buttons_a_b & 0x40) != 0) {
|
|
running_timer = 10;
|
|
goto LABEL_41;
|
|
}
|
|
if (!running_timer) {
|
|
LABEL_37:
|
|
++v3;
|
|
++R0_;
|
|
if (running_speed || player_x_speed_absolute >= 0x21u)
|
|
++R0_;
|
|
}
|
|
}
|
|
LABEL_41:
|
|
max_left_speed = kMaxLeftXSpdData[v3];
|
|
if (game_engine_subroutine == 7)
|
|
v3 = 3;
|
|
max_right_speed = kMaxRightXSpdData[v3];
|
|
friction_adder_low = kFrictionData[R0_];
|
|
friction_adder_high = 0;
|
|
if (player_facing_dir != player_moving_dir) {
|
|
v4 = __CFSHL__(friction_adder_low, 1);
|
|
friction_adder_low *= 2;
|
|
friction_adder_high = 2 * friction_adder_high + v4;
|
|
}
|
|
}
|
|
|
|
void GetPlayerAnimSpeed() {
|
|
uint8 v0; // di
|
|
uint8 v1; // al
|
|
|
|
v0 = 0;
|
|
v1 = player_x_speed_absolute;
|
|
if (player_x_speed_absolute >= 0x1Cu)
|
|
goto LABEL_7;
|
|
v0 = 1;
|
|
if (player_x_speed_absolute < 0xEu)
|
|
v0 = 2;
|
|
if ((saved_joypad_bits & 0x7F) != 0) {
|
|
if ((saved_joypad_bits & 3) == player_moving_dir) {
|
|
v1 = 0;
|
|
LABEL_7:
|
|
running_speed = v1;
|
|
goto LABEL_10;
|
|
}
|
|
if (player_x_speed_absolute < 0xBu) {
|
|
player_moving_dir = player_facing_dir;
|
|
obj_xspeed.player = 0;
|
|
player_x_move_force = 0;
|
|
}
|
|
}
|
|
LABEL_10:
|
|
player_anim_timer_set = kPlayerAnimTmrData[v0];
|
|
}
|
|
|
|
void ImposeFriction(uint8 a) {
|
|
int8 v1; // al
|
|
uint8 player; // al
|
|
bool v3; // cf
|
|
|
|
v1 = player_collision_bits & a;
|
|
if (v1) {
|
|
if (v1 & 1) {
|
|
LABEL_6:
|
|
v3 = __CFADD__(friction_adder_low, player_x_move_force);
|
|
player_x_move_force += friction_adder_low;
|
|
player = friction_adder_high + v3 + obj_xspeed.player;
|
|
obj_xspeed.player = player;
|
|
if ((int8)(player - max_right_speed) >= 0) {
|
|
player = max_right_speed;
|
|
obj_xspeed.player = max_right_speed;
|
|
goto LABEL_12;
|
|
}
|
|
goto LABEL_10;
|
|
}
|
|
} else {
|
|
player = obj_xspeed.player;
|
|
if (!obj_xspeed.player)
|
|
goto LABEL_12;
|
|
if ((obj_xspeed.player & 0x80u) != 0)
|
|
goto LABEL_6;
|
|
}
|
|
v3 = player_x_move_force >= friction_adder_low;
|
|
player_x_move_force -= friction_adder_low;
|
|
player = obj_xspeed.player - (!v3 + friction_adder_high);
|
|
obj_xspeed.player = player;
|
|
if ((int8)(player - max_left_speed) < 0) {
|
|
player = max_left_speed;
|
|
obj_xspeed.player = max_left_speed;
|
|
}
|
|
LABEL_10:
|
|
if (sign8(player))
|
|
player = -player;
|
|
LABEL_12:
|
|
player_x_speed_absolute = player;
|
|
}
|
|
|
|
void ProcFireball_Bubble() {
|
|
int8 i; // si
|
|
|
|
if (player_status >= 2u) {
|
|
if ((buttons_a_b & 0x40) != 0 && (buttons_a_b_previous & buttons_a_b & 0x40) == 0 && !fireball_state[fireball_counter & 1] &&
|
|
obj_ypos_hi.player == 1 && !crouching_flag && player_state != 3) {
|
|
sound_ch3 = 6;
|
|
fireball_state[fireball_counter & 1] = 2;
|
|
fireball_throwing_timer = player_anim_timer_set;
|
|
player_anim_timer = player_anim_timer_set - 1;
|
|
++fireball_counter;
|
|
}
|
|
ProcessPlayerFireballs(0);
|
|
ProcessPlayerFireballs(1u);
|
|
}
|
|
if (!area_type) {
|
|
for (i = 2; i >= 0; --i) {
|
|
object_index = i;
|
|
BubbleCheck(i);
|
|
RelativeBubblePosition(i);
|
|
GetBubbleOffscreenBits(i);
|
|
DrawBubble(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProcessPlayerFireballs(uint8 k) {
|
|
uint8 v1; // di
|
|
bool v2; // cf
|
|
uint8 v3; // si
|
|
uint8 v4; // si
|
|
|
|
object_index = k;
|
|
if (__CFSHL__(fireball_state[k], 1)) {
|
|
RelativeFireballPosition(k);
|
|
DrawExplodingPlayerFireball(k);
|
|
} else {
|
|
v1 = fireball_state[k];
|
|
if (v1) {
|
|
if (v1 != 1) {
|
|
v2 = __CFADD__(obj_xpos_lo.player, 4);
|
|
obj_xpos_lo.fireball[k] = obj_xpos_lo.player + 4;
|
|
obj_xpos_hi.fireball[k] = v2 + obj_xpos_hi.player;
|
|
obj_ypos_lo.fireball[k] = obj_ypos_lo.player;
|
|
obj_ypos_hi.fireball[k] = 1;
|
|
obj_xspeed.fireball[k] = kFireballXSpdData[(uint8)(player_facing_dir - 1)];
|
|
obj_yspeed.fireball[k] = 4;
|
|
fireball_hitbox_size_index[k] = 7;
|
|
--fireball_state[k];
|
|
}
|
|
v3 = k + 11;
|
|
R0_ = 80;
|
|
R2_ = 3;
|
|
ImposeGravity(v3, 0);
|
|
MoveObjectHoriz(v3);
|
|
v4 = object_index;
|
|
RelativeFireballPosition(object_index);
|
|
GetFireballOffscreenBits(v4);
|
|
GetFireballBoundBox(v4);
|
|
FireballBGCollision(v4);
|
|
if ((offscreen_bits.fireball & 0xFC) == 0) {
|
|
FireballEnemyCollision(v4);
|
|
LABEL_13:
|
|
DrawFireball(v4);
|
|
return;
|
|
}
|
|
if ((offscreen_bits.fireball & 0xF0) == 0) {
|
|
if ((obj_xspeed.fireball[v4] & 0x80u) != 0) {
|
|
if ((offscreen_bits.fireball & 0xC) != 12)
|
|
goto LABEL_13;
|
|
} else if ((offscreen_bits.fireball & 0xF) != 15) {
|
|
goto LABEL_13;
|
|
}
|
|
}
|
|
fireball_state[v4] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void BubbleCheck(uint8 k) {
|
|
R7_ = *(&random_byte2 + k) & 1;
|
|
if (obj_ypos_lo.bubble[k] == 0xF8) {
|
|
if (!air_bubble_timer)
|
|
SetupBubble(k);
|
|
} else {
|
|
func_sub_B7F4(k);
|
|
}
|
|
}
|
|
|
|
void SetupBubble(uint8 k) {
|
|
int8 v1; // di
|
|
bool v2; // cf
|
|
|
|
v1 = 0;
|
|
if (player_facing_dir & 1)
|
|
v1 = 8;
|
|
v2 = __CFADD__(obj_xpos_lo.player, v1);
|
|
obj_xpos_lo.bubble[k] = obj_xpos_lo.player + v1;
|
|
obj_xpos_hi.bubble[k] = v2 + obj_xpos_hi.player;
|
|
obj_ypos_lo.bubble[k] = obj_ypos_lo.player + 8;
|
|
obj_ypos_hi.bubble[k] = 1;
|
|
air_bubble_timer = kBubbleTimerData[R7_];
|
|
func_sub_B7F4(k);
|
|
}
|
|
|
|
void func_sub_B7F4(uint8 k) {
|
|
uint8 v1; // al
|
|
bool v2; // cf
|
|
uint8 v3; // al
|
|
|
|
v1 = obj_sub_ypos.bubble[k];
|
|
v2 = v1 < kBubble_MForceData[R7_];
|
|
obj_sub_ypos.bubble[k] = v1 - kBubble_MForceData[R7_];
|
|
v3 = obj_ypos_lo.bubble[k] - v2;
|
|
if (v3 < 0x20u)
|
|
v3 = -8;
|
|
obj_ypos_lo.bubble[k] = v3;
|
|
}
|
|
|
|
void RunGameTimer() {
|
|
if (game_mode && game_engine_subroutine >= 8u && game_engine_subroutine != 11 && sign8(obj_ypos_hi.player - 2) && !game_paused_timer) {
|
|
if (level_timer_ones | (uint8)(level_timer_tens | level_timer_hundreds)) {
|
|
if (level_timer_hundreds == 1 && !__PAIR16__(level_timer_ones, level_timer_tens))
|
|
sound_ch1 = -1;
|
|
game_paused_timer = 24;
|
|
digit_modifier[5] = -1;
|
|
if (!level_free_movement_debug_flag)
|
|
DigitsMathRoutine(0x23u);
|
|
PrintStatusBarNumbers(0xA4u);
|
|
} else {
|
|
player_status = 0;
|
|
ForceInjury(0);
|
|
++game_timer_expired_flag;
|
|
}
|
|
}
|
|
}
|
|
|
|
void WarpZoneObject(uint8 k) {
|
|
if (scroll_lock) {
|
|
if ((obj_ypos_hi.player & obj_ypos_lo.player) == 0) {
|
|
scroll_lock = 0;
|
|
++warp_zone_control;
|
|
EraseEnemyObject(k);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProcessWhirlpools() {
|
|
uint8 v0; // di
|
|
uint8 v1; // al
|
|
bool v2; // cf
|
|
uint8 v3; // al
|
|
|
|
if (!area_type) {
|
|
cannon_timer[0] = area_type;
|
|
AdjustUnderwaterHDMAGradient();
|
|
if (!timer_control) {
|
|
v0 = 4;
|
|
while (1) {
|
|
uint16 t = cannon_ypos_lo[v0] + cannon_xpos_lo[v0];
|
|
R2_ = t;
|
|
if (cannon_xpos_hi[v0]) {
|
|
R1_ = cannon_xpos_hi[v0] + (t >> 8);
|
|
if ((int8)(obj_xpos_hi.player - ((obj_xpos_lo.player < cannon_xpos_lo[v0]) + cannon_xpos_hi[v0])) >= 0 &&
|
|
(int8)(R1_ - ((R2_ < obj_xpos_lo.player) + obj_xpos_hi.player)) >= 0) {
|
|
break;
|
|
}
|
|
}
|
|
if ((--v0 & 0x80u) != 0)
|
|
return;
|
|
}
|
|
R0_ = cannon_ypos_lo[v0] >> 1;
|
|
v1 = cannon_xpos_lo[v0];
|
|
R1_ = R0_ + v1;
|
|
R0_ = __CFADD__(R0_, v1) + cannon_xpos_hi[v0];
|
|
if (!(frame_counter & 1))
|
|
goto LABEL_15;
|
|
if ((int8)(R0_ - ((R1_ < obj_xpos_lo.player) + obj_xpos_hi.player)) >= 0) {
|
|
if (!(player_collision_bits & 1)) {
|
|
LABEL_15:
|
|
R0_ = 16;
|
|
cannon_timer[0] = 1;
|
|
R2_ = 1;
|
|
ImposeGravity(0, 0);
|
|
return;
|
|
}
|
|
v2 = __CFADD__(obj_xpos_lo.player++, 1);
|
|
v3 = v2 + obj_xpos_hi.player;
|
|
} else {
|
|
v2 = obj_xpos_lo.player-- != 0;
|
|
v3 = obj_xpos_hi.player - !v2;
|
|
}
|
|
obj_xpos_hi.player = v3;
|
|
goto LABEL_15;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FlagpoleRoutine() {
|
|
uint8 v0; // si
|
|
uint8 v1; // al
|
|
bool v2; // cf
|
|
int8 v3; // al
|
|
int8 v4; // al
|
|
|
|
v0 = 5;
|
|
object_index = 5;
|
|
if (enemy_id[5] == 48) {
|
|
if (game_engine_subroutine == 4 && player_state == 3) {
|
|
if (obj_ypos_lo.enemy[5] >= 0xAAu || obj_ypos_lo.player >= 0xA2u) {
|
|
int t0 = kFlagpoleScoreDigits[flagpole_score];
|
|
digit_modifier[t0] = kFlagpoleScoreMods[flagpole_score];
|
|
AddToScore();
|
|
game_engine_subroutine = 5;
|
|
music_ch1 = 12;
|
|
if ((player_facing_dir & 2) != 0)
|
|
v4 = 96;
|
|
else
|
|
v4 = 110;
|
|
LOBYTE(some_xpos16_var02fd) = v4;
|
|
LOBYTE(flagpole_player_xpos16) = obj_xpos_lo.player;
|
|
HIBYTE(flagpole_player_xpos16) = obj_xpos_hi.player;
|
|
flagpole_timer_var03fb = 32;
|
|
flagpole_timer_var03fa = 32;
|
|
} else {
|
|
v1 = obj_sub_ypos.enemy[5];
|
|
v2 = __CFADD__(obj_ypos_lo.player >= 0xA2u, v1);
|
|
v3 = (obj_ypos_lo.player >= 0xA2u) + v1;
|
|
obj_sub_ypos.enemy[5] = v3 - 1;
|
|
obj_ypos_lo.enemy[5] += (v2 || v3 != 0) + 1;
|
|
v2 = flagpole_score_sub_ypos++ == 0xFFu;
|
|
flagpole_score_ypos_lo -= !v2 + 1;
|
|
}
|
|
}
|
|
GetEnemyOffscreenBits(v0);
|
|
RelativeEnemyPosition(v0);
|
|
FlagpoleGfxHandler(v0);
|
|
}
|
|
}
|
|
|
|
void JumpspringHandler(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
GetEnemyOffscreenBits(k);
|
|
if (!timer_control && jumpspring_anim_ctrl) {
|
|
v1 = jumpspring_anim_ctrl - 1;
|
|
if (((jumpspring_anim_ctrl - 1) & 2) != 0) {
|
|
--obj_ypos_lo.player;
|
|
--obj_ypos_lo.player;
|
|
} else {
|
|
++obj_ypos_lo.player;
|
|
++obj_ypos_lo.player;
|
|
}
|
|
obj_ypos_lo.enemy[k] = kJumpspring_Y_PosData[v1] + obj_xspeed.enemy[k];
|
|
if (v1 && (buttons_a_b & 0x80u) != 0 && (buttons_a_b_previous & buttons_a_b & 0x80) == 0)
|
|
jumpspring_force = -12;
|
|
if (v1 == 3) {
|
|
obj_yspeed.player = jumpspring_force;
|
|
jumpspring_anim_ctrl = 0;
|
|
sound_ch3 = 8;
|
|
}
|
|
}
|
|
RelativeEnemyPosition(k);
|
|
EnemyGfxHandler_New(k);
|
|
OffscreenBoundsCheck(k);
|
|
if (jumpspring_anim_ctrl) {
|
|
if (!jumpspring_timer) {
|
|
jumpspring_timer = 4;
|
|
++jumpspring_anim_ctrl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Spr02F_Vine_Init(uint8 k, uint8 j) {
|
|
uint8 v2; // al
|
|
|
|
enemy_id[k] = 47;
|
|
enemy_flag[k] = 1;
|
|
obj_xpos_hi.enemy[k] = obj_xpos_hi.block[j];
|
|
obj_xpos_lo.enemy[k] = obj_xpos_lo.block[j];
|
|
v2 = obj_ypos_lo.block[j];
|
|
if (!v2)
|
|
v2 = -16;
|
|
obj_ypos_lo.enemy[k] = v2;
|
|
if (!vine_flag_offset)
|
|
vinestart_y_pos = v2;
|
|
vine_obj_offset[vine_flag_offset++] = k;
|
|
sound_ch3 = 3;
|
|
}
|
|
|
|
void Spr02F_Vine_Init2(uint8 k) {
|
|
Spr02F_Vine_Init(k, 0);
|
|
}
|
|
|
|
void VineObjectHandler(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
if (k == 9) {
|
|
if (vine_at_entrance_flag)
|
|
v1 = kVineHeightData[0];
|
|
else
|
|
v1 = kVineHeightData[1];
|
|
if (v1 != vine_height && frame_counter & 1) {
|
|
obj_ypos_lo.enemy[9] -= !(frame_counter & 1) + 1;
|
|
++vine_height;
|
|
}
|
|
if (vine_height >= 8u) {
|
|
RelativeEnemyPosition(9u);
|
|
GetEnemyOffscreenBits(9u);
|
|
DrawVine(0);
|
|
if ((offscreen_bits.enemy & 0xF) == 15) {
|
|
EraseEnemyObject(9u);
|
|
vine_flag_offset = 0;
|
|
vine_height = 0;
|
|
}
|
|
if (vine_height >= 0x20u) {
|
|
BlockBufferCollision(0xAu, 0x1Bu, 1u);
|
|
if (R2_ < 0xD0u && (vine_at_entrance_flag || (R2_ & 0x80u) == 0) && !RomPtr_RAM(*(uint16 *)&R6_)[R2_])
|
|
RomPtr_RAM(*(uint16 *)&R6_)[R2_] = 42;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProcessCannons() {
|
|
uint8 v0; // si
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
|
|
if (area_type) {
|
|
v0 = 2;
|
|
while (1) {
|
|
object_index = v0;
|
|
if (enemy_flag[v0])
|
|
goto LABEL_10;
|
|
if ((uint8)(kCannonBitmasks[secondary_hard_mode] & *(&random_byte2 + v0)) >= 6u)
|
|
goto LABEL_10;
|
|
v1 = kCannonBitmasks[secondary_hard_mode] & *(&random_byte2 + v0);
|
|
if (!cannon_xpos_hi[v1])
|
|
goto LABEL_10;
|
|
v2 = cannon_timer[v1];
|
|
if (v2)
|
|
break;
|
|
if (timer_control)
|
|
goto LABEL_10;
|
|
cannon_timer[v1] = 14;
|
|
obj_xpos_hi.enemy[v0] = cannon_xpos_hi[v1];
|
|
obj_xpos_lo.enemy[v0] = cannon_xpos_lo[v1];
|
|
obj_ypos_lo.enemy[v0] = cannon_ypos_lo[v1] - 8;
|
|
obj_ypos_hi.enemy[v0] = 1;
|
|
enemy_flag[v0] = 1;
|
|
enemy_state[v0] = 0;
|
|
enemy_hitbox_ctrl[v0] = 9;
|
|
enemy_id[v0] = 51;
|
|
LABEL_13:
|
|
if ((--v0 & 0x80u) != 0)
|
|
return;
|
|
}
|
|
cannon_timer[v1] = v2 - 1;
|
|
LABEL_10:
|
|
if (enemy_id[v0] == 51) {
|
|
OffscreenBoundsCheck(v0);
|
|
if (enemy_flag[v0]) {
|
|
GetEnemyOffscreenBits(v0);
|
|
BulletBillHandler(v0);
|
|
}
|
|
}
|
|
goto LABEL_13;
|
|
}
|
|
}
|
|
|
|
void BulletBillHandler(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
if (timer_control) {
|
|
LABEL_13:
|
|
GetEnemyOffscreenBits(k);
|
|
RelativeEnemyPosition(k);
|
|
GetEnemyBoundBox(k);
|
|
PlayerEnemyCollision(k);
|
|
EnemyGfxHandler_New(k);
|
|
return;
|
|
}
|
|
if (!enemy_state[k]) {
|
|
if ((offscreen_bits.enemy & 0xC) == 12)
|
|
goto LABEL_14;
|
|
v1 = 1;
|
|
if ((PlayerEnemyDiff(k) & 0x80u) == 0)
|
|
v1 = 2;
|
|
enemy_moving_dir[k] = v1;
|
|
obj_xspeed.enemy[k] = kBulletBillXSpdData[(uint8)(v1 - 1)];
|
|
if ((uint8)(R0_ + 40) < 0x50u)
|
|
goto LABEL_14;
|
|
enemy_state[k] = 1;
|
|
enemy_frame_timer[k] = 10;
|
|
sound_ch3 = 74;
|
|
BulletBillSfxHandler(k, 0x4Au);
|
|
}
|
|
if ((offscreen_bits.enemy & 0xF0) != 0xF0) {
|
|
if ((enemy_state[k] & 0x20) != 0)
|
|
MoveD_EnemyVert(k);
|
|
if (!var0E67) {
|
|
MoveEnemyHoriz(k);
|
|
BulletBill_MoveNew(k);
|
|
}
|
|
goto LABEL_13;
|
|
}
|
|
LABEL_14:
|
|
EraseEnemyObject(k);
|
|
}
|
|
|
|
uint8 SpawnThrownHammer(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
v1 = random_byte2 & 7;
|
|
if ((random_byte2 & 7) == 0)
|
|
v1 = random_byte2 & 8;
|
|
if (misc_state[v1] || enemy_flag[kHammerEnemyOfsData[v1]])
|
|
return 0;
|
|
hammer_enemy_offset[v1] = object_index;
|
|
misc_state[v1] = -112;
|
|
misc_boundboxctrl[v1] = 7;
|
|
return 1;
|
|
}
|
|
|
|
void ProcHammerObj(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // cl
|
|
uint8 v3; // si
|
|
int8 v4; // al
|
|
bool v5; // cf
|
|
|
|
if (!timer_control) {
|
|
v1 = hammer_enemy_offset[k];
|
|
v2 = misc_state[k] & 0x7F;
|
|
if (v2 == 2) {
|
|
obj_yspeed.misc[k] = -2;
|
|
enemy_state[v1] &= ~8u;
|
|
k = object_index;
|
|
obj_xspeed.misc[object_index] = kHammerXSpdData[(uint8)(enemy_moving_dir[v1] - 1)];
|
|
} else if (v2 < 2u) {
|
|
v3 = k + 17;
|
|
R0_ = 16;
|
|
R1_ = 15;
|
|
R2_ = 4;
|
|
ImposeGravity(v3, 0);
|
|
MoveObjectHoriz(v3);
|
|
k = object_index;
|
|
PlayerHammerCollision(object_index);
|
|
goto LABEL_14;
|
|
}
|
|
if (--misc_state[k] == 0x81)
|
|
sound_ch1 = 55;
|
|
if (enemy_id[v1] == 45) {
|
|
v4 = 8;
|
|
} else if (enemy_moving_dir[v1] == 2) {
|
|
v4 = 6;
|
|
} else {
|
|
v4 = 2;
|
|
}
|
|
v5 = __CFADD__(obj_xpos_lo.enemy[v1], v4);
|
|
obj_xpos_lo.misc[k] = obj_xpos_lo.enemy[v1] + v4;
|
|
obj_xpos_hi.misc[k] = v5 + obj_xpos_hi.enemy[v1];
|
|
obj_ypos_lo.misc[k] = obj_ypos_lo.enemy[v1] - 10;
|
|
obj_ypos_hi.misc[k] = 1;
|
|
}
|
|
LABEL_14:
|
|
GetMiscOffscreenBits(k);
|
|
RelativeMiscPosition(k);
|
|
GetMiscBoundBox(k);
|
|
DrawHammer(k);
|
|
}
|
|
|
|
void SetupJumpCoin(uint8 k) {
|
|
uint8 EmptyMiscSlot; // di
|
|
|
|
EmptyMiscSlot = FindEmptyMiscSlot();
|
|
obj_xpos_hi.misc[EmptyMiscSlot] = block_xpos_hi2[k];
|
|
obj_xpos_lo.misc[EmptyMiscSlot] = (16 * R6_) | 5;
|
|
obj_ypos_lo.misc[EmptyMiscSlot] = R2_ + 32;
|
|
SetupCoinCommon(k, EmptyMiscSlot);
|
|
}
|
|
|
|
void SetupCoinCommon(uint8 k, uint8 j) {
|
|
obj_yspeed.misc[j] = -5;
|
|
obj_ypos_hi.misc[j] = 1;
|
|
misc_state[j] = 1;
|
|
sound_ch3 = 1;
|
|
object_index = k;
|
|
GiveOneCoin();
|
|
++coin_tally_for_1ups;
|
|
}
|
|
|
|
uint8 FindEmptyMiscSlot() {
|
|
uint8 result; // di
|
|
|
|
result = 8;
|
|
while (misc_state[result]) {
|
|
if (--result == 5) {
|
|
result = 8;
|
|
break;
|
|
}
|
|
}
|
|
misc_slot_index = result;
|
|
return result;
|
|
}
|
|
|
|
void MiscObjectsCore() {
|
|
uint8 i; // si
|
|
uint8 v1; // al
|
|
uint8 v2; // al
|
|
bool v3; // cf
|
|
|
|
for (i = 8; (i & 0x80u) == 0; --i) {
|
|
object_index = i;
|
|
v1 = misc_state[i];
|
|
if (!v1)
|
|
continue;
|
|
if (__CFSHL__(v1, 1)) {
|
|
ProcHammerObj(i);
|
|
continue;
|
|
}
|
|
if (misc_state[i] == 1) {
|
|
R0_ = 80;
|
|
R2_ = 6;
|
|
R1_ = 3;
|
|
ImposeGravity(i + 17, 0);
|
|
i = object_index;
|
|
if (obj_yspeed.misc[object_index] == 5)
|
|
++misc_state[object_index];
|
|
} else {
|
|
++misc_state[i];
|
|
v2 = obj_xpos_lo.misc[i];
|
|
v3 = __CFADD__(scroll_amount, v2);
|
|
obj_xpos_lo.misc[i] = scroll_amount + v2;
|
|
obj_xpos_hi.misc[i] += v3;
|
|
if (misc_state[i] == 48) {
|
|
misc_state[i] = 0;
|
|
continue;
|
|
}
|
|
}
|
|
if (!obj_yspeed.misc[i])
|
|
SpinningCoinSprite_Init(i);
|
|
RelativeMiscPosition(i);
|
|
GetMiscOffscreenBits(i);
|
|
GetMiscBoundBox(i);
|
|
DrawSpinningCoinSprite(i);
|
|
}
|
|
}
|
|
|
|
void GiveOneCoin() {
|
|
digit_modifier[5] = 1;
|
|
DigitsMathRoutine(kCoinTallyOffsets[current_player]);
|
|
if (++player_coin_count == 100) {
|
|
player_coin_count = 0;
|
|
GiveExtraLife();
|
|
sound_ch3 = 5;
|
|
}
|
|
digit_modifier[4] = 2;
|
|
AddToScore();
|
|
}
|
|
|
|
void AddToScore() {
|
|
DigitsMathRoutine(kScoreOffsets[current_player]);
|
|
GetSBNibbles();
|
|
}
|
|
|
|
void GetSBNibbles() {
|
|
UpdateNumber(kStatusBarNybbles[current_player_mirror]);
|
|
}
|
|
|
|
void UpdateNumber(uint8 a) {
|
|
int8 v1; // al
|
|
|
|
PrintStatusBarNumbers(a);
|
|
if (!vram_buffer1[vram_buffer1_offset - 11]) {
|
|
v1 = 40;
|
|
if (vram_buffer1[vram_buffer1_offset - 15] == 2)
|
|
v1 = 36;
|
|
vram_buffer1[vram_buffer1_offset - 11] = v1;
|
|
}
|
|
}
|
|
// 7E16F6: using guessed type uint8[10];
|
|
|
|
void Spr02E_Powerup_Init(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
enemy_state[9] = 1;
|
|
enemy_flag[9] = 1;
|
|
enemy_hitbox_ctrl[9] = 3;
|
|
if (power_up_type < 2u) {
|
|
v1 = player_status;
|
|
if (player_status >= 2u)
|
|
v1 = player_status >> 1;
|
|
power_up_type = v1;
|
|
}
|
|
enemy_sprattrib[9] = 48;
|
|
sound_ch3 = 2;
|
|
}
|
|
|
|
void PowerUpObjHandler(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
object_index = 9;
|
|
if (enemy_state[9]) {
|
|
if (__CFSHL__(enemy_state[9], 1)) {
|
|
if (!timer_control) {
|
|
if (!power_up_type || power_up_type == 3) {
|
|
MoveNormalEnemy(9u);
|
|
EnemyToBGCollisionDet(9u);
|
|
} else if (power_up_type == 2) {
|
|
MoveJumpingEnemy(9u);
|
|
EnemyJump(9u);
|
|
}
|
|
}
|
|
LABEL_13:
|
|
RelativeEnemyPosition(9u);
|
|
GetEnemyOffscreenBits(9u);
|
|
GetEnemyBoundBox(9u);
|
|
DrawPowerUp();
|
|
PlayerEnemyCollision(9u);
|
|
OffscreenBoundsCheck(9u);
|
|
return;
|
|
}
|
|
if ((frame_counter & 3) == 0) {
|
|
--obj_ypos_lo.enemy[9];
|
|
v1 = enemy_state[9]++;
|
|
if (v1 >= 0x11u) {
|
|
obj_xspeed.enemy[9] = 16;
|
|
enemy_state[9] = 0x80;
|
|
enemy_sprattrib[9] = 0;
|
|
enemy_moving_dir[9] = __CFSHL__(0x80, 1);
|
|
}
|
|
}
|
|
if (enemy_state[9] >= 6u)
|
|
goto LABEL_13;
|
|
}
|
|
}
|
|
// 7E0241: using guessed type int8;
|
|
|
|
void PlayerHeadCollision(uint8 a) {
|
|
uint8 v1; // al
|
|
uint8 v2; // si
|
|
uint8 v3; // al
|
|
int v4; // edx
|
|
uint8 v5; // al
|
|
uint8 v6; // di
|
|
uint8 v7; // di
|
|
uint8 t;
|
|
|
|
v1 = 17;
|
|
if (!player_size)
|
|
v1 = 18;
|
|
block_state[spr_data_offset_ctrl] = v1;
|
|
DestroyBlockMetatile();
|
|
v2 = spr_data_offset_ctrl;
|
|
v3 = R2_;
|
|
v4 = spr_data_offset_ctrl;
|
|
block_orig_ypos[spr_data_offset_ctrl] = R2_;
|
|
block_bbuf_low[v4] = R6_;
|
|
v5 = RomPtr_RAM(*(uint16 *)&R6_)[v3];
|
|
t = BlockBumpedChk(v5);
|
|
R0_ = v5;
|
|
if (!player_size)
|
|
v5 = player_size;
|
|
if (t != 0xff) {
|
|
block_state[v2] = 17;
|
|
v5 = -4;
|
|
v6 = R0_;
|
|
if (R0_ == 91 || R0_ == 96) {
|
|
if (!brick_coin_timer_flag) {
|
|
brick_coin_timer = 11;
|
|
++brick_coin_timer_flag;
|
|
}
|
|
if (!brick_coin_timer)
|
|
v6 = -4;
|
|
v5 = v6;
|
|
}
|
|
}
|
|
block_metatile[v2] = v5;
|
|
InitBlock_XY_Pos(v2);
|
|
RomPtr_RAM(*(uint16 *)&R6_)[R2_] = 39;
|
|
block_bounce_timer = 16;
|
|
R5_ = a;
|
|
v7 = 0;
|
|
if (crouching_flag || player_size)
|
|
v7 = 1;
|
|
obj_ypos_lo.block[v2] = (kBlockYPosAdderData[v7] + obj_ypos_lo.player) & 0xF0;
|
|
if (block_state[v2] == 17)
|
|
BumpBlock();
|
|
else
|
|
BrickShatter();
|
|
spr_data_offset_ctrl ^= 1u;
|
|
}
|
|
|
|
void InitBlock_XY_Pos(uint8 k) {
|
|
uint t = PAIR16(obj_xpos_hi.player, obj_xpos_lo.player) + 8;
|
|
obj_xpos_lo.block[k] = t & ~0xf;
|
|
LOBYTE(xpos_new_var0E16) = t & ~0xf;
|
|
obj_xpos_hi.block[k] = t >> 8;
|
|
block_xpos_hi2[k] = t >> 8;
|
|
HIBYTE(xpos_new_var0E16) = t >> 8;
|
|
obj_ypos_hi.block[k] = obj_ypos_hi.player;
|
|
}
|
|
|
|
void BumpBlock() {
|
|
uint8 v0; // si
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
uint8 v3; // al
|
|
uint8 EmptyMiscSlot; // di
|
|
|
|
v0 = CheckTopOfBlock();
|
|
sound_ch1 = 1;
|
|
obj_xspeed.block[v0] = 0;
|
|
obj_sub_yspeed.block[v0] = 0;
|
|
obj_yspeed.player = 0;
|
|
obj_yspeed.block[v0] = -2;
|
|
v1 = BlockBumpedChk(R5_);
|
|
if (v1 != 0xff) {
|
|
v2 = v1;
|
|
if (v1 >= 9u)
|
|
v2 = v1 - 5;
|
|
R4_ = *((uint8 *)kDATA_03BF64 + (uint8)(2 * v2));
|
|
R5_ = *((uint8 *)kDATA_03BF64 + (uint8)(2 * v2) + 1);
|
|
switch ((uint8)(2 * v2) >> 1) {
|
|
case 0:
|
|
case 4: v3 = 0; goto LABEL_8;
|
|
case 1:
|
|
case 2:
|
|
case 7:
|
|
EmptyMiscSlot = FindEmptyMiscSlot();
|
|
obj_xpos_hi.misc[EmptyMiscSlot] = obj_xpos_hi.block[v0];
|
|
obj_xpos_lo.misc[EmptyMiscSlot] = obj_xpos_lo.block[v0] | 5;
|
|
obj_ypos_lo.misc[EmptyMiscSlot] = obj_ypos_lo.block[v0] - 16;
|
|
SetupCoinCommon(v0, EmptyMiscSlot);
|
|
return;
|
|
case 3:
|
|
case 8: v3 = 3; goto LABEL_8;
|
|
case 5: Spr02F_Vine_Init(9u, spr_data_offset_ctrl); return;
|
|
case 6:
|
|
v3 = 2;
|
|
LABEL_8:
|
|
power_up_type = v3;
|
|
enemy_id[9] = 46;
|
|
obj_xpos_hi.enemy[9] = obj_xpos_hi.block[v0];
|
|
obj_xpos_lo.enemy[9] = obj_xpos_lo.block[v0];
|
|
obj_ypos_hi.enemy[9] = 1;
|
|
obj_ypos_lo.enemy[9] = obj_ypos_lo.block[v0] - 8;
|
|
Spr02E_Powerup_Init(v0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// 7E0082: using guessed type int8;
|
|
// 7E00C5: using guessed type int8;
|
|
// 7E0223: using guessed type int8;
|
|
|
|
uint8 BlockBumpedChk(uint8 a) {
|
|
uint8 result; // di
|
|
|
|
for (result = 13; (result & 0x80u) == 0; --result) {
|
|
if (a == kBrickQBlockMetatiles[result])
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void BrickShatter() {
|
|
uint8 v0; // si
|
|
|
|
v0 = CheckTopOfBlock();
|
|
block_repflag[v0] = 1;
|
|
if (!sound_ch3)
|
|
sound_ch3 = 7;
|
|
SpawnBrickChunks(v0);
|
|
obj_yspeed.player = -2;
|
|
digit_modifier[5] = 5;
|
|
AddToScore();
|
|
}
|
|
|
|
uint8 CheckTopOfBlock() {
|
|
uint8 result; // si
|
|
uint8 v1; // di
|
|
uint8 v2; // di
|
|
|
|
result = spr_data_offset_ctrl;
|
|
v1 = R2_;
|
|
if (R2_) {
|
|
R2_ -= 16;
|
|
v2 = v1 - 16;
|
|
if (RomPtr_RAM(*(uint16 *)&R6_)[v2] == 0xE9) {
|
|
RomPtr_RAM(*(uint16 *)&R6_)[v2] = 0;
|
|
sound_ch3 = 1;
|
|
RemoveCoin_Axe();
|
|
result = spr_data_offset_ctrl;
|
|
SetupJumpCoin(spr_data_offset_ctrl);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void SpawnBrickChunks(uint8 k) {
|
|
block_orig_xpos_lo[k] = obj_xpos_lo.block[k];
|
|
obj_xspeed.block[k] = -16;
|
|
obj_xspeed.misc[k - 2] = -16;
|
|
obj_yspeed.block[k] = -6;
|
|
obj_yspeed.misc[k - 2] = -4;
|
|
obj_sub_yspeed.block[k] = 0;
|
|
obj_sub_yspeed.misc[k - 2] = 0;
|
|
obj_xpos_hi.misc[k - 2] = obj_xpos_hi.block[k];
|
|
obj_xpos_lo.misc[k - 2] = obj_xpos_lo.block[k];
|
|
obj_ypos_lo.misc[k - 2] = obj_ypos_lo.block[k] + 8;
|
|
obj_yspeed.block[k] = -6;
|
|
}
|
|
|
|
void BlockObjectsCore(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // si
|
|
uint8 v3; // si
|
|
uint8 v4; // si
|
|
|
|
v1 = block_state[k];
|
|
if (v1) {
|
|
v2 = k + 13;
|
|
if ((v1 & 0xF) == 1) {
|
|
ImposeGravityBlock(v2);
|
|
v4 = object_index;
|
|
RelativeBlockPosition(object_index);
|
|
GetBlockOffscreenBits(v4);
|
|
DrawBlock(v4);
|
|
block_state[v4] = 1;
|
|
if ((obj_ypos_lo.block[v4] & 0xFu) >= 5)
|
|
return;
|
|
block_repflag[v4] = 1;
|
|
goto LABEL_10;
|
|
}
|
|
ImposeGravityBlock(v2);
|
|
MoveObjectHoriz(v2);
|
|
v3 = v2 + 2;
|
|
ImposeGravityBlock(v3);
|
|
MoveObjectHoriz(v3);
|
|
v4 = object_index;
|
|
RelativeBlockPosition(object_index);
|
|
GetBlockOffscreenBits(v4);
|
|
DrawBrickChunks(v4);
|
|
if (obj_ypos_hi.block[v4]) {
|
|
if (obj_ypos_lo.misc[v4 - 2] > 0xF0u)
|
|
obj_ypos_lo.misc[v4 - 2] = -16;
|
|
if (obj_ypos_lo.block[v4] >= 0xF0u)
|
|
LABEL_10:
|
|
block_state[v4] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void BlockObjMT_Updater() {
|
|
uint8 i; // si
|
|
uint8 v1; // al
|
|
|
|
for (i = 1; (i & 0x80u) == 0; --i) {
|
|
object_index = i;
|
|
if (block_repflag[i]) {
|
|
R6_ = block_bbuf_low[i];
|
|
R7_ = 5;
|
|
R2_ = block_orig_ypos[i];
|
|
v1 = block_metatile[i];
|
|
RomPtr_RAM(*(uint16 *)&R6_)[R2_] = v1;
|
|
ReplaceBlockMetatile(i, v1);
|
|
block_repflag[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint8 MoveEnemyHoriz(uint8 k) {
|
|
return MoveObjectHoriz(k + 1);
|
|
}
|
|
|
|
uint8 MovePlayerHoriz() {
|
|
uint8 result; // al
|
|
|
|
result = jumpspring_anim_ctrl;
|
|
if (!jumpspring_anim_ctrl)
|
|
return MoveObjectHoriz(jumpspring_anim_ctrl);
|
|
return result;
|
|
}
|
|
|
|
uint8 MoveObjectHoriz(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
v1 = (int8) * (&obj_xspeed.player + k) >> 4;
|
|
uint16 t = *(&obj_xpos_fract.player + k) + (uint8)(16 * *(&obj_xspeed.player + k));
|
|
*(&obj_xpos_fract.player + k) = t;
|
|
t = (t >> 8) + (int8)v1;
|
|
AddHiLo(&obj_xpos_hi.player + k, &obj_xpos_lo.player + k, t);
|
|
UNUSED_byte_7E0EB6 = v1;
|
|
return t;
|
|
}
|
|
|
|
void MovePlayerVert() {
|
|
if (timer_control || !jumpspring_anim_ctrl) {
|
|
R0_ = vertical_force;
|
|
ImposeGravitySpr(0, 4u);
|
|
}
|
|
}
|
|
|
|
void MoveD_EnemyVert(uint8 k) {
|
|
if (enemy_state[k] == 5)
|
|
MoveFallingPlatform(k);
|
|
else
|
|
func_sub_C17F(k, 0x3Du);
|
|
}
|
|
|
|
void MoveFallingPlatform(uint8 k) {
|
|
func_sub_C17F(k, 0x20u);
|
|
}
|
|
|
|
void MoveRedPTroopaDown(uint8 k) {
|
|
MoveRedPTroopa(k, 0);
|
|
}
|
|
|
|
void MoveRedPTroopaUp(uint8 k) {
|
|
MoveRedPTroopa(k, 1u);
|
|
}
|
|
|
|
void MoveRedPTroopa(uint8 k, uint8 j) {
|
|
R0_ = 3;
|
|
R1_ = 6;
|
|
R2_ = 2;
|
|
RedPTroopaGrav(k + 1, j);
|
|
}
|
|
|
|
void MoveDropPlatform(uint8 k) {
|
|
func_sub_C179(k, 0x7Fu);
|
|
}
|
|
|
|
void MoveEnemySlowVert(uint8 k) {
|
|
func_sub_C179(k, 0xFu);
|
|
}
|
|
|
|
void func_sub_C179(uint8 k, uint8 j) {
|
|
SetXMoveAmt(k, j, 2u);
|
|
}
|
|
|
|
void MoveJ_EnemyVert(uint8 k) {
|
|
func_sub_C17F(k, 0x1Cu);
|
|
}
|
|
|
|
void func_sub_C17F(uint8 k, uint8 j) {
|
|
SetXMoveAmt(k, j, 3u);
|
|
}
|
|
|
|
void SetXMoveAmt(uint8 k, uint8 j, uint8 a) {
|
|
R0_ = j;
|
|
ImposeGravitySpr(k + 1, a);
|
|
}
|
|
|
|
void func_sub_C18C(uint8 k) {
|
|
ImposeGravityBlock(k);
|
|
}
|
|
|
|
void ImposeGravityBlock(uint8 k) {
|
|
R0_ = 80;
|
|
ImposeGravitySpr(k, kMaxSpdBlockData[1]);
|
|
}
|
|
|
|
void ImposeGravitySpr(uint8 k, uint8 a) {
|
|
R2_ = a;
|
|
ImposeGravity(k, 0);
|
|
}
|
|
|
|
void MovePlatformDown(uint8 k) {
|
|
MovePlatformCommon(k, 0);
|
|
}
|
|
|
|
void MovePlatformUp(uint8 k) {
|
|
MovePlatformCommon(k, 1u);
|
|
}
|
|
|
|
void MovePlatformCommon(uint8 k, uint8 a) {
|
|
uint8 v2; // di
|
|
uint8 v3; // si
|
|
uint8 v4; // al
|
|
|
|
v2 = enemy_id[k];
|
|
v3 = k + 1;
|
|
v4 = 5;
|
|
if (v2 == 41)
|
|
v4 = 9;
|
|
R0_ = v4;
|
|
R1_ = 10;
|
|
R2_ = 3;
|
|
RedPTroopaGrav(v3, a);
|
|
}
|
|
|
|
void RedPTroopaGrav(uint8 k, uint8 a) {
|
|
ImposeGravity(k, a);
|
|
}
|
|
|
|
void ImposeGravity_Far(uint8 k, uint8 a) {
|
|
ImposeGravity(k, a);
|
|
}
|
|
|
|
void ImposeGravity(uint8 k, uint8 a) {
|
|
bool v4; // cf
|
|
int8 v5; // al
|
|
uint8 v6; // al
|
|
uint8 v7; // al
|
|
uint8 v8; // al
|
|
|
|
uint16 t = *(&obj_sub_ypos.player + k) + *(&obj_sub_yspeed.player + k);
|
|
*(&obj_sub_ypos.player + k) = t;
|
|
AddHiLo((&obj_ypos_hi.player + k), (&obj_ypos_lo.player + k), (int8) * (&obj_yspeed.player + k) + (t >> 8));
|
|
|
|
v5 = *(&obj_sub_yspeed.player + k);
|
|
v4 = __CFADD__(R0_, v5);
|
|
*(&obj_sub_yspeed.player + k) = R0_ + v5;
|
|
v6 = v4 + *(&obj_yspeed.player + k);
|
|
*(&obj_yspeed.player + k) = v6;
|
|
|
|
if (!sign8(v6 - R2_) && *(&obj_sub_yspeed.player + k) >= 0x80u) {
|
|
*(&obj_yspeed.player + k) = R2_;
|
|
*(&obj_sub_yspeed.player + k) = 0;
|
|
}
|
|
if (a) {
|
|
R7_ = -R2_;
|
|
v7 = *(&obj_sub_yspeed.player + k);
|
|
v4 = v7 < R1_;
|
|
*(&obj_sub_yspeed.player + k) = v7 - R1_;
|
|
v8 = *(&obj_yspeed.player + k) - v4;
|
|
*(&obj_yspeed.player + k) = v8;
|
|
if (sign8(v8 - R7_)) {
|
|
if (*(&obj_sub_yspeed.player + k) < 0x80u) {
|
|
*(&obj_yspeed.player + k) = R7_;
|
|
*(&obj_sub_yspeed.player + k) = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BulletBill_MoveNew(uint8 k) {
|
|
int16 v1; // ax
|
|
uint8 v2; // di
|
|
OamEnt *oam; // rbp
|
|
uint8 v4; // si
|
|
int16 v5; // [rsp+46h] [rbp-2h]
|
|
|
|
if (bullet_bill_arr0E9D[k]) {
|
|
if (++bullet_bill_arr0EA2[k] >> 3 == 3) {
|
|
bullet_bill_arr0E9D[k] = 0;
|
|
tempE8 = 8 * k;
|
|
v4 = 24 * k;
|
|
get_OamEnt(oam_buf, v4)[64].ypos = -16;
|
|
oam_tile_size_buffer[v4 + 256] = 0;
|
|
} else {
|
|
tempE4 = 2 * (bullet_bill_arr0EA2[k] >> 3) + 64;
|
|
tempE5 = bullet_bill_arr0EAC[k];
|
|
tempE6 = bullet_bill_arr0EA7[k];
|
|
v5 = *(uint16 *)&tempE5 - screen_left_xpos16;
|
|
if (*(int16 *)&bullet_bill_arr0EB1[4] < 0)
|
|
v1 = v5 - 12;
|
|
else
|
|
v1 = v5 + 12;
|
|
*(uint16 *)&tempE5 = v1;
|
|
v2 = enemy_obj_id[k];
|
|
oam = get_OamEnt(oam_buf, v2);
|
|
oam[64].xpos = v1;
|
|
oam[64].ypos = bullet_bill_arr0EB1[k];
|
|
oam[64].charnum = tempE4;
|
|
oam[64].flags = 45;
|
|
oam_tile_size_buffer[v2 + 256] = 2;
|
|
if (tempE6)
|
|
oam_tile_size_buffer[v2 + 256] = 3;
|
|
}
|
|
}
|
|
}
|
|
|
|
void BulletBillSfxHandler(uint8 k, uint8 a) {
|
|
bullet_bill_arr0E9D[k] = a;
|
|
bullet_bill_arr0EA2[k] = 0;
|
|
bullet_bill_arr0EAC[k] = obj_xpos_lo.enemy[k];
|
|
bullet_bill_arr0EA7[k] = obj_xpos_hi.enemy[k];
|
|
bullet_bill_arr0EB1[k] = obj_ypos_lo.enemy[k] + 8;
|
|
}
|
|
|
|
void HandleScreenTransition() {
|
|
if (fade_direction & 1) {
|
|
if ((inidisp_mirror & 0x80u) == 0) {
|
|
if (!cutscene_var1680 || inidisp_mirror) {
|
|
if (--inidisp_mirror)
|
|
goto LABEL_14;
|
|
}
|
|
WriteReg(INIDISP, 0x80u);
|
|
inidisp_mirror = 0x80;
|
|
WriteReg(HDMAEN, 0);
|
|
hdmaenable_mirror = 0;
|
|
pause_menu_idx = 0;
|
|
cutscene_var1680 = 0;
|
|
Dma_FillWith0x24();
|
|
ClearAllOams();
|
|
CODE_03C36E();
|
|
}
|
|
fade_direction = 0;
|
|
disable_screen_flag = 1;
|
|
} else {
|
|
if (!override_player_xpos2_flag && !override_player_xpos_flag) {
|
|
override_player_xpos_flag = 1;
|
|
GameMode01_Level_GameCoreRoutine();
|
|
}
|
|
var0E67 = 0;
|
|
if (inidisp_mirror == 15 || (++inidisp_mirror, inidisp_mirror == 15)) {
|
|
fade_direction = 0;
|
|
disable_screen_flag = 0;
|
|
override_player_xpos_flag = 0;
|
|
}
|
|
}
|
|
LABEL_14:
|
|
if (enable_mosaic_fades_flag) {
|
|
ClearAllOams();
|
|
mosaic_mirror = (16 * (inidisp_mirror ^ 0xF)) | 0xF;
|
|
CODE_03C35C();
|
|
if (inidisp_mirror == 15)
|
|
enable_mosaic_fades_flag = 0;
|
|
}
|
|
}
|
|
|
|
void ClearAllOams() {
|
|
uint8 v0; // si
|
|
OamEnt *oam; // rbp
|
|
|
|
v0 = 0;
|
|
do {
|
|
oam = get_OamEnt(oam_buf, v0);
|
|
oam->ypos = -16;
|
|
oam[64].ypos = -16;
|
|
oam_tile_size_buffer[v0] = 0;
|
|
oam_tile_size_buffer[v0 + 256] = 0;
|
|
v0 += 4;
|
|
} while (v0);
|
|
}
|
|
|
|
void CODE_03C35C() {
|
|
uint8 i; // di
|
|
|
|
for (i = -48; i != 0xF0; i += 4)
|
|
get_OamEnt(oam_buf, i)->ypos = -16;
|
|
}
|
|
|
|
void CODE_03C36E() {
|
|
UploadSpriteGFX();
|
|
cutscene_var0BA5 = 0;
|
|
game_over_screen_blinking_cursor_pos = 0;
|
|
vblank_which_layer2_scroll_flag = 0;
|
|
turn_around_smoke_flag = 0;
|
|
turn_around_smoke_flag2 = 0;
|
|
turn_around_smoke_bits[0] = 0;
|
|
enable_layer3_bgflag = 0;
|
|
if (override_player_xpos2_flag) {
|
|
override_player_xpos2_flag = 0;
|
|
} else {
|
|
rel_ypos.player = obj_ypos_lo.player;
|
|
rel_xpos_lo.player = obj_xpos_lo.player;
|
|
}
|
|
override_player_xpos_flag = 0;
|
|
}
|
|
|
|
void EnemiesAndLoopsCore(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // di
|
|
uint8 *v3; // rdx
|
|
int8 v4; // di
|
|
uint8 v5; // di
|
|
uint8 v6; // al
|
|
uint8 v7; // al
|
|
uint8 v8; // di
|
|
uint8 *v9; // rdx
|
|
uint8 v10; // al
|
|
uint8 v11; // al
|
|
uint8 v12; // di
|
|
uint8 v13; // di
|
|
uint8 v14; // [rsp+47h] [rbp-1h]
|
|
|
|
v14 = enemy_flag[k];
|
|
if (__CFSHL__(v14, 1)) {
|
|
if (!enemy_flag[v14 & 0xF])
|
|
enemy_flag[k] = 0;
|
|
return;
|
|
}
|
|
if (v14) {
|
|
RunEnemyObjectsCore();
|
|
return;
|
|
}
|
|
if ((area_parser_task_num & 7) != 7) {
|
|
while (!loop_command || current_column_pos_lo) {
|
|
LABEL_31:
|
|
if (enemy_frenzy_queue) {
|
|
enemy_id[k] = enemy_frenzy_queue;
|
|
enemy_flag[k] = 1;
|
|
enemy_state[k] = 0;
|
|
enemy_frenzy_queue = 0;
|
|
InitEnemyObject(k);
|
|
return;
|
|
}
|
|
v2 = enemy_data_offset2;
|
|
v3 = IndirPtr(enemy_data_ptr, enemy_data_offset2);
|
|
if (*v3 == 0xFF)
|
|
goto LABEL_59;
|
|
if ((*v3 & 0xF) != 14 && k >= 8u && (*IndirPtr(enemy_data_ptr, (uint8)(v2 + 1)) & 0x3F) != 46)
|
|
return;
|
|
uint16 t;
|
|
t = PAIR16(screen_right_xpos_hi, screen_right_xpos) + 48;
|
|
R7_ = t & 0xF0;
|
|
R6_ = t >> 8;
|
|
v4 = enemy_data_offset2 + 1;
|
|
if (__CFSHL__(*IndirPtr(enemy_data_ptr, (uint8)(enemy_data_offset2 + 1)), 1) && !enemy_object_page_sel) {
|
|
++enemy_object_page_sel;
|
|
++enemy_object_page_loc;
|
|
}
|
|
v5 = v4 - 1;
|
|
if ((*IndirPtr(enemy_data_ptr, v5) & 0xF) != 15 || enemy_object_page_sel) {
|
|
obj_xpos_hi.enemy[k] = enemy_object_page_loc;
|
|
v6 = *IndirPtr(enemy_data_ptr, v5) & 0xF0;
|
|
obj_xpos_lo.enemy[k] = v6;
|
|
if (obj_xpos_hi.enemy[k] >= ((v6 < screen_right_xpos) + screen_right_xpos_hi)) {
|
|
if (R6_ < ((R7_ < obj_xpos_lo.enemy[k]) + obj_xpos_hi.enemy[k])) {
|
|
LABEL_59:
|
|
v11 = enemy_frenzy_buffer;
|
|
if (!enemy_frenzy_buffer) {
|
|
if (vine_flag_offset != 1)
|
|
return;
|
|
v11 = 0;
|
|
}
|
|
if (k == 9) {
|
|
InitEnemyObject(9u);
|
|
} else {
|
|
enemy_id[k] = v11;
|
|
InitEnemyObject(k);
|
|
}
|
|
} else {
|
|
obj_ypos_hi.enemy[k] = 1;
|
|
v7 = 16 * *IndirPtr(enemy_data_ptr, v5);
|
|
obj_ypos_lo.enemy[k] = v7;
|
|
if (v7 == 0xE0)
|
|
goto LABEL_66;
|
|
v8 = v5 + 1;
|
|
if ((*IndirPtr(enemy_data_ptr, v8) & 0x40) != 0 && !secondary_hard_mode)
|
|
goto LABEL_71;
|
|
v9 = IndirPtr(enemy_data_ptr, v8);
|
|
v10 = *v9 & 0x3F;
|
|
if (v10 < 0x37u || (*v9 & 0x3F) == 63) {
|
|
if (v10 == 6 && primary_hard_mode)
|
|
v10 = 2;
|
|
enemy_id[k] = v10;
|
|
if (v10 == 45)
|
|
bowser_var0F4C = 0;
|
|
enemy_flag[k] = 1;
|
|
InitEnemyObject(k);
|
|
if (enemy_flag[k])
|
|
goto LABEL_71;
|
|
} else {
|
|
HandleGroupEnemies(v10);
|
|
}
|
|
}
|
|
} else {
|
|
if ((*IndirPtr(enemy_data_ptr, v5) & 0xF) != 14) {
|
|
if ((*IndirPtr(enemy_data_ptr, enemy_data_offset2) & 0xF) == 14)
|
|
goto LABEL_70;
|
|
goto LABEL_71;
|
|
}
|
|
LABEL_66:
|
|
v12 = v5 + 2;
|
|
if (*IndirPtr(enemy_data_ptr, v12) >> 5 == world_number) {
|
|
v13 = v12 - 1;
|
|
area_pointer = *IndirPtr(enemy_data_ptr, v13);
|
|
entrance_page = *IndirPtr(enemy_data_ptr, (uint8)(v13 + 1)) & 0x1F;
|
|
}
|
|
LABEL_70:
|
|
++enemy_data_offset2;
|
|
LABEL_71:
|
|
++enemy_data_offset2;
|
|
++enemy_data_offset2;
|
|
enemy_object_page_sel = 0;
|
|
}
|
|
return;
|
|
}
|
|
enemy_object_page_loc = *IndirPtr(enemy_data_ptr, (uint8)(v5 + 1)) & 0x3F;
|
|
++enemy_data_offset2;
|
|
++enemy_data_offset2;
|
|
++enemy_object_page_sel;
|
|
}
|
|
v1 = 11;
|
|
do {
|
|
if ((--v1 & 0x80u) != 0)
|
|
goto LABEL_31;
|
|
} while (world_number != kLoopCmdWorldNumber[v1] || column_pos_hi != kLoopCmdPageNumber[v1]);
|
|
if (obj_ypos_lo.player != kLoopCmdYPosition[v1] || player_state) {
|
|
if (world_number != 6) {
|
|
if (!var0EDB) {
|
|
sound_ch3 = 42;
|
|
var0EDB = 42;
|
|
}
|
|
goto LABEL_28;
|
|
}
|
|
if (!var0EDB) {
|
|
sound_ch3 = 42;
|
|
var0EDB = 42;
|
|
}
|
|
} else if (!var0EDB) {
|
|
sound_ch3 = 41;
|
|
if (world_number != 6)
|
|
goto LABEL_29;
|
|
++multi_loop_correct_cntr;
|
|
}
|
|
if (++multi_loop_pass_cntr != 3) {
|
|
LABEL_30:
|
|
loop_command = 0;
|
|
goto LABEL_31;
|
|
}
|
|
if (multi_loop_correct_cntr == 3) {
|
|
LABEL_29:
|
|
multi_loop_pass_cntr = 0;
|
|
multi_loop_correct_cntr = 0;
|
|
goto LABEL_30;
|
|
}
|
|
LABEL_28:
|
|
ExecGameLoopback(v1);
|
|
KillAllEnemies();
|
|
goto LABEL_29;
|
|
}
|
|
}
|
|
|
|
void ExecGameLoopback(uint8 j) {
|
|
obj_xpos_hi.player -= 4;
|
|
column_pos_hi -= 4;
|
|
screen_left_xpos_hi -= 4;
|
|
screen_right_xpos_hi -= 4;
|
|
area_object_page_loc -= 4;
|
|
enemy_object_page_sel = 0;
|
|
area_object_page_sel = 0;
|
|
enemy_data_offset2 = 0;
|
|
enemy_object_page_loc = 0;
|
|
LOBYTE(area_data_offset) = kAreaDataOfsLoopback[j];
|
|
var0EDB = 0;
|
|
}
|
|
|
|
void InitEnemyObject(uint8 k) {
|
|
enemy_state[k] = 0;
|
|
CheckpointEnemyID(k);
|
|
}
|
|
|
|
void CheckpointEnemyID(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
v1 = enemy_id[k];
|
|
if (v1 < 0x15u) {
|
|
obj_ypos_lo.enemy[k] += 8;
|
|
spr_array_D[k] = 1;
|
|
}
|
|
R4_ = *((uint8 *)kDATA_03C62F + (uint8)(2 * v1));
|
|
R5_ = *((uint8 *)kDATA_03C62F + (uint8)(2 * v1) + 1);
|
|
((void (*)(uint8, uint8))funcs_A6DE[(uint8)(2 * v1) >> 1])(k, 2 * v1);
|
|
}
|
|
// A6E6: using guessed type int (*funcs_A6DE[55])();
|
|
|
|
void NoEnemyInit(uint8 k) {
|
|
;
|
|
}
|
|
|
|
void Goomba_Init(uint8 k) {
|
|
NormalEnemy_Init(k);
|
|
SmallBBox(k);
|
|
}
|
|
|
|
void Podoboo_Init(uint8 k) {
|
|
obj_ypos_lo.enemy[k] = -48;
|
|
obj_ypos_hi.enemy[k] = 1;
|
|
*(&enemy_interval_timer + k) = 1;
|
|
enemy_state[k] = 0;
|
|
podoboo_array_1[k] = 1;
|
|
podoboo_array_2[k] = 0;
|
|
sound_ch3 = 39;
|
|
SmallBBox(k);
|
|
}
|
|
|
|
void RetainerObj_Init(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
if (world_number == 7)
|
|
v1 = 112;
|
|
else
|
|
v1 = -72;
|
|
obj_ypos_lo.enemy[k] = v1;
|
|
}
|
|
|
|
void NormalEnemy_Init(uint8 k) {
|
|
obj_xspeed.enemy[k] = kNormalXSpdData[primary_hard_mode != 0];
|
|
SetBBox_3(k);
|
|
}
|
|
|
|
void RedKoopa_Init(uint8 k) {
|
|
NormalEnemy_Init(k);
|
|
enemy_state[k] = 1;
|
|
}
|
|
|
|
void HammerBro_Init(uint8 k) {
|
|
enemy_data_d[k] = 0;
|
|
obj_xspeed.enemy[k] = 0;
|
|
*(&enemy_interval_timer + k) = kHBroWalkingTimerData[secondary_hard_mode];
|
|
enemy_hitbox_ctrl[k] = 11;
|
|
enemy_moving_dir[k] = 2;
|
|
InitVStf(k);
|
|
}
|
|
|
|
void InitHorizFlySwimEnemy(uint8 k) {
|
|
obj_xspeed.enemy[k] = 0;
|
|
SetBBox_3(k);
|
|
}
|
|
|
|
void Blooper_Init(uint8 k) {
|
|
obj_xspeed.enemy[k] = 0;
|
|
SmallBBox(k);
|
|
}
|
|
|
|
void SmallBBox(uint8 k) {
|
|
enemy_hitbox_ctrl[k] = 9;
|
|
enemy_moving_dir[k] = 2;
|
|
InitVStf(k);
|
|
}
|
|
|
|
void RedPTroopa_Init(uint8 k) {
|
|
int8 v1; // di
|
|
int8 v2; // al
|
|
|
|
v1 = 48;
|
|
v2 = obj_ypos_lo.enemy[k];
|
|
obj_xpos_fract.enemy[k] = v2;
|
|
if (v2 < 0)
|
|
v1 = -32;
|
|
obj_xspeed.enemy[k] = obj_ypos_lo.enemy[k] + v1;
|
|
SetBBox_3(k);
|
|
}
|
|
|
|
void SetBBox_3(uint8 k) {
|
|
enemy_hitbox_ctrl[k] = 3;
|
|
enemy_moving_dir[k] = 2;
|
|
InitVStf(k);
|
|
}
|
|
|
|
void InitVStf(uint8 k) {
|
|
obj_yspeed.enemy[k] = 0;
|
|
obj_sub_yspeed.enemy[k] = 0;
|
|
}
|
|
|
|
void BulletBill_Init(uint8 k) {
|
|
enemy_moving_dir[k] = 2;
|
|
enemy_hitbox_ctrl[k] = 9;
|
|
}
|
|
|
|
void CheepCheep_Init(uint8 k) {
|
|
SmallBBox(k);
|
|
obj_xspeed.enemy[k] = *(&random_byte1 + k) & 0x10;
|
|
obj_sub_yspeed.enemy[k] = obj_ypos_lo.enemy[k];
|
|
}
|
|
|
|
void Lakitu_Init(uint8 k) {
|
|
if (enemy_frenzy_buffer)
|
|
EraseEnemyObject(k);
|
|
else
|
|
SetupLakitu(k);
|
|
}
|
|
|
|
void SetupLakitu(uint8 k) {
|
|
lakitu_reappear_timer = 0;
|
|
InitHorizFlySwimEnemy(k);
|
|
TallBBox2(k);
|
|
}
|
|
|
|
void LakituAndSpinyHandler(uint8 k) {
|
|
uint8 i; // di
|
|
uint8 v2; // si
|
|
|
|
if (!frenzy_enemy_timer && k < 9u) {
|
|
frenzy_enemy_timer = 0x80;
|
|
for (i = 8; (i & 0x80u) == 0; --i) {
|
|
if (enemy_id[i] == 17) {
|
|
CreateSpiny(k, i);
|
|
return;
|
|
}
|
|
}
|
|
if (++lakitu_reappear_timer >= 7u) {
|
|
v2 = 8;
|
|
while (enemy_flag[v2]) {
|
|
if ((--v2 & 0x80u) != 0)
|
|
return;
|
|
}
|
|
enemy_state[v2] = 0;
|
|
enemy_id[v2] = 17;
|
|
SetupLakitu(v2);
|
|
PutAtRightExtent(v2, 0x20u);
|
|
}
|
|
}
|
|
}
|
|
// AC5C: conditional instruction was optimized away because si.1<0
|
|
|
|
void CreateSpiny(uint8 k, uint8 j) {
|
|
uint8 v2; // di
|
|
int8 i; // si
|
|
uint8 v4; // si
|
|
uint8 v5; // di
|
|
|
|
if (obj_ypos_lo.player >= 0x2Cu && !enemy_state[j]) {
|
|
obj_xpos_hi.enemy[k] = obj_xpos_hi.enemy[j];
|
|
obj_xpos_lo.enemy[k] = obj_xpos_lo.enemy[j];
|
|
obj_ypos_hi.enemy[k] = 1;
|
|
obj_ypos_lo.enemy[k] = obj_ypos_lo.enemy[j] - 8;
|
|
v2 = *(&random_byte1 + k) & 3;
|
|
for (i = 2; i >= 0; --i) {
|
|
*(&R1_ + (uint8)i) = kPRDiffAdjustData[v2];
|
|
v2 += 4;
|
|
}
|
|
v4 = object_index;
|
|
PlayerLakituDiff(object_index);
|
|
SmallBBox(v4);
|
|
v5 = 2;
|
|
obj_xspeed.enemy[v4] = 0;
|
|
if (!sign8(0))
|
|
v5 = 1;
|
|
enemy_moving_dir[v4] = v5;
|
|
obj_yspeed.enemy[v4] = -3;
|
|
enemy_flag[v4] = 1;
|
|
enemy_state[v4] = 5;
|
|
}
|
|
}
|
|
|
|
void LongFirebar_Init(uint8 k) {
|
|
DuplicateEnemyObj(k);
|
|
ShortFirebar_Init(k);
|
|
}
|
|
|
|
void ShortFirebar_Init(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
|
|
obj_xspeed.enemy[k] = 0;
|
|
v1 = enemy_id[k] - 27;
|
|
enemy_data_b[k] = kFirebarSpinSpdData[v1];
|
|
enemy_data_a[k] = kFirebarSpinDirData[v1];
|
|
obj_ypos_lo.enemy[k] += 4;
|
|
v2 = obj_xpos_lo.enemy[k];
|
|
obj_xpos_lo.enemy[k] = v2 + 4;
|
|
obj_xpos_hi.enemy[k] += __CFADD__(v2, 4);
|
|
TallBBox2(k);
|
|
}
|
|
|
|
void FlyingCheepCheep_Init(uint8 k) {
|
|
uint8 v1; // di
|
|
int8 v2; // al
|
|
uint8 v3; // di
|
|
bool v4; // cf
|
|
uint8 v5; // al
|
|
|
|
if (!frenzy_enemy_timer) {
|
|
SmallBBox(k);
|
|
frenzy_enemy_timer = kFlyCCTimerData[*(&random_byte2 + k) & 3];
|
|
v1 = 3;
|
|
if (secondary_hard_mode)
|
|
v1 = 4;
|
|
R0_ = v1;
|
|
if (k < v1) {
|
|
R0_ = *(&random_byte1 + k) & 3;
|
|
R1_ = R0_;
|
|
obj_yspeed.enemy[k] = -5;
|
|
v2 = 0;
|
|
if (obj_xspeed.player) {
|
|
v2 = 4;
|
|
if (obj_xspeed.player >= 0x19u)
|
|
v2 = 8;
|
|
}
|
|
R0_ += v2;
|
|
if ((*(&random_byte2 + k) & 3) != 0)
|
|
R0_ = *(&random_byte3 + k) & 0xF;
|
|
v3 = R1_ + v2;
|
|
obj_xspeed.enemy[k] = kFlyCCXSpeedData[(uint8)(R1_ + v2)];
|
|
enemy_moving_dir[k] = 1;
|
|
if (!obj_xspeed.player) {
|
|
v3 = R0_;
|
|
if ((R0_ & 2) != 0) {
|
|
obj_xspeed.enemy[k] = -obj_xspeed.enemy[k];
|
|
++enemy_moving_dir[k];
|
|
}
|
|
}
|
|
if ((v3 & 2) != 0) {
|
|
v4 = __CFADD__(kFlyCCXPositionData[v3], obj_xpos_lo.player);
|
|
obj_xpos_lo.enemy[k] = kFlyCCXPositionData[v3] + obj_xpos_lo.player;
|
|
v5 = v4 + obj_xpos_hi.player;
|
|
} else {
|
|
v4 = obj_xpos_lo.player >= kFlyCCXPositionData[v3];
|
|
obj_xpos_lo.enemy[k] = obj_xpos_lo.player - kFlyCCXPositionData[v3];
|
|
v5 = obj_xpos_hi.player - !v4;
|
|
}
|
|
obj_xpos_hi.enemy[k] = v5;
|
|
enemy_flag[k] = 1;
|
|
obj_ypos_hi.enemy[k] = 1;
|
|
obj_ypos_lo.enemy[k] = -8;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Bowser_Init(uint8 k) {
|
|
DuplicateEnemyObj(k);
|
|
browser_front_offset = k;
|
|
browser_body_controls = 0;
|
|
bridge_collapse_offset = 0;
|
|
bowser_orig_xpos = obj_xpos_lo.enemy[k];
|
|
bowser_fire_breath_timer = -33;
|
|
enemy_moving_dir[k] = -33;
|
|
bowser_feet_counter = 32;
|
|
enemy_frame_timer[k] = 32;
|
|
enemy_sprattrib[k] = 32;
|
|
bowser_hit_points = 5;
|
|
bowser_movement_speed = 2;
|
|
}
|
|
|
|
void DuplicateEnemyObj(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
v1 = -1;
|
|
do
|
|
++v1;
|
|
while (enemy_flag[v1]);
|
|
duplicate_obj_offset = v1;
|
|
enemy_flag[v1] = k | 0x80;
|
|
obj_xpos_hi.enemy[v1] = obj_xpos_hi.enemy[k];
|
|
obj_xpos_lo.enemy[v1] = obj_xpos_lo.enemy[k];
|
|
enemy_flag[k] = 1;
|
|
obj_ypos_hi.enemy[v1] = 1;
|
|
obj_ypos_lo.enemy[v1] = obj_ypos_lo.enemy[k];
|
|
}
|
|
|
|
void BowserFlame_Init(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // al
|
|
bool v3; // cf
|
|
|
|
if (!frenzy_enemy_timer) {
|
|
obj_sub_yspeed.enemy[k] = frenzy_enemy_timer;
|
|
bowser_var014B = 6;
|
|
bowser_var0F4C = 24;
|
|
var0F4D_new = k;
|
|
if (enemy_id[browser_front_offset] != 45) {
|
|
v1 = SetFlameTimer() + 32;
|
|
if (secondary_hard_mode)
|
|
v1 -= 16;
|
|
frenzy_enemy_timer = v1;
|
|
v2 = *(&random_byte1 + k) & 3;
|
|
obj_sub_ypos.enemy[k] = v2;
|
|
obj_ypos_lo.enemy[k] = kFlameYPosData[v2];
|
|
v3 = __CFADD__(screen_right_xpos, 32);
|
|
obj_xpos_lo.enemy[k] = screen_right_xpos + 32;
|
|
obj_xpos_hi.enemy[k] = v3 + screen_right_xpos_hi;
|
|
bowser_var0F4C = 0;
|
|
var0F4D_new = 0;
|
|
bowser_var014B = 0;
|
|
sound_ch3 = 23;
|
|
enemy_hitbox_ctrl[k] = 8;
|
|
obj_ypos_hi.enemy[k] = 1;
|
|
enemy_flag[k] = 1;
|
|
obj_xpos_fract.enemy[k] = 0;
|
|
enemy_state[k] = 0;
|
|
}
|
|
bowser_flame_enemy_index = k;
|
|
}
|
|
}
|
|
|
|
void PutAtRightExtent(uint8 k, uint8 a) {
|
|
bool v2; // cf
|
|
|
|
obj_ypos_lo.enemy[k] = a;
|
|
v2 = __CFADD__(screen_right_xpos, 32);
|
|
obj_xpos_lo.enemy[k] = screen_right_xpos + 32;
|
|
obj_xpos_hi.enemy[k] = v2 + screen_right_xpos_hi;
|
|
enemy_hitbox_ctrl[k] = 8;
|
|
obj_ypos_hi.enemy[k] = 1;
|
|
enemy_flag[k] = 1;
|
|
obj_xpos_fract.enemy[k] = 0;
|
|
enemy_state[k] = 0;
|
|
}
|
|
|
|
void InitFireworks(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
uint8 v3; // di
|
|
bool v4; // cf
|
|
|
|
if (!frenzy_enemy_timer) {
|
|
frenzy_enemy_timer = 32;
|
|
--fireworks_counter;
|
|
v1 = 10;
|
|
do
|
|
--v1;
|
|
while (enemy_id[v1] != 49);
|
|
v2 = obj_xpos_lo.enemy[v1];
|
|
R0_ = obj_xpos_hi.enemy[v1] - (v2 < 0x30u);
|
|
v3 = enemy_state[v1] + fireworks_counter;
|
|
v2 -= 48;
|
|
v4 = __CFADD__(kFireworksXPosData[v3], v2);
|
|
obj_xpos_lo.enemy[k] = kFireworksXPosData[v3] + v2;
|
|
obj_xpos_hi.enemy[k] = v4 + R0_;
|
|
obj_ypos_lo.enemy[k] = kFireworksYPosData[v3];
|
|
obj_ypos_hi.enemy[k] = 1;
|
|
enemy_flag[k] = 1;
|
|
obj_xspeed.enemy[k] = 0;
|
|
obj_yspeed.enemy[k] = 8;
|
|
}
|
|
}
|
|
|
|
void BulletBillCheepCheep(uint8 k) {
|
|
int8 v1; // di
|
|
uint8 v2; // al
|
|
uint8 i; // al
|
|
uint8 v4; // di
|
|
uint8 v5; // al
|
|
uint8 v6; // di
|
|
|
|
if (!frenzy_enemy_timer) {
|
|
if (area_type) {
|
|
v6 = -1;
|
|
while (++v6 < 9u) {
|
|
if (enemy_flag[v6] && enemy_id[v6] == 8)
|
|
return;
|
|
}
|
|
sound_ch3 = 9;
|
|
v2 = 8;
|
|
} else {
|
|
if (k >= 3u)
|
|
return;
|
|
v1 = *(&random_byte1 + k) >= 0xAAu;
|
|
if (world_number != 1)
|
|
++v1;
|
|
v2 = kSwimCC_IDData[v1 & 1];
|
|
}
|
|
enemy_id[k] = v2;
|
|
if (bit_m_filter == 0xFF)
|
|
bit_m_filter = 0;
|
|
for (i = *(&random_byte1 + k) & 7;; i = (v4 + 1) & 7) {
|
|
v4 = i;
|
|
v5 = kBitmasks[i];
|
|
if ((bit_m_filter & v5) == 0)
|
|
break;
|
|
}
|
|
bit_m_filter |= v5;
|
|
PutAtRightExtent(k, kEnemy17YPosData[v4]);
|
|
obj_sub_ypos.enemy[k] = 0;
|
|
frenzy_enemy_timer = 32;
|
|
CheckpointEnemyID(k);
|
|
}
|
|
}
|
|
|
|
void HandleGroupEnemies(uint8 a) {
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
uint8 v3; // di
|
|
uint8 v4; // di
|
|
uint8 v5; // si
|
|
uint8 v6; // al
|
|
|
|
v1 = 0;
|
|
v2 = a - 55;
|
|
if (v2 < 4u) {
|
|
v1 = 6;
|
|
if (primary_hard_mode)
|
|
v1 = 2;
|
|
}
|
|
R1_ = v1;
|
|
v3 = -80;
|
|
if ((v2 & 2) != 0)
|
|
v3 = 112;
|
|
R0_ = v3;
|
|
R2_ = screen_right_xpos_hi;
|
|
R3_ = screen_right_xpos;
|
|
v4 = 2;
|
|
if (v2 & 1)
|
|
v4 = 3;
|
|
number_of_group_enemies = v4;
|
|
LABEL_9:
|
|
v5 = -1;
|
|
while (++v5 < 9u) {
|
|
if (!enemy_flag[v5]) {
|
|
enemy_id[v5] = R1_;
|
|
obj_xpos_hi.enemy[v5] = R2_;
|
|
v6 = R3_;
|
|
obj_xpos_lo.enemy[v5] = R3_;
|
|
R3_ = v6 + 24;
|
|
R2_ += __CFADD__(v6, 24);
|
|
obj_ypos_lo.enemy[v5] = R0_;
|
|
obj_ypos_hi.enemy[v5] = 1;
|
|
enemy_flag[v5] = 1;
|
|
CheckpointEnemyID(v5);
|
|
if (--number_of_group_enemies)
|
|
goto LABEL_9;
|
|
break;
|
|
}
|
|
}
|
|
++enemy_data_offset2;
|
|
++enemy_data_offset2;
|
|
enemy_object_page_sel = 0;
|
|
}
|
|
|
|
void PiranhaPlant_Init(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
obj_xspeed.enemy[k] = 1;
|
|
enemy_state[k] = 0;
|
|
obj_yspeed.enemy[k] = 0;
|
|
v1 = obj_ypos_lo.enemy[k];
|
|
obj_sub_yspeed.enemy[k] = v1;
|
|
obj_sub_ypos.enemy[k] = v1 - 24;
|
|
enemy_hitbox_ctrl[k] = 12;
|
|
}
|
|
|
|
void InitEnemyFrenzy(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
enemy_frenzy_buffer = enemy_id[k];
|
|
v1 = enemy_frenzy_buffer - 18;
|
|
R4_ = kDATA_03CBCC[v1];
|
|
R5_ = HIBYTE(kDATA_03CBCC[v1]);
|
|
((void (*)(uint8))funcs_B851[(unsigned int)(v1 * 2) >> 1])(k);
|
|
}
|
|
// B859: using guessed type int (*funcs_B851[6])();
|
|
|
|
void NoFrenzyCode(uint8 k) {
|
|
;
|
|
}
|
|
|
|
void EndFrenzy(uint8 k) {
|
|
uint8 i; // di
|
|
|
|
for (i = 9; (i & 0x80u) == 0; --i) {
|
|
if (enemy_id[i] == 17)
|
|
enemy_state[i] = 1;
|
|
}
|
|
enemy_frenzy_buffer = 0;
|
|
enemy_flag[k] = 0;
|
|
}
|
|
|
|
void JumpGPTroopa_Init(uint8 k) {
|
|
enemy_moving_dir[k] = 2;
|
|
obj_xspeed.enemy[k] = -8;
|
|
TallBBox2(k);
|
|
}
|
|
|
|
void TallBBox2(uint8 k) {
|
|
enemy_hitbox_ctrl[k] = 3;
|
|
}
|
|
|
|
void BalPlatform_Init(uint8 k) {
|
|
uint8 v1; // di
|
|
int8 v2; // al
|
|
|
|
--obj_ypos_lo.enemy[k];
|
|
--obj_ypos_lo.enemy[k];
|
|
if (!secondary_hard_mode)
|
|
PosPlatform(k, 2u);
|
|
v1 = -1;
|
|
v2 = bal_platform_alignment;
|
|
enemy_state[k] = bal_platform_alignment;
|
|
if (v2 < 0)
|
|
v1 = k;
|
|
bal_platform_alignment = v1;
|
|
enemy_moving_dir[k] = 0;
|
|
PosPlatform(k, 0);
|
|
InitDropPlatform_Init(k);
|
|
}
|
|
|
|
void InitDropPlatform_Init(uint8 k) {
|
|
enemy_data_d[k] = -1;
|
|
InitVStf(k);
|
|
SPBBox(k);
|
|
}
|
|
|
|
void InitHoriPlatform_Init(uint8 k) {
|
|
obj_xspeed.enemy[k] = 0;
|
|
InitVStf(k);
|
|
SPBBox(k);
|
|
}
|
|
|
|
void VertPlatform_Init(uint8 k) {
|
|
int8 v1; // di
|
|
int8 v2; // al
|
|
|
|
v1 = 64;
|
|
v2 = obj_ypos_lo.enemy[k];
|
|
if (v2 < 0) {
|
|
v2 = -v2;
|
|
v1 = -64;
|
|
}
|
|
obj_xpos_fract.enemy[k] = v2;
|
|
obj_xspeed.enemy[k] = obj_ypos_lo.enemy[k] + v1;
|
|
InitVStf(k);
|
|
SPBBox(k);
|
|
}
|
|
|
|
void SPBBox(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
v1 = 5;
|
|
if (area_type != 3 && !secondary_hard_mode)
|
|
v1 = 6;
|
|
enemy_hitbox_ctrl[k] = v1;
|
|
}
|
|
|
|
void LargeLiftUp_Init(uint8 k) {
|
|
PlatLiftUp_Init(k);
|
|
SPBBox(k);
|
|
}
|
|
|
|
void LargeLiftDown_Init(uint8 k) {
|
|
PlatLiftDown_Init(k);
|
|
SPBBox(k);
|
|
}
|
|
|
|
void PlatLiftUp_Init(uint8 k) {
|
|
obj_sub_yspeed.enemy[k] = 16;
|
|
obj_yspeed.enemy[k] = -1;
|
|
PosPlatform(k, 1u);
|
|
enemy_hitbox_ctrl[k] = 4;
|
|
}
|
|
|
|
void PlatLiftDown_Init(uint8 k) {
|
|
obj_sub_yspeed.enemy[k] = -16;
|
|
obj_yspeed.enemy[k] = 0;
|
|
PosPlatform(k, 1u);
|
|
enemy_hitbox_ctrl[k] = 4;
|
|
}
|
|
|
|
void PosPlatform(uint8 k, uint8 j) {
|
|
uint8 v2; // al
|
|
bool v3; // cf
|
|
|
|
v2 = obj_xpos_lo.enemy[k];
|
|
v3 = __CFADD__(kPlatPosDataLow[j], v2);
|
|
obj_xpos_lo.enemy[k] = kPlatPosDataLow[j] + v2;
|
|
obj_xpos_hi.enemy[k] += kPlatPosDataHigh[j] + v3;
|
|
}
|
|
|
|
void EndOfEnemyInitCode(uint8 k) {
|
|
;
|
|
}
|
|
|
|
void RunEnemyObjectsCore() {
|
|
int8 v0; // al
|
|
uint8 v1; // di
|
|
|
|
v0 = 0;
|
|
v1 = enemy_id[object_index];
|
|
if (v1 >= 0x15u)
|
|
v0 = v1 - 20;
|
|
((void (*)(uint8))funcs_BC01[v0])(object_index);
|
|
}
|
|
// BC09: using guessed type int (*funcs_BC01[34])();
|
|
|
|
void NoRunCode(uint8 k) {
|
|
;
|
|
}
|
|
|
|
void RunRetainerObj(uint8 k) {
|
|
GetEnemyOffscreenBits(k);
|
|
RelativeEnemyPosition(k);
|
|
EnemyGfxHandler_New(k);
|
|
}
|
|
|
|
void RunNormalEnemies(uint8 k) {
|
|
enemy_sprattrib[k] = 32;
|
|
GetEnemyOffscreenBits(k);
|
|
RelativeEnemyPosition(k);
|
|
EnemyGfxHandler_New(k);
|
|
GetEnemyBoundBox(k);
|
|
EnemyToBGCollisionDet(k);
|
|
EnemiesCollision(k);
|
|
PlayerEnemyCollision(k);
|
|
if (!timer_control)
|
|
EnemyMovementSubs(k);
|
|
OffscreenBoundsCheck(k);
|
|
}
|
|
|
|
void EnemyMovementSubs(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
v1 = enemy_id[k];
|
|
R4_ = kDATA_03CD48[v1];
|
|
R5_ = HIBYTE(kDATA_03CD48[v1]);
|
|
funcs_BDE8[(unsigned int)(v1 * 2) >> 1](k);
|
|
}
|
|
// BDF0: using guessed type int (*funcs_BDE8[21])();
|
|
|
|
void NoMoveCode(uint8 k) {
|
|
;
|
|
}
|
|
|
|
void RunBowserFlame(uint8 k) {
|
|
ProcBowserFlame(k);
|
|
GetEnemyOffscreenBits(k);
|
|
RelativeEnemyPosition(k);
|
|
GetEnemyBoundBox(k);
|
|
PlayerEnemyCollision(k);
|
|
OffscreenBoundsCheck(k);
|
|
}
|
|
|
|
void RunFirebarObj(uint8 k) {
|
|
ProcFirebar(k);
|
|
OffscreenBoundsCheck(k);
|
|
}
|
|
|
|
void RunSmallPlatform(uint8 k) {
|
|
GetEnemyOffscreenBits(k);
|
|
RelativeEnemyPosition(k);
|
|
SmallPlatformBoundBox(k);
|
|
SmallPlatformCollision(k);
|
|
RelativeEnemyPosition(k);
|
|
DrawSmallPlatform(k);
|
|
MoveSmallPlatform(k);
|
|
OffscreenBoundsCheck(k);
|
|
}
|
|
|
|
void RunLargePlatform(uint8 k) {
|
|
GetEnemyOffscreenBits(k);
|
|
RelativeEnemyPosition(k);
|
|
LargePlatformBoundBox(k);
|
|
LargePlatformCollision(k);
|
|
if (!timer_control)
|
|
LargePlatformSubroutines(k);
|
|
RelativeEnemyPosition(k);
|
|
DrawLargePlatform(k);
|
|
OffscreenBoundsCheck(k);
|
|
}
|
|
|
|
void LargePlatformSubroutines(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
v1 = enemy_id[k] - 36;
|
|
R4_ = kDATA_03CDD4[v1];
|
|
R5_ = HIBYTE(kDATA_03CDD4[v1]);
|
|
((void (*)(uint8))funcs_BFB5[(unsigned int)(v1 * 2) >> 1])(k);
|
|
}
|
|
// BFBD: using guessed type int (*funcs_BFB5[7])();
|
|
|
|
void EraseEnemyObject(uint8 k) {
|
|
*(&enemy_interval_timer + k) = 0;
|
|
EraseEnemyObject2(k);
|
|
}
|
|
|
|
void EraseEnemyObject2(uint8 k) {
|
|
OamEnt *oam; // rbp
|
|
|
|
if (k == 9) {
|
|
oam = get_OamEnt(oam_buf, 0);
|
|
oam[120].ypos = -16;
|
|
oam[121].ypos = -16;
|
|
oam[122].ypos = -16;
|
|
oam[123].ypos = -16;
|
|
if (area_data_addr_index == 34)
|
|
cloud_type_override = 0;
|
|
}
|
|
enemy_flag[k] = 0;
|
|
enemy_id[k] = 0;
|
|
enemy_state[k] = 0;
|
|
floateynum_control[k] = 0;
|
|
shell_chain_counter[k] = 0;
|
|
enemy_frame_timer[k] = 0;
|
|
enemy_data_d[k] = 0;
|
|
enemy_sprattrib[k] = 32;
|
|
}
|
|
|
|
void MovePodoboo(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
if (!*(&enemy_interval_timer + k)) {
|
|
Podoboo_Init(k);
|
|
v1 = *(&random_byte2 + k) | 0x80;
|
|
obj_sub_yspeed.enemy[k] = v1;
|
|
*(&enemy_interval_timer + k) = v1 & 9 | 6;
|
|
obj_yspeed.enemy[k] = -7;
|
|
}
|
|
if ((obj_yspeed.enemy[k] & 0x80u) == 0 && obj_ypos_lo.enemy[k] >= 0xC0u && podoboo_array_1[k] == 2) {
|
|
++podoboo_array_1[k];
|
|
podoboo_array_2[k] = 0;
|
|
sound_ch3 = 39;
|
|
}
|
|
++podoboo_array_2[k];
|
|
MovePodoboo_Sub1(k);
|
|
MoveJ_EnemyVert(k);
|
|
}
|
|
|
|
void ProcHammerBro(uint8 k) {
|
|
uint8 v1; // di
|
|
int8 v2; // al
|
|
|
|
if ((enemy_state[k] & 0x20) != 0) {
|
|
MoveD_EnemyVert(k);
|
|
MoveEnemyHoriz(k);
|
|
} else if (enemy_data_c[k]) {
|
|
--enemy_data_c[k];
|
|
if ((offscreen_bits.enemy & 0xC) != 0) {
|
|
LABEL_4:
|
|
CODE_03CEE9(k);
|
|
return;
|
|
}
|
|
if (enemy_data_d[k] || (enemy_data_d[k] = kHammerThrowTmrData[secondary_hard_mode], !(SpawnThrownHammer(k) & 1))) {
|
|
--enemy_data_d[k];
|
|
CODE_03CEE9(k);
|
|
} else {
|
|
enemy_state[k] |= 8u;
|
|
CODE_03CEE9(k);
|
|
}
|
|
} else {
|
|
if ((enemy_state[k] & 7) == 1)
|
|
goto LABEL_4;
|
|
R0_ = 0;
|
|
v1 = -6;
|
|
v2 = obj_ypos_lo.enemy[k];
|
|
if (v2 < 0 || (v1 = -3, ++R0_, (uint8)v2 < 0x70u) || (--R0_, (*(&random_byte2 + k) & 1) != 0))
|
|
CODE_03CEC7(k, v1);
|
|
else
|
|
CODE_03CEC7(k, 0xFAu);
|
|
}
|
|
}
|
|
|
|
void CODE_03CEC7(uint8 k, uint8 j) {
|
|
uint8 v2; // di
|
|
|
|
obj_yspeed.enemy[k] = j;
|
|
enemy_state[k] |= 1u;
|
|
v2 = *(&random_byte3 + k) & R0_;
|
|
if (!secondary_hard_mode)
|
|
v2 = secondary_hard_mode;
|
|
enemy_frame_timer[k] = kHammerBroJumpLData[v2];
|
|
enemy_data_c[k] = *(&random_byte2 + k) | 0xC0;
|
|
CODE_03CEE9(k);
|
|
}
|
|
|
|
void CODE_03CEE9(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // di
|
|
|
|
v1 = -4;
|
|
if ((frame_counter & 0x40) == 0)
|
|
v1 = 4;
|
|
obj_xspeed.enemy[k] = v1;
|
|
v2 = 1;
|
|
if ((PlayerEnemyDiff(k) & 0x80u) == 0) {
|
|
v2 = 2;
|
|
if (!*(&enemy_interval_timer + k))
|
|
obj_xspeed.enemy[k] = -8;
|
|
}
|
|
enemy_moving_dir[k] = v2;
|
|
MoveNormalEnemy(k);
|
|
}
|
|
|
|
void MoveNormalEnemy(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
int8 v3; // al
|
|
int8 v4; // al
|
|
uint8 v5; // di
|
|
uint8 v6; // di
|
|
uint8 v7; // [rsp+47h] [rbp-1h]
|
|
|
|
v1 = 0;
|
|
if ((enemy_state[k] & 0x40) != 0)
|
|
goto LABEL_7;
|
|
if (__CFSHL__(enemy_state[k], 1))
|
|
goto LABEL_12;
|
|
if ((enemy_state[k] & 0x20) != 0) {
|
|
MoveD_EnemyVert(k);
|
|
MoveEnemyHoriz(k);
|
|
return;
|
|
}
|
|
v2 = enemy_state[k] & 7;
|
|
if (!v2)
|
|
goto LABEL_12;
|
|
if (v2 == 5 || v2 < 3u) {
|
|
LABEL_7:
|
|
MoveD_EnemyVert(k);
|
|
v1 = 0;
|
|
if (enemy_state[k] == 2) {
|
|
MoveEnemyHoriz(k);
|
|
return;
|
|
}
|
|
if ((enemy_state[k] & 0x40) != 0 && enemy_id[k] != 46)
|
|
v1 = 1;
|
|
LABEL_12:
|
|
v3 = obj_xspeed.enemy[k];
|
|
v7 = v3;
|
|
if (v3 < 0)
|
|
v1 += 2;
|
|
obj_xspeed.enemy[k] = kXSpeedAdderData[v1] + v3;
|
|
MoveEnemyHoriz(k);
|
|
obj_xspeed.enemy[k] = v7;
|
|
return;
|
|
}
|
|
v4 = *(&enemy_interval_timer + k);
|
|
if (v4) {
|
|
if (v4 == 14 && enemy_id[k] == 6)
|
|
EraseEnemyObject(k);
|
|
} else {
|
|
enemy_state[k] = 0;
|
|
v5 = (frame_counter & 1) + 1;
|
|
enemy_moving_dir[k] = v5;
|
|
v6 = v5 - 1;
|
|
if (primary_hard_mode)
|
|
v6 += 2;
|
|
obj_xspeed.enemy[k] = kRevivedXSpeed[v6];
|
|
}
|
|
}
|
|
|
|
void MoveJumpingEnemy(uint8 k) {
|
|
MoveJ_EnemyVert(k);
|
|
MoveEnemyHoriz(k);
|
|
}
|
|
|
|
void ProcMoveRedPTroopa(uint8 k) {
|
|
if (obj_sub_yspeed.enemy[k] | obj_yspeed.enemy[k] || (obj_sub_ypos.enemy[k] = 0, obj_ypos_lo.enemy[k] >= obj_xpos_fract.enemy[k])) {
|
|
if (obj_ypos_lo.enemy[k] < obj_xspeed.enemy[k])
|
|
MoveRedPTroopaDown(k);
|
|
else
|
|
MoveRedPTroopaUp(k);
|
|
} else if ((frame_counter & 7) == 0) {
|
|
++obj_ypos_lo.enemy[k];
|
|
}
|
|
}
|
|
|
|
void MoveFlyGreenPTroopa(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
XMoveCntr_GreenPTroopa(k);
|
|
MoveWithXMCntrs(k);
|
|
v1 = 1;
|
|
if ((frame_counter & 3) == 0) {
|
|
if ((frame_counter & 0x40) == 0)
|
|
v1 = -1;
|
|
R0_ = v1;
|
|
obj_ypos_lo.enemy[k] += v1;
|
|
}
|
|
}
|
|
|
|
void XMoveCntr_GreenPTroopa(uint8 k) {
|
|
XMoveCntr_Platform(k, 0x13u);
|
|
}
|
|
|
|
void XMoveCntr_Platform(uint8 k, uint8 a) {
|
|
uint8 v2; // di
|
|
|
|
R1_ = a;
|
|
if ((frame_counter & 3) == 0) {
|
|
v2 = obj_xspeed.enemy[k];
|
|
if (obj_yspeed.enemy[k] & 1) {
|
|
if (v2) {
|
|
--obj_xspeed.enemy[k];
|
|
return;
|
|
}
|
|
} else if (v2 != R1_) {
|
|
++obj_xspeed.enemy[k];
|
|
return;
|
|
}
|
|
++obj_yspeed.enemy[k];
|
|
}
|
|
}
|
|
|
|
void MoveWithXMCntrs(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // [rsp+47h] [rbp-1h]
|
|
|
|
v2 = obj_xspeed.enemy[k];
|
|
v1 = 1;
|
|
if ((obj_yspeed.enemy[k] & 2) == 0) {
|
|
obj_xspeed.enemy[k] = -obj_xspeed.enemy[k];
|
|
v1 = 2;
|
|
}
|
|
enemy_moving_dir[k] = v1;
|
|
R0_ = MoveEnemyHoriz(k);
|
|
obj_xspeed.enemy[k] = v2;
|
|
}
|
|
|
|
void MoveBloober(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
bool v3; // cf
|
|
uint8 v4; // al
|
|
|
|
if ((enemy_state[k] & 0x20) != 0) {
|
|
MoveEnemySlowVert(k);
|
|
} else {
|
|
if ((kBlooberBitmasks[secondary_hard_mode] & *(&random_byte2 + k)) == 0) {
|
|
if (k & 1) {
|
|
v1 = player_moving_dir;
|
|
} else {
|
|
v1 = 2;
|
|
if ((PlayerEnemyDiff(k) & 0x80u) != 0)
|
|
v1 = 1;
|
|
}
|
|
enemy_moving_dir[k] = v1;
|
|
}
|
|
ProcSwimmingB(k);
|
|
if ((uint8)(obj_ypos_lo.enemy[k] - obj_sub_yspeed.enemy[k]) >= 0x20u)
|
|
obj_ypos_lo.enemy[k] -= obj_sub_yspeed.enemy[k];
|
|
v2 = obj_xpos_lo.enemy[k];
|
|
if (enemy_moving_dir[k] == 1) {
|
|
v3 = __CFADD__(obj_xspeed.enemy[k], v2);
|
|
obj_xpos_lo.enemy[k] = obj_xspeed.enemy[k] + v2;
|
|
v4 = v3 + obj_xpos_hi.enemy[k];
|
|
} else {
|
|
v3 = v2 < obj_xspeed.enemy[k];
|
|
obj_xpos_lo.enemy[k] = v2 - obj_xspeed.enemy[k];
|
|
v4 = obj_xpos_hi.enemy[k] - v3;
|
|
}
|
|
obj_xpos_hi.enemy[k] = v4;
|
|
}
|
|
}
|
|
|
|
void ProcSwimmingB(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // al
|
|
int8 v3; // [rsp+47h] [rbp-1h]
|
|
|
|
if ((obj_yspeed.enemy[k] & 2) != 0) {
|
|
if (*(&enemy_interval_timer + k) || (uint8)(obj_ypos_lo.enemy[k] + 16) < obj_ypos_lo.player) {
|
|
if (!(frame_counter & 1))
|
|
++obj_ypos_lo.enemy[k];
|
|
} else {
|
|
obj_yspeed.enemy[k] = 0;
|
|
}
|
|
} else {
|
|
v3 = frame_counter & 7;
|
|
if (obj_yspeed.enemy[k] & 1) {
|
|
if (!v3) {
|
|
v2 = obj_sub_yspeed.enemy[k] - 1;
|
|
obj_sub_yspeed.enemy[k] = v2;
|
|
obj_xspeed.enemy[k] = v2;
|
|
if (!v2) {
|
|
++obj_yspeed.enemy[k];
|
|
*(&enemy_interval_timer + k) = 2;
|
|
}
|
|
}
|
|
} else if (!v3) {
|
|
v1 = obj_sub_yspeed.enemy[k] + 1;
|
|
obj_sub_yspeed.enemy[k] = v1;
|
|
obj_xspeed.enemy[k] = v1;
|
|
if (v1 == 2)
|
|
++obj_yspeed.enemy[k];
|
|
}
|
|
}
|
|
}
|
|
|
|
void MoveBulletBill(uint8 k) {
|
|
if ((enemy_state[k] & 0x20) != 0) {
|
|
MoveJ_EnemyVert(k);
|
|
} else {
|
|
obj_xspeed.enemy[k] = -24;
|
|
MoveEnemyHoriz(k);
|
|
}
|
|
}
|
|
|
|
void MoveSwimmingCheepCheep(uint8 k) {
|
|
uint8 v1; // al
|
|
bool v2; // cf
|
|
uint8 v3; // al
|
|
uint8 v4; // al
|
|
uint8 v5; // al
|
|
int8 v6; // al
|
|
bool v7; // tt
|
|
uint8 v8; // al
|
|
uint8 v9; // al
|
|
int8 v10; // tt
|
|
uint8 v11; // di
|
|
int8 v12; // al
|
|
|
|
if ((enemy_state[k] & 0x20) != 0) {
|
|
MoveEnemySlowVert(k);
|
|
} else {
|
|
R3_ = 0;
|
|
R2_ = kSwimCCXMoveData[(uint8)(enemy_id[k] - 10)];
|
|
v1 = obj_xpos_fract.enemy[k];
|
|
v2 = v1 < R2_;
|
|
obj_xpos_fract.enemy[k] = v1 - R2_;
|
|
v3 = obj_xpos_lo.enemy[k];
|
|
obj_xpos_lo.enemy[k] = v3 - v2;
|
|
obj_xpos_hi.enemy[k] -= v3 < (uint8)v2;
|
|
R2_ = 32;
|
|
if (k >= 2u) {
|
|
v4 = obj_sub_ypos.enemy[k];
|
|
if (obj_xspeed.enemy[k] < 0x10u) {
|
|
v2 = v4 < R2_;
|
|
obj_sub_ypos.enemy[k] = v4 - R2_;
|
|
v9 = obj_ypos_lo.enemy[k];
|
|
v10 = v2 + R3_;
|
|
v2 = v9 < (uint8)(v2 + R3_);
|
|
obj_ypos_lo.enemy[k] = v9 - v10;
|
|
v8 = obj_ypos_hi.enemy[k] - v2;
|
|
} else {
|
|
v2 = __CFADD__(R2_, v4);
|
|
obj_sub_ypos.enemy[k] = R2_ + v4;
|
|
v5 = obj_ypos_lo.enemy[k];
|
|
v7 = v2;
|
|
v2 = __CFADD__(v2, v5);
|
|
v6 = v7 + v5;
|
|
v2 |= __CFADD__(R3_, v6);
|
|
obj_ypos_lo.enemy[k] = R3_ + v6;
|
|
v8 = v2 + obj_ypos_hi.enemy[k];
|
|
}
|
|
obj_ypos_hi.enemy[k] = v8;
|
|
v11 = 0;
|
|
v12 = obj_ypos_lo.enemy[k] - obj_sub_yspeed.enemy[k];
|
|
if (v12 < 0) {
|
|
v11 = 16;
|
|
v12 = obj_sub_yspeed.enemy[k] - obj_ypos_lo.enemy[k];
|
|
}
|
|
if ((uint8)v12 >= 0xFu)
|
|
obj_xspeed.enemy[k] = v11;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProcFirebar(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // al
|
|
uint8 v3; // di
|
|
uint8 enemy; // al
|
|
OamEnt *oam; // rbp
|
|
uint8 v6; // al
|
|
uint8 v7; // di
|
|
|
|
GetEnemyOffscreenBits(k);
|
|
if ((offscreen_bits.enemy & 8) == 0) {
|
|
if (!timer_control)
|
|
obj_yspeed.enemy[k] = FirebarSpin(k, enemy_data_b[k]) & 0x1F;
|
|
v1 = obj_yspeed.enemy[k];
|
|
if (enemy_id[k] >= 0x1Fu && (v1 == 8 || v1 == 24))
|
|
obj_yspeed.enemy[k] = ++v1;
|
|
tempEF = v1;
|
|
v2 = RelativeEnemyPosition(k);
|
|
GetFirebarPosition(v2);
|
|
v3 = enemy_obj_id[k];
|
|
enemy = rel_ypos.enemy;
|
|
oam = get_OamEnt(oam_buf, v3);
|
|
oam[64].ypos = rel_ypos.enemy;
|
|
R7_ = enemy;
|
|
v6 = rel_xpos_lo.enemy;
|
|
oam[64].xpos = rel_xpos_lo.enemy;
|
|
R6_ = v6;
|
|
R0_ = 1;
|
|
FirebarCollision(v3);
|
|
v7 = 5;
|
|
if (enemy_id[k] >= 0x1Fu)
|
|
v7 = 11;
|
|
tempED = v7;
|
|
R0_ = 0;
|
|
do {
|
|
GetFirebarPosition(tempEF);
|
|
DrawFirebar_Collision();
|
|
if (R0_ == 4)
|
|
R6_ = enemy_obj_id[duplicate_obj_offset];
|
|
++R0_;
|
|
} while (R0_ < tempED);
|
|
}
|
|
}
|
|
// 7E03B9: using guessed type int8;
|
|
|
|
void DrawFirebar_Collision() {
|
|
uint8 v0; // di
|
|
uint8 v1; // al
|
|
uint8 v2; // al
|
|
OamEnt *oam; // rdx
|
|
uint8 v4; // al
|
|
uint8 enemy; // al
|
|
uint8 v6; // al
|
|
int8 v7; // cf
|
|
|
|
v0 = R6_;
|
|
v1 = R1_;
|
|
R5_ = R3_ >> 1;
|
|
if (!(R3_ & 1))
|
|
v1 = -R1_;
|
|
v2 = rel_xpos_lo.enemy + v1;
|
|
oam = get_OamEnt(oam_buf, R6_);
|
|
oam[64].xpos = v2;
|
|
R6_ = v2;
|
|
if (v2 >= rel_xpos_lo.enemy)
|
|
v4 = v2 - rel_xpos_lo.enemy;
|
|
else
|
|
v4 = rel_xpos_lo.enemy - R6_;
|
|
if (v4 < 0x59u) {
|
|
enemy = rel_ypos.enemy;
|
|
if (rel_ypos.enemy != 0xF8) {
|
|
v6 = R2_;
|
|
v7 = R5_ & 1;
|
|
R5_ >>= 1;
|
|
if (!v7)
|
|
v6 = -R2_;
|
|
enemy = rel_ypos.enemy + v6;
|
|
}
|
|
} else {
|
|
enemy = -8;
|
|
}
|
|
oam[64].ypos = enemy;
|
|
R7_ = enemy;
|
|
oam_tile_size_buffer[v0 + 256] = enemy >= 0xF0u;
|
|
FirebarCollision(v0);
|
|
}
|
|
// 7E03B9: using guessed type int8;
|
|
|
|
void FirebarCollision(uint8 j) {
|
|
uint8 player; // di
|
|
uint8 i; // al
|
|
int8 v3; // al
|
|
int8 v4; // al
|
|
uint8 v5; // si
|
|
uint8 v6; // [rsp+46h] [rbp-2h]
|
|
|
|
DrawFirebar(j);
|
|
if (!(timer_control | player_star_power_timer)) {
|
|
R5_ = 0;
|
|
if (obj_ypos_hi.player == 1) {
|
|
player = obj_ypos_lo.player;
|
|
if (player_size || crouching_flag) {
|
|
++R5_;
|
|
++R5_;
|
|
player = obj_ypos_lo.player + 24;
|
|
}
|
|
for (i = player;; i = kFirebarYPos[R5_++] + obj_ypos_lo.player) {
|
|
v3 = i - R7_;
|
|
if (v3 < 0)
|
|
v3 = -v3;
|
|
if ((uint8)v3 < 8u && R6_ < 0xF0u) {
|
|
R4_ = rel_xpos_lo.player + 4;
|
|
v4 = rel_xpos_lo.player + 4 - R6_;
|
|
if (v4 < 0)
|
|
v4 = R6_ - (rel_xpos_lo.player + 4);
|
|
if ((uint8)v4 < 8u)
|
|
break;
|
|
}
|
|
if (R5_ == 2)
|
|
goto LABEL_19;
|
|
}
|
|
v5 = 1;
|
|
if (R4_ < R6_)
|
|
v5 = 2;
|
|
enemy_moving_dir[0] = v5;
|
|
v6 = R0_;
|
|
InjurePlayer();
|
|
R0_ = v6;
|
|
}
|
|
}
|
|
LABEL_19:
|
|
R6_ = j + 4;
|
|
}
|
|
|
|
void GetFirebarPosition(uint8 a) {
|
|
uint8 v1; // al
|
|
uint8 v2; // al
|
|
|
|
v1 = a & 0xF;
|
|
if (v1 >= 9u)
|
|
v1 = (v1 ^ 0xF) + 1;
|
|
R1_ = v1;
|
|
R1_ = kFirebarPosLookupTbl[(uint8)(v1 + kFirebarTblOffsets[R0_])];
|
|
v2 = (a + 8) & 0xF;
|
|
if (v2 >= 9u)
|
|
v2 = (v2 ^ 0xF) + 1;
|
|
R2_ = v2;
|
|
R2_ = kFirebarPosLookupTbl[(uint8)(v2 + kFirebarTblOffsets[R0_])];
|
|
R3_ = kFirebarMirrorData[a >> 3];
|
|
}
|
|
|
|
void MoveFlyingCheepCheep(uint8 k) {
|
|
uint8 v1; // di
|
|
int8 v2; // al
|
|
|
|
if ((enemy_state[k] & 0x20) != 0) {
|
|
enemy_sprattrib[k] = 32;
|
|
MoveJ_EnemyVert(k);
|
|
} else {
|
|
MoveEnemyHoriz(k);
|
|
SetXMoveAmt(k, 0xDu, 5u);
|
|
v1 = obj_sub_yspeed.enemy[k] >> 4;
|
|
v2 = obj_ypos_lo.enemy[k] - kPRandomSubtracter[v1];
|
|
if (v2 < 0)
|
|
v2 = kPRandomSubtracter[v1] - obj_ypos_lo.enemy[k];
|
|
if ((uint8)v2 < 8u)
|
|
v1 = (uint8)(obj_sub_yspeed.enemy[k] + 16) >> 4;
|
|
enemy_sprattrib[k] = kFlyCCBPriority[v1];
|
|
}
|
|
}
|
|
|
|
void MoveLakitu(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 i; // di
|
|
uint8 v3; // di
|
|
|
|
if ((enemy_state[k] & 0x20) != 0) {
|
|
MoveD_EnemyVert(k);
|
|
} else {
|
|
if (enemy_state[k]) {
|
|
obj_yspeed.enemy[k] = 0;
|
|
enemy_frenzy_buffer = 0;
|
|
v1 = 16;
|
|
} else {
|
|
enemy_frenzy_buffer = 18;
|
|
for (i = 2; (i & 0x80u) == 0; --i)
|
|
*(&R1_ + i) = kLakituDiffAdj[i];
|
|
v1 = PlayerLakituDiff(k);
|
|
}
|
|
obj_xspeed.enemy[k] = v1;
|
|
v3 = 1;
|
|
if ((obj_yspeed.enemy[k] & 1) == 0) {
|
|
obj_xspeed.enemy[k] = -obj_xspeed.enemy[k];
|
|
v3 = 2;
|
|
}
|
|
enemy_moving_dir[k] = v3;
|
|
MoveEnemyHoriz(k);
|
|
}
|
|
}
|
|
|
|
uint8 PlayerLakituDiff(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 result; // al
|
|
uint8 v3; // di
|
|
int8 v4; // di
|
|
|
|
v1 = 0;
|
|
if ((PlayerEnemyDiff(k) & 0x80u) != 0) {
|
|
v1 = 1;
|
|
R0_ = -R0_;
|
|
}
|
|
if (R0_ >= 0x3Cu) {
|
|
R0_ = 60;
|
|
if (enemy_id[k] == 17 && v1 != obj_yspeed.enemy[k]) {
|
|
if (obj_yspeed.enemy[k]) {
|
|
result = --obj_xspeed.enemy[k];
|
|
if (result)
|
|
return result;
|
|
}
|
|
obj_yspeed.enemy[k] = v1;
|
|
}
|
|
}
|
|
R0_ = (uint8)(R0_ & 0x3C) >> 2;
|
|
v3 = 0;
|
|
if (obj_xspeed.player && scroll_amount) {
|
|
v3 = 1;
|
|
if (obj_xspeed.player >= 0x19u && scroll_amount >= 2u)
|
|
v3 = 2;
|
|
if ((enemy_id[k] != 18 || !obj_xspeed.player) && !obj_yspeed.enemy[k])
|
|
v3 = 0;
|
|
}
|
|
result = *(&R1_ + v3);
|
|
v4 = R0_;
|
|
do {
|
|
--result;
|
|
--v4;
|
|
} while (v4 >= 0);
|
|
return result;
|
|
}
|
|
|
|
void BridgeCollapse_Sub(uint8 a) {
|
|
uint8 v1; // si
|
|
|
|
v1 = bridge_collapse_offset - 2;
|
|
bridge_segment_index[0] = bridge_collapse_offset - 2;
|
|
if ((a & 0x80) != 0) {
|
|
bridge_animation_frame[v1] = 0;
|
|
bridge_sprite_slot_exists_flag[v1] = 1;
|
|
tempE4 = 8 * (R4_ & 0x1F);
|
|
level_bridge_spr_xpos_lo[v1] = tempE4 - screen_left_xpos16;
|
|
level_bridge_spr_animation_frame_timer[v1] = 3;
|
|
}
|
|
}
|
|
|
|
void BridgeCollapse() {
|
|
uint8 v0; // si
|
|
uint8 v1; // al
|
|
|
|
v0 = browser_front_offset;
|
|
if (enemy_id[browser_front_offset] != 45) {
|
|
LABEL_5:
|
|
if (!bridge_collapse_sfx_flag) {
|
|
music_ch1 = 11;
|
|
bridge_collapse_sfx_flag = 11;
|
|
}
|
|
++game_mode_task;
|
|
KillAllEnemies();
|
|
return;
|
|
}
|
|
object_index = browser_front_offset;
|
|
v1 = enemy_state[browser_front_offset];
|
|
if (v1) {
|
|
if ((v1 & 0x40) != 0 && obj_ypos_lo.enemy[browser_front_offset] < 0xE0u) {
|
|
MoveEnemySlowVert(browser_front_offset);
|
|
BowserGfxHandler(v0);
|
|
return;
|
|
}
|
|
goto LABEL_5;
|
|
}
|
|
if (!--bowser_feet_counter) {
|
|
bowser_feet_counter = 4;
|
|
browser_body_controls ^= 1u;
|
|
R5_ = 2;
|
|
R4_ = kBridgeCollapseData[bridge_collapse_offset];
|
|
BridgeCollapse_Sub(R4_);
|
|
RemBridge(0x18u, vram_buffer1_offset + 1);
|
|
v0 = object_index;
|
|
MoveVOffset();
|
|
sound_ch3 = 22;
|
|
if (!bridge_collapse_offset) {
|
|
bowser_var014B = 8;
|
|
bowser_var0F4C = -1;
|
|
}
|
|
if (++bridge_collapse_offset == 15) {
|
|
InitVStf(v0);
|
|
enemy_state[v0] = 64;
|
|
}
|
|
}
|
|
BowserGfxHandler(v0);
|
|
}
|
|
|
|
void RunBowser(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
uint8 v3; // al
|
|
uint8 v4; // al
|
|
uint8 v5; // al
|
|
|
|
if ((enemy_state[k] & 0x20) != 0) {
|
|
if (obj_ypos_lo.enemy[k] < 0xE0u) {
|
|
MoveEnemySlowVert(k);
|
|
BowserGfxHandler(k);
|
|
} else {
|
|
KillAllEnemies();
|
|
}
|
|
} else {
|
|
enemy_frenzy_buffer = 0;
|
|
if (!timer_control) {
|
|
if ((browser_body_controls & 0x80u) == 0) {
|
|
if (!--bowser_feet_counter) {
|
|
bowser_feet_counter = 32;
|
|
browser_body_controls ^= 1u;
|
|
}
|
|
if ((frame_counter & 0xF) == 0)
|
|
enemy_moving_dir[k] = 2;
|
|
if (!enemy_frame_timer[k] || (PlayerEnemyDiff(k) & 0x80u) == 0 ||
|
|
(enemy_moving_dir[k] = 1, bowser_movement_speed = 2, enemy_frame_timer[k] = 32, bowser_fire_breath_timer = 32,
|
|
obj_xpos_lo.enemy[k] < 0xB0u)) {
|
|
if ((frame_counter & 3) == 0) {
|
|
if (obj_xpos_lo.enemy[k] == bowser_orig_xpos)
|
|
bowser_var06DC = kDATA_03D55A[*(&random_byte1 + k) & 3];
|
|
v1 = bowser_movement_speed + obj_xpos_lo.enemy[k];
|
|
obj_xpos_lo.enemy[k] = v1;
|
|
if (enemy_moving_dir[k] != 1) {
|
|
v2 = -1;
|
|
v3 = v1 - bowser_orig_xpos;
|
|
if ((v3 & 0x80u) != 0) {
|
|
v3 = -v3;
|
|
v2 = 1;
|
|
}
|
|
if (v3 >= bowser_var06DC)
|
|
bowser_movement_speed = v2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
v4 = enemy_frame_timer[k];
|
|
if (v4) {
|
|
if (v4 == 1) {
|
|
--obj_ypos_lo.enemy[k];
|
|
InitVStf(k);
|
|
obj_yspeed.enemy[k] = -2;
|
|
}
|
|
} else {
|
|
MoveEnemySlowVert(k);
|
|
if (world_number >= 5u && (frame_counter & 3) == 0)
|
|
SpawnThrownHammer(k);
|
|
if (obj_ypos_lo.enemy[k] >= 0x80u)
|
|
enemy_frame_timer[k] = kDATA_03D55A[*(&random_byte1 + k) & 3];
|
|
}
|
|
}
|
|
do {
|
|
if (world_number != 7 && world_number >= 5u || bowser_fire_breath_timer) {
|
|
BowserGfxHandler(k);
|
|
return;
|
|
}
|
|
bowser_fire_breath_timer = 32;
|
|
browser_body_controls ^= 0x80u;
|
|
} while ((browser_body_controls & 0x80u) != 0);
|
|
v5 = SetFlameTimer();
|
|
if (secondary_hard_mode)
|
|
v5 -= 16;
|
|
bowser_fire_breath_timer = v5;
|
|
enemy_frenzy_buffer = 21;
|
|
BowserGfxHandler(k);
|
|
}
|
|
}
|
|
|
|
void KillAllEnemies() {
|
|
int8 i; // si
|
|
|
|
for (i = 8; i >= 0; --i)
|
|
EraseEnemyObject(i);
|
|
enemy_frenzy_buffer = 0;
|
|
}
|
|
|
|
void BowserGfxHandler(uint8 k) {
|
|
int8 v1; // di
|
|
uint8 v2; // al
|
|
uint8 v3; // di
|
|
uint8 v4; // si
|
|
uint8 v5; // al
|
|
uint8 v6; // [rsp+47h] [rbp-1h]
|
|
|
|
ProcessBowserHalf(k);
|
|
v1 = 16;
|
|
if (enemy_moving_dir[k] & 1)
|
|
v1 = -16;
|
|
v2 = obj_xpos_lo.enemy[k] + v1;
|
|
v3 = duplicate_obj_offset;
|
|
obj_xpos_lo.enemy[duplicate_obj_offset] = v2;
|
|
obj_ypos_lo.enemy[v3] = obj_ypos_lo.enemy[k] + 8;
|
|
enemy_state[v3] = enemy_state[k];
|
|
enemy_moving_dir[v3] = enemy_moving_dir[k];
|
|
v6 = object_index;
|
|
v4 = duplicate_obj_offset;
|
|
object_index = duplicate_obj_offset;
|
|
if (!bowser_var0097) {
|
|
if (world_number == 7)
|
|
v5 = 5;
|
|
else
|
|
v5 = 4;
|
|
music_ch1 = v5;
|
|
bowser_var0097 = v5;
|
|
}
|
|
enemy_id[duplicate_obj_offset] = 45;
|
|
enemy_sprattrib[v4] = 32;
|
|
object_index = v6;
|
|
bowser_gfx_flag = 0;
|
|
}
|
|
|
|
void ProcessBowserHalf(uint8 k) {
|
|
++bowser_gfx_flag;
|
|
RunRetainerObj(k);
|
|
if (!enemy_state[k]) {
|
|
enemy_hitbox_ctrl[k] = 10;
|
|
GetEnemyBoundBox(k);
|
|
if (game_mode != 2)
|
|
PlayerEnemyCollision(k);
|
|
}
|
|
}
|
|
|
|
uint8 SetFlameTimer() {
|
|
uint8 v0; // di
|
|
|
|
v0 = bowser_flame_timer_ctrl++;
|
|
bowser_flame_timer_ctrl &= 7u;
|
|
return kFlameTimerData[v0];
|
|
}
|
|
|
|
void ProcBowserFlame(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // al
|
|
bool v3; // cf
|
|
uint8 v4; // al
|
|
uint8 v5; // al
|
|
|
|
if (k != var0F4D_new || !bowser_var0F4C || bowser_var014B != 6) {
|
|
if (!timer_control) {
|
|
v1 = 64;
|
|
if (secondary_hard_mode)
|
|
v1 = 96;
|
|
R0_ = v1;
|
|
v2 = obj_xpos_fract.enemy[k];
|
|
v3 = v2 < R0_;
|
|
obj_xpos_fract.enemy[k] = v2 - R0_;
|
|
v4 = obj_xpos_lo.enemy[k];
|
|
obj_xpos_lo.enemy[k] = v4 - (v3 + 1);
|
|
obj_xpos_hi.enemy[k] -= v4 < (uint8)(v3 + 1);
|
|
v5 = obj_ypos_lo.enemy[k];
|
|
if (v5 != kFlameYPosData[obj_sub_ypos.enemy[k]])
|
|
obj_ypos_lo.enemy[k] = obj_sub_yspeed.enemy[k] + v5;
|
|
}
|
|
RelativeEnemyPosition(k);
|
|
if (!enemy_state[k])
|
|
ProcBowserFlame_Sub(k);
|
|
}
|
|
}
|
|
|
|
void RunFireworks(uint8 k) {
|
|
uint8 v2; // di
|
|
|
|
if (obj_yspeed.enemy[k]-- != 1)
|
|
goto LABEL_5;
|
|
obj_yspeed.enemy[k] = 8;
|
|
if (++obj_xspeed.enemy[k] == 1) {
|
|
sound_ch1 = 41;
|
|
LABEL_5:
|
|
RelativeEnemyPosition(k);
|
|
rel_ypos.fireball = rel_ypos.enemy;
|
|
rel_xpos_lo.fireball = rel_xpos_lo.enemy;
|
|
DrawExplosion_Fireworks(enemy_obj_id[k], obj_xspeed.enemy[k]);
|
|
return;
|
|
}
|
|
if (obj_xspeed.enemy[k] < 4u)
|
|
goto LABEL_5;
|
|
enemy_flag[k] = 0;
|
|
v2 = enemy_obj_id[k];
|
|
oam_tile_size_buffer[v2 + 256] = 3;
|
|
oam_tile_size_buffer[v2 + 260] = 3;
|
|
oam_tile_size_buffer[v2 + 264] = 3;
|
|
oam_tile_size_buffer[v2 + 268] = 3;
|
|
digit_modifier[4] = 5;
|
|
EndAreaPoints();
|
|
}
|
|
// 7E03AF: using guessed type int8;
|
|
// 7E03B9: using guessed type int8;
|
|
// 7E03BA: using guessed type int8;
|
|
|
|
void RunStarFlagObj(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
|
|
enemy_frenzy_buffer = 0;
|
|
switch (star_flag_task_control) {
|
|
case 1:
|
|
v1 = 5;
|
|
v2 = level_timer_ones;
|
|
if (level_timer_ones != 1) {
|
|
v1 = 3;
|
|
if (level_timer_ones != 3) {
|
|
v1 = 0;
|
|
if (level_timer_ones != 6)
|
|
v2 = -1;
|
|
}
|
|
}
|
|
fireworks_counter = v2;
|
|
enemy_state[k] = v1;
|
|
if ((ReadReg(APUI03) & 0x7F) != 75)
|
|
sound_ch3 = 75;
|
|
++star_flag_task_control;
|
|
break;
|
|
case 2:
|
|
if ((level_timer_hundreds | level_timer_tens | level_timer_ones) == 0) {
|
|
unused_byte_7E0E1A = sound_ch3 = 0x4c;
|
|
++star_flag_task_control;
|
|
} else {
|
|
CODE_03D809();
|
|
}
|
|
break;
|
|
case 3: RaiseFlagSetoffFWorks(k); break;
|
|
case 4: DelayToAreaEnd(k); break;
|
|
}
|
|
}
|
|
|
|
void CODE_03D809() {
|
|
digit_modifier[5] = -1;
|
|
DigitsMathRoutine(0x23u);
|
|
digit_modifier[5] = 5;
|
|
EndAreaPoints();
|
|
}
|
|
|
|
void EndAreaPoints() {
|
|
uint8 v0; // di
|
|
|
|
v0 = 11;
|
|
if (current_player)
|
|
v0 = 17;
|
|
DigitsMathRoutine(v0);
|
|
UpdateNumber((16 * current_player) | 4);
|
|
}
|
|
|
|
void RaiseFlagSetoffFWorks(uint8 k) {
|
|
disable_sprite_oamreset_flag = 1;
|
|
if (obj_ypos_lo.enemy[k] < 0x72u) {
|
|
if ((int8)fireworks_counter > 0) {
|
|
enemy_frenzy_buffer = 22;
|
|
DrawStarFlag(k);
|
|
} else {
|
|
DrawFlagSetTimer(k);
|
|
}
|
|
} else {
|
|
--obj_ypos_lo.enemy[k];
|
|
DrawStarFlag(k);
|
|
}
|
|
}
|
|
|
|
void DrawStarFlag(uint8 k) {
|
|
uint8 v1; // di
|
|
OamEnt *oam; // rbp
|
|
|
|
RelativeEnemyPosition(k);
|
|
v1 = enemy_obj_id[k];
|
|
oam = get_OamEnt(oam_buf, v1);
|
|
oam[64].ypos = rel_ypos.enemy;
|
|
oam[64].charnum = ((uint8)(frame_counter & 0x18) >> 2) + 4;
|
|
oam[64].flags = 11;
|
|
oam[64].xpos = rel_xpos_lo.enemy;
|
|
oam_tile_size_buffer[v1 + 256] = 2;
|
|
}
|
|
// 7E03B9: using guessed type int8;
|
|
|
|
void DrawFlagSetTimer(uint8 k) {
|
|
DrawStarFlag(k);
|
|
*(&enemy_interval_timer + k) = 6;
|
|
IncrementSFTask2();
|
|
}
|
|
|
|
void IncrementSFTask2() {
|
|
++star_flag_task_control;
|
|
}
|
|
|
|
void DelayToAreaEnd(uint8 k) {
|
|
DrawStarFlag(k);
|
|
if (!*(&enemy_interval_timer + k) && !event_music_buffer)
|
|
IncrementSFTask2();
|
|
}
|
|
|
|
void MovePiranhaPlant(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // al
|
|
|
|
if (enemy_state[k] || enemy_frame_timer[k])
|
|
goto LABEL_15;
|
|
if (obj_yspeed.enemy[k])
|
|
goto LABEL_9;
|
|
if ((obj_xspeed.enemy[k] & 0x80u) != 0)
|
|
goto LABEL_8;
|
|
if ((PlayerEnemyDiff(k) & 0x80u) != 0)
|
|
R0_ = -R0_;
|
|
if (R0_ >= 0x21u) {
|
|
LABEL_8:
|
|
obj_xspeed.enemy[k] = -obj_xspeed.enemy[k];
|
|
++obj_yspeed.enemy[k];
|
|
LABEL_9:
|
|
v1 = obj_sub_yspeed.enemy[k];
|
|
if ((obj_xspeed.enemy[k] & 0x80u) != 0)
|
|
v1 = obj_sub_ypos.enemy[k];
|
|
R0_ = v1;
|
|
if (frame_counter & 1) {
|
|
if (!timer_control) {
|
|
v2 = obj_xspeed.enemy[k] + obj_ypos_lo.enemy[k];
|
|
obj_ypos_lo.enemy[k] = v2;
|
|
if (v2 == R0_) {
|
|
obj_yspeed.enemy[k] = 0;
|
|
enemy_frame_timer[k] = 64;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
LABEL_15:
|
|
enemy_sprattrib[k] = 0;
|
|
}
|
|
|
|
uint8 FirebarSpin(uint8 k, uint8 a) {
|
|
uint8 v2; // al
|
|
bool v3; // cf
|
|
|
|
R7_ = a;
|
|
v2 = obj_xspeed.enemy[k];
|
|
if (enemy_data_a[k]) {
|
|
v3 = v2 < R7_;
|
|
obj_xspeed.enemy[k] = v2 - R7_;
|
|
return obj_yspeed.enemy[k] - v3;
|
|
} else {
|
|
v3 = __CFADD__(R7_, v2);
|
|
obj_xspeed.enemy[k] = R7_ + v2;
|
|
return v3 + obj_yspeed.enemy[k];
|
|
}
|
|
}
|
|
|
|
void BalancePlatform(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
int8 v3; // al
|
|
uint8 v4; // al
|
|
int8 v5; // al
|
|
int8 v6; // al
|
|
uint8 v7; // di
|
|
int8 v8; // al
|
|
uint16 v9; // si
|
|
int16 v10; // ax
|
|
int v11; // edx
|
|
int16 v12; // ax
|
|
uint16 v13; // si
|
|
int16 v14; // ax
|
|
int v15; // edx
|
|
int16 v16; // ax
|
|
uint8 v17; // [rsp+47h] [rbp-1h]
|
|
uint8 v18; // [rsp+47h] [rbp-1h]
|
|
|
|
if (obj_ypos_hi.enemy[k] == 3) {
|
|
EraseEnemyObject(k);
|
|
return;
|
|
}
|
|
v1 = enemy_state[k];
|
|
if ((v1 & 0x80u) != 0)
|
|
return;
|
|
v2 = enemy_state[k];
|
|
R0_ = enemy_data_d[k];
|
|
if (enemy_moving_dir[k]) {
|
|
PlatformFall(k, v1);
|
|
return;
|
|
}
|
|
if (obj_ypos_lo.enemy[k] <= 0x2Du) {
|
|
if (v1 != R0_) {
|
|
obj_ypos_lo.enemy[k] = 47;
|
|
StopPlatforms(k, v1);
|
|
return;
|
|
}
|
|
goto LABEL_9;
|
|
}
|
|
if (obj_ypos_lo.enemy[v1] > 0x2Du) {
|
|
v17 = obj_ypos_lo.enemy[k];
|
|
v3 = enemy_data_d[k];
|
|
if (v3 >= 0) {
|
|
if (v3 != object_index)
|
|
goto LABEL_19;
|
|
} else {
|
|
v4 = obj_sub_yspeed.enemy[k];
|
|
R0_ = v4 + 5;
|
|
v5 = __CFADD__(v4, 5) + obj_yspeed.enemy[k];
|
|
if (v5 >= 0) {
|
|
if (!v5 && R0_ < 0xBu) {
|
|
StopPlatforms(k, v2);
|
|
goto LABEL_22;
|
|
}
|
|
LABEL_19:
|
|
MovePlatformUp(k);
|
|
LABEL_22:
|
|
obj_ypos_lo.enemy[enemy_state[k]] += v17 - obj_ypos_lo.enemy[k];
|
|
v6 = enemy_data_d[k];
|
|
if (v6 >= 0)
|
|
PositionPlayerOnVPlat(v6);
|
|
v7 = object_index;
|
|
if (obj_sub_yspeed.enemy[object_index] | obj_yspeed.enemy[object_index]) {
|
|
v18 = obj_yspeed.enemy[object_index];
|
|
SetupPlatformRope(object_index, v18);
|
|
tempF3 = (uint8)screen_left_xpos16 >> 3;
|
|
tempF4 = (4 * (HIBYTE(screen_left_xpos16) & 1)) | 0x20;
|
|
v8 = ((uint8)screen_left_xpos16 >> 3) + 31;
|
|
tempF5 = v8 & 0x1F;
|
|
if ((v8 & 0x20) != 0)
|
|
tempF6 = tempF4 ^ 4;
|
|
if ((unsigned int)(*(uint16 *)&R0_ & 0x241F) >= *(uint16 *)&tempF3 ||
|
|
(unsigned int)(*(uint16 *)&R0_ & 0x241F) < *(uint16 *)&tempF5) {
|
|
v9 = *(uint16 *)&vram_buffer1_offset;
|
|
LOBYTE(v10) = (uint16)(*(uint16 *)&R0_ & 0x1FFF) >> 8;
|
|
HIBYTE(v10) = R0_;
|
|
v11 = *(uint16 *)&vram_buffer1_offset;
|
|
*(uint16 *)&vram_buffer1[*(uint16 *)&vram_buffer1_offset + 1] = v10;
|
|
*(uint16 *)&vram_buffer1[v11 + 3] = 768;
|
|
if ((obj_yspeed.enemy[v7] & 0x80) != 0) {
|
|
*(uint16 *)&vram_buffer1[v9 + 5] = 36;
|
|
*(uint16 *)&vram_buffer1[v9 + 7] = 36;
|
|
} else {
|
|
if ((*(uint16 *)&vram_buffer1[v9 + 1] & 0xF003) == 0xA000 || (*(uint16 *)&vram_buffer1[v9 + 1] & 0xF003) == 0xB000) {
|
|
v12 = 6236;
|
|
} else {
|
|
v12 = 4258;
|
|
}
|
|
*(uint16 *)&vram_buffer1[v9 + 5] = v12;
|
|
*(uint16 *)&vram_buffer1[v9 + 7] = 6307;
|
|
}
|
|
*(uint16 *)&vram_buffer1[v9 + 9] = -1;
|
|
*(uint16 *)&vram_buffer1_offset = v9 + 8;
|
|
}
|
|
SetupPlatformRope(enemy_state[v7], ~v18);
|
|
if ((unsigned int)(*(uint16 *)&R0_ & 0x241F) >= *(uint16 *)&tempF3 ||
|
|
(unsigned int)(*(uint16 *)&R0_ & 0x241F) < *(uint16 *)&tempF5) {
|
|
v13 = *(uint16 *)&vram_buffer1_offset;
|
|
LOBYTE(v14) = (uint16)(*(uint16 *)&R0_ & 0x1FFF) >> 8;
|
|
HIBYTE(v14) = R0_;
|
|
v15 = *(uint16 *)&vram_buffer1_offset;
|
|
*(uint16 *)&vram_buffer1[*(uint16 *)&vram_buffer1_offset + 1] = v14;
|
|
*(uint16 *)&vram_buffer1[v15 + 3] = 768;
|
|
if ((v18 & 0x80) != 0) {
|
|
*(uint16 *)&vram_buffer1[v13 + 5] = 4258;
|
|
if ((*(uint16 *)&vram_buffer1[v13 + 1] & 0xF003) == 0xA000 || (*(uint16 *)&vram_buffer1[v13 + 1] & 0xF003) == 0xB000) {
|
|
v16 = 6207;
|
|
} else {
|
|
v16 = 6307;
|
|
}
|
|
*(uint16 *)&vram_buffer1[v13 + 7] = v16;
|
|
} else {
|
|
*(uint16 *)&vram_buffer1[v13 + 5] = 36;
|
|
*(uint16 *)&vram_buffer1[v13 + 7] = 36;
|
|
}
|
|
*(uint16 *)&vram_buffer1[v13 + 9] = -1;
|
|
*(uint16 *)&vram_buffer1_offset = v13 + 8;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
MovePlatformDown(k);
|
|
goto LABEL_22;
|
|
}
|
|
if (k == R0_) {
|
|
LABEL_9:
|
|
InitPlatformFall(k, v1);
|
|
return;
|
|
}
|
|
obj_ypos_lo.enemy[v1] = 47;
|
|
StopPlatforms(k, v1);
|
|
}
|
|
|
|
void SetupPlatformRope(uint8 j, uint8 a) {
|
|
int8 v2; // al
|
|
bool v3; // cf
|
|
uint8 v4; // si
|
|
|
|
v2 = obj_xpos_lo.enemy[j] + 8;
|
|
v3 = 0;
|
|
if (!secondary_hard_mode) {
|
|
v3 = __CFADD__(v2, 16);
|
|
v2 = obj_xpos_lo.enemy[j] + 24;
|
|
}
|
|
R2_ = v3 + obj_xpos_hi.enemy[j];
|
|
R0_ = (uint8)(v2 & 0xF0) >> 3;
|
|
v4 = obj_ypos_lo.enemy[j];
|
|
if ((a & 0x80u) != 0)
|
|
v4 += 8;
|
|
R1_ = (2 * (4 * v4 + __CFSHL__(v4, 1)) + __CFSHL__(2 * v4, 1)) & 3 | 0x20;
|
|
R1_ |= 4 * (R2_ & 1);
|
|
R0_ += (4 * v4 + __CFSHL__(v4, 1)) & 0xE0;
|
|
if (obj_ypos_lo.enemy[j] >= 0xE8u)
|
|
R0_ &= ~0x40u;
|
|
}
|
|
|
|
void InitPlatformFall(uint8 k, uint8 j) {
|
|
GetEnemyOffscreenBits(j);
|
|
SetupFloateyNumber(k, 6u);
|
|
score_spr_xpos_lo[k] = rel_xpos_lo.player;
|
|
score_spr_ypos_lo[k] = obj_ypos_lo.player;
|
|
enemy_moving_dir[k] = 1;
|
|
StopPlatforms(k, j);
|
|
}
|
|
|
|
void StopPlatforms(uint8 k, uint8 j) {
|
|
InitVStf(k);
|
|
obj_yspeed.enemy[j] = 0;
|
|
obj_sub_yspeed.enemy[j] = 0;
|
|
}
|
|
|
|
void PlatformFall(uint8 k, uint8 j) {
|
|
int8 v2; // al
|
|
|
|
MoveFallingPlatform(k);
|
|
if ((enemy_state[j] & 0x80u) != 0)
|
|
MoveFallingPlatform(j);
|
|
v2 = enemy_data_d[object_index];
|
|
if (v2 >= 0)
|
|
PositionPlayerOnVPlat(v2);
|
|
}
|
|
|
|
void YMovingPlatform(uint8 k) {
|
|
if (obj_sub_yspeed.enemy[k] | obj_yspeed.enemy[k] || (obj_sub_ypos.enemy[k] = 0, obj_ypos_lo.enemy[k] >= obj_xpos_fract.enemy[k])) {
|
|
if (obj_ypos_lo.enemy[k] < obj_xspeed.enemy[k])
|
|
MovePlatformDown(k);
|
|
else
|
|
MovePlatformUp(k);
|
|
} else if ((frame_counter & 7) == 0) {
|
|
++obj_ypos_lo.enemy[k];
|
|
}
|
|
ChkYPCollision(k);
|
|
}
|
|
|
|
void ChkYPCollision(uint8 k) {
|
|
if ((enemy_data_d[k] & 0x80u) == 0)
|
|
PositionPlayerOnVPlat(k);
|
|
}
|
|
|
|
void XMovingPlatform(uint8 k) {
|
|
XMoveCntr_Platform(k, 0xEu);
|
|
MoveWithXMCntrs(k);
|
|
if ((enemy_data_d[k] & 0x80u) == 0)
|
|
PositionPlayerOnHPlat(k);
|
|
}
|
|
|
|
void PositionPlayerOnHPlat(uint8 k) {
|
|
uint8 player; // al
|
|
|
|
bool carry = __CFADD__uint8(obj_xpos_lo.player, R0_);
|
|
|
|
obj_xpos_lo.player += R0_;
|
|
if ((R0_ & 0x80u) != 0)
|
|
player = obj_xpos_hi.player - 1 + carry;
|
|
else
|
|
player = obj_xpos_hi.player + carry;
|
|
obj_xpos_hi.player = player;
|
|
platform_x_scroll = R0_;
|
|
PositionPlayerOnVPlat(k);
|
|
}
|
|
|
|
void DropPlatform(uint8 k) {
|
|
if ((enemy_data_d[k] & 0x80u) == 0) {
|
|
MoveDropPlatform(k);
|
|
PositionPlayerOnVPlat(k);
|
|
}
|
|
}
|
|
|
|
void RightPlatform(uint8 k) {
|
|
R0_ = MoveEnemyHoriz(k);
|
|
if ((enemy_data_d[k] & 0x80u) == 0) {
|
|
obj_xspeed.enemy[k] = 16;
|
|
PositionPlayerOnHPlat(k);
|
|
}
|
|
}
|
|
|
|
void MoveLargeLiftPlat(uint8 k) {
|
|
MoveLiftPlatforms(k);
|
|
ChkYPCollision(k);
|
|
}
|
|
|
|
void MoveSmallPlatform(uint8 k) {
|
|
MoveLiftPlatforms(k);
|
|
ChkSmallPlatCollision(k);
|
|
}
|
|
|
|
void MoveLiftPlatforms(uint8 k) {
|
|
uint8 v1; // al
|
|
bool v2; // cf
|
|
|
|
if (!timer_control) {
|
|
v1 = obj_sub_ypos.enemy[k];
|
|
v2 = __CFADD__(obj_sub_yspeed.enemy[k], v1);
|
|
obj_sub_ypos.enemy[k] = obj_sub_yspeed.enemy[k] + v1;
|
|
obj_ypos_lo.enemy[k] += obj_yspeed.enemy[k] + v2;
|
|
}
|
|
}
|
|
|
|
void ChkSmallPlatCollision(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
v1 = enemy_data_d[k];
|
|
if (v1) {
|
|
if (v1 != 0xFF)
|
|
PositionPlayerOnS_Plat(k, v1);
|
|
}
|
|
}
|
|
|
|
void OffscreenBoundsCheck(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
int8 v3; // cf
|
|
int8 v4; // tt
|
|
|
|
if (enemy_id[k] != 20) {
|
|
v1 = screen_left_xpos_lo;
|
|
v2 = enemy_id[k];
|
|
v3 = v2 >= 5u;
|
|
if (v2 == 5 || (v3 = v2 >= 0xDu, v2 == 13)) {
|
|
v4 = v3;
|
|
v3 = __CFADD__(v3, screen_left_xpos_lo) | __CFADD__(v3 + screen_left_xpos_lo, 56);
|
|
v1 = v4 + screen_left_xpos_lo + 56;
|
|
}
|
|
R1_ = v1 - (!v3 + 72);
|
|
R0_ = screen_left_xpos_hi - (v1 < (uint8)(!v3 + 72));
|
|
R3_ = screen_right_xpos + 72;
|
|
R2_ = __CFADD__(screen_right_xpos, 72) + screen_right_xpos_hi;
|
|
if ((int8)(obj_xpos_hi.enemy[k] - ((obj_xpos_lo.enemy[k] < R1_) + R0_)) < 0 ||
|
|
(int8)(obj_xpos_hi.enemy[k] - ((obj_xpos_lo.enemy[k] < R3_) + R2_)) >= 0 && enemy_state[k] != 5 && v2 != 13 && v2 != 48 &&
|
|
v2 != 49 && v2 != 50) {
|
|
EraseEnemyObject(k);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FireballEnemyCollision(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
uint8 v3; // si
|
|
uint8 v4; // al
|
|
|
|
v1 = fireball_state[k];
|
|
if (v1 && !__CFSHL__(v1, 1) && !(frame_counter & 1)) {
|
|
v2 = 4 * k + 44;
|
|
v3 = 8;
|
|
do {
|
|
R1_ = v3;
|
|
if ((enemy_state[v3] & 0x20) == 0) {
|
|
if (enemy_flag[v3]) {
|
|
v4 = enemy_id[v3];
|
|
if ((v4 < 0x24u || v4 >= 0x2Bu) && (v4 != 6 || enemy_state[v3] < 2u) && !spr_array_D[v3]) {
|
|
if (SprObjectCollisionCore(4 * v3 + 4, v2) & 1) {
|
|
fireball_state[object_index] = 0x80;
|
|
HandleEnemyFBallCol(R1_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
v3 = R1_ - 1;
|
|
} while ((int8)(R1_ - 1) >= 0);
|
|
}
|
|
}
|
|
|
|
void HandleEnemyFBallCol(uint8 k) {
|
|
uint8 v1; // si
|
|
int8 v2; // al
|
|
uint8 v3; // al
|
|
uint8 v4; // di
|
|
uint8 v5; // al
|
|
int8 v6; // si
|
|
uint8 v7; // al
|
|
uint8 v8; // si
|
|
uint8 v9; // al
|
|
uint8 v10; // [rsp+47h] [rbp-1h]
|
|
|
|
RelativeEnemyPosition(k);
|
|
sound_ch1 = 1;
|
|
v1 = R1_;
|
|
v2 = enemy_flag[R1_];
|
|
if (v2 < 0) {
|
|
v1 = v2 & 0xF;
|
|
if (enemy_id[v2 & 0xF] == 45)
|
|
goto LABEL_6;
|
|
v1 = R1_;
|
|
}
|
|
v3 = enemy_id[v1];
|
|
if (v3 == 2)
|
|
return;
|
|
if (v3 != 45) {
|
|
if (v3 != 8 && v3 != 12 && v3 < 0x15u)
|
|
ShellOrBlockDefeat(v1);
|
|
return;
|
|
}
|
|
LABEL_6:
|
|
bowser_var014B = 8;
|
|
bowser_var0F4C = 24;
|
|
if (--bowser_hit_points) {
|
|
if (bowser_hit_points == 1) {
|
|
bowser_woozy_effect_animation_frame = 0;
|
|
bowser_feeling_woozy_flag = 1;
|
|
}
|
|
} else {
|
|
bowser_var014B = 8;
|
|
bowser_var0F4C = -1;
|
|
InitVStf(v1);
|
|
obj_xspeed.enemy[v1] = 0;
|
|
enemy_frenzy_buffer = 0;
|
|
obj_yspeed.enemy[v1] = -2;
|
|
v4 = world_number;
|
|
v5 = kBowserIdentities[world_number];
|
|
enemy_id[v1] = v5;
|
|
bowser_enemy_slot_plus1 = v1 + 1;
|
|
if (v5 != 45) {
|
|
v10 = v1;
|
|
if (area_data_addr_index != 33) {
|
|
obj_xspeed.bubble[0] = v1 + 1;
|
|
v6 = 8;
|
|
while (1) {
|
|
v7 = enemy_id[(uint8)v6--];
|
|
if (v6 < 0)
|
|
break;
|
|
if (v7 == 45) {
|
|
v8 = v6 + 1;
|
|
enemy_flag[v8] = 0;
|
|
enemy_id[v8] = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
v1 = v10;
|
|
}
|
|
v9 = 32;
|
|
if (v4 < 3u)
|
|
v9 = 35;
|
|
enemy_state[v1] = v9;
|
|
func_sub_DDAE(R1_, 9u);
|
|
}
|
|
}
|
|
|
|
void ShellOrBlockDefeat(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // al
|
|
uint8 v3; // di
|
|
|
|
v1 = enemy_id[k];
|
|
if (v1 == 13) {
|
|
v1 = obj_ypos_lo.enemy[k] + 25;
|
|
obj_ypos_lo.enemy[k] = v1;
|
|
}
|
|
ChkToStunEnemies(k, v1);
|
|
enemy_state[k] = enemy_state[k] & 0x1F | 0x20;
|
|
v2 = 2;
|
|
v3 = enemy_id[k];
|
|
if (v3 == 5)
|
|
v2 = 6;
|
|
if (v3 == 6)
|
|
func_sub_DDAE(k, 1u);
|
|
else
|
|
func_sub_DDAE(k, v2);
|
|
}
|
|
|
|
void func_sub_DDAE(uint8 k, uint8 a) {
|
|
SetupFloateyNumber(k, a);
|
|
if (sound_ch1 != 3) {
|
|
sound_ch1 = 3;
|
|
InitializeContactSprite(k);
|
|
}
|
|
}
|
|
|
|
void PlayerHammerCollision(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // si
|
|
|
|
if (frame_counter & 1 && !(offscreen_bits.misc | timer_control)) {
|
|
v1 = PlayerCollisionCore(4 * k + 52);
|
|
v2 = object_index;
|
|
if (v1 & 1) {
|
|
if (!misc_collision_flag[object_index]) {
|
|
misc_collision_flag[object_index] = 1;
|
|
obj_xspeed.misc[v2] = -obj_xspeed.misc[v2];
|
|
if (!player_star_power_timer)
|
|
InjurePlayer();
|
|
}
|
|
} else {
|
|
misc_collision_flag[object_index] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void HandlePowerUpCollision(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
EraseEnemyObject2(k);
|
|
SetupFloateyNumber1(k, 6u);
|
|
sound_ch1 = 10;
|
|
if (power_up_type < 2u) {
|
|
if (player_status) {
|
|
if (player_status != 1)
|
|
return;
|
|
player_status = 2;
|
|
GetPlayerColors();
|
|
v1 = 12;
|
|
} else {
|
|
player_status = 1;
|
|
v1 = 9;
|
|
}
|
|
SetPRout(0, v1);
|
|
} else if (power_up_type == 3) {
|
|
floateynum_control[k] = 11;
|
|
sound_ch1 = 0;
|
|
} else {
|
|
player_star_power_timer = 35;
|
|
music_ch1 = 13;
|
|
}
|
|
}
|
|
|
|
void PlayerEnemyCollision(uint8 k) {
|
|
uint8 EnemyBoundBoxOfs; // di
|
|
uint8 v2; // al
|
|
uint8 v3; // si
|
|
uint8 v4; // di
|
|
uint8 v5; // al
|
|
uint8 v6; // di
|
|
|
|
if (!(frame_counter & 1) && !(CheckPlayerVertical() & 1) && (k == 9 && rel_xpos_lo.enemy > 0xF3u || !spr_array_D[k]) &&
|
|
game_engine_subroutine == 8 && (enemy_state[k] & 0x20) == 0) {
|
|
EnemyBoundBoxOfs = GetEnemyBoundBoxOfs();
|
|
v2 = PlayerCollisionCore(EnemyBoundBoxOfs);
|
|
v3 = object_index;
|
|
if (!(v2 & 1)) {
|
|
enemy_collision_bits[object_index] &= ~1u;
|
|
return;
|
|
}
|
|
v4 = enemy_id[object_index];
|
|
if (v4 == 46) {
|
|
HandlePowerUpCollision(object_index);
|
|
return;
|
|
}
|
|
if (player_star_power_timer) {
|
|
ShellOrBlockDefeat(object_index);
|
|
return;
|
|
}
|
|
if (!(spr_array_D[object_index] | enemy_collision_bits[object_index] & 1)) {
|
|
enemy_collision_bits[object_index] |= 1u;
|
|
switch (v4) {
|
|
case 0x12u: goto LABEL_23;
|
|
case 0xDu:
|
|
case 0xCu: goto LABEL_21;
|
|
case 0x33u:
|
|
LABEL_23:
|
|
ChkForPlayerInjury(v3);
|
|
return;
|
|
}
|
|
if (v4 >= 0x15u || !area_type) {
|
|
LABEL_21:
|
|
InjurePlayer();
|
|
return;
|
|
}
|
|
if (__CFSHL__(enemy_state[v3], 1) || (enemy_state[v3] & 7u) < 2)
|
|
goto LABEL_23;
|
|
if (enemy_id[v3] != 6) {
|
|
sound_ch1 = 3;
|
|
InitializeContactSprite(v3);
|
|
enemy_array_F40[v3] = 0;
|
|
enemy_state[v3] |= 0x80u;
|
|
uint8 yy = EnemyFacePlayer(v3);
|
|
obj_xspeed.enemy[v3] = kKickedShellXSpdData[yy];
|
|
v5 = stomp_chain_counter + 3;
|
|
v6 = *(&enemy_interval_timer + v3);
|
|
if (v6 < 3u)
|
|
v5 = kKickedShellPtsData[v6];
|
|
SetupFloateyNumber(v3, v5);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ChkForPlayerInjury(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
uint8 v3; // [rsp+47h] [rbp-1h]
|
|
|
|
if ((int8)obj_yspeed.player > 0 || enemy_id[k] >= 7u && (uint8)(obj_ypos_lo.player + 12) < obj_ypos_lo.enemy[k] || stomp_timer) {
|
|
if (enemy_id[k] == 18)
|
|
goto LABEL_25;
|
|
sound_ch1 = 2;
|
|
v1 = enemy_id[k];
|
|
v2 = 0;
|
|
if (v1 == 20 || v1 == 8 || v1 == 51 || v1 == 12 || (v2 = 1, v1 == 5) || (v2 = 2, v1 == 17) || (v2 = 3, v1 == 7)) {
|
|
SetupFloateyNumber(k, kStompedEnemyPtsData[v2]);
|
|
v3 = enemy_moving_dir[k];
|
|
SetStun(k);
|
|
enemy_moving_dir[k] = v3;
|
|
enemy_state[k] = 32;
|
|
InitVStf(k);
|
|
obj_xspeed.enemy[k] = 0;
|
|
obj_yspeed.player = -3;
|
|
} else {
|
|
if (v1 < 9u) {
|
|
enemy_state[k] = 4;
|
|
++stomp_chain_counter;
|
|
SetupFloateyNumber(k, stomp_timer + stomp_chain_counter);
|
|
++stomp_timer;
|
|
*(&enemy_interval_timer + k) = kRevivalRateData[primary_hard_mode];
|
|
} else {
|
|
enemy_id[k] = v1 & 1;
|
|
enemy_state[k] = 0;
|
|
SetupFloateyNumber(k, 3u);
|
|
InitVStf(k);
|
|
uint8 yy = EnemyFacePlayer(k);
|
|
obj_xspeed.enemy[k] = kDemotedKoopaXSpdData[yy];
|
|
}
|
|
obj_yspeed.player = -5;
|
|
}
|
|
} else if (!player_hurt_timer) {
|
|
if (rel_xpos_lo.player >= rel_xpos_lo.enemy) {
|
|
if (enemy_moving_dir[k] == 1) {
|
|
LABEL_25:
|
|
InjurePlayer();
|
|
return;
|
|
}
|
|
} else if (enemy_moving_dir[k] != 1) {
|
|
goto LABEL_25;
|
|
}
|
|
EnemyTurnAround(k);
|
|
InjurePlayer();
|
|
}
|
|
}
|
|
|
|
void InjurePlayer() {
|
|
if (!player_hurt_timer)
|
|
ForceInjury(player_hurt_timer);
|
|
}
|
|
|
|
void ForceInjury(uint8 a) {
|
|
if (player_status) {
|
|
player_status = a;
|
|
player_hurt_timer = 8;
|
|
sound_ch1 = 4;
|
|
GetPlayerColors();
|
|
SetPROut_1(0xAu);
|
|
} else {
|
|
KillPlayer(player_status);
|
|
}
|
|
}
|
|
|
|
void SetPROut_1(uint8 a) {
|
|
SetPRout(1u, a);
|
|
}
|
|
|
|
void SetPRout(uint8 j, uint8 a) {
|
|
game_engine_subroutine = a;
|
|
player_state = j;
|
|
timer_control = -1;
|
|
scroll_amount = 0;
|
|
}
|
|
|
|
void KillPlayer(uint8 k) {
|
|
obj_xspeed.player = k;
|
|
player_size = 1;
|
|
GetPlayerColors();
|
|
music_ch1 = 9;
|
|
var0E67 = 9;
|
|
scroll_lock = 9;
|
|
obj_yspeed.player = -4;
|
|
SetPROut_1(0xBu);
|
|
}
|
|
|
|
uint8 EnemyFacePlayer(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
v1 = 1;
|
|
if ((PlayerEnemyDiff(k) & 0x80u) != 0)
|
|
v1 = 2;
|
|
enemy_moving_dir[k] = v1;
|
|
return v1 - 1;
|
|
}
|
|
|
|
void SetupFloateyNumber1(uint8 k, uint8 a) {
|
|
floateynum_control[k] = a;
|
|
floateynum_timer[k] = 48;
|
|
score_spr_ypos_lo[k] = obj_ypos_lo.enemy[k];
|
|
score_spr_xpos_lo[k] = rel_xpos_lo.enemy;
|
|
tempED = obj_xpos_lo.enemy[k];
|
|
tempEE = obj_xpos_hi.enemy[k];
|
|
floateynum_xpos_word[(uint8)(2 * k) >> 1] = *(uint16 *)&tempED - screen_left_xpos16;
|
|
}
|
|
|
|
uint8 SetupFloateyNumber(uint8 k, uint8 a) {
|
|
if (a >= floateynum_control[k]) {
|
|
floateynum_control[k] = a;
|
|
floateynum_timer[k] = 48;
|
|
score_spr_ypos_lo[k] = obj_ypos_lo.enemy[k];
|
|
score_spr_xpos_lo[k] = rel_xpos_lo.enemy;
|
|
tempE4 = obj_xpos_lo.enemy[k];
|
|
tempE5 = obj_xpos_hi.enemy[k];
|
|
a = tempE4 - screen_left_xpos16;
|
|
floateynum_xpos_word[(uint8)(2 * k) >> 1] = *(uint16 *)&tempE4 - screen_left_xpos16;
|
|
score_spr_xpos_lo[k] = a;
|
|
}
|
|
return a;
|
|
}
|
|
|
|
void EnemiesCollision(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 EnemyBoundBoxOfs; // di
|
|
uint8 v3; // si
|
|
uint8 v4; // al
|
|
uint8 v5; // al
|
|
uint8 v6; // si
|
|
uint8 v7; // di
|
|
uint8 v8; // [rsp+47h] [rbp-1h]
|
|
|
|
if (frame_counter & 1) {
|
|
if (area_type) {
|
|
v1 = enemy_id[k];
|
|
if (v1 < 0x15u && v1 != 17 && v1 != 13 && !spr_array_D[k]) {
|
|
EnemyBoundBoxOfs = GetEnemyBoundBoxOfs();
|
|
v3 = k - 1;
|
|
if ((v3 & 0x80u) == 0) {
|
|
while (1) {
|
|
R1_ = v3;
|
|
v8 = EnemyBoundBoxOfs;
|
|
if (!enemy_flag[v3])
|
|
goto LABEL_20;
|
|
v4 = enemy_id[v3];
|
|
if (v4 >= 0x15u || v4 == 17 || v4 == 13 || spr_array_D[v3])
|
|
goto LABEL_20;
|
|
v5 = SprObjectCollisionCore(4 * v3 + 4, EnemyBoundBoxOfs);
|
|
v6 = object_index;
|
|
v7 = R1_;
|
|
if (!(v5 & 1)) {
|
|
enemy_collision_bits[R1_] &= kClearBitsMask[object_index];
|
|
goto LABEL_20;
|
|
}
|
|
if (((enemy_state[R1_] | enemy_state[object_index]) & 0x80u) != 0)
|
|
goto LABEL_18;
|
|
if ((kSetBitsMask[object_index] & enemy_collision_bits[R1_]) == 0)
|
|
break;
|
|
LABEL_20:
|
|
EnemyBoundBoxOfs = v8;
|
|
v3 = R1_ - 1;
|
|
if ((int8)(R1_ - 1) < 0)
|
|
return;
|
|
}
|
|
enemy_collision_bits[R1_] |= kSetBitsMask[object_index];
|
|
LABEL_18:
|
|
ProcEnemyCollisions(v6, v7);
|
|
goto LABEL_20;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProcEnemyCollisions(uint8 k, uint8 j) {
|
|
uint8 v2; // si
|
|
uint8 v3; // al
|
|
|
|
if (((enemy_state[k] | enemy_state[j]) & 0x20) != 0)
|
|
return;
|
|
if (enemy_id[k] == 5)
|
|
enemy_state[k] = 0;
|
|
if (enemy_state[k] >= 6u) {
|
|
if (__CFSHL__(enemy_state[j], 1)) {
|
|
SetupFloateyNumber(k, 6u);
|
|
ShellOrBlockDefeat(k);
|
|
j = R1_;
|
|
}
|
|
ShellOrBlockDefeat(j);
|
|
SetupFloateyNumber(R1_, shell_chain_counter[object_index] + 4);
|
|
v2 = object_index;
|
|
++shell_chain_counter[object_index];
|
|
goto LABEL_12;
|
|
}
|
|
if (enemy_state[j] < 6u) {
|
|
EnemyTurnAround(j);
|
|
EnemyTurnAround(object_index);
|
|
return;
|
|
}
|
|
if (enemy_id[j] != 5) {
|
|
ShellOrBlockDefeat(k);
|
|
SetupFloateyNumber(object_index, shell_chain_counter[R1_] + 4);
|
|
v2 = R1_;
|
|
++shell_chain_counter[R1_];
|
|
LABEL_12:
|
|
v3 = shell_chain_counter[v2] + 18;
|
|
if (v3 >= 0x1Au)
|
|
v3 = 0;
|
|
sound_ch1 = v3;
|
|
}
|
|
}
|
|
|
|
void EnemyTurnAround(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
v1 = enemy_id[k];
|
|
if (v1 != 13 && v1 != 17 && v1 != 5 && (v1 == 18 || v1 == 14 || v1 < 7u))
|
|
ReverseXSpeed(k);
|
|
}
|
|
|
|
void ReverseXSpeed(uint8 k) {
|
|
obj_xspeed.enemy[k] = -obj_xspeed.enemy[k];
|
|
enemy_moving_dir[k] ^= 3u;
|
|
}
|
|
|
|
void LargePlatformCollision(uint8 k) {
|
|
enemy_data_d[k] = -1;
|
|
if (timer_control || (enemy_state[k] & 0x80u) != 0) {
|
|
|
|
} else {
|
|
if (enemy_id[k] == 36) {
|
|
ChkForPlayerC_LargeP(enemy_state[k]);
|
|
}
|
|
ChkForPlayerC_LargeP(k);
|
|
}
|
|
}
|
|
|
|
void ChkForPlayerC_LargeP(uint8 k) {
|
|
uint8 EnemyBoundBoxOfsArg; // di
|
|
|
|
if (!(CheckPlayerVertical() & 1)) {
|
|
EnemyBoundBoxOfsArg = GetEnemyBoundBoxOfsArg(k);
|
|
R0_ = obj_ypos_lo.enemy[k];
|
|
if (PlayerCollisionCore(EnemyBoundBoxOfsArg) & 1)
|
|
ProcLPlatCollisions(k, EnemyBoundBoxOfsArg);
|
|
}
|
|
}
|
|
|
|
|
|
void SmallPlatformCollision(uint8 k) {
|
|
uint8 EnemyBoundBoxOfs; // di
|
|
|
|
if (!timer_control) {
|
|
enemy_data_d[k] = timer_control;
|
|
if (!(CheckPlayerVertical() & 1)) {
|
|
R0_ = 2;
|
|
do {
|
|
EnemyBoundBoxOfs = GetEnemyBoundBoxOfs();
|
|
if ((offscreen_bits.enemy & 2) != 0)
|
|
break;
|
|
if (*(&player_hitbox_top + EnemyBoundBoxOfs) >= 0x20u && PlayerCollisionCore(EnemyBoundBoxOfs) & 1) {
|
|
ProcLPlatCollisions(object_index, EnemyBoundBoxOfs);
|
|
return;
|
|
}
|
|
*(&player_hitbox_top + EnemyBoundBoxOfs) += 0x80;
|
|
*(&player_hitbox_bottom + EnemyBoundBoxOfs) += 0x80;
|
|
--R0_;
|
|
} while (R0_);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProcLPlatCollisions(uint8 k, uint8 j) {
|
|
uint8 v2; // al
|
|
uint8 v3; // di
|
|
|
|
if ((uint8)(*(&player_hitbox_bottom + j) - player_hitbox_top) < 4u && (obj_yspeed.player & 0x80u) != 0)
|
|
obj_yspeed.player = 1;
|
|
if ((uint8)(player_hitbox_bottom - *(&player_hitbox_top + j)) >= 6u || (obj_yspeed.player & 0x80u) != 0) {
|
|
R0_ = 1;
|
|
if ((uint8)(player_hitbox_right - *(&player_hitbox_left + j)) < 8u ||
|
|
(++R0_, (uint8)(*(&player_hitbox_right + j) - (player_hitbox_left + 1)) < 9u)) {
|
|
ImpedePlayerMove();
|
|
}
|
|
} else {
|
|
v2 = R0_;
|
|
v3 = enemy_id[k];
|
|
if (v3 != 43 && v3 != 44)
|
|
v2 = k;
|
|
enemy_data_d[object_index] = v2;
|
|
player_state = 0;
|
|
}
|
|
}
|
|
|
|
void PositionPlayerOnS_Plat(uint8 k, uint8 a) {
|
|
uint8 v2; // al
|
|
|
|
v2 = kPlayerPosSPlatData[a - 1] + obj_ypos_lo.enemy[k];
|
|
if (v2)
|
|
CODE_03E2CE(k, v2);
|
|
else
|
|
obj_ypos_hi.player = 2;
|
|
}
|
|
|
|
void PositionPlayerOnVPlat(uint8 k) {
|
|
CODE_03E2CE(k, obj_ypos_lo.enemy[k]);
|
|
}
|
|
|
|
void CODE_03E2CE(uint8 k, uint8 a) {
|
|
if (game_engine_subroutine != 11 && obj_ypos_hi.enemy[k] == 1) {
|
|
obj_ypos_lo.player = a - 32;
|
|
obj_ypos_hi.player = a >= 0x20u;
|
|
obj_yspeed.player = 0;
|
|
obj_sub_yspeed.player = 0;
|
|
}
|
|
}
|
|
|
|
uint8 CheckPlayerVertical() {
|
|
return (offscreen_bits.player & 0xF0) != 0;
|
|
}
|
|
|
|
uint8 GetEnemyBoundBoxOfs() {
|
|
return GetEnemyBoundBoxOfsArg(object_index);
|
|
}
|
|
|
|
uint8 GetEnemyBoundBoxOfsArg(uint8 a) {
|
|
return 4 * a + 4;
|
|
}
|
|
|
|
void PlayerBGCollision() {
|
|
uint8 v0; // al
|
|
uint8 v1; // di
|
|
uint8 v2; // si
|
|
uint8 v3; // al
|
|
uint8 v6; // al
|
|
uint8 v8; // al
|
|
uint8 v9; // di
|
|
uint8 v10; // al
|
|
uint8 v12; // al
|
|
uint8 v13; // al
|
|
uint8 v16; // al
|
|
uint8 v17; // al
|
|
uint8 v18; // di
|
|
uint8 v19; // di
|
|
uint8 v20; // al
|
|
uint8 v22; // al
|
|
uint8 v25; // al
|
|
uint8 v27; // al
|
|
int8 v29; // al
|
|
uint8 a; // [rsp+47h] [rbp-1h]
|
|
|
|
if (disable_collision_detection || game_engine_subroutine == 11 || game_engine_subroutine < 4u)
|
|
return;
|
|
v0 = 1;
|
|
if (!swimming_flag) {
|
|
if (player_state && player_state != 3)
|
|
goto LABEL_9;
|
|
v0 = 2;
|
|
}
|
|
player_state = v0;
|
|
LABEL_9:
|
|
if (obj_ypos_hi.player != 1)
|
|
return;
|
|
player_collision_bits = -1;
|
|
if (obj_ypos_lo.player >= 0xCFu)
|
|
return;
|
|
v1 = 2;
|
|
if (!crouching_flag && !player_size)
|
|
v1 = swimming_flag != 0;
|
|
tempEB = kBlockBufferAdderData[v1];
|
|
v2 = player_size;
|
|
if (crouching_flag)
|
|
v2 = player_size + 1;
|
|
if (obj_ypos_lo.player < kPlayerBGUpperExtent[v2])
|
|
goto LABEL_29;
|
|
tempE4 = 1;
|
|
v3 = BlockBufferColli_Head(tempEB);
|
|
if (!v3)
|
|
goto LABEL_29;
|
|
v6 = v3;
|
|
if (CheckForCoinMTiles(v3))
|
|
goto LABEL_61;
|
|
if ((obj_yspeed.player & 0x80u) == 0 || R4_ < 4u)
|
|
goto LABEL_29;
|
|
v8 = v6;
|
|
if (CheckForSolidMTiles(v6)) {
|
|
if (v8 != 42)
|
|
sound_ch1 = 1;
|
|
} else if (area_type && !block_bounce_timer) {
|
|
PlayerHeadCollision(v8);
|
|
goto LABEL_29;
|
|
}
|
|
obj_yspeed.player = 1;
|
|
LABEL_29:
|
|
v9 = tempEB;
|
|
if (obj_ypos_lo.player >= 0xCFu)
|
|
goto LABEL_45;
|
|
tempE4 = 0;
|
|
v10 = BlockBufferColli_Feet(tempEB);
|
|
v12 = v10;
|
|
if (CheckForCoinMTiles(v10)) {
|
|
LABEL_61:
|
|
HandleCoinMetatile();
|
|
return;
|
|
}
|
|
a = v12;
|
|
tempE4 = 0;
|
|
R0_ = BlockBufferColli_Feet(v9 + 1);
|
|
v13 = a;
|
|
R1_ = a;
|
|
if (!a) {
|
|
if (!R0_)
|
|
goto LABEL_45;
|
|
v13 = R0_;
|
|
if (CheckForCoinMTiles(v13))
|
|
goto LABEL_61;
|
|
}
|
|
v16 = v13;
|
|
if (!CheckForClimbMTiles(v13) && (obj_yspeed.player & 0x80u) == 0) {
|
|
if (v16 == 0xFD) {
|
|
HandleAxeMetatile();
|
|
return;
|
|
}
|
|
v17 = v16;
|
|
if (ChkInvisibleMTiles(v16)) {
|
|
if (!jumpspring_anim_ctrl) {
|
|
if (R4_ >= 5u) {
|
|
R0_ = player_moving_dir;
|
|
ImpedePlayerMove();
|
|
return;
|
|
}
|
|
ChkForLandJumpSpring(v17);
|
|
obj_ypos_lo.player &= 0xF0u;
|
|
HandlePipeEntry();
|
|
obj_yspeed.player = 0;
|
|
obj_sub_yspeed.player = 0;
|
|
stomp_chain_counter = 0;
|
|
}
|
|
player_state = 0;
|
|
}
|
|
}
|
|
LABEL_45:
|
|
v18 = tempEB + 2;
|
|
R0_ = 2;
|
|
while (1) {
|
|
v19 = v18 + 1;
|
|
tempEB = v19;
|
|
if (obj_ypos_lo.player >= 0x20u) {
|
|
if (obj_ypos_lo.player >= 0xE4u)
|
|
return;
|
|
tempE4 = 0;
|
|
v20 = BlockBufferColli_Side(v19);
|
|
if (v20) {
|
|
if (v20 != 32 && v20 != 117) {
|
|
v22 = v20;
|
|
if (!CheckForClimbMTiles(v20))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
v18 = tempEB + 1;
|
|
if (obj_ypos_lo.player < 8u || obj_ypos_lo.player >= 0xD0u)
|
|
return;
|
|
tempE4 = 0;
|
|
v22 = BlockBufferColli_Side(v18);
|
|
if (v22)
|
|
break;
|
|
if (!--R0_)
|
|
return;
|
|
}
|
|
if (ChkInvisibleMTiles(v22)) {
|
|
v25 = v22;
|
|
if (CheckForClimbMTiles(v22)) {
|
|
HandleClimbing(v25);
|
|
return;
|
|
}
|
|
v27 = v25;
|
|
if (CheckForCoinMTiles(v25))
|
|
goto LABEL_61;
|
|
v29 = v27;
|
|
if (ChkJumpspringMetatiles(v27)) {
|
|
if (jumpspring_anim_ctrl)
|
|
return;
|
|
goto LABEL_76;
|
|
}
|
|
if (player_state || player_facing_dir != 1 || v29 != 118 && v29 != 35) {
|
|
LABEL_76:
|
|
ImpedePlayerMove();
|
|
return;
|
|
}
|
|
if (player_sprattrib && !play_sound_flag_var009a) {
|
|
sound_ch1 = 4;
|
|
play_sound_flag_var009a = 4;
|
|
player_star_power_timer = 0;
|
|
}
|
|
player_sprattrib &= 0xCFu;
|
|
if ((obj_xpos_lo.player & 0xF) != 0)
|
|
change_area_timer = kAreaChangeTimerData[screen_left_xpos_hi != 0];
|
|
if (game_engine_subroutine == 8)
|
|
game_engine_subroutine = 2;
|
|
}
|
|
}
|
|
|
|
void HandleCoinMetatile() {
|
|
EraseCoinMetatile();
|
|
++coin_tally_for_1ups;
|
|
GiveOneCoin();
|
|
}
|
|
|
|
void HandleAxeMetatile() {
|
|
uint8 i; // si
|
|
|
|
game_mode_task = 0;
|
|
game_mode = 2;
|
|
if (ReadReg(APUI02) != 11)
|
|
music_ch1 = -16;
|
|
obj_xspeed.player = 24;
|
|
for (i = 0; i != 9; ++i) {
|
|
if (enemy_id[i] == 45 && enemy_flag[i] == 1) {
|
|
rel_xpos_lo.enemy = obj_xpos_lo.enemy[i] - layer1_xpos_lo;
|
|
rel_ypos.enemy = obj_ypos_lo.enemy[i];
|
|
BowserDraw(i);
|
|
}
|
|
}
|
|
EraseCoinMetatile();
|
|
}
|
|
// 7E03B9: using guessed type int8;
|
|
|
|
void EraseCoinMetatile() {
|
|
RomPtr_RAM(*(uint16 *)&R6_)[R2_] = 0;
|
|
RemoveCoin_Axe();
|
|
}
|
|
|
|
void HandleClimbing(uint8 a) {
|
|
uint8 v1; // si
|
|
|
|
if (R4_ >= 6u && R4_ < 0xAu) {
|
|
if (a == 40 || a == 41) {
|
|
if (game_engine_subroutine != 5) {
|
|
player_facing_dir = 1;
|
|
++scroll_lock;
|
|
if (game_engine_subroutine != 4) {
|
|
KillEnemies(0x33u);
|
|
SpawnCastleTilesWithPriority();
|
|
music_ch1 = -16;
|
|
sound_ch1 = 70;
|
|
flagpole_sound_queue = 35;
|
|
v1 = 4;
|
|
climbing_ypos_unk = obj_ypos_lo.player;
|
|
do {
|
|
if (obj_ypos_lo.player >= kFlagpoleYPosData[v1])
|
|
break;
|
|
--v1;
|
|
} while (v1);
|
|
flagpole_score = v1;
|
|
}
|
|
game_engine_subroutine = 4;
|
|
}
|
|
} else if (a == 42 && obj_ypos_lo.player < 0x20u) {
|
|
game_engine_subroutine = 1;
|
|
}
|
|
player_state = 3;
|
|
obj_xspeed.player = 0;
|
|
player_x_move_force = 0;
|
|
if (vine_flag_offset && rel_xpos_lo.enemy >= 0xF8u) {
|
|
tempE5 = obj_xpos_hi.enemy[9];
|
|
tempE4 = obj_xpos_lo.enemy[9];
|
|
*(uint16 *)&tempE4 += 7;
|
|
obj_xpos_lo.player = tempE4;
|
|
obj_xpos_hi.player = tempE5;
|
|
player_facing_dir = 2;
|
|
} else {
|
|
if ((uint8)(obj_xpos_lo.player - screen_left_xpos_lo) < 0x10u)
|
|
player_facing_dir = 2;
|
|
obj_xpos_lo.player = kClimbXPosAdder[player_facing_dir - 1] + 16 * R6_;
|
|
if (!R6_)
|
|
obj_xpos_hi.player = kClimbPLocAdder[player_facing_dir - 1] + screen_right_xpos_hi;
|
|
}
|
|
}
|
|
}
|
|
// 7E0082: using guessed type int8;
|
|
// 7E0223: using guessed type int8;
|
|
|
|
uint8 ChkInvisibleMTiles(uint8 a) {
|
|
return a != 0x62 && a != 0x63;
|
|
}
|
|
|
|
void ChkForLandJumpSpring(uint8 a) {
|
|
if (ChkJumpspringMetatiles(a)) {
|
|
vertical_force = 112;
|
|
jumpspring_force = -7;
|
|
jumpspring_timer = 3;
|
|
jumpspring_anim_ctrl = 1;
|
|
}
|
|
}
|
|
|
|
uint8 ChkJumpspringMetatiles(uint8 a) {
|
|
return (a == 111 || a == 112);
|
|
}
|
|
|
|
void HandlePipeEntry() {
|
|
uint8 v0; // al
|
|
uint8 v1; // si
|
|
uint8 v2; // si
|
|
|
|
if ((buttons_up_down & 4) != 0 && R0_ == 21 && R1_ == 20) {
|
|
change_area_timer = 48;
|
|
game_engine_subroutine = 3;
|
|
player_hurt_timer = 4;
|
|
player_star_power_timer = 0;
|
|
player_sprattrib = 0;
|
|
v0 = warp_zone_control;
|
|
if (warp_zone_control) {
|
|
if (warp_zone_control < 4u) {
|
|
v1 = 4;
|
|
if (world_number) {
|
|
v1 = 5;
|
|
if (area_type == 1)
|
|
v1 = 6;
|
|
}
|
|
v0 = v1;
|
|
warp_zone_control = v1;
|
|
}
|
|
v2 = 4 * (v0 & 3);
|
|
if (obj_xpos_lo.player >= 0x60u) {
|
|
++v2;
|
|
if (obj_xpos_lo.player >= 0xA0u)
|
|
++v2;
|
|
}
|
|
world_number = kWarpZoneNumbers[v2] - 1;
|
|
area_pointer = kAreaAddrOffsets[kWorldAddrOffsets[world_number]];
|
|
entrance_page = 0;
|
|
area_number = 0;
|
|
level_number = 0;
|
|
alt_entrance_ctrl = 0;
|
|
++hidden_1up_flag;
|
|
++fetch_new_game_timer_flag;
|
|
music_ch1 = -13;
|
|
unused_byte_7E0E1A = -13;
|
|
}
|
|
sound_ch1 = 4;
|
|
}
|
|
}
|
|
|
|
void ImpedePlayerMove() {
|
|
uint8 v0; // si
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
bool v3; // cf
|
|
|
|
if (R0_ == 1) {
|
|
v0 = 1;
|
|
if ((obj_xspeed.player & 0x80u) != 0)
|
|
goto LABEL_9;
|
|
v1 = -1;
|
|
} else {
|
|
v0 = 2;
|
|
if ((int8)(obj_xspeed.player - 1) >= 0)
|
|
goto LABEL_9;
|
|
v1 = 1;
|
|
}
|
|
side_collision_timer = 16;
|
|
v2 = 0;
|
|
obj_xspeed.player = 0;
|
|
if (sign8(v1))
|
|
v2 = -1;
|
|
R0_ = v2;
|
|
v3 = __CFADD__(obj_xpos_lo.player, v1);
|
|
obj_xpos_lo.player += v1;
|
|
obj_xpos_hi.player += v2 + v3;
|
|
LABEL_9:
|
|
player_collision_bits &= ~v0;
|
|
}
|
|
|
|
uint8 CheckForSolidMTiles(uint8 a) {
|
|
return a >= kSolidMTileUpperExt[GetMTileAttrib(a)];
|
|
}
|
|
|
|
uint8 CheckForClimbMTiles(uint8 a) {
|
|
uint8 t = kClimbMTileUpperExt[GetMTileAttrib(a)];
|
|
return a >= t;
|
|
}
|
|
|
|
uint8 CheckForCoinMTiles(uint8 a) {
|
|
if (a != 0xE9 && a != 0xEA)
|
|
return 0;
|
|
sound_ch3 = 1;
|
|
return 1;
|
|
}
|
|
|
|
uint8 GetMTileAttrib(uint8 a) {
|
|
return 2 * (4 * (a & 0xC0) + __CFSHL__(a & 0xC0, 1)) + __CFSHL__(2 * (a & 0xC0), 1);
|
|
}
|
|
|
|
void EnemyToBGCollisionDet(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
uint8 v4; // al
|
|
uint8 v6; // al
|
|
uint8 v7; // al
|
|
int8 v8; // di
|
|
uint8 v9; // di
|
|
uint8 v10; // al
|
|
uint8 v11; // al
|
|
|
|
if ((enemy_state[k] & 0x20) != 0)
|
|
return;
|
|
if (!(SubtEnemyYPos(k) & 1))
|
|
return;
|
|
v1 = enemy_id[k];
|
|
if (v1 == 18 && obj_ypos_lo.enemy[k] < 0x25u)
|
|
return;
|
|
if (v1 == 14) {
|
|
EnemyJump(k);
|
|
return;
|
|
}
|
|
if (v1 != 5) {
|
|
if (v1 != 18 && v1 != 46 && v1 >= 7u)
|
|
return;
|
|
v2 = ChkUnderEnemy(k);
|
|
if (!v2)
|
|
goto LABEL_58;
|
|
if (!ChkForNonSolids(v2))
|
|
goto LABEL_58;
|
|
if (v2 == 39) {
|
|
RomPtr_RAM(*(uint16 *)&R6_)[R2_] = 0;
|
|
v4 = enemy_id[k];
|
|
if (v4 < 0x15u) {
|
|
if (v4 == 6)
|
|
KillEnemyAboveBlock(k);
|
|
v4 = SetupFloateyNumber(k, 1u);
|
|
}
|
|
ChkToStunEnemies(k, v4);
|
|
return;
|
|
}
|
|
if ((uint8)(R4_ - 8) >= 5u) {
|
|
LABEL_58:
|
|
if (enemy_id[k] != 3 || enemy_state[k]) {
|
|
v9 = enemy_state[k];
|
|
if (__CFSHL__(v9, 1))
|
|
v10 = enemy_state[k] | 0x40;
|
|
else
|
|
v10 = kEnemyBGCStateData[v9];
|
|
enemy_state[k] = v10;
|
|
DoEnemySideCheck(k);
|
|
} else {
|
|
ChkForBump_HammerBroJ(k);
|
|
}
|
|
return;
|
|
}
|
|
if ((enemy_state[k] & 0x40) == 0) {
|
|
if (__CFSHL__(enemy_state[k], 1) || (v6 = enemy_state[k]) == 0) {
|
|
DoEnemySideCheck(k);
|
|
return;
|
|
}
|
|
if (v6 != 5) {
|
|
if (v6 >= 3u)
|
|
return;
|
|
if (enemy_state[k] == 2) {
|
|
v7 = 16;
|
|
if (enemy_id[k] == 18)
|
|
v7 = 0;
|
|
*(&enemy_interval_timer + k) = v7;
|
|
enemy_state[k] = 3;
|
|
EnemyLanding(k);
|
|
return;
|
|
}
|
|
}
|
|
if (enemy_id[k] != 6) {
|
|
if (enemy_id[k] != 18 || (enemy_moving_dir[k] = 1, obj_xspeed.enemy[k] = 8, (frame_counter & 7) != 0)) {
|
|
v8 = 1;
|
|
if ((PlayerEnemyDiff(k) & 0x80u) != 0)
|
|
v8 = 2;
|
|
if (v8 == enemy_moving_dir[k])
|
|
ChkForBump_HammerBroJ(k);
|
|
}
|
|
}
|
|
}
|
|
EnemyLanding(k);
|
|
if ((enemy_state[k] & 0x80u) != 0)
|
|
enemy_state[k] &= ~0x40u;
|
|
else
|
|
enemy_state[k] = 0;
|
|
return;
|
|
}
|
|
v11 = ChkUnderEnemy(k);
|
|
if (!v11)
|
|
goto LABEL_55;
|
|
if (v11 == 39) {
|
|
KillEnemyAboveBlock(k);
|
|
return;
|
|
}
|
|
if (enemy_frame_timer[k]) {
|
|
LABEL_55:
|
|
enemy_state[k] |= 1u;
|
|
} else {
|
|
enemy_state[k] &= 0x88u;
|
|
EnemyLanding(k);
|
|
DoEnemySideCheck(k);
|
|
}
|
|
}
|
|
|
|
void ChkToStunEnemies(uint8 k, uint8 a) {
|
|
if (a >= 9u && a < 0x11u && (a < 0xAu || a >= 0xDu)) {
|
|
enemy_id[k] = a & 1;
|
|
SetStun(k);
|
|
} else {
|
|
SetStun(k);
|
|
}
|
|
}
|
|
|
|
void SetStun(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
|
|
enemy_state[k] = enemy_state[k] & 0xF0 | 2;
|
|
--obj_ypos_lo.enemy[k];
|
|
--obj_ypos_lo.enemy[k];
|
|
if (enemy_id[k] == 7 || (v1 = -3, !area_type))
|
|
v1 = -1;
|
|
obj_yspeed.enemy[k] = v1;
|
|
v2 = 1;
|
|
if ((PlayerEnemyDiff(k) & 0x80u) != 0)
|
|
v2 = 2;
|
|
if (enemy_id[k] != 51 && enemy_id[k] != 8)
|
|
enemy_moving_dir[k] = v2;
|
|
obj_xspeed.enemy[k] = kEnemyBGCXSpdData[(uint8)(v2 - 1)];
|
|
}
|
|
|
|
void DoEnemySideCheck(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
|
|
if (obj_ypos_lo.enemy[k] >= 0x20u) {
|
|
v1 = 22;
|
|
tempEB = 2;
|
|
while (1) {
|
|
if (tempEB == enemy_moving_dir[k]) {
|
|
v2 = BlockBufferChk_Enemy(k, v1, 1u);
|
|
if (v2) {
|
|
if (ChkForNonSolids(v2))
|
|
break;
|
|
}
|
|
}
|
|
--tempEB;
|
|
if (++v1 >= 0x18u)
|
|
return;
|
|
}
|
|
ChkForBump_HammerBroJ(k);
|
|
}
|
|
}
|
|
|
|
void ChkForBump_HammerBroJ(uint8 k) {
|
|
if (k != 9 && __CFSHL__(enemy_state[k], 1)) {
|
|
sound_ch1 = 1;
|
|
InitializeContactSprite(k);
|
|
}
|
|
if (enemy_id[k] == 5) {
|
|
R0_ = 0;
|
|
CODE_03CEC7(k, 0xFAu);
|
|
} else {
|
|
ReverseXSpeed(k);
|
|
}
|
|
}
|
|
// 110B3: conditional instruction was optimized away because si.1!=9
|
|
|
|
uint8 PlayerEnemyDiff(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
v1 = obj_xpos_lo.enemy[k];
|
|
R0_ = v1 - obj_xpos_lo.player;
|
|
return obj_xpos_hi.enemy[k] - ((v1 < obj_xpos_lo.player) + obj_xpos_hi.player);
|
|
}
|
|
|
|
void EnemyLanding(uint8 k) {
|
|
InitVStf(k);
|
|
obj_ypos_lo.enemy[k] = obj_ypos_lo.enemy[k] & 0xF0 | 8;
|
|
}
|
|
|
|
uint8 SubtEnemyYPos(uint8 k) {
|
|
return (uint8)(obj_ypos_lo.enemy[k] + 62) >= 0x44u;
|
|
}
|
|
|
|
void EnemyJump(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
if (SubtEnemyYPos(k) & 1) {
|
|
if ((uint8)(obj_yspeed.enemy[k] + 2) >= 3u) {
|
|
v1 = ChkUnderEnemy(k);
|
|
if (v1) {
|
|
if (ChkForNonSolids(v1)) {
|
|
EnemyLanding(k);
|
|
obj_yspeed.enemy[k] = -3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DoEnemySideCheck(k);
|
|
}
|
|
|
|
void KillEnemyAboveBlock(uint8 k) {
|
|
ShellOrBlockDefeat(k);
|
|
obj_yspeed.enemy[k] = -4;
|
|
}
|
|
|
|
uint8 ChkUnderEnemy(uint8 k) {
|
|
return BlockBufferChk_Enemy(k, 0x15u, 0);
|
|
}
|
|
|
|
uint8 ChkForNonSolids(uint8 a) {
|
|
return (a != 42 && a != 0xE9 && a != 0xEA && a != 98);
|
|
}
|
|
|
|
void FireballBGCollision(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
if (obj_ypos_lo.fireball[k] >= 0x18u && (v1 = BlockBufferChk_FBall(k)) != 0 && ChkForNonSolids(v1)) {
|
|
if ((obj_yspeed.fireball[k] & 0x80u) != 0 || fire_spr_hit_ground_flag[k]) {
|
|
fireball_state[k] = 0x80;
|
|
sound_ch1 = 1;
|
|
} else {
|
|
obj_yspeed.fireball[k] = -3;
|
|
fire_spr_hit_ground_flag[k] = 1;
|
|
obj_ypos_lo.fireball[k] &= 0xF8u;
|
|
}
|
|
} else {
|
|
fire_spr_hit_ground_flag[k] = 0;
|
|
}
|
|
}
|
|
|
|
void GetFireballBoundBox(uint8 k) {
|
|
FBallB(k + 11, 2u);
|
|
}
|
|
|
|
void GetMiscBoundBox(uint8 k) {
|
|
FBallB(k + 13, 6u);
|
|
}
|
|
|
|
void FBallB(uint8 k, uint8 j) {
|
|
j = BoundingBoxCore(k, j);
|
|
CheckRightScreenBBox(k, j);
|
|
}
|
|
|
|
void GetEnemyBoundBox(uint8 k) {
|
|
R0_ = 72;
|
|
GetMaskedOffScrBits(k, 0x44u);
|
|
}
|
|
|
|
void SmallPlatformBoundBox(uint8 k) {
|
|
R0_ = 8;
|
|
GetMaskedOffScrBits(k, 4u);
|
|
}
|
|
|
|
void GetMaskedOffScrBits(uint8 k, uint8 j) {
|
|
uint8 v2; // al
|
|
int8 v3; // al
|
|
|
|
v2 = obj_xpos_lo.enemy[k];
|
|
R1_ = v2 - screen_left_xpos_lo;
|
|
v3 = obj_xpos_hi.enemy[k] - ((v2 < screen_left_xpos_lo) + screen_left_xpos_hi);
|
|
if (v3 >= 0 && R1_ | (uint8)v3)
|
|
j = R0_;
|
|
spr_array_D[k] = offscreen_bits.enemy & j;
|
|
if (k == 9) {
|
|
func_sub_EA11(9u);
|
|
} else if (spr_array_D[k]) {
|
|
func_sub_EA1E(k);
|
|
} else {
|
|
func_sub_EA11(k);
|
|
}
|
|
}
|
|
|
|
void LargePlatformBoundBox(uint8 k) {
|
|
int v1; // rsi
|
|
uint8 XOffscreenBits; // al
|
|
uint8 v3; // si
|
|
|
|
v1 = (uint8)(k + 1);
|
|
XOffscreenBits = GetXOffscreenBits(v1);
|
|
v3 = v1 - 1;
|
|
if (XOffscreenBits < 0xFEu)
|
|
func_sub_EA11(v3);
|
|
else
|
|
func_sub_EA1E(v3);
|
|
}
|
|
|
|
void func_sub_EA11(uint8 k) {
|
|
uint8 j = BoundingBoxCore(k + 1, 1u);
|
|
CheckRightScreenBBox(k + 1, j);
|
|
}
|
|
|
|
void func_sub_EA1E(uint8 k) {
|
|
uint8 v1; // di
|
|
|
|
v1 = 4 * k;
|
|
*(&enemy_hitbox_left + v1) = -1;
|
|
*(&enemy_hitbox_top + v1) = -1;
|
|
*(&enemy_hitbox_right + v1) = -1;
|
|
*(&enemy_hitbox_bottom + v1) = -1;
|
|
}
|
|
|
|
uint8 BoundingBoxCore(uint8 k, uint8 j) {
|
|
uint8 v2; // di
|
|
uint8 v3; // si
|
|
|
|
R0_ = k;
|
|
R2_ = *(&rel_ypos.player + j);
|
|
R1_ = *(&rel_xpos_lo.player + j);
|
|
v2 = 4 * k;
|
|
v3 = 4 * *(&player_hitbox_ctrl + k);
|
|
*(&player_hitbox_left + v2) = kBoundBoxCtrlData[v3] + R1_;
|
|
*(&player_hitbox_right + v2) = kBoundBoxCtrlData[v3++ + 2] + R1_;
|
|
*(&player_hitbox_left + ++v2) = kBoundBoxCtrlData[v3] + R2_;
|
|
*(&player_hitbox_right + v2) = kBoundBoxCtrlData[v3 + 2] + R2_;
|
|
return 4 * k;
|
|
}
|
|
|
|
void CheckRightScreenBBox(uint8 k, uint8 j) {
|
|
R2_ = screen_left_xpos_lo + 0x80;
|
|
R1_ = __CFADD__(screen_left_xpos_lo, 0x80) + screen_left_xpos_hi;
|
|
if (*(&obj_xpos_hi.player + k) < (*(&obj_xpos_lo.player + k) < R2_) + R1_) {
|
|
if (*(&player_hitbox_left + j) >= 0xA0u) {
|
|
if ((*(&player_hitbox_right + j) & 0x80u) != 0)
|
|
*(&player_hitbox_right + j) = 0;
|
|
*(&player_hitbox_left + j) = 0;
|
|
}
|
|
} else if ((*(&player_hitbox_right + j) & 0x80u) == 0) {
|
|
if ((*(&player_hitbox_left + j) & 0x80u) == 0)
|
|
*(&player_hitbox_left + j) = -1;
|
|
*(&player_hitbox_right + j) = -1;
|
|
}
|
|
}
|
|
|
|
uint8 PlayerCollisionCore(uint8 j) {
|
|
return SprObjectCollisionCore(0, j) & 1;
|
|
}
|
|
|
|
uint8 SprObjectCollisionCore(uint8 k, uint8 j) {
|
|
uint8 v2; // al
|
|
uint8 v3; // al
|
|
uint8 v5; // al
|
|
|
|
R6_ = j;
|
|
R7_ = 1;
|
|
do {
|
|
v2 = *(&player_hitbox_left + j);
|
|
if (v2 >= *(&player_hitbox_left + k)) {
|
|
if (v2 != *(&player_hitbox_left + k) && v2 > *(&player_hitbox_right + k) &&
|
|
(v2 <= *(&player_hitbox_right + j) || *(&player_hitbox_right + j) < *(&player_hitbox_left + k))) {
|
|
return 0;
|
|
}
|
|
} else if (v2 < *(&player_hitbox_right + k)) {
|
|
if (*(&player_hitbox_right + k) >= *(&player_hitbox_left + k)) {
|
|
v5 = *(&player_hitbox_right + j);
|
|
if (v5 < *(&player_hitbox_left + k))
|
|
return v5 >= *(&player_hitbox_left + k);
|
|
}
|
|
} else if (v2 != *(&player_hitbox_right + k)) {
|
|
v3 = *(&player_hitbox_right + j);
|
|
if (v3 >= *(&player_hitbox_left + j) && v3 < *(&player_hitbox_left + k))
|
|
return v3 >= *(&player_hitbox_left + k);
|
|
}
|
|
++k;
|
|
++j;
|
|
--R7_;
|
|
} while ((R7_ & 0x80u) == 0);
|
|
return 1;
|
|
}
|
|
|
|
uint8 BlockBufferChk_Enemy(uint8 k, uint8 j, uint8 a) {
|
|
return BBChk_E(k + 1, j, a);
|
|
}
|
|
|
|
uint8 BlockBufferChk_FBall(uint8 k) {
|
|
return BBChk_E(k + 11, 0x1Au, 0);
|
|
}
|
|
|
|
uint8 BBChk_E(uint8 k, uint8 j, uint8 a) {
|
|
return BlockBufferCollision(k, j, a);
|
|
}
|
|
|
|
uint8 BlockBufferColli_Feet(uint8 j) {
|
|
return BlockBufferColli_Head(j + 1);
|
|
}
|
|
|
|
uint8 BlockBufferColli_Head(uint8 j) {
|
|
return CODE_03EB81(j, 0);
|
|
}
|
|
|
|
uint8 BlockBufferColli_Side(uint8 j) {
|
|
return CODE_03EB81(j, 1u);
|
|
}
|
|
|
|
uint8 CODE_03EB81(uint8 j, uint8 a) {
|
|
return BlockBufferCollision(0, j, a);
|
|
}
|
|
|
|
uint8 BlockBufferCollision(uint8 k, uint8 j, uint8 a) {
|
|
uint8 v3; // al
|
|
bool v4; // cf
|
|
int8 v5; // al
|
|
|
|
R4_ = j;
|
|
v3 = kBlockBuffer_X_Adder[j];
|
|
v4 = __CFADD__(*(&obj_xpos_lo.player + k), v3);
|
|
R5_ = *(&obj_xpos_lo.player + k) + v3;
|
|
|
|
uint8 t = ((v4 + *(&obj_xpos_hi.player + k)) & 1);
|
|
GetBlockBufferAddr((uint8)(R5_ >> 1 | t << 7) >> 3);
|
|
R2_ = ((kBlockBuffer_Y_Adder[R4_] + *(&obj_ypos_lo.player + k)) & 0xF0) - 32;
|
|
R3_ = RomPtr_RAM(*(uint16 *)&R6_)[R2_];
|
|
if (a)
|
|
v5 = *(&obj_xpos_lo.player + k);
|
|
else
|
|
v5 = *(&obj_ypos_lo.player + k);
|
|
R4_ = v5 & 0xF;
|
|
if (!tempE4 && (R3_ == 98 || R3_ == 99))
|
|
R3_ = 0;
|
|
return R3_;
|
|
}
|
|
|
|
void SixSpriteStacker(uint8 j, uint8 a) {
|
|
int8 v2; // si
|
|
|
|
v2 = 6;
|
|
do {
|
|
get_OamEnt(oam_buf, j)[64].xpos = a;
|
|
a += 8;
|
|
j += 4;
|
|
--v2;
|
|
} while (v2);
|
|
}
|
|
|
|
void CODE_03EC3C(uint8 j, uint8 a) {
|
|
OamEnt *oam; // rbp
|
|
|
|
oam = get_OamEnt(oam_buf, j);
|
|
oam[3].ypos = a;
|
|
oam[2].ypos = a;
|
|
DumpTwoSpr_(j, a);
|
|
}
|
|
|
|
void DumpTwoSpr_(uint8 j, uint8 a) {
|
|
OamEnt *oam; // rbp
|
|
|
|
oam = get_OamEnt(oam_buf, j);
|
|
oam[1].ypos = a;
|
|
oam->ypos = a;
|
|
}
|
|
|
|
void MoveSixSpritesOffscreen(uint8 j) {
|
|
DumpSixSpr(j, 0xF0u);
|
|
}
|
|
|
|
void DumpSixSpr(uint8 j, uint8 a) {
|
|
OamEnt *oam; // rbp
|
|
|
|
oam = get_OamEnt(oam_buf, j);
|
|
oam[69].ypos = a;
|
|
oam[68].ypos = a;
|
|
DumpFourSpr(j, a);
|
|
}
|
|
|
|
void DumpFourSpr(uint8 j, uint8 a) {
|
|
get_OamEnt(oam_buf, j)[67].ypos = a;
|
|
DumpThreeSpr(j, a);
|
|
}
|
|
|
|
void DumpThreeSpr(uint8 j, uint8 a) {
|
|
get_OamEnt(oam_buf, j)[66].ypos = a;
|
|
DumpTwoSpr(j, a);
|
|
}
|
|
|
|
void DumpTwoSpr(uint8 j, uint8 a) {
|
|
OamEnt *oam; // rbp
|
|
|
|
oam = get_OamEnt(oam_buf, j);
|
|
oam[65].ypos = a;
|
|
oam[64].ypos = a;
|
|
}
|
|
|
|
void DrawLargePlatform(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // si
|
|
uint8 v3; // al
|
|
uint8 v4; // di
|
|
OamEnt *oam; // rbp
|
|
uint8 v6; // si
|
|
uint8 v7; // di
|
|
uint8 v8; // di
|
|
uint8 v9; // di
|
|
uint8 v10; // di
|
|
uint8 v11; // di
|
|
uint8 v12; // di
|
|
uint8 j; // [rsp+47h] [rbp-1h]
|
|
|
|
if (cloud_type_override) {
|
|
DrawLargePlatform_Sub1();
|
|
} else {
|
|
R2_ = enemy_obj_id[k];
|
|
v1 = R2_;
|
|
SixSpriteStacker(R2_, rel_xpos_lo.enemy);
|
|
v2 = object_index;
|
|
v3 = obj_ypos_lo.enemy[object_index];
|
|
DumpFourSpr(v1, v3);
|
|
if (area_type == 3 || secondary_hard_mode)
|
|
v3 = -16;
|
|
v4 = enemy_obj_id[v2];
|
|
oam = get_OamEnt(oam_buf, v4);
|
|
oam[68].ypos = v3;
|
|
oam[69].ypos = v3;
|
|
v6 = object_index;
|
|
DumpSixSpr(++v4, 0x87u);
|
|
DumpSixSpr(v4 + 1, 0x2Cu);
|
|
GetXOffscreenBits(v6);
|
|
v7 = enemy_obj_id[v6];
|
|
GetEnemyXPos(v6);
|
|
DrawLargePlatform_DrawOne(v7);
|
|
j = v7;
|
|
v8 = DrawLargePlatform_Next(v7);
|
|
DrawLargePlatform_DrawOne(v8);
|
|
v9 = DrawLargePlatform_Next(v8);
|
|
DrawLargePlatform_DrawOne(v9);
|
|
v10 = DrawLargePlatform_Next(v9);
|
|
DrawLargePlatform_DrawOne(v10);
|
|
v11 = DrawLargePlatform_Next(v10);
|
|
DrawLargePlatform_DrawOne(v11);
|
|
v12 = DrawLargePlatform_Next(v11);
|
|
DrawLargePlatform_DrawOne(v12);
|
|
if (__CFSHL__(offscreen_bits.enemy, 1) && enemy_id[v6] != 39 && enemy_id[v6] != 38 &&
|
|
(obj_ypos_hi.enemy[v6] != 1 || rel_ypos.enemy >= 0xF0u)) {
|
|
MoveSixSpritesOffscreen(j);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawPowerUp() {
|
|
uint8 v0; // di
|
|
uint8 v1; // si
|
|
int8 v2; // al
|
|
uint8 v3; // al
|
|
OamEnt *oam; // rdx
|
|
uint8 v5; // [rsp+47h] [rbp-1h]
|
|
|
|
v0 = enemy_obj_id[9] + 8;
|
|
R2_ = rel_ypos.enemy + 8;
|
|
R5_ = rel_xpos_lo.enemy;
|
|
R4_ = enemy_sprattrib[9] ^ kPowerUpAttributes[power_up_type];
|
|
v5 = power_up_type;
|
|
v1 = 4 * power_up_type;
|
|
R7_ = 1;
|
|
R3_ = 1;
|
|
do {
|
|
R0_ = kPowerUpGfxTable[v1];
|
|
v0 = DrawOneSpriteRow(v1, v0, kPowerUpGfxTable[v1 + 1]);
|
|
v1 += 2;
|
|
--R7_;
|
|
} while ((R7_ & 0x80u) == 0);
|
|
if (v5 && v5 != 3) {
|
|
R0_ = v5;
|
|
v2 = frame_counter & 6;
|
|
if ((frame_counter & 6) == 6)
|
|
v2 = 14;
|
|
v3 = (enemy_sprattrib[9] | v2) ^ 0x28;
|
|
oam = get_OamEnt(oam_buf, (uint8)(enemy_obj_id[9] + 8));
|
|
oam[64].flags = v3;
|
|
oam[65].flags = v3;
|
|
oam[66].flags = v3;
|
|
oam[67].flags = v3;
|
|
if (R0_ != 1) {
|
|
oam[66].flags = v3;
|
|
oam[67].flags = v3;
|
|
}
|
|
oam[65].flags |= 0x40u;
|
|
oam[67].flags |= 0x40u;
|
|
}
|
|
SprObjectOffscrChk(enemy_obj_id[9] + 8);
|
|
}
|
|
// 7E03B9: using guessed type int8;
|
|
|
|
void EnemyGfxHandler_New(uint8 k) {
|
|
uint8 v1; // al
|
|
|
|
v1 = enemy_id[k];
|
|
switch (v1) {
|
|
case 0xCu: EnemyGfxHandler_Sub4(k); return;
|
|
case 8u:
|
|
if (obj_ypos_hi.enemy[k] == 2)
|
|
EraseEnemyObject(k);
|
|
break;
|
|
case 0x33u:
|
|
if (obj_ypos_hi.enemy[k] == 2)
|
|
EraseEnemyObject(k);
|
|
break;
|
|
default: DrawLevelPreviewSprites_Sub3(k, v1); return;
|
|
}
|
|
EnemyGfxHandler_Sub1(k);
|
|
}
|
|
|
|
void DrawLevelPreviewSprites_Sub3(uint8 k, uint8 a) {
|
|
uint8 v2; // di
|
|
uint8 v3; // al
|
|
uint8 v4; // al
|
|
uint8 v5; // di
|
|
uint8 v6; // al
|
|
uint8 v7; // al
|
|
uint8 v8; // al
|
|
uint8 v9; // si
|
|
uint8 v10; // di
|
|
uint8 v11; // si
|
|
uint8 v12; // di
|
|
uint8 v13; // al
|
|
uint8 v14; // si
|
|
OamEnt *oam; // rbp
|
|
OamEnt *v16; // rdx
|
|
uint8 v17; // di
|
|
uint8 v18; // si
|
|
OamEnt *v19; // rbp
|
|
OamEnt *v20; // rbx
|
|
uint8 v21; // si
|
|
OamEnt *v22; // rdx
|
|
uint8 v23; // al
|
|
uint8 v24; // al
|
|
uint8 v25; // al
|
|
OamEnt *v26; // rdx
|
|
uint8 v27; // al
|
|
OamEnt *v28; // rbp
|
|
OamEnt *v29; // rbp
|
|
OamEnt *v30; // rbp
|
|
uint8 v31; // [rsp+46h] [rbp-2h]
|
|
uint8 charnum; // [rsp+47h] [rbp-1h]
|
|
|
|
if (a == 45) {
|
|
BowserDraw(k);
|
|
return;
|
|
}
|
|
if (a == 53) {
|
|
if (world_number == 7)
|
|
DrawLevelPreviewSprites_Sub7();
|
|
else
|
|
DrawToadAndRelatedSprites(k);
|
|
return;
|
|
}
|
|
R2_ = obj_ypos_lo.enemy[k];
|
|
R5_ = rel_xpos_lo.enemy;
|
|
tempEB = enemy_obj_id[k];
|
|
tempF0 = 0;
|
|
R3_ = enemy_moving_dir[k];
|
|
R4_ = enemy_sprattrib[k];
|
|
if (enemy_id[k] != 13 || (obj_xspeed.enemy[k] & 0x80u) != 0 || !enemy_frame_timer[k]) {
|
|
tempED = enemy_state[k];
|
|
v2 = tempED & 0x1F;
|
|
v3 = enemy_id[k];
|
|
if (v3 == 53) {
|
|
v2 = 0;
|
|
R3_ = 1;
|
|
v3 = 21;
|
|
}
|
|
if (v3 == 51) {
|
|
--R2_;
|
|
v4 = 32;
|
|
if (enemy_frame_timer[k])
|
|
v4 = 16;
|
|
R4_ = v4;
|
|
v2 = 0;
|
|
tempED = 0;
|
|
v3 = 8;
|
|
}
|
|
if (v3 == 50) {
|
|
v2 = 3;
|
|
v3 = kJumpspringFrameOffsets[jumpspring_anim_ctrl];
|
|
}
|
|
tempEF = v3;
|
|
tempEC = v2;
|
|
if (v3 == 12 && (obj_yspeed.enemy[object_index] & 0x80u) == 0)
|
|
++tempF0;
|
|
if (bowser_gfx_flag) {
|
|
v5 = 22;
|
|
if (bowser_gfx_flag != 1)
|
|
v5 = 23;
|
|
tempEF = v5;
|
|
}
|
|
if (tempEF == 6) {
|
|
v6 = enemy_state[object_index];
|
|
if (v6 >= 2u)
|
|
tempEC = 4;
|
|
if (!(timer_control | v6 & 0x20) && (frame_counter & 8) == 0)
|
|
R3_ ^= 3u;
|
|
}
|
|
if (tempEF == 20)
|
|
v7 = 60;
|
|
else
|
|
v7 = R4_ ^ kEnemyAttributeData[tempEF];
|
|
R4_ = v7;
|
|
if (tempEF == 21 && world_number == 7)
|
|
R4_ = R4_ & 0xF0 | 4;
|
|
if (which_enemy_gfx_offs)
|
|
v8 = kEnemyGfxTableOffsets[tempEF] + 6;
|
|
else
|
|
v8 = kEnemyGfxTableOffsets[tempEF];
|
|
v9 = v8;
|
|
if (bowser_gfx_flag) {
|
|
if (bowser_gfx_flag == 1) {
|
|
if ((browser_body_controls & 0x80u) != 0)
|
|
v9 = -34;
|
|
if ((tempED & 0x20) != 0)
|
|
goto LABEL_45;
|
|
} else {
|
|
if ((browser_body_controls & 1) != 0)
|
|
v9 = -28;
|
|
if ((tempED & 0x20) != 0) {
|
|
R2_ -= 16;
|
|
LABEL_45:
|
|
tempF0 = v9;
|
|
}
|
|
}
|
|
LABEL_92:
|
|
v10 = tempEB;
|
|
if (!(CODE_05E8CA(tempEB) & 1)) {
|
|
DrawEnemyObjRow(v9, v10);
|
|
DrawEnemyObjRow(v9 + 2, v10 + 8);
|
|
DrawEnemyObjRow(v9 + 4, v10 + 16);
|
|
DrawLevelPreviewSprites_Sub8();
|
|
}
|
|
v11 = object_index;
|
|
v12 = enemy_obj_id[object_index];
|
|
if (enemy_id[object_index] == 12) {
|
|
++enemy_arr_0E1B[object_index];
|
|
v13 = enemy_arr_0E1B[v11];
|
|
if (v13 >= 0x12u) {
|
|
enemy_arr_0E1B[v11] = 0;
|
|
v13 = enemy_arr_0E1B[v11];
|
|
}
|
|
v14 = kDATA_03EECB[v13];
|
|
oam = get_OamEnt(oam_buf, v12);
|
|
oam[64].charnum = kDATA_03EEDD[v14];
|
|
oam[65].charnum = kDATA_03EEDD[v14 + 1];
|
|
oam[66].charnum = kDATA_03EEDD[v14 + 2];
|
|
oam[67].charnum = kDATA_03EEDD[v14 + 3];
|
|
oam[68].charnum = kDATA_03EEDD[v14 + 4];
|
|
oam[69].charnum = kDATA_03EEDD[v14 + 5];
|
|
}
|
|
if (tempEF == 8)
|
|
goto LABEL_127;
|
|
if (tempF0) {
|
|
v16 = get_OamEnt(oam_buf, v12);
|
|
v17 = v12 + 2;
|
|
DumpSixSpr(v17, v16[64].flags | 0x80);
|
|
v12 = v17 - 2;
|
|
v18 = v12;
|
|
if (tempEF != 5 && tempEF != 17 && tempEF < 0x15u)
|
|
v18 = v12 + 8;
|
|
v19 = get_OamEnt(oam_buf, v18);
|
|
charnum = v19[64].charnum;
|
|
v31 = v19[65].charnum;
|
|
v20 = get_OamEnt(oam_buf, v12);
|
|
v19[64].charnum = v20[68].charnum;
|
|
v19[65].charnum = v20[69].charnum;
|
|
v20[69].charnum = v31;
|
|
v20[68].charnum = charnum;
|
|
}
|
|
if (bowser_gfx_flag)
|
|
goto LABEL_127;
|
|
v21 = tempEC;
|
|
if (tempEF == 5)
|
|
goto LABEL_127;
|
|
if ((tempEF == 7 || tempEF == 13 || tempEF == 12 || (tempEF != 18 || tempEC == 5) && tempEC >= 2u) && !bowser_gfx_flag &&
|
|
!enemy_array_F40[9]) {
|
|
v22 = get_OamEnt(oam_buf, v12);
|
|
v23 = v22[64].flags & 0xBE;
|
|
v22[64].flags = v23;
|
|
v22[66].flags = v23;
|
|
v22[68].flags = v23;
|
|
v24 = v23 | 0x40;
|
|
if (v21 == 5)
|
|
v24 |= 0x80u;
|
|
v22[65].flags = v24;
|
|
v22[67].flags = v24;
|
|
v22[69].flags = v24;
|
|
if (v21 == 4) {
|
|
v25 = v22[66].flags | 0x80;
|
|
v22[66].flags = v25;
|
|
v22[68].flags = v25;
|
|
v25 |= 0x40u;
|
|
v22[67].flags = v25;
|
|
v22[69].flags = v25;
|
|
}
|
|
}
|
|
if (tempEF == 17) {
|
|
if (!tempF0) {
|
|
v26 = get_OamEnt(oam_buf, v12);
|
|
v26[68].flags &= ~0x40u;
|
|
v27 = v26[69].flags | 0x40;
|
|
v26[69].flags = v27;
|
|
if (frenzy_enemy_timer < 0x10u) {
|
|
v26[67].flags = v27;
|
|
v26[66].flags = v27 & 0xBF;
|
|
}
|
|
LABEL_127:
|
|
if (tempEF == 13) {
|
|
v30 = get_OamEnt(oam_buf, v12);
|
|
v30[68].flags = v30[68].flags & 0xF0 | 8;
|
|
v30[69].flags = v30[69].flags & 0xF0 | 8;
|
|
}
|
|
SprObjectOffscrChk(v12);
|
|
return;
|
|
}
|
|
v28 = get_OamEnt(oam_buf, v12);
|
|
v28[64].flags &= ~0x40u;
|
|
v28[65].flags |= 0x40u;
|
|
}
|
|
if (tempEF >= 0x18u) {
|
|
v29 = get_OamEnt(oam_buf, v12);
|
|
v29[66].flags = -84;
|
|
v29[68].flags = -84;
|
|
v29[67].flags = -20;
|
|
v29[69].flags = -20;
|
|
v29[64].flags = 44;
|
|
v29[65].flags = 108;
|
|
}
|
|
goto LABEL_127;
|
|
}
|
|
if (v8 == 36) {
|
|
if (tempEC == 5) {
|
|
v9 = 48;
|
|
R3_ = 2;
|
|
tempEC = 5;
|
|
}
|
|
} else {
|
|
if (v8 == 0x90) {
|
|
if ((tempED & 0x20) == 0 && frenzy_enemy_timer < 0x10u)
|
|
v9 = -106;
|
|
goto LABEL_89;
|
|
}
|
|
if (tempEF < 4u && tempEC >= 2u) {
|
|
v9 = 90;
|
|
if (tempEF == 2) {
|
|
v9 = 126;
|
|
++R2_;
|
|
}
|
|
}
|
|
if (tempEC == 4) {
|
|
v9 = 114;
|
|
++R2_;
|
|
if (tempEF != 2) {
|
|
v9 = 102;
|
|
++R2_;
|
|
}
|
|
if (tempEF == 6) {
|
|
v9 = 84;
|
|
if ((tempED & 0x20) == 0) {
|
|
v9 = -118;
|
|
--R2_;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (tempEF == 5) {
|
|
if (tempED) {
|
|
if ((tempED & 8) == 0)
|
|
goto LABEL_89;
|
|
v9 = -76;
|
|
}
|
|
} else if (v9 != 72) {
|
|
if (*(&enemy_interval_timer + object_index) >= 5u)
|
|
goto LABEL_89;
|
|
if (v9 == 60) {
|
|
if (*(&enemy_interval_timer + object_index) != 1) {
|
|
++R2_;
|
|
++R2_;
|
|
++R2_;
|
|
goto LABEL_87;
|
|
}
|
|
LABEL_89:
|
|
if ((tempED & 0x20) != 0 && tempEF >= 4u) {
|
|
tempF0 = 1;
|
|
tempEC = 0;
|
|
}
|
|
goto LABEL_92;
|
|
}
|
|
}
|
|
if (tempEF != 6 && tempEF != 8 && tempEF != 12 && tempEF < 0x18u) {
|
|
if (tempEF == 21) {
|
|
if (world_number < 7u) {
|
|
v9 = -94;
|
|
tempEC = 3;
|
|
}
|
|
goto LABEL_89;
|
|
}
|
|
if ((kEnemyAnimTimingBMask[0] & frame_counter) == 0) {
|
|
LABEL_87:
|
|
if (!(timer_control | tempED & 0xA0))
|
|
v9 += 6;
|
|
goto LABEL_89;
|
|
}
|
|
}
|
|
goto LABEL_89;
|
|
}
|
|
}
|
|
|
|
void SprObjectOffscrChk(uint8 j) {
|
|
uint8 v1; // si
|
|
uint8 v2; // di
|
|
int8 v3; // cf
|
|
uint8 v4; // [rsp+47h] [rbp-1h]
|
|
uint8 v5; // [rsp+47h] [rbp-1h]
|
|
|
|
v1 = object_index;
|
|
GetEnemyXPos(object_index);
|
|
R4_ = 0;
|
|
CODE_03FEE5(j);
|
|
v2 = DrawLargePlatform_Next(j);
|
|
R4_ = 0;
|
|
CODE_03FEE5(v2);
|
|
v4 = offscreen_bits.enemy >> 6;
|
|
if ((offscreen_bits.enemy & 0x20) != 0)
|
|
CODE_03F313(v1, 0x10u);
|
|
v3 = v4 & 1;
|
|
v5 = v4 >> 1;
|
|
if (v3)
|
|
CODE_03F313(v1, 8u);
|
|
if (v5 & 1) {
|
|
CODE_03F313(v1, v5 >> 1);
|
|
if (enemy_id[v1] != 12 && obj_ypos_hi.enemy[v1] == 2)
|
|
EraseEnemyObject(v1);
|
|
}
|
|
}
|
|
|
|
void DrawEnemyObjRow(uint8 k, uint8 j) {
|
|
R0_ = kEnemyGraphicsTable[k];
|
|
DrawOneSpriteRow(k, j, kEnemyGraphicsTable[k + 1]);
|
|
}
|
|
|
|
uint8 DrawOneSpriteRow(uint8 k, uint8 j, uint8 a) {
|
|
R1_ = a;
|
|
if (R2_ == 0xF9)
|
|
R2_ = -16;
|
|
return DrawOneSpriteRow_Sub(j);
|
|
}
|
|
|
|
uint8 DrawOneSpriteRow_(uint8 j, uint8 a) {
|
|
OamEnt *oam; // rdx
|
|
int8 v3; // al
|
|
uint8 v4; // al
|
|
OamEnt *v5; // rbp
|
|
uint8 v6; // al
|
|
uint8 v7; // al
|
|
|
|
R1_ = a;
|
|
oam = get_OamEnt(oam_buf, j);
|
|
if ((R3_ & 2) != 0) {
|
|
oam[1].charnum = R0_;
|
|
oam->charnum = R1_;
|
|
v3 = 64;
|
|
} else {
|
|
oam->charnum = R0_;
|
|
oam[1].charnum = R1_;
|
|
v3 = 0;
|
|
}
|
|
v4 = R4_ | v3;
|
|
v5 = get_OamEnt(oam_buf, j);
|
|
v5->flags = v4;
|
|
v5[1].flags = v4;
|
|
v6 = R2_;
|
|
v5->ypos = R2_;
|
|
v5[1].ypos = v6;
|
|
v7 = R5_;
|
|
v5->xpos = R5_;
|
|
v5[1].xpos = v7 + 8;
|
|
R2_ += 8;
|
|
return j + 8;
|
|
}
|
|
|
|
void CODE_03F313(uint8 k, uint8 a) {
|
|
object_index = k;
|
|
if (k == 10)
|
|
k = 9;
|
|
DumpTwoSpr(enemy_obj_id[k] + a, 0xF0u);
|
|
}
|
|
|
|
void CODE_03F326(uint8 k, uint8 a) {
|
|
OamEnt *oam; // rbp
|
|
|
|
object_index = k;
|
|
if (k == 10)
|
|
k = 9;
|
|
oam = get_OamEnt(oam_buf, (uint8)(enemy_obj_id[k] + a));
|
|
oam[64].ypos = -16;
|
|
oam[66].ypos = -16;
|
|
oam[68].ypos = -16;
|
|
}
|
|
|
|
void DrawBlock(uint8 k) {
|
|
uint8 v1; // di
|
|
OamEnt *oam; // rbp
|
|
int8 v3; // al
|
|
|
|
v1 = block_obj_id[k];
|
|
oam = get_OamEnt(oam_buf, v1);
|
|
oam->xpos = rel_xpos_lo.block;
|
|
oam->ypos = rel_ypos.block;
|
|
oam->flags = 43;
|
|
oam_tile_size_buffer[v1] = 2;
|
|
if (block_metatile[k] == 0xFC)
|
|
v3 = 0;
|
|
else
|
|
v3 = 2;
|
|
oam->charnum = v3;
|
|
tempE5 = obj_xpos_hi.block[k];
|
|
tempE4 = obj_xpos_lo.block[k];
|
|
*(uint16 *)&tempE4 -= screen_left_xpos16;
|
|
if (tempE5)
|
|
oam_tile_size_buffer[v1] = 3;
|
|
}
|
|
// 7E03B1: using guessed type int8;
|
|
// 7E03BC: using guessed type int8;
|
|
|
|
void DrawBrickChunks(uint8 k) {
|
|
uint8 v1; // al
|
|
uint8 v2; // di
|
|
uint8 v3; // di
|
|
uint8 block; // al
|
|
OamEnt *oam; // rbp
|
|
uint8 unk5; // al
|
|
|
|
R0_ = 44;
|
|
v1 = 117;
|
|
if (game_engine_subroutine != 5) {
|
|
R0_ = 42;
|
|
v1 = -124;
|
|
}
|
|
v2 = block_obj_id[k] + 1;
|
|
CODE_03EC3C(v2++, v1);
|
|
CODE_03EC3C(v2, R0_ | (16 * frame_counter) & 0xC0);
|
|
v3 = v2 - 2;
|
|
block = rel_ypos.block;
|
|
if (rel_ypos.block >= 0xF0u)
|
|
block = -16;
|
|
DumpTwoSpr_(v3, block);
|
|
oam = get_OamEnt(oam_buf, v3);
|
|
oam->xpos = rel_xpos_lo.block;
|
|
R0_ = block_orig_xpos_lo[k] - screen_left_xpos_lo;
|
|
oam[1].xpos = R0_ + R0_ - rel_xpos_lo.block + 6;
|
|
unk5 = rel_ypos.unk5;
|
|
if (rel_ypos.unk5 >= 0xF0u)
|
|
unk5 = -16;
|
|
oam[2].ypos = unk5;
|
|
oam[3].ypos = unk5;
|
|
oam[2].xpos = rel_xpos_lo.unk5;
|
|
oam[3].xpos = R0_ + R0_ - rel_xpos_lo.unk5 + 6;
|
|
if (__CFSHL__(offscreen_bits.block, 1))
|
|
DumpTwoSpr_(v3, 0xF0u);
|
|
if (offscreen_bits.block) {
|
|
oam_tile_size_buffer[v3] = 1;
|
|
oam_tile_size_buffer[v3 + 8] = 1;
|
|
}
|
|
if (offscreen_bits.unk5) {
|
|
oam_tile_size_buffer[v3 + 4] = 1;
|
|
oam_tile_size_buffer[v3 + 12] = 1;
|
|
}
|
|
}
|
|
// 7E03B1: using guessed type int8;
|
|
// 7E03B2: using guessed type int8;
|
|
// 7E03BC: using guessed type int8;
|
|
// 7E03BD: using guessed type int8;
|
|
|
|
void DrawFireball(uint8 k) {
|
|
uint8 v1; // di
|
|
OamEnt *oam; // rdx
|
|
int8 v3; // al
|
|
int8 v4; // [rsp+47h] [rbp-1h]
|
|
|
|
v1 = fireball_oam_id[k];
|
|
oam = get_OamEnt(oam_buf, v1);
|
|
oam->ypos = rel_ypos.fireball;
|
|
oam->xpos = rel_xpos_lo.fireball;
|
|
v4 = frame_counter >> 2;
|
|
oam->charnum = ((frame_counter & 4) != 0) ^ 0xBE;
|
|
v3 = 40;
|
|
if ((v4 & 2) != 0)
|
|
v3 = -24;
|
|
oam->flags = v3;
|
|
if ((obj_xspeed.fireball[k] & 0x80u) != 0 && rel_xpos_lo.fireball >= 0xF8u)
|
|
oam_tile_size_buffer[v1] = 1;
|
|
}
|
|
// 7E03AF: using guessed type int8;
|
|
// 7E03BA: using guessed type int8;
|
|
|
|
void DrawFirebar(uint8 j) {
|
|
OamEnt *oam; // rdx
|
|
int8 v2; // al
|
|
int8 v3; // [rsp+47h] [rbp-1h]
|
|
|
|
v3 = frame_counter >> 2;
|
|
oam = get_OamEnt(oam_buf, j);
|
|
oam[64].charnum = ((frame_counter & 4) != 0) ^ 0xBE;
|
|
v2 = 56;
|
|
if ((v3 & 2) != 0)
|
|
v2 = -8;
|
|
oam[64].flags = v2;
|
|
}
|
|
|
|
void DrawExplodingPlayerFireball(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // al
|
|
uint8 v3; // al
|
|
uint8 v4; // di
|
|
uint8 v5; // al
|
|
OamEnt *oam; // rbp
|
|
uint8 fireball; // al
|
|
|
|
v1 = block_obj_id[k];
|
|
if ((obj_xspeed.fireball[k] & 0x80u) == 0) {
|
|
rel_xpos_lo.fireball -= 4;
|
|
if (rel_xpos_lo.fireball < 0xF8u)
|
|
goto LABEL_8;
|
|
goto LABEL_3;
|
|
}
|
|
if (rel_xpos_lo.fireball >= 0xF0u) {
|
|
if (rel_xpos_lo.fireball < 0xF8u) {
|
|
oam_tile_size_buffer[v1] = 1;
|
|
oam_tile_size_buffer[v1 + 4] = 1;
|
|
LABEL_3:
|
|
oam_tile_size_buffer[v1 + 8] = 1;
|
|
oam_tile_size_buffer[v1 + 12] = 1;
|
|
goto LABEL_8;
|
|
}
|
|
oam_tile_size_buffer[v1] = 1;
|
|
oam_tile_size_buffer[v1 + 4] = 1;
|
|
}
|
|
LABEL_8:
|
|
v2 = fireball_state[k];
|
|
fireball_state[k] = v2 + 1;
|
|
v3 = (v2 >> 1) & 7;
|
|
if (v3 >= 3u) {
|
|
fireball_state[k] = 0;
|
|
} else {
|
|
v4 = v1 + 1;
|
|
CODE_03EC3C(v4, kDATA_03F4A4[v3]);
|
|
v5 = rel_ypos.fireball - 4;
|
|
oam = get_OamEnt(oam_buf, (uint8)(v4 - 1));
|
|
oam->ypos = rel_ypos.fireball - 4;
|
|
oam[2].ypos = v5;
|
|
v5 += 8;
|
|
oam[1].ypos = v5;
|
|
oam[3].ypos = v5;
|
|
fireball = rel_xpos_lo.fireball;
|
|
oam->xpos = rel_xpos_lo.fireball;
|
|
oam[1].xpos = fireball;
|
|
fireball += 8;
|
|
oam[2].xpos = fireball;
|
|
oam[3].xpos = fireball;
|
|
oam->flags = 40;
|
|
oam[1].flags = -88;
|
|
oam[2].flags = 104;
|
|
oam[3].flags = -24;
|
|
}
|
|
}
|
|
// 7E03AF: using guessed type int8;
|
|
// 7E03BA: using guessed type int8;
|
|
|
|
void DrawExplosion_Fireworks(uint8 j, uint8 a) {
|
|
int v2; // rdi
|
|
uint8 v3; // si
|
|
uint8 v4; // al
|
|
OamEnt *oam; // rbp
|
|
uint8 v6; // al
|
|
uint8 v7; // si
|
|
|
|
v2 = (uint8)(j + 1);
|
|
DumpFourSpr(v2, kDATA_03F53B[a]);
|
|
LOBYTE(v2) = v2 - 1;
|
|
v3 = object_index;
|
|
v4 = rel_ypos.fireball - 16;
|
|
oam = get_OamEnt(oam_buf, (uint8)v2);
|
|
oam[64].ypos = rel_ypos.fireball - 16;
|
|
oam[66].ypos = v4;
|
|
v4 += 16;
|
|
oam[65].ypos = v4;
|
|
oam[67].ypos = v4;
|
|
v6 = rel_xpos_lo.fireball - 8;
|
|
oam[64].xpos = rel_xpos_lo.fireball - 8;
|
|
oam[65].xpos = v6;
|
|
v6 += 16;
|
|
oam[66].xpos = v6;
|
|
oam[67].xpos = v6;
|
|
oam_tile_size_buffer[(uint8)v2 + 256] = 2;
|
|
oam_tile_size_buffer[(uint8)v2 + 260] = 2;
|
|
oam_tile_size_buffer[(uint8)v2 + 264] = 2;
|
|
oam_tile_size_buffer[(uint8)v2 + 268] = 2;
|
|
v7 = obj_yspeed.enemy[v3] - 1;
|
|
oam[64].flags = kDATA_03F53F[v7] | 0x20;
|
|
oam[65].flags = kDATA_03F53F[v7] | 0xA0;
|
|
oam[66].flags = kDATA_03F53F[v7] | 0x60;
|
|
oam[67].flags = kDATA_03F53F[v7] | 0xE0;
|
|
}
|
|
// 7E03AF: using guessed type int8;
|
|
// 7E03BA: using guessed type int8;
|
|
|
|
void DrawSmallPlatform(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 v2; // di
|
|
uint8 enemy; // al
|
|
OamEnt *oam; // rbp
|
|
uint8 v5; // [rsp+47h] [rbp-1h]
|
|
uint8 v6; // [rsp+47h] [rbp-1h]
|
|
|
|
v1 = enemy_obj_id[k] + 1;
|
|
DumpSixSpr(v1++, 0x87u);
|
|
DumpSixSpr(v1, 0x2Cu);
|
|
v2 = v1 - 2;
|
|
enemy = rel_xpos_lo.enemy;
|
|
oam = get_OamEnt(oam_buf, v2);
|
|
oam[64].xpos = rel_xpos_lo.enemy;
|
|
oam[67].xpos = enemy;
|
|
enemy += 8;
|
|
oam[65].xpos = enemy;
|
|
oam[68].xpos = enemy;
|
|
enemy += 8;
|
|
oam[66].xpos = enemy;
|
|
oam[69].xpos = enemy;
|
|
v5 = obj_ypos_lo.enemy[k];
|
|
DumpThreeSpr(v2, v5);
|
|
oam[67].ypos = v5 + 0x80;
|
|
oam[68].ypos = v5 + 0x80;
|
|
oam[69].ypos = v5 + 0x80;
|
|
v6 = offscreen_bits.enemy;
|
|
if ((offscreen_bits.enemy & 8) != 0) {
|
|
oam_tile_size_buffer[v2 + 256] = 1;
|
|
oam_tile_size_buffer[v2 + 268] = 1;
|
|
}
|
|
if ((v6 & 4) != 0) {
|
|
oam_tile_size_buffer[v2 + 260] = 1;
|
|
oam_tile_size_buffer[v2 + 272] = 1;
|
|
}
|
|
if ((v6 & 2) != 0) {
|
|
oam_tile_size_buffer[v2 + 264] = 1;
|
|
oam_tile_size_buffer[v2 + 276] = 1;
|
|
}
|
|
}
|
|
// 7E03D1: using guessed type int8;
|
|
|
|
void PlayerGfxHandler() {
|
|
uint8 v0; // di
|
|
OamEnt *oam; // rdx
|
|
uint8 xpos; // al
|
|
uint8 v3; // al
|
|
OamEnt *v4; // rdx
|
|
|
|
if (turn_around_smoke_flag2)
|
|
goto LABEL_5;
|
|
if (player_gfx_offset == 24 || player_gfx_offset == 120) {
|
|
++turn_around_smoke_flag2;
|
|
turn_around_smoke_flag = 0;
|
|
LABEL_5:
|
|
HandleTurnAroundSmoke();
|
|
}
|
|
if (game_engine_subroutine == 3 || !player_hurt_timer || !(frame_counter & 1)) {
|
|
if (game_engine_subroutine == 11) {
|
|
PlayerKilled();
|
|
} else if (player_change_size_flag) {
|
|
DoChangeSize();
|
|
} else if (swimming_flag && player_state) {
|
|
FindPlayerAction();
|
|
v0 = spr_data_offset;
|
|
if (!(player_facing_dir & 1))
|
|
v0 = spr_data_offset + 4;
|
|
if (!player_size) {
|
|
if (player_facing_dir == 2 || (oam = get_OamEnt(oam_buf, v0), xpos = oam[4].xpos, oam[4].xpos = xpos - 8, xpos >= 8u)) {
|
|
v3 = 2;
|
|
} else {
|
|
v3 = 3;
|
|
}
|
|
oam_tile_size_buffer[v0 + 16] = v3;
|
|
v4 = get_OamEnt(oam_buf, v0);
|
|
v4[4].charnum = ((uint8)(player_gfx_offset - 40) >> 2) + 8;
|
|
if (v4[6].ypos >= 0xF0u)
|
|
v4[4].ypos = -16;
|
|
v4[6].ypos = -16;
|
|
}
|
|
} else {
|
|
FindPlayerAction();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FindPlayerAction() {
|
|
uint8 v0; // al
|
|
|
|
v0 = ProcessPlayerAction();
|
|
PlayerGfxProcessing(v0);
|
|
}
|
|
|
|
void DoChangeSize() {
|
|
uint8 v0; // al
|
|
|
|
v0 = HandleChangeSize();
|
|
PlayerGfxProcessing(v0);
|
|
}
|
|
|
|
void PlayerKilled() {
|
|
PlayerGfxProcessing(kPlayerGfxTblOffsets[14]);
|
|
}
|
|
|
|
void PlayerGfxProcessing(uint8 a) {
|
|
uint8 v1; // al
|
|
int8 v2; // cf
|
|
uint8 v3; // di
|
|
int8 v4; // si
|
|
uint8 v5; // di
|
|
|
|
player_gfx_offset = a;
|
|
v1 = mario_goal_walk_var03ce;
|
|
if (mario_goal_walk_var03ce)
|
|
goto LABEL_6;
|
|
if (vertical_pipe_flag_var0218) {
|
|
if (!player_size) {
|
|
player_gfx_offset = -40;
|
|
goto LABEL_7;
|
|
}
|
|
v1 = -32;
|
|
LABEL_6:
|
|
player_gfx_offset = v1;
|
|
}
|
|
LABEL_7:
|
|
RenderPlayerSub(4u);
|
|
UNUSED_ChkForPlayerAttrib();
|
|
if (R2_ == 3 && obj_xpos_hi.player != (obj_xpos_lo.player < (uint8)screen_left_xpos16) + HIBYTE(screen_left_xpos16)) {
|
|
oam_tile_size_buffer[208] = 1;
|
|
oam_tile_size_buffer[216] = 1;
|
|
oam_tile_size_buffer[224] = 1;
|
|
oam_tile_size_buffer[232] = 1;
|
|
}
|
|
if (fireball_throwing_timer) {
|
|
v2 = player_anim_timer >= fireball_throwing_timer;
|
|
fireball_throwing_timer = 0;
|
|
if (!v2) {
|
|
fireball_throwing_timer = player_anim_timer;
|
|
if (player_state != 1)
|
|
player_gfx_offset = kPlayerGfxTblOffsets[7];
|
|
v3 = 4;
|
|
if (buttons_left_right | obj_xspeed.player)
|
|
v3 = 3;
|
|
RenderPlayerSub(v3);
|
|
}
|
|
}
|
|
R0_ = offscreen_bits.player >> 4;
|
|
v4 = 3;
|
|
v5 = spr_data_offset + 24;
|
|
do {
|
|
v2 = R0_ & 1;
|
|
R0_ >>= 1;
|
|
if (v2)
|
|
DumpTwoSpr_(v5, 0xF0u);
|
|
v5 -= 8;
|
|
--v4;
|
|
} while (v4 >= 0);
|
|
PlayerGfxProcessing_Sub_New();
|
|
}
|
|
|
|
void DrawLevelPreviewSprites() {
|
|
uint8 i; // si
|
|
|
|
DrawLevelPreviewSprites_Sub_New();
|
|
player_gfx_offset = -48;
|
|
RenderPlayerSub_New();
|
|
for (i = 5; (i & 0x80u) == 0; --i)
|
|
*(&R2_ + i) = kIntermediatePlayerData[i];
|
|
uint8 j = DrawPlayerLoop(0xB8u, 0xD0u);
|
|
DrawLevelPreviewSprites_Sub(j);
|
|
Entrance_GameTimerSetup();
|
|
}
|
|
|
|
void DrawLevelPreviewSprites_Sub(uint8 j) {
|
|
OamEnt *oam; // rbp
|
|
uint8 v2; // si
|
|
uint8 v3; // di
|
|
uint8 v4; // si
|
|
OamEnt *v5; // rdx
|
|
int8 i; // si
|
|
uint8 v7; // [rsp+45h] [rbp-3h]
|
|
|
|
do {
|
|
oam = get_OamEnt(oam_buf, j);
|
|
oam->ypos = -16;
|
|
oam[64].ypos = -16;
|
|
++j;
|
|
} while (j);
|
|
j = DrawLevelPreviewSprites_Sub2();
|
|
v2 = 0;
|
|
tempE2 = 48;
|
|
do {
|
|
if (DrawLevelPreviewSprites_Sub4(v2, j) == 2) {
|
|
if (enemy_id[v2] == 22) {
|
|
DrawLevelPreviewSprites_Sub5(v2);
|
|
goto LABEL_16;
|
|
}
|
|
v7 = j;
|
|
DrawLevelPreviewSprites_Sub3(v2, enemy_id[v2]);
|
|
v3 = enemy_obj_id[v2];
|
|
oam_tile_size_buffer[v3 + 256] = 0;
|
|
oam_tile_size_buffer[v3 + 260] = 0;
|
|
oam_tile_size_buffer[v3 + 264] = 0;
|
|
oam_tile_size_buffer[v3 + 268] = 0;
|
|
oam_tile_size_buffer[v3 + 272] = 0;
|
|
oam_tile_size_buffer[v3 + 276] = 0;
|
|
obj_xpos_hi.enemy[v2] = HIBYTE(screen_left_xpos16);
|
|
j = v7;
|
|
if (enemy_id[v2] == 18)
|
|
DrawLakituAboveSpinyInLevelPreview(v2);
|
|
}
|
|
++j;
|
|
++v2;
|
|
} while (v2 != 5);
|
|
if (area_type != 3) {
|
|
v4 = 0;
|
|
do {
|
|
v5 = get_OamEnt(oam_buf, v4);
|
|
if (v5[64].charnum == v5[65].charnum) {
|
|
v5[64].flags &= 0x3Fu;
|
|
v5[65].flags |= 0x40u;
|
|
} else {
|
|
v5[64].flags = v5[65].flags;
|
|
}
|
|
v4 += 8;
|
|
} while (v4);
|
|
}
|
|
LABEL_16:
|
|
for (i = 4; i >= 0; --i)
|
|
enemy_id[(uint8)i] = 0;
|
|
which_enemy_gfx_offs = 0;
|
|
}
|
|
|
|
uint8 DrawLevelPreviewSprites_Sub4(uint8 k, uint8 j) {
|
|
uint8 v2; // al
|
|
uint8 result; // al
|
|
uint8 v4; // al
|
|
|
|
which_enemy_gfx_offs = 0;
|
|
if (player_hard_mode_flag)
|
|
v2 = kDATA_05EC92[j];
|
|
else
|
|
v2 = kDATA_05EBED[j];
|
|
if (v2 == 0xFF) {
|
|
result = tempE2 + 24;
|
|
tempE2 += 24;
|
|
} else {
|
|
obj_ypos_hi.enemy[k] = 0;
|
|
enemy_id[k] = v2;
|
|
if (v2 == 14 || v2 == 15 || v2 == 16 || v2 == 20 || v2 == 8)
|
|
v4 = -120;
|
|
else
|
|
v4 = -104;
|
|
obj_ypos_lo.enemy[k] = v4;
|
|
tempE2 += 24;
|
|
rel_xpos_lo.enemy = tempE2;
|
|
enemy_sprattrib[k] = 32;
|
|
if (kDATA_05EBED[j] == 5) {
|
|
which_enemy_gfx_offs = kDATA_05EBED[j];
|
|
DrawLevelPreviewSprites_Sub6(k);
|
|
}
|
|
result = 2;
|
|
enemy_moving_dir[k] = 2;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
uint8 DrawLevelPreviewSprites_Sub2() {
|
|
uint8 v0; // si
|
|
|
|
v0 = area_number + 5 * world_number;
|
|
background_color_ctrl_0 = kDATA_05ED37[v0];
|
|
level_level_preview_image_to_use = kDATA_05ED64[v0];
|
|
uint8 rv = level_level_preview_image_to_use * 5;
|
|
LOBYTE(screen_left_xpos16_b) = screen_left_xpos_lo;
|
|
HIBYTE(screen_left_xpos16_b) = screen_left_xpos_hi;
|
|
++draw_level_preview_sprites_var009B;
|
|
screen_left_xpos_hi = 0;
|
|
layer1_xpos_lo = 0;
|
|
layer2_xpos = 0;
|
|
layer3_xpos = 0;
|
|
WriteReg(BG1HOFS, 0);
|
|
WriteReg(BG1HOFS, 0);
|
|
WriteReg(BG2HOFS, 0);
|
|
WriteReg(BG2HOFS, 0);
|
|
WriteReg(BG3HOFS, 0);
|
|
WriteReg(BG3HOFS, 0);
|
|
return rv;
|
|
}
|
|
|
|
void Unused_CODE_03F9EC() {
|
|
OamEnt *oam; // rbp
|
|
|
|
oam = get_OamEnt(oam_buf, 0);
|
|
oam[88].charnum = kDATA_03F9E6[0];
|
|
oam[89].charnum = kDATA_03F9E6[1];
|
|
oam[90].charnum = kDATA_03F9E6[2];
|
|
oam[91].charnum = kDATA_03F9E6[3];
|
|
oam[92].charnum = kDATA_03F9E6[4];
|
|
oam[93].charnum = kDATA_03F9E6[5];
|
|
}
|
|
|
|
void DrawLakituAboveSpinyInLevelPreview(uint8 k) {
|
|
uint8 v1; // di
|
|
uint8 enemy; // al
|
|
OamEnt *oam; // rbp
|
|
uint8 v4; // al
|
|
int v5; // edx
|
|
|
|
R3_ = 3;
|
|
obj_ypos_lo.enemy[k] -= 40;
|
|
tempE3 = 0;
|
|
v1 = 0;
|
|
do {
|
|
enemy = rel_xpos_lo.enemy;
|
|
oam = get_OamEnt(oam_buf, v1);
|
|
oam[100].xpos = rel_xpos_lo.enemy;
|
|
oam[101].xpos = enemy + 8;
|
|
v4 = obj_ypos_lo.enemy[k];
|
|
oam[100].ypos = v4;
|
|
oam[101].ypos = v4;
|
|
obj_ypos_lo.enemy[k] = v4 + 8;
|
|
oam[100].flags = 42;
|
|
oam[101].flags = 42;
|
|
v5 = tempE3;
|
|
oam[100].charnum = kDATA_03FA11[tempE3];
|
|
oam[101].charnum = kDATA_03FA11[v5 + 1];
|
|
++tempE3;
|
|
++tempE3;
|
|
v1 += 8;
|
|
--R3_;
|
|
} while (R3_);
|
|
}
|
|
|
|
void DrawLevelPreviewSprites_Sub5(uint8 k) {
|
|
uint8 enemy; // al
|
|
OamEnt *oam; // rbp
|
|
uint8 v3; // al
|
|
OamEnt *v4; // rbx
|
|
|
|
rel_ypos.enemy = obj_ypos_lo.enemy[k] - 8;
|
|
rel_xpos_lo.enemy -= 16;
|
|
enemy = rel_xpos_lo.enemy;
|
|
oam = get_OamEnt(oam_buf, 0x90u);
|
|
oam[64].xpos = rel_xpos_lo.enemy;
|
|
oam[66].xpos = enemy;
|
|
enemy += 8;
|
|
oam[68].xpos = enemy;
|
|
enemy += 8;
|
|
oam[65].xpos = enemy;
|
|
oam[67].xpos = enemy;
|
|
oam[69].xpos = enemy;
|
|
v3 = rel_ypos.enemy;
|
|
oam[64].ypos = rel_ypos.enemy;
|
|
oam[65].ypos = v3;
|
|
v3 += 16;
|
|
oam[66].ypos = v3;
|
|
oam[67].ypos = v3;
|
|
v3 -= 24;
|
|
oam[68].ypos = v3;
|
|
oam[69].ypos = v3;
|
|
oam_tile_size_buffer[160] = 0;
|
|
oam_tile_size_buffer[164] = 0;
|
|
oam_tile_size_buffer[400] = 2;
|
|
oam_tile_size_buffer[404] = 2;
|
|
oam_tile_size_buffer[408] = 2;
|
|
oam_tile_size_buffer[412] = 2;
|
|
oam[64].flags = 97;
|
|
oam[65].flags = 97;
|
|
oam[66].flags = 97;
|
|
oam[67].flags = 97;
|
|
oam[68].flags = 97;
|
|
oam[69].flags = 97;
|
|
oam[68].charnum = -59;
|
|
oam[69].charnum = -60;
|
|
oam[64].charnum = -18;
|
|
oam[65].charnum = -64;
|
|
oam[66].charnum = -30;
|
|
oam[67].charnum = -32;
|
|
v4 = get_OamEnt(oam_buf, 0);
|
|
v4[124].xpos = 112;
|
|
v4[125].xpos = 120;
|
|
v4[124].ypos = -104;
|
|
v4[125].ypos = -104;
|
|
v4[124].charnum = -122;
|
|
v4[125].charnum = -121;
|
|
v4[124].flags = 33;
|
|
v4[125].flags = 33;
|
|
oam_tile_size_buffer[496] = 2;
|
|
oam_tile_size_buffer[500] = 2;
|
|
}
|
|
// 7E03B9: using guessed type int8;
|
|
|
|
void DrawLevelPreviewSprites_Sub6(uint8 k) {
|
|
OamEnt *oam; // rbp
|
|
|
|
oam = get_OamEnt(oam_buf, 0);
|
|
oam[32].ypos = obj_ypos_lo.enemy[k] - 10;
|
|
oam[32].xpos = rel_xpos_lo.enemy + 3;
|
|
oam[32].flags = 42;
|
|
oam[32].charnum = 68;
|
|
oam_tile_size_buffer[128] = 2;
|
|
}
|
|
|
|
void RenderPlayerSub(uint8 a) {
|
|
R7_ = a;
|
|
player_pos_for_scroll = rel_xpos_lo.player;
|
|
R5_ = rel_xpos_lo.player;
|
|
R2_ = rel_ypos.player;
|
|
R3_ = player_facing_dir;
|
|
RenderPlayerSub_New();
|
|
R4_ = player_sprattrib;
|
|
DrawPlayerLoop(player_gfx_offset & 7, spr_data_offset);
|
|
}
|
|
|
|
uint8 DrawPlayerLoop(uint8 k, uint8 j) {
|
|
do {
|
|
R0_ = kPlayerGraphicsTable[k];
|
|
j = DrawOneSpriteRow_(j, kPlayerGraphicsTable[k + 1]);
|
|
k += 2;
|
|
--R7_;
|
|
} while (R7_);
|
|
if (R5_ >= 0xF8u) {
|
|
oam_tile_size_buffer[208] = 1;
|
|
oam_tile_size_buffer[216] = 1;
|
|
oam_tile_size_buffer[224] = 1;
|
|
oam_tile_size_buffer[232] = 1;
|
|
}
|
|
return j;
|
|
}
|
|
|
|
uint8 ProcessPlayerAction() {
|
|
uint8 v0; // di
|
|
uint8 v1; // di
|
|
uint8 GfxOffsetAdder; // di
|
|
uint8 v4; // di
|
|
uint8 v5; // al
|
|
uint8 v6; // al
|
|
uint8 CurrentAnimOffset; // [rsp+47h] [rbp-1h]
|
|
|
|
if (player_state != 3) {
|
|
if (player_state == 2) {
|
|
GfxOffsetAdder = GetGfxOffsetAdder(4u);
|
|
return GetCurrentAnimOffset(GfxOffsetAdder);
|
|
}
|
|
if (player_state == 1) {
|
|
if (!swimming_flag) {
|
|
v0 = 6;
|
|
if (!crouching_flag)
|
|
v0 = 0;
|
|
goto LABEL_12;
|
|
}
|
|
v4 = GetGfxOffsetAdder(1u);
|
|
if (!(player_anim_ctrl | jump_swim_timer) && !__CFSHL__(buttons_a_b, 1))
|
|
return GetCurrentAnimOffset(v4);
|
|
goto LABEL_20;
|
|
}
|
|
v0 = 6;
|
|
if (crouching_flag)
|
|
goto LABEL_12;
|
|
v0 = 2;
|
|
if (!(buttons_left_right | obj_xspeed.player))
|
|
goto LABEL_12;
|
|
if (player_x_speed_absolute < 9u || (player_facing_dir & player_moving_dir) != 0) {
|
|
v4 = GetGfxOffsetAdder(4u);
|
|
LABEL_20:
|
|
v5 = 3;
|
|
goto LABEL_21;
|
|
}
|
|
v0 = 3;
|
|
LABEL_12:
|
|
v1 = GetGfxOffsetAdder(v0);
|
|
player_anim_ctrl = 0;
|
|
return kPlayerGfxTblOffsets[v1];
|
|
}
|
|
v0 = 5;
|
|
if (!obj_yspeed.player)
|
|
goto LABEL_12;
|
|
v4 = GetGfxOffsetAdder(5u);
|
|
v5 = 2;
|
|
LABEL_21:
|
|
R0_ = v5;
|
|
CurrentAnimOffset = GetCurrentAnimOffset(v4);
|
|
if (!player_anim_timer) {
|
|
player_anim_timer = player_anim_timer_set;
|
|
v6 = player_anim_ctrl + 1;
|
|
if ((uint8)(player_anim_ctrl + 1) >= R0_)
|
|
v6 = 0;
|
|
player_anim_ctrl = v6;
|
|
}
|
|
return CurrentAnimOffset;
|
|
}
|
|
|
|
uint8 GetCurrentAnimOffset(uint8 j) {
|
|
return kPlayerGfxTblOffsets[j] + 8 * player_anim_ctrl;
|
|
}
|
|
|
|
uint8 GetGfxOffsetAdder(uint8 j) {
|
|
if (player_size)
|
|
j += 8;
|
|
return j;
|
|
}
|
|
|
|
uint8 HandleChangeSize() {
|
|
uint8 v0; // di
|
|
uint8 v2; // si
|
|
uint8 v3; // di
|
|
|
|
v0 = player_anim_ctrl;
|
|
if ((frame_counter & 3) == 0) {
|
|
v0 = player_anim_ctrl + 1;
|
|
if ((uint8)(player_anim_ctrl + 1) >= 0xAu) {
|
|
v0 = 0;
|
|
player_change_size_flag = 0;
|
|
}
|
|
player_anim_ctrl = v0;
|
|
}
|
|
if (!player_size)
|
|
return kPlayerGfxTblOffsets[15] + 8 * kChangeSizeOffsetAdder[v0];
|
|
v2 = v0 + 10;
|
|
v3 = 9;
|
|
if (!kChangeSizeOffsetAdder[v2])
|
|
v3 = 1;
|
|
return kPlayerGfxTblOffsets[v3];
|
|
}
|
|
|
|
void UNUSED_ChkForPlayerAttrib() {
|
|
;
|
|
}
|
|
|
|
void PlayerGfxProcessing_Sub_New() {
|
|
uint8 i; // si
|
|
OamEnt *oam; // rbp
|
|
OamEnt *v2; // rbx
|
|
|
|
if (player_gfx_processing_flag) {
|
|
for (i = 0; i != 32; ++i) {
|
|
oam = get_OamEnt(oam_buf, i);
|
|
oam[120].xpos = oam[52].xpos;
|
|
}
|
|
v2 = get_OamEnt(oam_buf, 0);
|
|
v2[52].ypos = -16;
|
|
v2[53].ypos = -16;
|
|
v2[54].ypos = -16;
|
|
v2[55].ypos = -16;
|
|
v2[56].ypos = -16;
|
|
v2[57].ypos = -16;
|
|
v2[58].ypos = -16;
|
|
v2[59].ypos = -16;
|
|
oam_tile_size_buffer[480] = oam_tile_size_buffer[208];
|
|
oam_tile_size_buffer[484] = oam_tile_size_buffer[212];
|
|
oam_tile_size_buffer[488] = oam_tile_size_buffer[216];
|
|
oam_tile_size_buffer[492] = oam_tile_size_buffer[220];
|
|
oam_tile_size_buffer[496] = oam_tile_size_buffer[224];
|
|
oam_tile_size_buffer[500] = oam_tile_size_buffer[228];
|
|
oam_tile_size_buffer[504] = oam_tile_size_buffer[232];
|
|
oam_tile_size_buffer[508] = oam_tile_size_buffer[236];
|
|
}
|
|
}
|
|
|
|
void RelativePlayerPosition() {
|
|
RelWOfs(0, kRelPos_Player);
|
|
}
|
|
|
|
void RelativeBubblePosition(uint8 k) {
|
|
uint8 ProperObjOffset; // si
|
|
|
|
ProperObjOffset = GetProperObjOffset(k, 1u);
|
|
RelWOfs(ProperObjOffset, kRelPos_Bubble);
|
|
}
|
|
|
|
void RelativeFireballPosition(uint8 k) {
|
|
uint8 ProperObjOffset; // si
|
|
|
|
ProperObjOffset = GetProperObjOffset(k, 0);
|
|
RelWOfs(ProperObjOffset, kRelPos_Fireball);
|
|
}
|
|
|
|
void RelWOfs(uint8 k, uint8 j) {
|
|
GetObjRelativePosition(k, j);
|
|
}
|
|
|
|
void RelativeMiscPosition(uint8 k) {
|
|
uint8 ProperObjOffset; // si
|
|
|
|
ProperObjOffset = GetProperObjOffset(k, 2u);
|
|
RelWOfs(ProperObjOffset, kRelPos_Misc);
|
|
}
|
|
|
|
uint8 RelativeEnemyPosition(uint8 k) {
|
|
return VariableObjOfsRelPos(k, kRelPos_Enemy, 1u);
|
|
}
|
|
|
|
void RelativeBlockPosition(uint8 k) {
|
|
VariableObjOfsRelPos(k, kRelPos_Block, 0xDu);
|
|
VariableObjOfsRelPos(k + 2, 5u, 0xDu);
|
|
}
|
|
|
|
uint8 VariableObjOfsRelPos(uint8 k, uint8 j, uint8 a) {
|
|
R0_ = k;
|
|
return GetObjRelativePosition(k + a, j);
|
|
}
|
|
|
|
uint8 GetObjRelativePosition(uint8 k, uint8 j) {
|
|
uint8 v2; // al
|
|
bool v3; // cf
|
|
uint8 result; // al
|
|
|
|
*(&rel_ypos.player + j) = *(&obj_ypos_lo.player + k);
|
|
if (!override_player_xpos_flag || obj_xpos_lo.player) {
|
|
v2 = *(&obj_xpos_lo.player + k);
|
|
v3 = v2 < screen_left_xpos_lo;
|
|
*(&rel_xpos_lo.player + j) = v2 - screen_left_xpos_lo;
|
|
*(&rel_xpos_hi.player + j) = *(&obj_xpos_hi.player + k) - (v3 + screen_left_xpos_hi);
|
|
} else {
|
|
obj_xpos_lo.player = 40;
|
|
}
|
|
tempE4 = *(&obj_xpos_lo.player + k);
|
|
tempE5 = *(&obj_xpos_hi.player + k);
|
|
result = tempE4 - screen_left_xpos16;
|
|
spr_rel_xpos16[(uint8)(2 * j) >> 1] = *(uint16 *)&tempE4 - screen_left_xpos16;
|
|
return result;
|
|
}
|
|
|
|
void GetPlayerOffscreenBits() {
|
|
GetOffScreenBitsSet(0, kRelPos_Player);
|
|
}
|
|
|
|
void GetFireballOffscreenBits(uint8 k) {
|
|
uint8 ProperObjOffset; // si
|
|
|
|
ProperObjOffset = GetProperObjOffset(k, 0);
|
|
GetOffScreenBitsSet(ProperObjOffset, kRelPos_Fireball);
|
|
}
|
|
|
|
void GetBubbleOffscreenBits(uint8 k) {
|
|
uint8 ProperObjOffset; // si
|
|
|
|
ProperObjOffset = GetProperObjOffset(k, 1u);
|
|
GetOffScreenBitsSet(ProperObjOffset, kRelPos_Bubble);
|
|
}
|
|
|
|
void GetMiscOffscreenBits(uint8 k) {
|
|
uint8 ProperObjOffset; // si
|
|
|
|
ProperObjOffset = GetProperObjOffset(k, 2u);
|
|
GetOffScreenBitsSet(ProperObjOffset, kRelPos_Misc);
|
|
}
|
|
|
|
uint8 GetProperObjOffset(uint8 k, uint8 j) {
|
|
return kObjOffsetData[j] + k;
|
|
}
|
|
|
|
void GetEnemyOffscreenBits(uint8 k) {
|
|
SetOffscrBitsOffset(k, 1u, kRelPos_Enemy);
|
|
}
|
|
|
|
void GetBlockOffscreenBits(uint8 k) {
|
|
SetOffscrBitsOffset(k, 0xDu, kRelPos_Block);
|
|
}
|
|
|
|
void SetOffscrBitsOffset(uint8 k, uint8 a, uint8 j) {
|
|
R0_ = k;
|
|
GetOffScreenBitsSet(k + a, j);
|
|
}
|
|
|
|
void GetOffScreenBitsSet(uint8 k, uint8 j) {
|
|
uint8 v2; // al
|
|
|
|
R0_ |= 16 * RunOffscrBitsSubs(k);
|
|
v2 = R0_;
|
|
*(&offscreen_bits.player + j) = R0_;
|
|
*(&offscreen_bits_and1.player + j) = (v2 & 4) != 0;
|
|
*(&offscreen_bits_shr1.player + j) = v2 >> 3;
|
|
}
|
|
|
|
uint8 RunOffscrBitsSubs(uint8 k) {
|
|
uint8 i; // di
|
|
uint8 v2; // al
|
|
bool v3; // cf
|
|
uint8 v4; // al
|
|
uint8 v5; // si
|
|
uint8 result; // al
|
|
|
|
R0_ = GetXOffscreenBits(k) >> 4;
|
|
R4_ = k;
|
|
for (i = 1; (i & 0x80u) == 0; --i) {
|
|
v2 = kHighPosUnitData[i];
|
|
v3 = v2 < *(&obj_ypos_lo.player + k);
|
|
R7_ = v2 - *(&obj_ypos_lo.player + k);
|
|
v4 = 1 - (v3 + *(&obj_ypos_hi.player + k));
|
|
v5 = kDefaultYOnscreenOfs[i];
|
|
if (!sign8(v4)) {
|
|
v5 = kDefaultYOnscreenOfs[i + 1];
|
|
if (sign8(v4 - 1)) {
|
|
R6_ = 32;
|
|
v5 = DividePDiff(v5, i, 4u);
|
|
}
|
|
}
|
|
result = kYOffscreenBitsData[v5];
|
|
k = R4_;
|
|
if (result)
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
uint8 GetXOffscreenBits(uint8 k) {
|
|
uint8 i; // di
|
|
uint8 v2; // al
|
|
bool v3; // cf
|
|
uint8 v4; // al
|
|
uint8 v5; // si
|
|
uint8 result; // al
|
|
|
|
R4_ = k;
|
|
for (i = 1; (i & 0x80u) == 0; --i) {
|
|
v2 = *(&screen_left_xpos_lo + i);
|
|
v3 = v2 < *(&obj_xpos_lo.player + k);
|
|
R7_ = v2 - *(&obj_xpos_lo.player + k);
|
|
v4 = *(&screen_left_xpos_hi + i) - (v3 + *(&obj_xpos_hi.player + k));
|
|
v5 = kDefaultXOnscreenOfs[i];
|
|
if (!sign8(v4)) {
|
|
v5 = kDefaultXOnscreenOfs[i + 1];
|
|
if (sign8(v4 - 1)) {
|
|
R6_ = 56;
|
|
v5 = DividePDiff(v5, i, 8u);
|
|
}
|
|
}
|
|
result = kXOffscreenBitsData[v5];
|
|
k = R4_;
|
|
if (result)
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
uint8 DividePDiff(uint8 k, uint8 j, uint8 a) {
|
|
uint8 v3; // al
|
|
|
|
R5_ = a;
|
|
if (R7_ < R6_) {
|
|
v3 = (R7_ >> 3) & 7;
|
|
if (!j)
|
|
v3 += R5_;
|
|
return v3;
|
|
}
|
|
return k;
|
|
}
|
|
|
|
void GetEnemyXPos(uint8 k) {
|
|
HIBYTE(xpos16) = obj_xpos_hi.enemy[k];
|
|
LOBYTE(xpos16) = obj_xpos_lo.enemy[k];
|
|
}
|
|
|
|
void GetSomeXpos_(uint8 k) {
|
|
xpos16 = xpos_new_var0E16;
|
|
}
|
|
|
|
void DrawLargePlatform_DrawOne(uint8 j) {
|
|
R4_ = 6;
|
|
some_xpos_0E12 = xpos16 - screen_left_xpos16;
|
|
oam_tile_size_buffer[j + 256] = (uint16)(xpos16 - screen_left_xpos16) >> 8 != 0;
|
|
}
|
|
|
|
void CODE_03FEE5(uint8 j) {
|
|
bool v1; // al
|
|
|
|
some_xpos_0E12 = xpos16 - screen_left_xpos16;
|
|
v1 = (uint16)(xpos16 - screen_left_xpos16) >> 8 != 0;
|
|
oam_tile_size_buffer[j + 272] = v1;
|
|
oam_tile_size_buffer[j + 264] = v1;
|
|
oam_tile_size_buffer[j + 256] = v1;
|
|
}
|
|
|
|
void Unused_CODE_03FF07(uint8 j) {
|
|
bool v1; // al
|
|
|
|
some_xpos_0E12 = xpos16 - screen_left_xpos16;
|
|
v1 = (uint16)(xpos16 - screen_left_xpos16) >> 8 != 0;
|
|
oam_tile_size_buffer[j + 8] = v1;
|
|
oam_tile_size_buffer[j] = v1;
|
|
}
|
|
|
|
void Unused_CODE_03FF26(uint8 j, uint8 a) {
|
|
oam_tile_size_buffer[j] = a;
|
|
oam_tile_size_buffer[j + 8] = a;
|
|
}
|
|
|
|
uint8 DrawLargePlatform_Next(uint8 j) {
|
|
xpos16 += 8;
|
|
return j + 4;
|
|
}
|
|
|
|
uint8 DrawOneSpriteRow_Sub(uint8 j) {
|
|
OamEnt *oam; // rdx
|
|
int8 v2; // al
|
|
uint8 v3; // al
|
|
OamEnt *v4; // rbp
|
|
uint8 v5; // al
|
|
uint8 v6; // al
|
|
|
|
oam = get_OamEnt(oam_buf, j);
|
|
if ((R3_ & 2) != 0) {
|
|
oam[65].charnum = R0_;
|
|
oam[64].charnum = R1_;
|
|
v2 = 64;
|
|
} else {
|
|
oam[64].charnum = R0_;
|
|
oam[65].charnum = R1_;
|
|
v2 = 0;
|
|
}
|
|
v3 = R4_ | v2;
|
|
v4 = get_OamEnt(oam_buf, j);
|
|
v4[64].flags = v3;
|
|
v4[65].flags = v3;
|
|
v5 = R2_;
|
|
v4[64].ypos = R2_;
|
|
v4[65].ypos = v5;
|
|
v6 = R5_;
|
|
v4[64].xpos = R5_;
|
|
v4[65].xpos = v6 + 8;
|
|
R2_ += 8;
|
|
return j + 8;
|
|
}
|