2668 lines
79 KiB
C
2668 lines
79 KiB
C
// System routines
|
|
|
|
#include "sm_rtl.h"
|
|
#include "ida_types.h"
|
|
#include "variables.h"
|
|
#include "funcs.h"
|
|
#include "enemy_types.h"
|
|
#include "spc_player.h"
|
|
|
|
|
|
#define kMusicPointers (*(LongPtr*)RomFixedPtr(0x8fe7e1))
|
|
#define kTimerDigitsSpritemapPtr ((uint16*)RomFixedPtr(0x809fd4))
|
|
#define kLoadStationLists ((uint16*)RomFixedPtr(0x80c4b5))
|
|
#define off_80CD46 ((uint16*)RomFixedPtr(0x80cd46))
|
|
|
|
|
|
|
|
|
|
void APU_UploadBank(uint32 addr) { // 0x808028
|
|
if (!g_use_my_apu_code)
|
|
return;
|
|
RtlApuUpload(RomPtr(addr));
|
|
}
|
|
|
|
uint16 NextRandom(void) { // 0x808111
|
|
uint16 RegWord = LOBYTE(random_number) * 5;
|
|
uint8 Reg = HIBYTE(random_number) * 5;
|
|
|
|
int carry = HIBYTE(RegWord) + Reg + 1;
|
|
HIBYTE(RegWord) = carry;
|
|
uint16 result = (carry >> 8) + RegWord + 17;
|
|
random_number = result;
|
|
return result;
|
|
}
|
|
|
|
void ReleaseButtonsFilter(uint16 v0) { // 0x808146
|
|
timed_held_input_timer_reset = v0;
|
|
bool v1 = ((uint16)~joypad1_newkeys & joypad1_lastkeys) == joypad_released_keys;
|
|
joypad_released_keys = ~joypad1_newkeys & joypad1_lastkeys;
|
|
if (!v1) {
|
|
timed_held_input_timer = timed_held_input_timer_reset;
|
|
timed_held_input = 0;
|
|
goto LABEL_6;
|
|
}
|
|
if ((--timed_held_input_timer & 0x8000) == 0) {
|
|
timed_held_input = 0;
|
|
goto LABEL_6;
|
|
}
|
|
timed_held_input_timer = 0;
|
|
previous_timed_held_input = timed_held_input;
|
|
timed_held_input = ~joypad1_newkeys & joypad1_lastkeys;
|
|
LABEL_6:
|
|
newly_held_down_timed_held_input = timed_held_input & (previous_timed_held_input ^ timed_held_input);
|
|
}
|
|
|
|
uint16 PrepareBitAccess(uint16 a) { // 0x80818E
|
|
bitmask = 1 << (a & 7);
|
|
return a >> 3;
|
|
}
|
|
|
|
void SetBossBitForCurArea(uint16 a) { // 0x8081A6
|
|
boss_bits_for_area[area_index] |= a;
|
|
}
|
|
|
|
void ClearBossBitForCurArea(uint16 a) { // 0x8081C0
|
|
boss_bits_for_area[area_index] &= ~a;
|
|
}
|
|
|
|
uint8 CheckBossBitForCurArea(uint16 a) { // 0x8081DC
|
|
return (a & boss_bits_for_area[area_index]) != 0;
|
|
}
|
|
|
|
void SetEventHappened(uint16 a) { // 0x8081FA
|
|
uint16 v1 = PrepareBitAccess(a);
|
|
events_that_happened[v1] |= bitmask;
|
|
}
|
|
|
|
void ClearEventHappened(uint16 v0) { // 0x808212
|
|
uint16 v1 = PrepareBitAccess(v0);
|
|
events_that_happened[v1] &= ~bitmask;
|
|
}
|
|
|
|
uint16 CheckEventHappened(uint16 a) { // 0x808233
|
|
uint16 idx = PrepareBitAccess(a);
|
|
return (bitmask & events_that_happened[idx]) != 0;
|
|
}
|
|
|
|
void CopySuperMetroidString(void) { // 0x80824F
|
|
memcpy(&g_sram[0x1fe0], "supermetroid", 12);
|
|
RtlWriteSram();
|
|
}
|
|
|
|
void VerifySRAM(void) { // 0x808261
|
|
num_demo_sets = 3;
|
|
if (LoadFromSram(0) && LoadFromSram(1) && LoadFromSram(2)) {
|
|
memcpy(&g_sram[0x1fe0], "madadameyohn", 12);
|
|
RtlWriteSram();
|
|
} else {
|
|
if (!memcmp(&g_sram[0x1fe0], "supermetroid", 12))
|
|
num_demo_sets = 4;
|
|
}
|
|
}
|
|
|
|
uint32 Multiply16x16(uint16 a, uint16 j) { // 0x8082D6
|
|
uint32 result = (uint32)a * (uint32)j;
|
|
return result;
|
|
}
|
|
|
|
CoroutineRet WaitForNMI_Async(void) { // 0x808338
|
|
// Return 0 from this routine as soon as the coroutine has finished
|
|
if (coroutine_completion_flags) {
|
|
coroutine_completion_flags = 0;
|
|
return 0;
|
|
}
|
|
waiting_for_nmi = 1;
|
|
coroutine_completion_flags = 1;
|
|
return 1;
|
|
}
|
|
|
|
CoroutineRet WaitForNMI_NoUpdate_Async(void) {
|
|
// Return 0 from this routine as soon as the coroutine has finished
|
|
if (coroutine_completion_flags) {
|
|
coroutine_completion_flags = 0;
|
|
return 0;
|
|
}
|
|
coroutine_completion_flags = 1;
|
|
return 1;
|
|
}
|
|
|
|
void EnableNMI(void) { // 0x80834B
|
|
uint8 v0 = reg_NMITIMEN | 0x80;
|
|
WriteReg(NMITIMEN, reg_NMITIMEN | 0x80);
|
|
reg_NMITIMEN = v0;
|
|
}
|
|
|
|
void DisableNMI(void) { // 0x80835D
|
|
uint8 v0 = reg_NMITIMEN & 0x7F;
|
|
WriteReg(NMITIMEN, reg_NMITIMEN & 0x7F);
|
|
reg_NMITIMEN = v0;
|
|
}
|
|
|
|
void ScreenOff(void) {
|
|
reg_INIDISP |= 0x80;
|
|
}
|
|
|
|
void ScreenOn(void) {
|
|
reg_INIDISP &= ~0x80;
|
|
}
|
|
|
|
void memset7E(uint16 *k, uint16 a, uint16 j) { // 0x8083F6
|
|
do {
|
|
*k++ = a;
|
|
} while (j -= 2);
|
|
}
|
|
|
|
CoroutineRet Vector_RESET_Async(void) { // 0x80841C
|
|
COROUTINE_BEGIN(coroutine_state_0, 1)
|
|
WriteReg(MEMSEL, 1);
|
|
reg_MEMSEL = 1;
|
|
// Removed code to wait 4 frames
|
|
uint16 bak = bug_fix_counter;
|
|
memset(g_ram, 0, 8192);
|
|
bug_fix_counter = bak;
|
|
COROUTINE_AWAIT(2, InitializeIoDisplayLogo_Async());
|
|
COROUTINE_MANUAL_POS(3); // Soft reset position
|
|
APU_UploadBank(0xCF8000);
|
|
WriteReg(INIDISP, 0x8F);
|
|
bak = bug_fix_counter;
|
|
memset(g_ram, 0, 0x10000);
|
|
bug_fix_counter = bak;
|
|
WriteReg(NMITIMEN, 0);
|
|
reg_NMITIMEN = 0;
|
|
reg_INIDISP = 0x8f;
|
|
InitializeCpuIoRegs();
|
|
InitializePpuIoRegs();
|
|
WriteLotsOf0x1c2f();
|
|
sfx_readpos[0] = 0;
|
|
sfx_readpos[1] = 0;
|
|
sfx_readpos[2] = 0;
|
|
sfx_writepos[0] = 0;
|
|
sfx_writepos[1] = 0;
|
|
sfx_writepos[2] = 0;
|
|
sfx_state[0] = 0;
|
|
sfx_state[1] = 0;
|
|
sfx_state[2] = 0;
|
|
sfx_cur[0] = 0;
|
|
sfx_cur[1] = 0;
|
|
sfx_cur[2] = 0;
|
|
sfx_clear_delay[0] = 0;
|
|
sfx_clear_delay[1] = 0;
|
|
sfx_clear_delay[2] = 0;
|
|
sfx1_queue[0] = 0;
|
|
sfx2_queue[0] = 0;
|
|
sfx3_queue[0] = 0;
|
|
oam_next_ptr = 0;
|
|
reg_OAMaddr_UNUSED = 0;
|
|
ClearOamExt();
|
|
ClearUnusedOam();
|
|
nmi_copy_samus_halves = 0;
|
|
nmi_copy_samus_top_half_src = 0;
|
|
nmi_copy_samus_bottom_half_src = 0;
|
|
EnableNMI();
|
|
RtlApuWrite(APUI00, 0);
|
|
RtlApuWrite(APUI02, 0);
|
|
|
|
// Removed code to wait 4 frames
|
|
random_number = 97;
|
|
music_timer = 0;
|
|
music_queue_delay[0] = 0;
|
|
music_queue_delay[1] = 0;
|
|
music_queue_delay[2] = 0;
|
|
music_queue_delay[3] = 0;
|
|
music_queue_delay[4] = 0;
|
|
music_queue_delay[5] = 0;
|
|
music_queue_delay[6] = 0;
|
|
music_queue_delay[7] = 0;
|
|
enable_debug = 0;
|
|
VerifySRAM();
|
|
debug_disable_sounds = 0;
|
|
sound_handler_downtime = 0;
|
|
COROUTINE_END(2);
|
|
}
|
|
|
|
void InvalidInterrupt_Crash(void) { // 0x808573
|
|
printf("InvalidInterrupt_Crash\n");
|
|
Unreachable();
|
|
for (;;);
|
|
}
|
|
|
|
void LoadMirrorOfExploredMapTiles(void) { // 0x80858C
|
|
uint16 v1 = swap16(area_index);
|
|
uint16 v2 = 0;
|
|
do {
|
|
*(uint16 *)&map_tiles_explored[v2] = explored_map_tiles_saved[v1 >> 1];
|
|
v1 += 2;
|
|
v2 += 2;
|
|
} while ((int16)(v2 - 256) < 0);
|
|
has_area_map = map_station_byte_array[area_index];
|
|
}
|
|
|
|
void SaveExploredMapTilesToSaved(void) { // 0x8085C6
|
|
uint16 v1 = swap16(area_index);
|
|
uint16 v2 = 0;
|
|
do {
|
|
explored_map_tiles_saved[v1 >> 1] = *(uint16 *)&map_tiles_explored[v2];
|
|
v1 += 2;
|
|
v2 += 2;
|
|
} while ((int16)(v2 - 256) < 0);
|
|
if (has_area_map)
|
|
*(uint16 *)&map_station_byte_array[area_index] |= 0xFF;
|
|
}
|
|
|
|
void InitializeCpuIoRegs(void) { // 0x80875D
|
|
WriteReg(NMITIMEN, 1);
|
|
reg_NMITIMEN = 1;
|
|
WriteReg(WRIO, 0);
|
|
WriteReg(WRMPYA, 0);
|
|
WriteReg(WRMPYB, 0);
|
|
WriteReg(WRDIVL, 0);
|
|
WriteReg(WRDIVH, 0);
|
|
WriteReg(WRDIVB, 0);
|
|
WriteReg(HTIMEL, 0);
|
|
WriteReg(HTIMEH, 0);
|
|
WriteReg(VTIMEL, 0);
|
|
WriteReg(VTIMEH, 0);
|
|
WriteReg(MDMAEN, 0);
|
|
WriteReg(HDMAEN, 0);
|
|
reg_HDMAEN = 0;
|
|
WriteReg(MEMSEL, 1);
|
|
reg_MEMSEL = 1;
|
|
}
|
|
|
|
void InitializePpuIoRegs(void) { // 0x808792
|
|
WriteReg(INIDISP, 0x8F);
|
|
reg_INIDISP = 0x8f;
|
|
WriteReg(OBSEL, 3);
|
|
reg_OBSEL = 3;
|
|
WriteReg(OAMADDL, 0);
|
|
LOBYTE(reg_OAMaddr_UNUSED) = 0;
|
|
WriteReg(OAMADDH, 0x80);
|
|
HIBYTE(reg_OAMaddr_UNUSED) = 0x80;
|
|
WriteReg(OAMDATA, 0);
|
|
WriteReg(OAMDATA, 0);
|
|
WriteReg(BGMODE, 9);
|
|
reg_BGMODE = 9;
|
|
WriteReg(MOSAIC, 0);
|
|
reg_MOSAIC = 0;
|
|
WriteReg(BG1SC, 0x40);
|
|
reg_BG1SC = 64;
|
|
WriteReg(BG2SC, 0x44);
|
|
reg_BG2SC = 68;
|
|
WriteReg(BG3SC, 0x48);
|
|
reg_BG3SC = 72;
|
|
WriteReg(BG4SC, 0);
|
|
reg_BG4SC = 0;
|
|
WriteReg(BG12NBA, 0);
|
|
reg_BG12NBA = 0;
|
|
WriteReg(BG34NBA, 5);
|
|
reg_BG34NBA = 5;
|
|
WriteReg(BG1HOFS, 0);
|
|
WriteReg(BG1HOFS, 0);
|
|
WriteReg(BG1VOFS, 0);
|
|
WriteReg(BG1VOFS, 0);
|
|
WriteReg(BG2HOFS, 0);
|
|
WriteReg(BG2HOFS, 0);
|
|
WriteReg(BG2VOFS, 0);
|
|
WriteReg(BG2VOFS, 0);
|
|
WriteReg(BG3HOFS, 0);
|
|
WriteReg(BG3HOFS, 0);
|
|
WriteReg(BG3VOFS, 0);
|
|
WriteReg(BG3VOFS, 0);
|
|
WriteReg(BG4HOFS, 0);
|
|
WriteReg(BG4HOFS, 0);
|
|
WriteReg(BG4VOFS, 0);
|
|
WriteReg(BG4VOFS, 0);
|
|
WriteReg(VMAIN, 0);
|
|
WriteReg(M7SEL, 0);
|
|
reg_M7SEL = 0;
|
|
WriteReg(M7A, 0);
|
|
WriteReg(M7B, 0);
|
|
WriteReg(M7C, 0);
|
|
WriteReg(M7D, 0);
|
|
WriteReg(M7X, 0);
|
|
WriteReg(M7Y, 0);
|
|
WriteReg(W12SEL, 0);
|
|
reg_W12SEL = 0;
|
|
WriteReg(W34SEL, 0);
|
|
reg_W34SEL = 0;
|
|
WriteReg(WOBJSEL, 0);
|
|
reg_WOBJSEL = 0;
|
|
WriteReg(WH0, 0);
|
|
reg_WH0 = 0;
|
|
WriteReg(WH1, 0xF8);
|
|
reg_WH1 = -8;
|
|
WriteReg(WH2, 0);
|
|
reg_WH2 = 0;
|
|
WriteReg(WH3, 0);
|
|
reg_WH3 = 0;
|
|
WriteReg(WBGLOG, 0);
|
|
reg_WBGLOG = 0;
|
|
WriteReg(WOBJLOG, 0);
|
|
reg_WOBJLOG = 0;
|
|
WriteReg(TM, 0x11);
|
|
reg_TM = 17;
|
|
WriteReg(TMW, 0x11);
|
|
reg_TMW = 17;
|
|
WriteReg(TS, 2);
|
|
reg_TS = 2;
|
|
WriteReg(TSW, 2);
|
|
reg_TSW = 2;
|
|
WriteReg(CGWSEL, 2);
|
|
next_gameplay_CGWSEL = 2;
|
|
WriteReg(CGADSUB, 0xA1);
|
|
next_gameplay_CGADSUB = -95;
|
|
WriteReg(COLDATA, 0xE0);
|
|
WriteReg(COLDATA, 0xE0);
|
|
WriteReg(COLDATA, 0x80);
|
|
reg_COLDATA[0] = 0x80;
|
|
WriteReg(COLDATA, 0x40);
|
|
reg_COLDATA[1] = 64;
|
|
WriteReg(COLDATA, 0x20);
|
|
reg_COLDATA[2] = 32;
|
|
WriteReg(SETINI, 0);
|
|
reg_SETINI = 0;
|
|
}
|
|
|
|
void WriteLotsOf0x1c2f(void) { // 0x8088D1
|
|
sub_8088EB(0x1C2F);
|
|
sub_8088FE(0x1C2F);
|
|
sub_808911(0x1C2F);
|
|
}
|
|
|
|
void sub_8088EB(uint16 a) { // 0x8088EB
|
|
memset7E((uint16*)(g_ram + 0x3000), a, 0x800);
|
|
}
|
|
|
|
void sub_8088FE(uint16 a) { // 0x8088FE
|
|
memset7E((uint16 *)(g_ram + 0x4000), a, 0x800);
|
|
}
|
|
|
|
void sub_808911(uint16 a) { // 0x808911
|
|
memset7E((uint16 *)(g_ram + 0x6000), a, 0x800);
|
|
}
|
|
|
|
void HandleFadeOut(void) { // 0x808924
|
|
if ((int16)(screen_fade_counter - 1) < 0) {
|
|
screen_fade_counter = screen_fade_delay;
|
|
if ((reg_INIDISP & 0xF) != 0) {
|
|
if ((reg_INIDISP & 0xF) == 1)
|
|
reg_INIDISP = 0x80;
|
|
else
|
|
reg_INIDISP = (reg_INIDISP & 0xF) - 1;
|
|
}
|
|
} else {
|
|
--screen_fade_counter;
|
|
}
|
|
}
|
|
|
|
void HandleFadeIn(void) { // 0x80894D
|
|
if ((int16)(screen_fade_counter - 1) < 0) {
|
|
screen_fade_counter = screen_fade_delay;
|
|
if (((reg_INIDISP + 1) & 0xF) != 0)
|
|
reg_INIDISP = (reg_INIDISP + 1) & 0xF;
|
|
} else {
|
|
--screen_fade_counter;
|
|
}
|
|
}
|
|
|
|
void ClearUnusedOam(void) {
|
|
for (int i = oam_next_ptr >> 2; i < 0x80; i++)
|
|
oam_ent[i].ycoord = 0xf0;
|
|
oam_next_ptr = 0;
|
|
}
|
|
|
|
void ClearOamExt(void) { // 0x808B1A
|
|
memset(oam_ext, 0, sizeof(oam_ext[0]) * 16);
|
|
}
|
|
|
|
void QueueMode7Transfers(uint8 db, uint16 k) { // 0x808B4F
|
|
const uint8 *p = RomPtrWithBank(db, k);
|
|
uint8 *dst = (uint8 *)mode7_write_queue + mode7_vram_write_queue_tail;
|
|
for (;;) {
|
|
int f = GET_BYTE(p);
|
|
if (f & 0x80) {
|
|
dst[9] = 0;
|
|
memcpy(dst, p, 9);
|
|
p += 9, dst += 9;
|
|
} else if (f & 0x40) {
|
|
dst[7] = 0;
|
|
memcpy(dst, p, 7);
|
|
p += 7, dst += 7;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
mode7_vram_write_queue_tail = dst - (uint8 *)mode7_write_queue;
|
|
}
|
|
|
|
void NMI_ProcessMode7Queue(void) { // 0x808BBA
|
|
if (mode7_vram_write_queue_tail) {
|
|
NMI_ProcessMode7QueueInner(&g_ram[0x2D0]);
|
|
*(uint16 *)&mode7_write_queue[0].field_0 = 0;
|
|
mode7_vram_write_queue_tail = 0;
|
|
}
|
|
}
|
|
|
|
void NMI_ProcessMode7QueueInner(const uint8 *p) { // 0x808BD3
|
|
while (1) {
|
|
uint8 v2;
|
|
while (1) {
|
|
v2 = *p;
|
|
if ((v2 & 0x80) == 0)
|
|
break;
|
|
WriteReg(DMAP1, v2 & 0x1F);
|
|
Mode7CgvmWriteQueue *v5 = (Mode7CgvmWriteQueue *)p;
|
|
WriteRegWord(A1T1L, v5->src_addr.addr);
|
|
WriteReg(A1B1, v5->src_addr.bank);
|
|
WriteRegWord(DAS1L, v5->count);
|
|
if (v2 & 0x40)
|
|
WriteReg(BBAD1, 0x19);
|
|
else
|
|
WriteReg(BBAD1, 0x18);
|
|
WriteRegWord(VMADDL, v5->vram_addr);
|
|
WriteReg(VMAIN, v5->vmain);
|
|
WriteReg(MDMAEN, 2);
|
|
p += sizeof(Mode7CgvmWriteQueue);
|
|
}
|
|
if (!(v2 & 0x40))
|
|
break;
|
|
WriteReg(DMAP1, v2 & 0x1F);
|
|
WriteRegWord(A1T1L, *(uint16 *)(p + 1));
|
|
WriteReg(A1B1, p[3]);
|
|
WriteRegWord(DAS1L, *((uint16 *)p + 2));
|
|
WriteReg(BBAD1, 0x22);
|
|
WriteReg(CGADD, p[6]);
|
|
WriteReg(MDMAEN, 2);
|
|
p += 7;
|
|
}
|
|
}
|
|
|
|
void NMI_ProcessVramWriteQueue(void) { // 0x808C83
|
|
if (vram_write_queue_tail) {
|
|
gVramWriteEntry(vram_write_queue_tail)->size = 0;
|
|
WriteRegWord(DMAP1, 0x1801);
|
|
for (int i = 0; ; i += 7) {
|
|
VramWriteEntry *e = gVramWriteEntry(i);
|
|
if (!e->size)
|
|
break;
|
|
WriteRegWord(DAS1L, e->size);
|
|
WriteRegWord(A1T1L, e->src.addr);
|
|
WriteReg(A1B1, e->src.bank);
|
|
WriteRegWord(VMAIN, sign16(e->vram_dst) ? 0x81 : 0x80);
|
|
WriteRegWord(VMADDL, e->vram_dst);
|
|
WriteReg(MDMAEN, 2);
|
|
}
|
|
}
|
|
vram_write_queue_tail = 0;
|
|
Nmi_ProcessHorizScrollingDma();
|
|
Nmi_ProcessVertScrollingDma();
|
|
}
|
|
|
|
void Nmi_ProcessHorizScrollingDma(void) { // 0x808CD8
|
|
WriteReg(VMAIN, 0x81);
|
|
if ((uint8)bg1_update_col_enable) {
|
|
LOBYTE(bg1_update_col_enable) = 0;
|
|
uint16 v0 = bg1_update_col_unwrapped_dst;
|
|
WriteRegWord(VMADDL, bg1_update_col_unwrapped_dst);
|
|
WriteRegWord(DMAP1, 0x1801);
|
|
WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg1_column_update_tilemap_left_halves));
|
|
WriteReg(A1B1, 0x7E);
|
|
uint16 v1 = bg1_update_col_unwrapped_size;
|
|
WriteRegWord(DAS1L, bg1_update_col_unwrapped_size);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, v0 + 1);
|
|
WriteRegWord(DAS1L, v1);
|
|
WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg1_column_update_tilemap_right_halves));
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(A1T1L, bg1_update_col_wrapped_left_src);
|
|
uint16 v2 = bg1_update_col_wrapped_size;
|
|
if (bg1_update_col_wrapped_size) {
|
|
WriteRegWord(DAS1L, bg1_update_col_wrapped_size);
|
|
uint16 v3 = bg1_update_col_wrapped_dst;
|
|
WriteRegWord(VMADDL, bg1_update_col_wrapped_dst);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, v3 + 1);
|
|
WriteRegWord(DAS1L, v2);
|
|
WriteRegWord(A1T1L, bg1_update_col_wrapped_right_src);
|
|
WriteReg(MDMAEN, 2);
|
|
}
|
|
}
|
|
if ((uint8)bg2_update_col_enable) {
|
|
LOBYTE(bg2_update_col_enable) = 0;
|
|
uint16 v4 = bg2_update_col_unwrapped_dst;
|
|
WriteRegWord(VMADDL, bg2_update_col_unwrapped_dst);
|
|
WriteRegWord(DMAP1, 0x1801);
|
|
WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg2_column_update_tilemap_left_halves));
|
|
WriteReg(A1B1, 0x7E);
|
|
uint16 v5 = bg2_update_col_unwrapped_size;
|
|
WriteRegWord(DAS1L, bg2_update_col_unwrapped_size);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, v4 + 1);
|
|
WriteRegWord(DAS1L, v5);
|
|
WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg2_column_update_tilemap_right_halves));
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(A1T1L, bg2_update_col_wrapped_left_src);
|
|
uint16 v6 = bg2_update_col_wrapped_size;
|
|
if (bg2_update_col_wrapped_size) {
|
|
WriteRegWord(DAS1L, bg2_update_col_wrapped_size);
|
|
uint16 v7 = bg2_update_col_wrapped_dst;
|
|
WriteRegWord(VMADDL, bg2_update_col_wrapped_dst);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, v7 + 1);
|
|
WriteRegWord(DAS1L, v6);
|
|
WriteRegWord(A1T1L, bg2_update_col_wrapped_right_src);
|
|
WriteReg(MDMAEN, 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Nmi_ProcessVertScrollingDma(void) { // 0x808DAC
|
|
WriteReg(VMAIN, 0x80);
|
|
if ((uint8)bg1_update_row_enable) {
|
|
LOBYTE(bg1_update_row_enable) = 0;
|
|
uint16 v0 = bg1_update_row_unwrapped_dst;
|
|
WriteRegWord(VMADDL, bg1_update_row_unwrapped_dst);
|
|
WriteRegWord(DMAP1, 0x1801);
|
|
WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg1_column_update_tilemap_top_halves));
|
|
WriteReg(A1B1, 0x7E);
|
|
uint16 v1 = bg1_update_row_unwrapped_size;
|
|
WriteRegWord(DAS1L, bg1_update_row_unwrapped_size);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, v0 | 0x20);
|
|
WriteRegWord(DAS1L, v1);
|
|
WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg1_column_update_tilemap_bottom_halves));
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(A1T1L, bg1_update_row_wrapped_top_src);
|
|
uint16 v2 = bg1_update_row_wrapped_size;
|
|
if (bg1_update_row_wrapped_size) {
|
|
WriteRegWord(DAS1L, bg1_update_row_wrapped_size);
|
|
uint16 v3 = bg1_update_row_wrapped_dst;
|
|
WriteRegWord(VMADDL, bg1_update_row_wrapped_dst);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, v3 | 0x20);
|
|
WriteRegWord(DAS1L, v2);
|
|
WriteRegWord(A1T1L, bg1_update_row_wrapped_bottom_src);
|
|
WriteReg(MDMAEN, 2);
|
|
}
|
|
}
|
|
if ((uint8)bg2_update_row_enable) {
|
|
LOBYTE(bg2_update_row_enable) = 0;
|
|
uint16 v4 = bg2_update_row_unwrapped_dst;
|
|
WriteRegWord(VMADDL, bg2_update_row_unwrapped_dst);
|
|
WriteRegWord(DMAP1, 0x1801);
|
|
WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg2_column_update_tilemap_top_halves));
|
|
WriteReg(A1B1, 0x7E);
|
|
uint16 v5 = bg2_update_row_unwrapped_size;
|
|
WriteRegWord(DAS1L, bg2_update_row_unwrapped_size);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, v4 | 0x20);
|
|
WriteRegWord(DAS1L, v5);
|
|
WriteRegWord(A1T1L, ADDR16_OF_RAM(*bg2_column_update_tilemap_bottom_halves));
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(A1T1L, bg2_update_row_wrapped_top_src);
|
|
uint16 v6 = bg2_update_row_wrapped_size;
|
|
if (bg2_update_row_wrapped_size) {
|
|
WriteRegWord(DAS1L, bg2_update_row_wrapped_size);
|
|
uint16 v7 = bg2_update_row_wrapped_dst;
|
|
WriteRegWord(VMADDL, bg2_update_row_wrapped_dst);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, v7 | 0x20);
|
|
WriteRegWord(DAS1L, v6);
|
|
WriteRegWord(A1T1L, bg2_update_row_wrapped_bottom_src);
|
|
WriteReg(MDMAEN, 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NMI_ProcessVramReadQueue(void) { // 0x808EA2
|
|
if ((uint8)vram_read_queue_tail) {
|
|
*((uint8 *)&vram_read_queue[0].vram_target + (uint8)vram_read_queue_tail) = 0;
|
|
int v0 = 0;
|
|
WriteReg(VMAIN, 0x80);
|
|
while (vram_read_queue[v0].vram_target) {
|
|
WriteRegWord(VMADDL, vram_read_queue[v0].vram_target);
|
|
ReadRegWord(RDVRAML);
|
|
WriteRegWord(DMAP1, vram_read_queue[v0].dma_parameters);
|
|
WriteRegWord(A1T1L, vram_read_queue[v0].src.addr);
|
|
WriteRegWord(A1T1H, *(VoidP *)((uint8 *)&vram_read_queue[v0].src.addr + 1));
|
|
WriteRegWord(DAS1L, vram_read_queue[v0].size);
|
|
WriteRegWord(DAS10, 0);
|
|
WriteRegWord(A2A1H, 0);
|
|
WriteReg(MDMAEN, 2);
|
|
++v0;
|
|
}
|
|
LOBYTE(vram_read_queue_tail) = 0;
|
|
}
|
|
}
|
|
|
|
uint8 HasQueuedMusic(void) { // 0x808EF4
|
|
int v0 = 14;
|
|
while (!music_queue_delay[v0 >> 1]) {
|
|
v0 -= 2;
|
|
if (v0 < 0)
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void HandleMusicQueue(void) { // 0x808F0C
|
|
bool v0 = music_timer-- == 1;
|
|
if ((music_timer & 0x8000) == 0) {
|
|
if (!v0)
|
|
return;
|
|
if ((music_entry & 0x8000) != 0) {
|
|
music_data_index = (uint8)music_entry;
|
|
cur_music_track = -1;
|
|
APU_UploadBank(Load24((LongPtr *)((uint8 *)&kMusicPointers + (uint8)music_entry)));
|
|
cur_music_track = 0;
|
|
int v5 = music_queue_read_pos;
|
|
music_queue_track[v5 >> 1] = 0;
|
|
music_queue_delay[v5 >> 1] = 0;
|
|
music_queue_read_pos = (v5 + 2) & 0xE;
|
|
sound_handler_downtime = 8;
|
|
return;
|
|
}
|
|
uint8 v1 = music_entry & 0x7F;
|
|
music_track_index = music_entry & 0x7F;
|
|
RtlApuWrite(APUI00, music_entry & 0x7F);
|
|
cur_music_track = v1;
|
|
sound_handler_downtime = 8;
|
|
int v2 = music_queue_read_pos;
|
|
music_queue_track[v2 >> 1] = 0;
|
|
music_queue_delay[v2 >> 1] = 0;
|
|
music_queue_read_pos = (v2 + 2) & 0xE;
|
|
}
|
|
if (music_queue_read_pos == music_queue_write_pos) {
|
|
music_timer = 0;
|
|
} else {
|
|
int v4 = music_queue_read_pos >> 1;
|
|
music_entry = music_queue_track[v4];
|
|
music_timer = music_queue_delay[v4];
|
|
}
|
|
}
|
|
|
|
void QueueMusic_Delayed8(uint16 a) { // 0x808FC1
|
|
int8 v1;
|
|
|
|
if (game_state < kGameState_40_TransitionToDemo && ((music_queue_write_pos + 2) & 0xE) != music_queue_read_pos) {
|
|
v1 = music_queue_write_pos;
|
|
int v2 = music_queue_write_pos >> 1;
|
|
music_queue_track[v2] = a;
|
|
music_queue_delay[v2] = 8;
|
|
music_queue_write_pos = (v1 + 2) & 0xE;
|
|
}
|
|
}
|
|
|
|
void QueueMusic_DelayedY(uint16 a, uint16 j) { // 0x808FF7
|
|
if (game_state < 0x28) {
|
|
int v2 = music_queue_write_pos;
|
|
music_queue_track[v2 >> 1] = a;
|
|
int v4 = j;
|
|
if (j < 8)
|
|
v4 = 8;
|
|
music_queue_delay[v2 >> 1] = v4;
|
|
music_queue_write_pos = (v2 + 2) & 0xE;
|
|
}
|
|
}
|
|
|
|
void QueueSfx1_Max15(uint16 a) { // 0x809021
|
|
QueueSfx1_Internal(a << 8 | 15);
|
|
}
|
|
|
|
void QueueSfx1_Max9(uint16 a) { // 0x80902B
|
|
QueueSfx1_Internal(a << 8 | 9);
|
|
}
|
|
|
|
void QueueSfx1_Max3(uint16 a) { // 0x809035
|
|
QueueSfx1_Internal(a << 8 | 3);
|
|
}
|
|
|
|
void QueueSfx1_Max1(uint16 a) { // 0x80903F
|
|
QueueSfx1_Internal(a << 8 | 1);
|
|
}
|
|
|
|
void QueueSfx1_Max6(uint16 a) { // 0x809049
|
|
QueueSfx1_Internal(a << 8 | 6);
|
|
}
|
|
|
|
void QueueSfx1_Internal(uint16 a) { // 0x809051
|
|
sfx_max_queued[0] = a;
|
|
if (((sfx_writepos[0] - sfx_readpos[0]) & 0xF) < (uint8)a) {
|
|
uint8 v2 = GET_HIBYTE(a);
|
|
if (!debug_disable_sounds && game_state < 0x28 && (power_bomb_explosion_status & 0x8000) == 0) {
|
|
uint8 v1 = sfx_writepos[0];
|
|
uint8 v3 = sfx_writepos[0] + 1;
|
|
if (v3 >= 0x10)
|
|
v3 = 0;
|
|
if (v3 == sfx_readpos[0]) {
|
|
if (v2 < sfx1_queue[v1])
|
|
sfx1_queue[v1] = v2;
|
|
} else {
|
|
sfx1_queue[sfx_writepos[0]] = v2;
|
|
sfx_writepos[0] = v3;
|
|
sfx1_queue[v3] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void QueueSfx2_Max15(uint16 a) { // 0x8090A3
|
|
QueueSfx2_Internal(a << 8 | 15);
|
|
}
|
|
|
|
void QueueSfx2_Max9(uint16 a) { // 0x8090AD
|
|
QueueSfx2_Internal(a << 8 | 9);
|
|
}
|
|
|
|
void QueueSfx2_Max3(uint16 a) { // 0x8090B7
|
|
QueueSfx2_Internal(a << 8 | 3);
|
|
}
|
|
|
|
void QueueSfx2_Max1(uint16 a) { // 0x8090C1
|
|
QueueSfx2_Internal(a << 8 | 1);
|
|
}
|
|
|
|
void QueueSfx2_Max6(uint16 a) { // 0x8090CB
|
|
QueueSfx2_Internal(a << 8 | 6);
|
|
}
|
|
|
|
void QueueSfx2_Internal(uint16 a) { // 0x8090D3
|
|
sfx_max_queued[1] = a;
|
|
if (((sfx_writepos[1] - sfx_readpos[1]) & 0xF) < (uint8)a) {
|
|
uint8 v2 = GET_HIBYTE(a);
|
|
if (!debug_disable_sounds && game_state < 0x28 && (power_bomb_explosion_status & 0x8000) == 0) {
|
|
uint8 v1 = sfx_writepos[1];
|
|
uint8 v3 = sfx_writepos[1] + 1;
|
|
if (v3 >= 0x10)
|
|
v3 = 0;
|
|
if (v3 == sfx_readpos[1]) {
|
|
if (v2 < sfx2_queue[v1])
|
|
sfx2_queue[v1] = v2;
|
|
} else {
|
|
sfx2_queue[sfx_writepos[1]] = v2;
|
|
sfx_writepos[1] = v3;
|
|
sfx2_queue[v3] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void QueueSfx3_Max15(uint16 a) { // 0x809125
|
|
QueueSfx3_Internal(a << 8 | 15);
|
|
}
|
|
|
|
void QueueSfx3_Max9(uint16 a) { // 0x80912F
|
|
QueueSfx3_Internal(a << 8 | 9);
|
|
}
|
|
|
|
void QueueSfx3_Max3(uint16 a) { // 0x809139
|
|
QueueSfx3_Internal(a << 8 | 3);
|
|
}
|
|
|
|
void QueueSfx3_Max1(uint16 a) { // 0x809143
|
|
QueueSfx3_Internal(a << 8 | 1);
|
|
}
|
|
|
|
void QueueSfx3_Max6(uint16 a) { // 0x80914D
|
|
QueueSfx3_Internal(a << 8 | 6);
|
|
}
|
|
|
|
void QueueSfx3_Internal(uint16 a) { // 0x809155
|
|
sfx_max_queued[2] = a;
|
|
if (((sfx_writepos[2] - sfx_readpos[2]) & 0xF) < (uint8)a) {
|
|
uint8 v2 = GET_HIBYTE(a);
|
|
if (!debug_disable_sounds && game_state < 0x28 && (power_bomb_explosion_status & 0x8000) == 0) {
|
|
uint8 v1 = sfx_writepos[2];
|
|
uint8 v3 = sfx_writepos[2] + 1;
|
|
if (v3 >= 0x10)
|
|
v3 = 0;
|
|
if (v3 == sfx_readpos[2]) {
|
|
if (v2 < sfx3_queue[v1])
|
|
sfx3_queue[v1] = v2;
|
|
} else {
|
|
sfx3_queue[sfx_writepos[2]] = v2;
|
|
sfx_writepos[2] = v3;
|
|
sfx3_queue[v3] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetupDmaTransfer(const void *p) { // 0x8091A9
|
|
const StartDmaCopy *s = (const StartDmaCopy *)p;
|
|
|
|
int v2 = s->chan * 16;
|
|
WriteRegWord((SnesRegs)(v2 + DMAP0), *(uint16 *)&s->dmap);
|
|
WriteRegWord((SnesRegs)(v2 + A1T0L), *(uint16 *)&s->a1.addr);
|
|
WriteReg((SnesRegs)(v2 + A1B0), s->a1.bank);
|
|
WriteRegWord((SnesRegs)(v2 + DAS0L), s->das);
|
|
}
|
|
|
|
void NmiUpdateIoRegisters(void) { // 0x8091EE
|
|
WriteReg(NMITIMEN, reg_NMITIMEN);
|
|
WriteReg(INIDISP, reg_INIDISP);
|
|
WriteReg(OBSEL, reg_OBSEL);
|
|
WriteReg(BGMODE, reg_BGMODE);
|
|
WriteReg(MOSAIC, reg_MOSAIC);
|
|
WriteReg(BG1SC, reg_BG1SC);
|
|
WriteReg(BG2SC, reg_BG2SC);
|
|
WriteReg(BG3SC, reg_BG3SC);
|
|
WriteReg(BG4SC, reg_BG4SC);
|
|
WriteReg(BG12NBA, reg_BG12NBA);
|
|
WriteReg(BG34NBA, reg_BG34NBA);
|
|
WriteReg(M7SEL, reg_M7SEL);
|
|
WriteReg(W12SEL, reg_W12SEL);
|
|
WriteReg(W34SEL, reg_W34SEL);
|
|
WriteReg(WOBJSEL, reg_WOBJSEL);
|
|
WriteReg(WH0, reg_WH0);
|
|
WriteReg(WH1, reg_WH1);
|
|
WriteReg(WH2, reg_WH2);
|
|
WriteReg(WH3, reg_WH3);
|
|
WriteReg(WBGLOG, reg_WBGLOG);
|
|
WriteReg(WOBJLOG, reg_WOBJLOG);
|
|
gameplay_TM = reg_TM;
|
|
WriteReg(TM, reg_TM);
|
|
WriteReg(TMW, reg_TMW);
|
|
WriteReg(TS, reg_TS);
|
|
WriteReg(TSW, reg_TSW);
|
|
WriteReg(CGWSEL, reg_CGWSEL);
|
|
WriteReg(CGADSUB, reg_CGADSUB);
|
|
gameplay_CGWSEL = next_gameplay_CGWSEL;
|
|
gameplay_CGADSUB = next_gameplay_CGADSUB;
|
|
WriteReg(COLDATA, reg_COLDATA[0]);
|
|
WriteReg(COLDATA, reg_COLDATA[1]);
|
|
WriteReg(COLDATA, reg_COLDATA[2]);
|
|
WriteReg(SETINI, reg_SETINI);
|
|
WriteReg(BG1HOFS, reg_BG1HOFS);
|
|
WriteReg(BG1HOFS, HIBYTE(reg_BG1HOFS));
|
|
WriteReg(BG1VOFS, reg_BG1VOFS);
|
|
WriteReg(BG1VOFS, HIBYTE(reg_BG1VOFS));
|
|
WriteReg(BG2HOFS, reg_BG2HOFS);
|
|
WriteReg(BG2HOFS, HIBYTE(reg_BG2HOFS));
|
|
WriteReg(BG2VOFS, reg_BG2VOFS);
|
|
WriteReg(BG2VOFS, HIBYTE(reg_BG2VOFS));
|
|
WriteReg(BG3HOFS, reg_BG3HOFS);
|
|
WriteReg(BG3HOFS, HIBYTE(reg_BG3HOFS));
|
|
WriteReg(BG3VOFS, reg_BG3VOFS);
|
|
WriteReg(BG3VOFS, HIBYTE(reg_BG3VOFS));
|
|
WriteReg(BG4HOFS, reg_BG4HOFS);
|
|
WriteReg(BG4HOFS, HIBYTE(reg_BG4HOFS));
|
|
WriteReg(BG4VOFS, reg_BG4VOFS);
|
|
WriteReg(BG4VOFS, HIBYTE(reg_BG4VOFS));
|
|
HIBYTE(hdma_data_table_in_ceres) = reg_BGMODE_fake;
|
|
if ((reg_BGMODE & 7) == 7 || (reg_BGMODE_fake & 7) == 7) {
|
|
WriteReg(M7A, reg_M7A);
|
|
WriteReg(M7A, HIBYTE(reg_M7A));
|
|
WriteReg(M7B, reg_M7B);
|
|
WriteReg(M7B, HIBYTE(reg_M7B));
|
|
WriteReg(M7C, reg_M7C);
|
|
WriteReg(M7C, HIBYTE(reg_M7C));
|
|
WriteReg(M7D, reg_M7D);
|
|
WriteReg(M7D, HIBYTE(reg_M7D));
|
|
WriteReg(M7X, reg_M7X);
|
|
WriteReg(M7X, HIBYTE(reg_M7X));
|
|
WriteReg(M7Y, reg_M7Y);
|
|
WriteReg(M7Y, HIBYTE(reg_M7Y));
|
|
}
|
|
}
|
|
|
|
void NmiUpdatePalettesAndOam(void) { // 0x80933A
|
|
WriteRegWord(DMAP0, 0x400);
|
|
WriteRegWord(A1T0L, ADDR16_OF_RAM(*oam_ent));
|
|
WriteReg(A1B0, 0);
|
|
WriteRegWord(DAS0L, 0x220);
|
|
WriteRegWord(OAMADDL, 0);
|
|
WriteRegWord(DMAP1, 0x2200);
|
|
WriteRegWord(A1T1L, ADDR16_OF_RAM(*palette_buffer));
|
|
WriteReg(A1B1, 0x7E);
|
|
WriteRegWord(DAS1L, 0x200);
|
|
WriteReg(CGADD, 0);
|
|
WriteReg(MDMAEN, 3);
|
|
}
|
|
|
|
void NmiTransferSamusToVram(void) { // 0x809376
|
|
WriteReg(VMAIN, 0x80);
|
|
if ((uint8)nmi_copy_samus_halves) {
|
|
const uint8 *rp = RomPtr_92(nmi_copy_samus_top_half_src);
|
|
WriteRegWord(VMADDL, 0x6000);
|
|
WriteRegWord(DMAP1, 0x1801);
|
|
uint16 v0 = GET_WORD(rp + 0);
|
|
WriteRegWord(A1T1L, v0);
|
|
WriteRegWord(A1B1, GET_WORD(rp + 2));
|
|
uint16 v2 = GET_WORD(rp + 3);
|
|
WriteRegWord(DAS1L, v2);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, 0x6100);
|
|
WriteRegWord(A1T1L, v0 + v2);
|
|
if (GET_WORD(rp + 5)) {
|
|
WriteRegWord(DAS1L, GET_WORD(rp + 5));
|
|
WriteReg(MDMAEN, 2);
|
|
}
|
|
}
|
|
if (HIBYTE(nmi_copy_samus_halves)) {
|
|
const uint8 *rp = RomPtr_92(nmi_copy_samus_bottom_half_src);
|
|
WriteRegWord(VMADDL, 0x6080);
|
|
WriteRegWord(DMAP1, 0x1801);
|
|
uint16 v4 = GET_WORD(rp + 0);
|
|
WriteRegWord(A1T1L, v4);
|
|
WriteRegWord(A1B1, GET_WORD(rp + 2));
|
|
uint16 v6 = GET_WORD(rp + 3);
|
|
WriteRegWord(DAS1L, v6);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, 0x6180);
|
|
WriteRegWord(A1T1L, v4 + v6);
|
|
if (GET_WORD(rp + 5)) {
|
|
WriteRegWord(DAS1L, GET_WORD(rp + 5));
|
|
WriteReg(MDMAEN, 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NmiProcessAnimtilesVramTransfers(void) { // 0x809416
|
|
if ((animtiles_enable_flag & 0x8000) != 0) {
|
|
for (int i = 10; (i & 0x80) == 0; i -= 2) {
|
|
int v1 = i >> 1;
|
|
if (animtiles_ids[v1]) {
|
|
if (animtiles_src_ptr[v1]) {
|
|
WriteRegWord(A1T0L, animtiles_src_ptr[v1]);
|
|
WriteReg(A1B0, 0x87);
|
|
WriteRegWord(DMAP0, 0x1801);
|
|
WriteRegWord(DAS0L, animtiles_sizes[v1]);
|
|
WriteRegWord(VMADDL, animtiles_vram_ptr[v1]);
|
|
WriteReg(VMAIN, 0x80);
|
|
WriteReg(MDMAEN, 1);
|
|
animtiles_src_ptr[v1] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReadJoypadInputs(void) { // 0x809459
|
|
uint16 RegWord = ReadRegWord(JOY1L);
|
|
joypad1_lastkeys = RegWord;
|
|
joypad1_newkeys = RegWord & (joypad1_prev ^ RegWord);
|
|
joypad1_newkeys2_UNUSED = RegWord & (joypad1_prev ^ RegWord);
|
|
if (RegWord && RegWord == joypad1_prev) {
|
|
if (!--joypad1_keyrepeat_ctr) {
|
|
joypad1_newkeys2_UNUSED = joypad1_lastkeys;
|
|
joypad1_keyrepeat_ctr = joypad_ctr_repeat_next;
|
|
}
|
|
} else {
|
|
joypad1_keyrepeat_ctr = joypad_ctr_repeat_first;
|
|
}
|
|
joypad1_prev = joypad1_lastkeys;
|
|
if (enable_debug) {
|
|
uint16 v1 = ReadRegWord(JOY2L);
|
|
joypad2_last = v1;
|
|
joypad2_new_keys = v1 & (joypad2_prev ^ v1);
|
|
joypad2_newkeys2 = v1 & (joypad2_prev ^ v1);
|
|
if (v1 && v1 == joypad2_prev) {
|
|
if (!--joypad2_keyrepeat_ctr) {
|
|
joypad2_newkeys2 = joypad2_last;
|
|
joypad2_keyrepeat_ctr = joypad_ctr_repeat_next;
|
|
}
|
|
} else {
|
|
joypad2_keyrepeat_ctr = joypad_ctr_repeat_first;
|
|
}
|
|
joypad2_prev = joypad2_last;
|
|
if (is_uploading_apu || joypad1_lastkeys != (kButton_Select | kButton_Start | kButton_L | kButton_R)) {
|
|
if (enable_debug) {
|
|
joypad_dbg_1 = 0;
|
|
joypad_dbg_2 = 0;
|
|
if ((joypad_dbg_flags & 0x4000) == 0) {
|
|
if ((joypad1_lastkeys & (kButton_Select | kButton_L)) == (kButton_Select | kButton_L)) {
|
|
joypad_dbg_1 = joypad1_newkeys;
|
|
joypad1_lastkeys = 0;
|
|
joypad1_newkeys = 0;
|
|
}
|
|
if ((joypad1_lastkeys & (kButton_Select | kButton_R)) == (kButton_Select | kButton_R)) {
|
|
joypad_dbg_2 = joypad1_newkeys;
|
|
joypad1_lastkeys = 0;
|
|
joypad1_newkeys = 0;
|
|
}
|
|
if ((joypad_dbg_2 & 0x80) != 0)
|
|
*(uint16 *)®_NMITIMEN ^= 0x30;
|
|
if ((joypad_dbg_2 & 0x8000) != 0) {
|
|
bool v2 = (~joypad_dbg_flags & 0x8000) != 0;
|
|
joypad_dbg_flags ^= 0x8000;
|
|
if (v2) {
|
|
joypad_dbg_missiles_swap = samus_missiles;
|
|
joypad_dbg_super_missiles_swap = samus_super_missiles;
|
|
joypad_dbg_power_bombs_swap = samus_power_bombs;
|
|
samus_missiles = 0;
|
|
samus_super_missiles = 0;
|
|
samus_power_bombs = 0;
|
|
} else {
|
|
samus_missiles = joypad_dbg_missiles_swap;
|
|
samus_super_missiles = joypad_dbg_super_missiles_swap;
|
|
samus_power_bombs = joypad_dbg_power_bombs_swap;
|
|
}
|
|
}
|
|
if ((joypad_dbg_2 & 0x40) != 0)
|
|
joypad_dbg_flags ^= 0x2000;
|
|
}
|
|
} else {
|
|
joypad_dbg_1 = 0;
|
|
joypad_dbg_2 = 0;
|
|
joypad2_last &= 0x10;
|
|
joypad2_new_keys &= 0x10;
|
|
}
|
|
} else {
|
|
debug_disable_sounds = 0;
|
|
SoftReset();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Vector_NMI(void) { // 0x809583
|
|
if (waiting_for_nmi) {
|
|
NmiUpdatePalettesAndOam();
|
|
NmiTransferSamusToVram();
|
|
NmiProcessAnimtilesVramTransfers();
|
|
NmiUpdateIoRegisters();
|
|
for (int i = 0; i != 6; ++i) {
|
|
if (hdma_object_channels_bitmask[i])
|
|
WriteRegWord((SnesRegs)(LOBYTE(hdma_object_bank_slot[i]) + 17154), hdma_object_table_pointers[i]);
|
|
}
|
|
if (reg_BGMODE == 7 || reg_BGMODE_fake == 7)
|
|
NMI_ProcessMode7Queue();
|
|
NMI_ProcessVramWriteQueue();
|
|
NMI_ProcessVramReadQueue();
|
|
WriteReg(HDMAEN, reg_HDMAEN);
|
|
waiting_for_nmi = 0;
|
|
nmi_frames_missed = 0;
|
|
++nmi_frame_counter_byte;
|
|
++nmi_frame_counter_word;
|
|
} else if (++nmi_frames_missed >= nmi_frames_missed_max) {
|
|
nmi_frames_missed_max = nmi_frames_missed;
|
|
}
|
|
++nmi_frame_counter_including_lag;
|
|
}
|
|
|
|
void Irq_DoorTransitionVramUpdate(void) { // 0x809632
|
|
WriteReg(INIDISP, 0x80);
|
|
WriteRegWord(VMADDL, door_transition_vram_update_dst);
|
|
WriteRegWord(DMAP1, 0x1801);
|
|
WriteRegWord(A1T1L, door_transition_vram_update_src.addr);
|
|
WriteReg(A1B1, door_transition_vram_update_src.bank);
|
|
WriteRegWord(DAS1L, door_transition_vram_update_size);
|
|
WriteReg(VMAIN, 0x80);
|
|
WriteReg(MDMAEN, 2);
|
|
door_transition_vram_update_enabled &= ~0x8000;
|
|
WriteReg(INIDISP, 0xF);
|
|
}
|
|
|
|
void WaitForIrqDoorTransitionVramUpdate(void) {
|
|
door_transition_vram_update_enabled |= 0x8000;
|
|
Irq_DoorTransitionVramUpdate();
|
|
}
|
|
|
|
void IrqHandler_SetResult(uint16 a, uint16 y, uint16 x) {
|
|
// printf("Setting irq next: %d, %d, %d\n", a, x, y);
|
|
cur_irq_handler = a;
|
|
WriteRegWord(VTIMEL, y);
|
|
WriteRegWord(HTIMEL, x);
|
|
}
|
|
|
|
void IrqHandler_0_Nothing(void) { // 0x80966E
|
|
uint16 a = irqhandler_next_handler;
|
|
irqhandler_next_handler = 0;
|
|
IrqHandler_SetResult(a, 0, 0);
|
|
}
|
|
|
|
void IrqHandler_2_DisableIRQ(void) { // 0x809680
|
|
*(uint16 *)®_NMITIMEN &= ~0x30;
|
|
IrqHandler_SetResult(0, 0, 0);
|
|
}
|
|
|
|
void IrqHandler_4_Main_BeginHudDraw(void) { // 0x80968B
|
|
WriteReg(BG3SC, 0x5A);
|
|
WriteReg(CGWSEL, 0);
|
|
WriteReg(CGADSUB, 0);
|
|
WriteReg(TM, 4);
|
|
IrqHandler_SetResult(6, 31, 152);
|
|
}
|
|
|
|
void IrqHandler_6_Main_EndHudDraw(void) { // 0x8096A9
|
|
WriteReg(CGWSEL, gameplay_CGWSEL);
|
|
WriteReg(CGADSUB, gameplay_CGADSUB);
|
|
WriteReg(BG3SC, gameplay_BG3SC);
|
|
WriteReg(TM, gameplay_TM);
|
|
|
|
uint16 a = irqhandler_next_handler;
|
|
irqhandler_next_handler = 0;
|
|
IrqHandler_SetResult(a ? a : 4, 0, 152);
|
|
}
|
|
|
|
void IrqHandler_8_StartOfDoor_BeginHud(void) { // 0x8096D3
|
|
WriteReg(BG3SC, 0x5A);
|
|
WriteReg(TM, 4);
|
|
WriteReg(CGWSEL, 0);
|
|
WriteReg(CGADSUB, 0);
|
|
IrqHandler_SetResult(10, 31, 152);
|
|
}
|
|
|
|
void IrqHandler_10_StartOfDoor_EndHud(void) { // 0x8096F1
|
|
uint8 v0;
|
|
if (((previous_cre_bitset | cre_bitset) & 1) != 0)
|
|
v0 = 16;
|
|
else
|
|
v0 = 17;
|
|
WriteReg(TM, v0);
|
|
uint16 a = irqhandler_next_handler;
|
|
irqhandler_next_handler = 0;
|
|
IrqHandler_SetResult(a ? a : 8, 0, 152);
|
|
}
|
|
|
|
void IrqHandler_12_Draygon_BeginHud(void) { // 0x80971A
|
|
WriteReg(TM, 4);
|
|
WriteReg(CGWSEL, 0);
|
|
WriteReg(CGADSUB, 0);
|
|
IrqHandler_SetResult(14, 31, 152);
|
|
}
|
|
|
|
void IrqHandler_14_Draygon_EndHud(void) { // 0x809733
|
|
WriteReg(BG3SC, gameplay_BG3SC);
|
|
WriteReg(CGWSEL, gameplay_CGWSEL);
|
|
WriteReg(CGADSUB, gameplay_CGADSUB);
|
|
uint16 a = irqhandler_next_handler;
|
|
irqhandler_next_handler = 0;
|
|
IrqHandler_SetResult(a ? a : 12, 0, 152);
|
|
}
|
|
|
|
void IrqHandler_16_VerticalDoor_BeginHud(void) { // 0x809758
|
|
WriteReg(TM, 4);
|
|
WriteReg(CGWSEL, 0);
|
|
WriteReg(CGADSUB, 0);
|
|
IrqHandler_SetResult(18, 31, 152);
|
|
}
|
|
|
|
void IrqHandler_18_VerticalDoor_EndHud(void) { // 0x809771
|
|
uint8 v0;
|
|
if (((previous_cre_bitset | cre_bitset) & 1) != 0)
|
|
v0 = 16;
|
|
else
|
|
v0 = 17;
|
|
WriteReg(TM, v0);
|
|
WriteReg(CGWSEL, 0);
|
|
WriteReg(CGADSUB, 0);
|
|
// if ((door_transition_vram_update_enabled & 0x8000) != 0)
|
|
// Irq_DoorTransitionVramUpdate();
|
|
if ((door_transition_flag & 0x8000) == 0)
|
|
Irq_FollowDoorTransition();
|
|
IrqHandler_SetResult(20, 216, 152);
|
|
}
|
|
|
|
void IrqHandler_20_VerticalDoor_EndDraw(void) { // 0x8097A9
|
|
// *(uint16 *)&waiting_for_nmi = 1;
|
|
uint16 a = irqhandler_next_handler;
|
|
irqhandler_next_handler = 0;
|
|
IrqHandler_SetResult(a ? a : 16, 0, 152);
|
|
}
|
|
|
|
void IrqHandler_22_HorizDoor_BeginHud(void) { // 0x8097C1
|
|
WriteReg(TM, 4);
|
|
WriteReg(CGWSEL, 0);
|
|
WriteReg(CGADSUB, 0);
|
|
IrqHandler_SetResult(24, 31, 152);
|
|
}
|
|
|
|
void IrqHandler_24_HorizDoor_EndHud(void) { // 0x8097DA
|
|
uint8 v0;
|
|
|
|
if (((previous_cre_bitset | cre_bitset) & 1) != 0)
|
|
v0 = 16;
|
|
else
|
|
v0 = 17;
|
|
WriteReg(TM, v0);
|
|
WriteReg(CGWSEL, 0);
|
|
WriteReg(CGADSUB, 0);
|
|
if ((door_transition_flag & 0x8000) == 0)
|
|
Irq_FollowDoorTransition();
|
|
IrqHandler_SetResult(26, 160, 152);
|
|
}
|
|
|
|
void IrqHandler_26_HorizDoor_EndDraw(void) { // 0x80980A
|
|
uint16 a = irqhandler_next_handler;
|
|
irqhandler_next_handler = 0;
|
|
IrqHandler_SetResult(a ? a : 22, 0, 152);
|
|
}
|
|
|
|
void EnableIrqInterrupts(void) { // 0x80982A
|
|
WriteRegWord(VTIMEL, 0);
|
|
WriteRegWord(HTIMEL, 152);
|
|
*(uint16 *)®_NMITIMEN |= 0x30;
|
|
}
|
|
|
|
void EnableIrqInterruptsNow(void) { // 0x809841
|
|
WriteRegWord(VTIMEL, 0);
|
|
WriteRegWord(HTIMEL, 152);
|
|
*(uint16 *)®_NMITIMEN |= 0x30;
|
|
WriteReg(NMITIMEN, reg_NMITIMEN);
|
|
}
|
|
|
|
void DisableIrqInterrupts(void) { // 0x80985F
|
|
*(uint16 *)®_NMITIMEN &= ~0x30;
|
|
}
|
|
|
|
static Func_V *const kIrqHandlers[14] = { // 0x80986A
|
|
IrqHandler_0_Nothing,
|
|
IrqHandler_2_DisableIRQ,
|
|
IrqHandler_4_Main_BeginHudDraw,
|
|
IrqHandler_6_Main_EndHudDraw,
|
|
IrqHandler_8_StartOfDoor_BeginHud,
|
|
IrqHandler_10_StartOfDoor_EndHud,
|
|
IrqHandler_12_Draygon_BeginHud,
|
|
IrqHandler_14_Draygon_EndHud,
|
|
IrqHandler_16_VerticalDoor_BeginHud,
|
|
IrqHandler_18_VerticalDoor_EndHud,
|
|
IrqHandler_20_VerticalDoor_EndDraw,
|
|
IrqHandler_22_HorizDoor_BeginHud,
|
|
IrqHandler_24_HorizDoor_EndHud,
|
|
IrqHandler_26_HorizDoor_EndDraw,
|
|
};
|
|
|
|
void Vector_IRQ(void) {
|
|
kIrqHandlers[cur_irq_handler >> 1]();
|
|
}
|
|
|
|
static const uint16 kHudTilemaps[32] = { // 0x8099CF
|
|
0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f,
|
|
0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1d, 0x2c1c,
|
|
};
|
|
static const uint16 kHudTilemaps_Row1to3[96] = {
|
|
0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f,
|
|
0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c12, 0x2c12, 0x2c23, 0x2c12, 0x2c12, 0x2c1e,
|
|
0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f,
|
|
0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2822, 0x2822, 0x2823, 0x2813, 0x2c14, 0x2c1e,
|
|
0x2c0f, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c32, 0x2c0f, 0x2c09, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f,
|
|
0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c0f, 0x2c12, 0x2c12, 0xa824, 0x2815, 0x2c16, 0x2c1e,
|
|
};
|
|
static const uint16 kHudTilemaps_AutoReserve[12] = { 0x3c33, 0x3c46, 0x3c47, 0x3c48, 0xbc33, 0xbc46, 0x2c33, 0x2c46, 0x2c47, 0x2c48, 0xac33, 0xac46 };
|
|
static const uint16 kHudTilemaps_Missiles[22] = {
|
|
0x344b, 0x3449, 0x744b, 0x344c, 0x344a, 0x744c, 0x3434, 0x7434, 0x3435, 0x7435, 0x3436, 0x7436, 0x3437, 0x7437, 0x3438, 0x7438,
|
|
0x3439, 0x7439, 0x343a, 0x743a, 0x343b, 0x743b,
|
|
};
|
|
|
|
void AddMissilesToHudTilemap(void) {
|
|
if ((hud_tilemap[10] & 0x3FF) == 15) {
|
|
hud_tilemap[10] = kHudTilemaps_Missiles[0];
|
|
hud_tilemap[11] = kHudTilemaps_Missiles[1];
|
|
hud_tilemap[12] = kHudTilemaps_Missiles[2];
|
|
hud_tilemap[42] = kHudTilemaps_Missiles[3];
|
|
hud_tilemap[43] = kHudTilemaps_Missiles[4];
|
|
hud_tilemap[44] = kHudTilemaps_Missiles[5];
|
|
}
|
|
}
|
|
|
|
void AddSuperMissilesToHudTilemap(void) { // 0x809A0E
|
|
AddToTilemapInner(0x1C, (const uint16*)RomPtr_80(addr_kHudTilemaps_Missiles + 12));
|
|
}
|
|
|
|
void AddPowerBombsToHudTilemap(void) { // 0x809A1E
|
|
AddToTilemapInner(0x22, (const uint16 *)RomPtr_80(addr_kHudTilemaps_Missiles + 20));
|
|
}
|
|
|
|
void AddGrappleToHudTilemap(void) { // 0x809A2E
|
|
AddToTilemapInner(0x28, (const uint16 *)RomPtr_80(addr_kHudTilemaps_Missiles + 28));
|
|
}
|
|
|
|
void AddXrayToHudTilemap(void) { // 0x809A3E
|
|
AddToTilemapInner(0x2E, (const uint16 *)RomPtr_80(addr_kHudTilemaps_Missiles + 36));
|
|
}
|
|
|
|
void AddToTilemapInner(uint16 k, const uint16 *j) { // 0x809A4C
|
|
int v2 = k >> 1;
|
|
if ((hud_tilemap[v2] & 0x3FF) == 15) {
|
|
hud_tilemap[v2] = j[0];
|
|
hud_tilemap[v2 + 1] = j[1];
|
|
hud_tilemap[v2 + 32] = j[2];
|
|
hud_tilemap[v2 + 33] = j[3];
|
|
}
|
|
}
|
|
|
|
void InitializeHud(void) { // 0x809A79
|
|
WriteRegWord(VMADDL, addr_unk_605800);
|
|
WriteRegWord(VMAIN, 0x80);
|
|
static const StartDmaCopy unk_809A8F = { 1, 1, 0x18, LONGPTR(0x80988b), 0x0040 };
|
|
SetupDmaTransfer(&unk_809A8F);
|
|
WriteReg(MDMAEN, 2);
|
|
for (int i = 0; i != 192; i += 2)
|
|
hud_tilemap[i >> 1] = kHudTilemaps_Row1to3[i >> 1];
|
|
if ((equipped_items & 0x8000) != 0)
|
|
AddXrayToHudTilemap();
|
|
if ((equipped_items & 0x4000) != 0)
|
|
AddGrappleToHudTilemap();
|
|
if (samus_max_missiles)
|
|
AddMissilesToHudTilemap();
|
|
if (samus_max_super_missiles)
|
|
AddSuperMissilesToHudTilemap();
|
|
if (samus_max_power_bombs)
|
|
AddPowerBombsToHudTilemap();
|
|
samus_prev_health = 0;
|
|
samus_prev_missiles = 0;
|
|
samus_prev_super_missiles = 0;
|
|
samus_prev_power_bombs = 0;
|
|
samus_prev_hud_item_index = 0;
|
|
InitializeMiniMapBroken();
|
|
if (samus_max_missiles)
|
|
DrawThreeHudDigits(addrl_kDigitTilesetsWeapon, samus_missiles, 0x94);
|
|
if (samus_max_super_missiles)
|
|
DrawTwoHudDigits(addrl_kDigitTilesetsWeapon, samus_super_missiles, 0x9C);
|
|
if (samus_max_power_bombs)
|
|
DrawTwoHudDigits(addrl_kDigitTilesetsWeapon, samus_power_bombs, 0xA2);
|
|
ToggleHudItemHighlight(hud_item_index, 0x1000);
|
|
ToggleHudItemHighlight(samus_prev_hud_item_index, 0x1400);
|
|
HandleHudTilemap();
|
|
}
|
|
|
|
static const uint16 kEnergyTankIconTilemapOffsets[14] = { 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 2, 4, 6, 8, 0xa, 0xc, 0xe };
|
|
|
|
void HandleHudTilemap(void) { // 0x809B44
|
|
if (reserve_health_mode == 1) {
|
|
const uint16 *v1 = (const uint16 *)RomPtr_80(addr_kHudTilemaps_AutoReserve);
|
|
if (!samus_reserve_health)
|
|
v1 += 6;
|
|
hud_tilemap[8] = v1[0];
|
|
hud_tilemap[9] = v1[1];
|
|
hud_tilemap[40] = v1[2];
|
|
hud_tilemap[41] = v1[3];
|
|
hud_tilemap[72] = v1[4];
|
|
hud_tilemap[73] = v1[5];
|
|
}
|
|
if (samus_health != samus_prev_health) {
|
|
samus_prev_health = samus_health;
|
|
|
|
uint16 r20 = SnesDivide(samus_health, 100);
|
|
uint16 r18 = SnesModulus(samus_health, 100);
|
|
int v2 = 0;
|
|
int n = SnesDivide(samus_max_health, 100) + 1;
|
|
do {
|
|
if (!--n)
|
|
break;
|
|
uint16 v3 = 13360;
|
|
if (r20) {
|
|
--r20;
|
|
v3 = 10289;
|
|
}
|
|
hud_tilemap[kEnergyTankIconTilemapOffsets[v2 >> 1] >> 1] = v3;
|
|
v2 += 2;
|
|
} while ((int16)(v2 - 28) < 0);
|
|
DrawTwoHudDigits(addrl_kDigitTilesetsHealth, r18, 0x8C);
|
|
}
|
|
if (samus_max_missiles && samus_missiles != samus_prev_missiles) {
|
|
samus_prev_missiles = samus_missiles;
|
|
DrawThreeHudDigits(addrl_kDigitTilesetsWeapon, samus_missiles, 0x94);
|
|
}
|
|
if (samus_max_super_missiles && samus_super_missiles != samus_prev_super_missiles) {
|
|
samus_prev_super_missiles = samus_super_missiles;
|
|
if ((joypad_dbg_flags & 0x1F40) != 0)
|
|
DrawThreeHudDigits(addrl_kDigitTilesetsWeapon, samus_prev_super_missiles, 0x9C);
|
|
else
|
|
DrawTwoHudDigits(addrl_kDigitTilesetsWeapon, samus_prev_super_missiles, 0x9C);
|
|
}
|
|
if (samus_max_power_bombs && samus_power_bombs != samus_prev_power_bombs) {
|
|
samus_prev_power_bombs = samus_power_bombs;
|
|
DrawTwoHudDigits(addrl_kDigitTilesetsWeapon, samus_power_bombs, 0xA2);
|
|
}
|
|
if (hud_item_index != samus_prev_hud_item_index) {
|
|
ToggleHudItemHighlight(hud_item_index, 0x1000);
|
|
ToggleHudItemHighlight(samus_prev_hud_item_index, 0x1400);
|
|
samus_prev_hud_item_index = hud_item_index;
|
|
if (samus_movement_type != 3
|
|
&& samus_movement_type != 20
|
|
&& grapple_beam_function == 0xC4F0
|
|
&& !time_is_frozen_flag) {
|
|
QueueSfx1_Max6(0x39);
|
|
}
|
|
}
|
|
uint16 v4 = 5120;
|
|
if ((nmi_frame_counter_byte & 0x10) != 0)
|
|
v4 = 4096;
|
|
ToggleHudItemHighlight(samus_auto_cancel_hud_item_index, v4);
|
|
uint16 v5 = vram_write_queue_tail;
|
|
gVramWriteEntry(vram_write_queue_tail)->size = 192;
|
|
v5 += 2;
|
|
gVramWriteEntry(v5)->size = ADDR16_OF_RAM(*hud_tilemap);
|
|
v5 += 2;
|
|
gVramWriteEntry(v5++)->size = 126;
|
|
gVramWriteEntry(v5)->size = addr_unk_605820;
|
|
vram_write_queue_tail = v5 + 2;
|
|
}
|
|
|
|
static const uint16 kHudItemTilemapOffsets[5] = { 0x14, 0x1c, 0x22, 0x28, 0x2e };
|
|
|
|
void ToggleHudItemHighlight(uint16 a, uint16 k) { // 0x809CEA
|
|
int16 v2;
|
|
|
|
hud_item_tilemap_palette_bits = k;
|
|
v2 = a - 1;
|
|
if (v2 >= 0) {
|
|
int v3 = kHudItemTilemapOffsets[v2] >> 1;
|
|
if (hud_tilemap[v3] != 11279)
|
|
hud_tilemap[v3] = hud_item_tilemap_palette_bits | hud_tilemap[v3] & 0xE3FF;
|
|
if (hud_tilemap[v3 + 1] != 11279)
|
|
hud_tilemap[v3 + 1] = hud_item_tilemap_palette_bits | hud_tilemap[v3 + 1] & 0xE3FF;
|
|
if (hud_tilemap[v3 + 32] != 11279)
|
|
hud_tilemap[v3 + 32] = hud_item_tilemap_palette_bits | hud_tilemap[v3 + 32] & 0xE3FF;
|
|
if (hud_tilemap[v3 + 33] != 11279)
|
|
hud_tilemap[v3 + 33] = hud_item_tilemap_palette_bits | hud_tilemap[v3 + 33] & 0xE3FF;
|
|
if (!(2 * v2)) {
|
|
if (hud_tilemap[v3 + 2] != 11279)
|
|
hud_tilemap[v3 + 2] = hud_item_tilemap_palette_bits | hud_tilemap[v3 + 2] & 0xE3FF;
|
|
if (hud_tilemap[v3 + 34] != 11279)
|
|
hud_tilemap[v3 + 34] = hud_item_tilemap_palette_bits | hud_tilemap[v3 + 34] & 0xE3FF;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawThreeHudDigits(uint32 addr, uint16 a, uint16 k) { // 0x809D78
|
|
hud_tilemap[k >> 1] = GET_WORD(RomPtr(addr + 2 * (a / 100)));
|
|
DrawTwoHudDigits(addr, a % 100, k + 2);
|
|
}
|
|
|
|
void DrawTwoHudDigits(uint32 addr, uint16 a, uint16 k) { // 0x809D98
|
|
int v3 = k >> 1;
|
|
hud_tilemap[v3] = GET_WORD(RomPtr(addr + 2 * (a / 10)));
|
|
hud_tilemap[v3 + 1] = GET_WORD(RomPtr(addr + 2 * (a % 10)));
|
|
}
|
|
|
|
static Func_U8 *const kTimerProcessFuncs[7] = { // 0x809DE7
|
|
ProcessTimer_Empty,
|
|
ProcessTimer_CeresStart,
|
|
ProcessTimer_MotherBrainStart,
|
|
ProcessTimer_InitialDelay,
|
|
ProcessTimer_MovementDelayed,
|
|
ProcessTimer_MovingIntoPlace,
|
|
ProcessTimer_Decrement,
|
|
};
|
|
|
|
uint8 ProcessTimer(void) {
|
|
return kTimerProcessFuncs[(uint8)timer_status]();
|
|
}
|
|
|
|
uint8 ProcessTimer_CeresStart(void) { // 0x809E09
|
|
ClearTimerRam();
|
|
SetTimerMinutes(0x100);
|
|
timer_status = -32765;
|
|
return 0;
|
|
}
|
|
|
|
uint8 ProcessTimer_Empty(void) { // 0x809E1A
|
|
return 0;
|
|
}
|
|
|
|
uint8 ProcessTimer_MotherBrainStart(void) { // 0x809E1C
|
|
ClearTimerRam();
|
|
SetTimerMinutes(0x300);
|
|
timer_status = -32765;
|
|
return 0;
|
|
}
|
|
|
|
uint8 ProcessTimer_InitialDelay(void) { // 0x809E2F
|
|
LOBYTE(timer_x_pos) = timer_x_pos + 1;
|
|
if ((uint8)timer_x_pos >= 0x10)
|
|
LOBYTE(timer_status) = timer_status + 1;
|
|
return 0;
|
|
}
|
|
|
|
uint8 ProcessTimer_MovementDelayed(void) { // 0x809E41
|
|
LOBYTE(timer_x_pos) = timer_x_pos + 1;
|
|
if ((uint8)timer_x_pos >= 0x60) {
|
|
LOBYTE(timer_x_pos) = 0;
|
|
LOBYTE(timer_status) = timer_status + 1;
|
|
}
|
|
return ProcessTimer_Decrement();
|
|
}
|
|
|
|
uint8 ProcessTimer_MovingIntoPlace(void) { // 0x809E58
|
|
int v0 = 0;
|
|
uint16 v1 = timer_x_pos + 224;
|
|
if ((uint16)(timer_x_pos + 224) >= 0xDC00) {
|
|
v0 = 1;
|
|
v1 = -9216;
|
|
}
|
|
timer_x_pos = v1;
|
|
uint16 v2 = timer_y_pos - 193;
|
|
if ((uint16)(timer_y_pos - 193) < 0x3000) {
|
|
++v0;
|
|
v2 = 12288;
|
|
}
|
|
timer_y_pos = v2;
|
|
if (v0 == 2)
|
|
++timer_status;
|
|
return ProcessTimer_Decrement();
|
|
}
|
|
|
|
void SetTimerMinutes(uint16 a) { // 0x809E8C
|
|
*(uint16 *)&timer_centiseconds = 0;
|
|
*(uint16 *)&timer_seconds = a;
|
|
}
|
|
|
|
void ClearTimerRam(void) { // 0x809E93
|
|
timer_x_pos = 0x8000;
|
|
timer_y_pos = 0x8000;
|
|
*(uint16 *)&timer_centiseconds = 0;
|
|
*(uint16 *)&timer_seconds = 0;
|
|
timer_status = 0;
|
|
}
|
|
|
|
bool DecrementDecimal(uint8 *number, uint8 value) {
|
|
int result = (*number & 0xf) + (~value & 0xf) + 1;
|
|
if (result < 0x10) result = (result - 0x6) & ((result - 0x6 < 0) ? 0xf : 0x1f);
|
|
result = (*number & 0xf0) + (~value & 0xf0) + result;
|
|
if (result < 0x100) result -= 0x60;
|
|
*number = result;
|
|
return result < 0x100;
|
|
}
|
|
|
|
uint8 ProcessTimer_Decrement(void) { // 0x809EA9
|
|
static const uint8 kTimerCentisecondDecrements[128] = {
|
|
1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2,
|
|
1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2,
|
|
1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2,
|
|
1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2,
|
|
1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2,
|
|
1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2,
|
|
1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2,
|
|
1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2,
|
|
};
|
|
if (DecrementDecimal(&timer_centiseconds, kTimerCentisecondDecrements[nmi_frame_counter_word & 0x7f])) {
|
|
if (DecrementDecimal(&timer_seconds, 1)) {
|
|
if (DecrementDecimal(&timer_minutes, 1)) {
|
|
timer_centiseconds = 0;
|
|
timer_seconds = 0;
|
|
timer_minutes = 0;
|
|
} else {
|
|
timer_seconds = 0x59;
|
|
}
|
|
}
|
|
}
|
|
return (timer_centiseconds | timer_seconds | timer_minutes) == 0;
|
|
|
|
}
|
|
|
|
void DrawTimer(void) { // 0x809F6C
|
|
DrawTimerSpritemap(0, addr_word_80A060);
|
|
DrawTwoTimerDigits(*(uint16 *)&timer_minutes, 0xFFE4);
|
|
DrawTwoTimerDigits(*(uint16 *)&timer_seconds, 0xFFFC);
|
|
DrawTwoTimerDigits(*(uint16 *)&timer_centiseconds, 0x14);
|
|
}
|
|
|
|
|
|
void DrawTwoTimerDigits(uint16 a, uint16 k) { // 0x809F95
|
|
DrawTimerSpritemap(k, kTimerDigitsSpritemapPtr[(a & 0xF0) >> 4]);
|
|
DrawTimerSpritemap(k + 8, kTimerDigitsSpritemapPtr[a & 0xF]);
|
|
}
|
|
|
|
void DrawTimerSpritemap(uint16 a, uint16 j) { // 0x809FB3
|
|
DrawSpritemap(0x80, j, a + HIBYTE(timer_x_pos), HIBYTE(timer_y_pos), 2560);
|
|
}
|
|
|
|
CoroutineRet StartGameplay_Async(void) { // 0x80A07B
|
|
COROUTINE_BEGIN(coroutine_state_2, 0)
|
|
WriteRegWord(MDMAEN, 0);
|
|
scrolling_finished_hook = 0;
|
|
music_data_index = 0;
|
|
music_track_index = 0;
|
|
timer_status = 0;
|
|
ResetSoundQueues();
|
|
debug_disable_sounds = -1;
|
|
DisableNMI();
|
|
DisableIrqInterrupts();
|
|
LoadDestinationRoomThings();
|
|
COROUTINE_AWAIT(1, Play20FramesOfMusic_Async());
|
|
ClearAnimtiles();
|
|
WaitUntilEndOfVblankAndClearHdma();
|
|
InitializeSpecialEffectsForNewRoom();
|
|
ClearPLMs();
|
|
ClearEnemyProjectiles();
|
|
ClearPaletteFXObjects();
|
|
UpdateBeamTilesAndPalette();
|
|
LoadColorsForSpritesBeamsAndEnemies();
|
|
LoadEnemies();
|
|
LoadRoomMusic();
|
|
COROUTINE_AWAIT(2, Play20FramesOfMusic_Async());
|
|
UpdateMusicTrackIndex();
|
|
NullFunc();
|
|
ClearBG2Tilemap();
|
|
LoadLevelDataAndOtherThings();
|
|
LoadFXHeader();
|
|
LoadLibraryBackground();
|
|
CalculateLayer2Xpos();
|
|
CalculateLayer2Ypos();
|
|
bg2_x_scroll = layer2_x_pos;
|
|
bg2_y_scroll = layer2_y_pos;
|
|
CalculateBgScrolls();
|
|
DisplayViewablePartOfRoom();
|
|
EnableNMI();
|
|
irqhandler_next_handler = (room_loading_irq_handler == 0) ? 4 : room_loading_irq_handler;
|
|
EnableIrqInterrupts();
|
|
COROUTINE_AWAIT(3, Play20FramesOfMusic_Async());
|
|
SpawnHardcodedPlm((SpawnHardcodedPlmArgs) { 0x08, 0x08, 0xb7eb });
|
|
door_transition_function = FUNC16(DoorTransition_FadeInScreenAndFinish);
|
|
COROUTINE_END(0);
|
|
}
|
|
|
|
CoroutineRet Play20FramesOfMusic_Async(void) { // 0x80A12B
|
|
COROUTINE_BEGIN(coroutine_state_3, 0)
|
|
EnableNMI();
|
|
for(my_counter = 0; my_counter != 20; my_counter++) {
|
|
HandleMusicQueue();
|
|
COROUTINE_AWAIT(1, WaitForNMI_Async());
|
|
}
|
|
DisableNMI();
|
|
COROUTINE_END(0);
|
|
}
|
|
|
|
void ResumeGameplay(void) { // 0x80A149
|
|
WriteRegWord(MDMAEN, 0);
|
|
DisableNMI();
|
|
DisableIrqInterrupts();
|
|
LoadCRETilesTilesetTilesAndPalette();
|
|
LoadLibraryBackground();
|
|
DisplayViewablePartOfRoom();
|
|
LoadRoomPlmGfx();
|
|
EnableNMI();
|
|
EnableIrqInterrupts();
|
|
}
|
|
|
|
void DisplayViewablePartOfRoom(void) { // 0x80A176
|
|
int v1, v2, v3;
|
|
|
|
v1 = (reg_BG1SC - reg_BG2SC) << 8;
|
|
size_of_bg2 = v1 & 0xF800;
|
|
CalculateBgScrollAndLayerPositionBlocks();
|
|
v2 = 0;
|
|
do {
|
|
v3 = v2;
|
|
blocks_to_update_x_block = layer1_x_block;
|
|
blocks_to_update_y_block = layer1_y_block;
|
|
vram_blocks_to_update_x_block = bg1_x_block;
|
|
vram_blocks_to_update_y_block = bg1_y_block;
|
|
UploadLevelDataColumn();
|
|
if (!(layer2_scroll_x & 1)) {
|
|
blocks_to_update_x_block = layer2_x_block;
|
|
blocks_to_update_y_block = layer2_y_block;
|
|
vram_blocks_to_update_x_block = bg2_x_block;
|
|
vram_blocks_to_update_y_block = bg2_y_block;
|
|
UploadBackgroundDataColumn();
|
|
}
|
|
NMI_ProcessVramWriteQueue();
|
|
++layer1_x_block;
|
|
++bg1_x_block;
|
|
++layer2_x_block;
|
|
++bg2_x_block;
|
|
++v2;
|
|
} while (v3 != 16);
|
|
}
|
|
|
|
void QueueClearingOfFxTilemap(void) { // 0x80A211
|
|
for (int i = 3838; i >= 0; i -= 2)
|
|
*(uint16 *)((uint8 *)ram4000.xray_tilemaps + (uint16)i) = 6222;
|
|
uint16 v1 = vram_write_queue_tail;
|
|
VramWriteEntry *v2 = gVramWriteEntry(vram_write_queue_tail);
|
|
v2->size = 3840;
|
|
v2->src.addr = ADDR16_OF_RAM(ram4000);
|
|
*(uint16 *)&v2->src.bank = 126;
|
|
v2->vram_dst = addr_unk_605880;
|
|
vram_write_queue_tail = v1 + 7;
|
|
}
|
|
|
|
void ClearBG2Tilemap(void) { // 0x80A23F
|
|
WriteRegWord(VMADDL, 0x4800);
|
|
WriteRegWord(DMAP1, 0x1808);
|
|
WriteRegWord(A1T1L, 0xA29A);
|
|
WriteRegWord(A1B1, 0x80);
|
|
WriteRegWord(DAS1L, 0x800);
|
|
WriteReg(VMAIN, 0);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, 0x4800);
|
|
WriteRegWord(DMAP1, 0x1908);
|
|
WriteRegWord(A1T1L, 0xA29A);
|
|
WriteRegWord(A1B1, 0x80);
|
|
WriteRegWord(DAS1L, 0x800);
|
|
WriteReg(VMAIN, 0x80);
|
|
WriteReg(MDMAEN, 2);
|
|
}
|
|
|
|
void ClearFXTilemap(void) { // 0x80A29C
|
|
WriteRegWord(VMADDL, 0x5880);
|
|
WriteRegWord(DMAP1, 0x1808);
|
|
WriteRegWord(A1T1L, 0xA2F7);
|
|
WriteRegWord(A1B1, 0x80);
|
|
WriteRegWord(DAS1L, 0x780);
|
|
WriteReg(VMAIN, 0);
|
|
WriteReg(MDMAEN, 2);
|
|
WriteRegWord(VMADDL, 0x5880);
|
|
WriteRegWord(DMAP1, 0x1908);
|
|
WriteRegWord(A1T1L, 0xA2F8);
|
|
WriteRegWord(A1B1, 0x80);
|
|
WriteRegWord(DAS1L, 0x780);
|
|
WriteReg(VMAIN, 0x80);
|
|
WriteReg(MDMAEN, 2);
|
|
}
|
|
|
|
uint8 CalculateLayer2Xpos(void) { // 0x80A2F9
|
|
if (!layer2_scroll_x) {
|
|
layer2_x_pos = layer1_x_pos;
|
|
return 0;
|
|
}
|
|
if (layer2_scroll_x != 1) {
|
|
int t = layer2_scroll_x & 0xFE;
|
|
uint8 var933 = t * LOBYTE(layer1_x_pos) >> 8;
|
|
layer2_x_pos = t * HIBYTE(layer1_x_pos) + var933;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
uint8 CalculateLayer2Ypos(void) { // 0x80A33A
|
|
if (!layer2_scroll_y) {
|
|
layer2_y_pos = layer1_y_pos;
|
|
return 0;
|
|
}
|
|
if (layer2_scroll_y != 1) {
|
|
int t = layer2_scroll_y & 0xFE;
|
|
uint8 var933 = t * (uint8)layer1_y_pos >> 8;
|
|
layer2_y_pos = t * HIBYTE(layer1_y_pos) + var933;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void CalculateBgScrolls(void) { // 0x80A37B
|
|
reg_BG1HOFS = bg1_x_offset + layer1_x_pos;
|
|
reg_BG1VOFS = bg1_y_offset + layer1_y_pos;
|
|
reg_BG2HOFS = bg2_x_scroll + layer2_x_pos;
|
|
reg_BG2VOFS = bg2_y_scroll + layer2_y_pos;
|
|
}
|
|
|
|
void UpdateScrollVarsUpdateMap(void) { // 0x80A3A0
|
|
CalculateBgScrolls();
|
|
UpdateBgGraphicsWhenScrolling();
|
|
}
|
|
|
|
void CalculateLayer2PosAndScrollsWhenScrolling(void) { // 0x80A3AB
|
|
if (!time_is_frozen_flag) {
|
|
reg_BG1HOFS = bg1_x_offset + layer1_x_pos;
|
|
reg_BG1VOFS = bg1_y_offset + layer1_y_pos;
|
|
if (!CalculateLayer2Xpos())
|
|
reg_BG2HOFS = bg2_x_scroll + layer2_x_pos;
|
|
if (!CalculateLayer2Ypos())
|
|
reg_BG2VOFS = bg2_y_scroll + layer2_y_pos;
|
|
UpdateBgGraphicsWhenScrolling();
|
|
}
|
|
}
|
|
|
|
void UpdateBgGraphicsWhenScrolling(void) { // 0x80A3DF
|
|
CalculateBgScrollAndLayerPositionBlocks();
|
|
int v0 = 0;
|
|
bool v1 = (int16)(layer1_x_block - previous_layer1_x_block) < 0;
|
|
if (layer1_x_block != previous_layer1_x_block) {
|
|
previous_layer1_x_block = layer1_x_block;
|
|
if (!v1)
|
|
v0 = 16;
|
|
blocks_to_update_x_block = layer1_x_block + v0;
|
|
vram_blocks_to_update_x_block = bg1_x_block + v0;
|
|
blocks_to_update_y_block = layer1_y_block;
|
|
vram_blocks_to_update_y_block = bg1_y_block;
|
|
UploadLevelDataColumn();
|
|
}
|
|
if (!(layer2_scroll_x & 1)) {
|
|
int v2 = 0;
|
|
bool v3 = (int16)(layer2_x_block - previous_layer2_x_block) < 0;
|
|
if (layer2_x_block != previous_layer2_x_block) {
|
|
previous_layer2_x_block = layer2_x_block;
|
|
if (!v3)
|
|
v2 = 16;
|
|
blocks_to_update_x_block = layer2_x_block + v2;
|
|
vram_blocks_to_update_x_block = bg2_x_block + v2;
|
|
blocks_to_update_y_block = layer2_y_block;
|
|
vram_blocks_to_update_y_block = bg2_y_block;
|
|
UploadBackgroundDataColumn();
|
|
}
|
|
}
|
|
int v4 = 1;
|
|
bool v5 = (int16)(layer1_y_block - previous_layer1_y_block) < 0;
|
|
if (layer1_y_block != previous_layer1_y_block) {
|
|
previous_layer1_y_block = layer1_y_block;
|
|
if (!v5)
|
|
v4 = 15;
|
|
blocks_to_update_y_block = layer1_y_block + v4;
|
|
vram_blocks_to_update_y_block = bg1_y_block + v4;
|
|
blocks_to_update_x_block = layer1_x_block;
|
|
vram_blocks_to_update_x_block = bg1_x_block;
|
|
UpdateLevelDataRow();
|
|
}
|
|
if (!(layer2_scroll_y & 1)) {
|
|
int v6 = 1;
|
|
bool v7 = (int16)(layer2_y_block - previous_layer2_y_block) < 0;
|
|
if (layer2_y_block != previous_layer2_y_block) {
|
|
previous_layer2_y_block = layer2_y_block;
|
|
if (!v7)
|
|
v6 = 15;
|
|
blocks_to_update_y_block = layer2_y_block + v6;
|
|
vram_blocks_to_update_y_block = bg2_y_block + v6;
|
|
blocks_to_update_x_block = layer2_x_block;
|
|
vram_blocks_to_update_x_block = bg2_x_block;
|
|
UpdateBackgroundDataRow();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CalculateBgScrollAndLayerPositionBlocks(void) { // 0x80A4BB
|
|
bg1_x_block = reg_BG1HOFS >> 4;
|
|
bg2_x_block = reg_BG2HOFS >> 4;
|
|
uint16 v0 = layer1_x_pos >> 4;
|
|
if (((layer1_x_pos >> 4) & 0x800) != 0)
|
|
v0 |= 0xF000;
|
|
layer1_x_block = v0;
|
|
uint16 v1 = layer2_x_pos >> 4;
|
|
if (((layer2_x_pos >> 4) & 0x800) != 0)
|
|
v1 |= 0xF000;
|
|
layer2_x_block = v1;
|
|
bg1_y_block = reg_BG1VOFS >> 4;
|
|
bg2_y_block = reg_BG2VOFS >> 4;
|
|
uint16 v2 = layer1_y_pos >> 4;
|
|
if (((layer1_y_pos >> 4) & 0x800) != 0)
|
|
v2 |= 0xF000;
|
|
layer1_y_block = v2;
|
|
uint16 v3 = layer2_y_pos >> 4;
|
|
if (((layer2_y_pos >> 4) & 0x800) != 0)
|
|
v3 |= 0xF000;
|
|
layer2_y_block = v3;
|
|
}
|
|
|
|
void HandleAutoscrolling_X(void) { // 0x80A528
|
|
int16 v1;
|
|
int16 v3;
|
|
int16 v6;
|
|
uint16 v4;
|
|
uint16 var933;
|
|
|
|
if (!time_is_frozen_flag) {
|
|
uint16 var939 = layer1_x_pos;
|
|
if ((layer1_x_pos & 0x8000) != 0)
|
|
layer1_x_pos = 0;
|
|
uint16 v0 = swap16(room_width_in_scrolls - 1);
|
|
if (v0 < layer1_x_pos)
|
|
layer1_x_pos = v0;
|
|
v1 = HIBYTE(layer1_x_pos);
|
|
uint16 v2 = Mult8x8((uint16)(layer1_y_pos + 128) >> 8, room_width_in_scrolls) + v1;
|
|
if (scrolls[v2]) {
|
|
if (scrolls[(uint16)(v2 + 1)])
|
|
return;
|
|
var933 = layer1_x_pos & 0xFF00;
|
|
uint16 v5 = var939 - absolute_moved_last_frame_x - 2;
|
|
if ((int16)(v5 - (layer1_x_pos & 0xFF00)) < 0) {
|
|
v4 = var933;
|
|
} else {
|
|
var939 = v5;
|
|
v6 = HIBYTE(var939);
|
|
if (scrolls[(uint16)(Mult8x8((uint16)(layer1_y_pos + 128) >> 8, room_width_in_scrolls) + v6)])
|
|
v4 = var939;
|
|
else
|
|
v4 = (var939 & 0xFF00) + 256;
|
|
}
|
|
} else {
|
|
var933 = (layer1_x_pos & 0xFF00) + 256;
|
|
if ((uint16)(absolute_moved_last_frame_x + var939 + 2) >= var933) {
|
|
v4 = var933;
|
|
} else {
|
|
var939 += absolute_moved_last_frame_x + 2;
|
|
v3 = (uint8)(HIBYTE(var939) + 1);
|
|
if (scrolls[(uint16)(Mult8x8((uint16)(layer1_y_pos + 128) >> 8, room_width_in_scrolls) + v3)])
|
|
v4 = var939;
|
|
else
|
|
v4 = var939 & 0xFF00;
|
|
}
|
|
}
|
|
layer1_x_pos = v4;
|
|
}
|
|
}
|
|
|
|
void HandleScrollingWhenTriggeringScrollRight(void) { // 0x80A641
|
|
int16 v1;
|
|
|
|
uint16 var939 = layer1_x_pos;
|
|
if ((int16)(ideal_layer1_xpos - layer1_x_pos) < 0) {
|
|
layer1_x_pos = ideal_layer1_xpos;
|
|
layer1_x_subpos = 0;
|
|
}
|
|
uint16 v0 = swap16(room_width_in_scrolls - 1);
|
|
if (v0 >= layer1_x_pos) {
|
|
v1 = HIBYTE(layer1_x_pos);
|
|
uint16 RegWord = Mult8x8((uint16)(layer1_y_pos + 128) >> 8, room_width_in_scrolls);
|
|
if (!scrolls[(uint16)(RegWord + 1 + v1)]) {
|
|
uint16 var933 = layer1_x_pos & 0xFF00;
|
|
uint16 v4 = var939 - absolute_moved_last_frame_x - 2;
|
|
if ((int16)(v4 - (layer1_x_pos & 0xFF00)) < 0)
|
|
v4 = var933;
|
|
layer1_x_pos = v4;
|
|
}
|
|
} else {
|
|
layer1_x_pos = v0;
|
|
}
|
|
}
|
|
|
|
void HandleScrollingWhenTriggeringScrollLeft(void) { // 0x80A6BB
|
|
int16 v0;
|
|
|
|
uint16 var939 = layer1_x_pos;
|
|
if ((int16)(layer1_x_pos - ideal_layer1_xpos) < 0) {
|
|
layer1_x_pos = ideal_layer1_xpos;
|
|
layer1_x_subpos = 0;
|
|
}
|
|
if ((layer1_x_pos & 0x8000) == 0) {
|
|
v0 = HIBYTE(layer1_x_pos);
|
|
uint16 prod = Mult8x8((uint16)(layer1_y_pos + 128) >> 8, room_width_in_scrolls);
|
|
if (!scrolls[(uint16)(prod + v0)]) {
|
|
uint16 var933 = (layer1_x_pos & 0xFF00) + 256;
|
|
uint16 v1 = absolute_moved_last_frame_x + var939 + 2;
|
|
if (v1 >= var933)
|
|
v1 = var933;
|
|
layer1_x_pos = v1;
|
|
}
|
|
} else {
|
|
layer1_x_pos = 0;
|
|
}
|
|
}
|
|
|
|
void HandleAutoscrolling_Y(void) { // 0x80A731
|
|
int16 v1;
|
|
int16 v2;
|
|
int16 v4;
|
|
int16 v7;
|
|
int16 v10;
|
|
uint16 v8;
|
|
|
|
if (!time_is_frozen_flag) {
|
|
uint16 v0 = 0;
|
|
v1 = (uint16)(layer1_x_pos + 128) >> 8;
|
|
uint16 r20 = Mult8x8(HIBYTE(layer1_y_pos), room_width_in_scrolls) + v1;
|
|
if (scrolls[r20] != 1)
|
|
v0 = 31;
|
|
uint16 var933 = v0;
|
|
uint16 var939 = layer1_y_pos;
|
|
if ((layer1_y_pos & 0x8000) != 0)
|
|
layer1_y_pos = 0;
|
|
LOBYTE(v2) = (uint16)(room_height_in_scrolls - 1) >> 8;
|
|
HIBYTE(v2) = room_height_in_scrolls - 1;
|
|
uint16 v3 = var933 + v2;
|
|
if (v3 < layer1_y_pos)
|
|
layer1_y_pos = v3;
|
|
v4 = (uint16)(layer1_x_pos + 128) >> 8;
|
|
uint16 v5 = Mult8x8(HIBYTE(layer1_y_pos), room_width_in_scrolls) + v4;
|
|
if (!scrolls[v5]) {
|
|
uint16 var935 = (layer1_y_pos & 0xFF00) + 256;
|
|
uint16 v6 = absolute_moved_last_frame_y + var939 + 2;
|
|
if (v6 >= var935) {
|
|
v8 = var935;
|
|
} else {
|
|
var939 += absolute_moved_last_frame_y + 2;
|
|
v7 = (uint16)(layer1_x_pos + 128) >> 8;
|
|
uint16 prod = Mult8x8(HIBYTE(v6) + 1, room_width_in_scrolls);
|
|
if (scrolls[(uint16)(prod + v7)])
|
|
v8 = var939;
|
|
else
|
|
v8 = var939 & 0xFF00;
|
|
}
|
|
layer1_y_pos = v8;
|
|
return;
|
|
}
|
|
if (!scrolls[(uint16)(room_width_in_scrolls + v5)]) {
|
|
uint16 var937 = var933 + (layer1_y_pos & 0xFF00);
|
|
if (var937 < layer1_y_pos) {
|
|
uint16 v9 = var939 - absolute_moved_last_frame_y - 2;
|
|
if ((int16)(v9 - var937) < 0) {
|
|
v8 = var937;
|
|
} else {
|
|
var939 = v9;
|
|
uint16 prod = Mult8x8(HIBYTE(v9), room_width_in_scrolls);
|
|
v10 = (uint16)(layer1_x_pos + 128) >> 8;
|
|
if (scrolls[(uint16)(prod + v10)])
|
|
v8 = var939;
|
|
else
|
|
v8 = (var939 & 0xFF00) + 256;
|
|
}
|
|
layer1_y_pos = v8;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void HandleScrollingWhenTriggeringScrollDown(void) { // 0x80A893
|
|
uint16 var939 = layer1_y_pos;
|
|
int v0 = 0;
|
|
uint16 prod = Mult8x8(HIBYTE(layer1_y_pos), room_width_in_scrolls);
|
|
uint16 v1 = (uint16)(layer1_x_pos + 128) >> 8;
|
|
uint16 r20 = prod + v1;
|
|
if (scrolls[r20] != 1)
|
|
v0 = 31;
|
|
uint16 var933 = v0;
|
|
if ((int16)(ideal_layer1_ypos - layer1_y_pos) < 0) {
|
|
layer1_y_pos = ideal_layer1_ypos;
|
|
layer1_y_subpos = 0;
|
|
}
|
|
uint16 v2 = swap16(room_height_in_scrolls - 1);
|
|
uint16 var937 = var933 + v2;
|
|
if ((uint16)(var933 + v2) < layer1_y_pos
|
|
|| !scrolls[(uint16)(room_width_in_scrolls + r20)]
|
|
&& (var937 = var933 + (layer1_y_pos & 0xFF00), var937 < layer1_y_pos)) {
|
|
uint16 v3 = var939 - absolute_moved_last_frame_y - 2;
|
|
if ((int16)(v3 - var937) < 0)
|
|
v3 = var937;
|
|
layer1_y_pos = v3;
|
|
}
|
|
}
|
|
|
|
void HandleScrollingWhenTriggeringScrollUp(void) { // 0x80A936
|
|
int16 v0;
|
|
|
|
uint16 var939 = layer1_y_pos;
|
|
if ((int16)(layer1_y_pos - ideal_layer1_ypos) < 0) {
|
|
layer1_y_pos = ideal_layer1_ypos;
|
|
layer1_y_subpos = 0;
|
|
}
|
|
if ((layer1_y_pos & 0x8000) == 0) {
|
|
uint16 prod = Mult8x8(HIBYTE(layer1_y_pos), room_width_in_scrolls);
|
|
v0 = (uint16)(layer1_x_pos + 128) >> 8;
|
|
if (!scrolls[(uint16)(prod + v0)]) {
|
|
uint16 var933 = (layer1_y_pos & 0xFF00) + 256;
|
|
uint16 v1 = absolute_moved_last_frame_y + var939 + 2;
|
|
if (v1 >= var933)
|
|
v1 = var933;
|
|
layer1_y_pos = v1;
|
|
}
|
|
} else {
|
|
layer1_y_pos = 0;
|
|
}
|
|
}
|
|
|
|
void DebugScrollPosSaveLoad(void) { // 0x80A9AC
|
|
if ((joypad2_new_keys & 0x40) != 0)
|
|
++debug_saveload_scrollpos_toggle;
|
|
if (debug_saveload_scrollpos_toggle & 1) {
|
|
layer1_x_pos = debug_saved_xscroll;
|
|
layer1_y_pos = debug_saved_yscroll;
|
|
} else {
|
|
debug_saved_xscroll = layer1_x_pos;
|
|
debug_saved_yscroll = layer1_y_pos;
|
|
}
|
|
}
|
|
|
|
void UploadBackgroundDataColumn(void) { // 0x80A9D6
|
|
UpdateLevelOrBackgroundDataColumn(0x1c);
|
|
}
|
|
|
|
void UploadLevelDataColumn(void) { // 0x80A9DB
|
|
UpdateLevelOrBackgroundDataColumn(0);
|
|
}
|
|
|
|
void UpdateLevelOrBackgroundDataColumn(uint16 k) { // 0x80A9DE
|
|
if (!irq_enable_mode7) {
|
|
uint16 prod = Mult8x8(blocks_to_update_y_block, room_width_in_blocks);
|
|
uint16 v1 = blocks_to_update_x_block;
|
|
uint16 v2 = 2 * (prod + v1) + 2;
|
|
if (k)
|
|
v2 += 0x9600;
|
|
copywithflip_src.addr = v2;
|
|
copywithflip_src.bank = 127;
|
|
uint16 v3 = (4 * vram_blocks_to_update_y_block) & 0x3C;
|
|
*(uint16 *)((uint8 *)&bg1_update_col_wrapped_size + k) = v3;
|
|
*(uint16 *)((uint8 *)&bg1_update_col_unwrapped_size + k) = (v3 ^ 0x3F) + 1;
|
|
prod = Mult8x8(vram_blocks_to_update_y_block & 0xF, 0x40);
|
|
uint16 var935 = vram_blocks_to_update_x_block & 0x1F;
|
|
uint16 v4 = 2 * var935;
|
|
uint16 var933 = prod + v4;
|
|
uint16 v5 = addr_unk_605000;
|
|
if (var935 >= 0x10)
|
|
v5 = addr_unk_6053E0;
|
|
if (k)
|
|
v5 -= size_of_bg2;
|
|
uint16 var937 = v5;
|
|
*(uint16 *)((uint8 *)&bg1_update_col_unwrapped_dst + k) = var933 + v5;
|
|
*(uint16 *)((uint8 *)&bg1_update_col_wrapped_dst + k) = var935 + var935 + var937;
|
|
uint16 v6 = ADDR16_OF_RAM(*bg1_column_update_tilemap_left_halves);
|
|
uint16 v7 = 0;
|
|
if (k) {
|
|
v6 = ADDR16_OF_RAM(*bg2_column_update_tilemap_left_halves);
|
|
v7 = 264;
|
|
}
|
|
uint16 v8 = *(uint16 *)((uint8 *)&bg1_update_col_unwrapped_size + k) + v6;
|
|
*(uint16 *)((uint8 *)&bg1_update_col_wrapped_left_src + k) = v8;
|
|
*(uint16 *)((uint8 *)&bg1_update_col_wrapped_right_src + k) = v8 + 64;
|
|
var937 = v7;
|
|
uint16 t2 = k;
|
|
uint16 v9 = 0;
|
|
uint16 var939 = 16;
|
|
do {
|
|
uint16 var93B = IndirReadWord(copywithflip_src, v9);
|
|
uint16 v10 = var93B & 0x3FF;
|
|
uint16 v17 = v9;
|
|
uint16 v11 = var937;
|
|
uint16 v12 = var93B & 0xC00;
|
|
if ((var93B & 0xC00) != 0) {
|
|
if (v12 == 1024) {
|
|
uint16 v14 = var937 >> 1;
|
|
bg1_column_update_tilemap_left_halves[v14] = tile_table.tables[v10].top_right ^ 0x4000;
|
|
bg1_column_update_tilemap_right_halves[v14] = tile_table.tables[v10].top_left ^ 0x4000;
|
|
bg1_column_update_tilemap_left_halves[v14 + 1] = tile_table.tables[v10].bottom_right ^ 0x4000;
|
|
bg1_column_update_tilemap_right_halves[v14 + 1] = tile_table.tables[v10].bottom_left ^ 0x4000;
|
|
} else {
|
|
uint16 v15 = var937 >> 1;
|
|
uint16 v16;
|
|
if (v12 == 2048) {
|
|
bg1_column_update_tilemap_left_halves[v15] = tile_table.tables[v10].bottom_left ^ 0x8000;
|
|
bg1_column_update_tilemap_right_halves[v15] = tile_table.tables[v10].bottom_right ^ 0x8000;
|
|
bg1_column_update_tilemap_left_halves[v15 + 1] = tile_table.tables[v10].top_left ^ 0x8000;
|
|
v16 = tile_table.tables[v10].top_right ^ 0x8000;
|
|
} else {
|
|
bg1_column_update_tilemap_left_halves[v15] = tile_table.tables[v10].bottom_right ^ 0xC000;
|
|
bg1_column_update_tilemap_right_halves[v15] = tile_table.tables[v10].bottom_left ^ 0xC000;
|
|
bg1_column_update_tilemap_left_halves[v15 + 1] = tile_table.tables[v10].top_right ^ 0xC000;
|
|
v16 = tile_table.tables[v10].top_left ^ 0xC000;
|
|
}
|
|
bg1_column_update_tilemap_right_halves[v15 + 1] = v16;
|
|
}
|
|
} else {
|
|
uint16 v13 = var937 >> 1;
|
|
bg1_column_update_tilemap_left_halves[v13] = tile_table.tables[v10].top_left;
|
|
bg1_column_update_tilemap_right_halves[v13] = tile_table.tables[v10].top_right;
|
|
bg1_column_update_tilemap_left_halves[v13 + 1] = tile_table.tables[v10].bottom_left;
|
|
bg1_column_update_tilemap_right_halves[v13 + 1] = tile_table.tables[v10].bottom_right;
|
|
}
|
|
var937 = v11 + 4;
|
|
v9 = room_width_in_blocks * 2 + v17;
|
|
--var939;
|
|
} while (var939);
|
|
++ *(uint16 *)((uint8 *)&bg1_update_col_enable + t2);
|
|
}
|
|
}
|
|
|
|
void UpdateBackgroundDataRow(void) { // 0x80AB70
|
|
UpdateLevelOrBackgroundDataRow(0x1c);
|
|
}
|
|
|
|
void UpdateLevelDataRow(void) { // 0x80AB75
|
|
UpdateLevelOrBackgroundDataRow(0);
|
|
}
|
|
|
|
void UpdateLevelOrBackgroundDataRow(uint16 v0) { // 0x80AB78
|
|
if (!irq_enable_mode7) {
|
|
uint16 prod = Mult8x8(blocks_to_update_y_block, room_width_in_blocks);
|
|
uint16 v1 = blocks_to_update_x_block;
|
|
uint16 v2 = 2 * (prod + v1) + 2;
|
|
if (v0)
|
|
v2 -= 27136;
|
|
copywithflip_src.addr = v2;
|
|
copywithflip_src.bank = 127;
|
|
uint16 var933 = vram_blocks_to_update_x_block & 0xF;
|
|
*(uint16 *)((uint8 *)&bg1_update_row_unwrapped_size + v0) = 4 * (16 - var933);
|
|
*(uint16 *)((uint8 *)&bg1_update_row_wrapped_size + v0) = 4 * (var933 + 1);
|
|
prod = Mult8x8(vram_blocks_to_update_y_block & 0xF, 0x40);
|
|
uint16 var935 = vram_blocks_to_update_x_block & 0x1F;
|
|
uint16 v3 = 2 * var935;
|
|
var933 = prod + v3;
|
|
uint16 var937 = addr_unk_605400;
|
|
uint16 v4 = addr_unk_605000;
|
|
if (var935 >= 0x10) {
|
|
var937 = addr_unk_605000;
|
|
v4 = addr_unk_6053E0;
|
|
}
|
|
if (v0)
|
|
v4 -= size_of_bg2;
|
|
*(uint16 *)((uint8 *)&bg1_update_row_unwrapped_dst + v0) = var933 + v4;
|
|
uint16 v5 = var937;
|
|
if (v0)
|
|
v5 = var937 - size_of_bg2;
|
|
*(uint16 *)((uint8 *)&bg1_update_row_wrapped_dst + v0) = prod + v5;
|
|
uint16 v6 = ADDR16_OF_RAM(*bg1_column_update_tilemap_top_halves);
|
|
uint16 v7 = 0;
|
|
if (v0) {
|
|
v6 = ADDR16_OF_RAM(*bg2_column_update_tilemap_top_halves);
|
|
v7 = 264;
|
|
}
|
|
uint16 v8 = *(uint16 *)((uint8 *)&bg1_update_row_unwrapped_size + v0) + v6;
|
|
*(uint16 *)((uint8 *)&bg1_update_row_wrapped_top_src + v0) = v8;
|
|
*(uint16 *)((uint8 *)&bg1_update_row_wrapped_bottom_src + v0) = v8 + 68;
|
|
var937 = v7;
|
|
uint16 t2 = v0;
|
|
uint16 v9 = 0;
|
|
uint16 var939 = 17;
|
|
do {
|
|
uint16 var93B = IndirReadWord(copywithflip_src, v9);
|
|
uint16 v10 = var93B & 0x3FF;
|
|
uint16 v17 = v9;
|
|
uint16 v11 = var937;
|
|
uint16 v12 = var93B & 0xC00;
|
|
if ((var93B & 0xC00) != 0) {
|
|
if (v12 == 1024) {
|
|
uint16 v14 = var937 >> 1;
|
|
bg1_column_update_tilemap_top_halves[v14] = tile_table.tables[v10].top_right ^ 0x4000;
|
|
bg1_column_update_tilemap_top_halves[v14 + 1] = tile_table.tables[v10].top_left ^ 0x4000;
|
|
bg1_column_update_tilemap_bottom_halves[v14] = tile_table.tables[v10].bottom_right ^ 0x4000;
|
|
bg1_column_update_tilemap_bottom_halves[v14 + 1] = tile_table.tables[v10].bottom_left ^ 0x4000;
|
|
} else {
|
|
uint16 v15 = var937 >> 1;
|
|
uint16 v16;
|
|
if (v12 == 2048) {
|
|
bg1_column_update_tilemap_top_halves[v15] = tile_table.tables[v10].bottom_left ^ 0x8000;
|
|
bg1_column_update_tilemap_top_halves[v15 + 1] = tile_table.tables[v10].bottom_right ^ 0x8000;
|
|
bg1_column_update_tilemap_bottom_halves[v15] = tile_table.tables[v10].top_left ^ 0x8000;
|
|
v16 = tile_table.tables[v10].top_right ^ 0x8000;
|
|
} else {
|
|
bg1_column_update_tilemap_top_halves[v15] = tile_table.tables[v10].bottom_right ^ 0xC000;
|
|
bg1_column_update_tilemap_top_halves[v15 + 1] = tile_table.tables[v10].bottom_left ^ 0xC000;
|
|
bg1_column_update_tilemap_bottom_halves[v15] = tile_table.tables[v10].top_right ^ 0xC000;
|
|
v16 = tile_table.tables[v10].top_left ^ 0xC000;
|
|
}
|
|
bg1_column_update_tilemap_bottom_halves[v15 + 1] = v16;
|
|
}
|
|
} else {
|
|
uint16 v13 = var937 >> 1;
|
|
bg1_column_update_tilemap_top_halves[v13] = tile_table.tables[v10].top_left;
|
|
bg1_column_update_tilemap_top_halves[v13 + 1] = tile_table.tables[v10].top_right;
|
|
bg1_column_update_tilemap_bottom_halves[v13] = tile_table.tables[v10].bottom_left;
|
|
bg1_column_update_tilemap_bottom_halves[v13 + 1] = tile_table.tables[v10].bottom_right;
|
|
}
|
|
var937 = v11 + 4;
|
|
v9 = v17 + 2;
|
|
--var939;
|
|
} while (var939);
|
|
++ *(uint16 *)((uint8 *)&bg1_update_row_enable + t2);
|
|
}
|
|
}
|
|
|
|
void FixDoorsMovingUp(void) { // 0x80AD1D
|
|
door_transition_frame_counter = 0;
|
|
CalculateBgScrollAndLayerPositionBlocks();
|
|
UpdatePreviousLayerBlocks();
|
|
++previous_layer1_y_block;
|
|
++previous_layer2_y_block;
|
|
DoorTransition_Up();
|
|
}
|
|
|
|
static Func_V *const kDoorTransitionSetupFuncs[4] = { // 0x80AD30
|
|
DoorTransitionScrollingSetup_Right,
|
|
DoorTransitionScrollingSetup_Left,
|
|
DoorTransitionScrollingSetup_Down,
|
|
DoorTransitionScrollingSetup_Up,
|
|
};
|
|
|
|
void DoorTransitionScrollingSetup(void) {
|
|
layer1_x_pos = door_destination_x_pos;
|
|
layer1_y_pos = door_destination_y_pos;
|
|
kDoorTransitionSetupFuncs[door_direction & 3]();
|
|
}
|
|
|
|
void DoorTransitionScrollingSetup_Right(void) { // 0x80AD4A
|
|
CalculateLayer2Xpos();
|
|
layer2_x_pos -= 256;
|
|
CalculateLayer2Ypos();
|
|
layer1_x_pos -= 256;
|
|
UpdateBgScrollOffsets();
|
|
CalculateBgScrollAndLayerPositionBlocks();
|
|
UpdatePreviousLayerBlocks();
|
|
--previous_layer1_x_block;
|
|
--previous_layer2_x_block;
|
|
DoorTransition_Right();
|
|
}
|
|
|
|
void DoorTransitionScrollingSetup_Left(void) { // 0x80AD74
|
|
CalculateLayer2Xpos();
|
|
layer2_x_pos += 256;
|
|
CalculateLayer2Ypos();
|
|
layer1_x_pos += 256;
|
|
UpdateBgScrollOffsets();
|
|
CalculateBgScrollAndLayerPositionBlocks();
|
|
UpdatePreviousLayerBlocks();
|
|
++previous_layer1_x_block;
|
|
++previous_layer2_x_block;
|
|
DoorTransition_Left();
|
|
}
|
|
|
|
void DoorTransitionScrollingSetup_Down(void) { // 0x80AD9E
|
|
CalculateLayer2Xpos();
|
|
CalculateLayer2Ypos();
|
|
layer2_y_pos -= 224;
|
|
layer1_y_pos -= 224;
|
|
UpdateBgScrollOffsets();
|
|
CalculateBgScrollAndLayerPositionBlocks();
|
|
UpdatePreviousLayerBlocks();
|
|
--previous_layer1_y_block;
|
|
--previous_layer2_y_block;
|
|
DoorTransition_Down();
|
|
}
|
|
|
|
void DoorTransitionScrollingSetup_Up(void) { // 0x80ADC8
|
|
CalculateLayer2Xpos();
|
|
uint16 v1 = layer1_y_pos;
|
|
layer1_y_pos += 31;
|
|
CalculateLayer2Ypos();
|
|
layer2_y_pos += 224;
|
|
layer1_y_pos = v1 + 256;
|
|
UpdateBgScrollOffsets();
|
|
door_destination_y_pos += 32;
|
|
CalculateBgScrollAndLayerPositionBlocks();
|
|
UpdatePreviousLayerBlocks();
|
|
++previous_layer1_y_block;
|
|
++previous_layer2_y_block;
|
|
--layer1_y_pos;
|
|
DoorTransition_Up();
|
|
}
|
|
|
|
void UpdatePreviousLayerBlocks(void) { // 0x80AE10
|
|
previous_layer1_x_block = layer1_x_block;
|
|
previous_layer2_x_block = layer2_x_block;
|
|
previous_layer1_y_block = layer1_y_block;
|
|
previous_layer2_y_block = layer2_y_block;
|
|
}
|
|
|
|
void UpdateBgScrollOffsets(void) { // 0x80AE29
|
|
bg1_x_offset = reg_BG1HOFS - layer1_x_pos;
|
|
bg1_y_offset = reg_BG1VOFS - layer1_y_pos;
|
|
bg2_x_scroll = reg_BG2HOFS - layer1_x_pos;
|
|
bg2_y_scroll = reg_BG2VOFS - layer1_y_pos;
|
|
}
|
|
|
|
static Func_U8 *const kDoorTransitionFuncs[4] = {
|
|
DoorTransition_Right,
|
|
DoorTransition_Left,
|
|
DoorTransition_Down,
|
|
DoorTransition_Up,
|
|
};
|
|
|
|
void Irq_FollowDoorTransition(void) {
|
|
if (kDoorTransitionFuncs[door_direction & 3]()) {
|
|
layer1_x_pos = door_destination_x_pos;
|
|
layer1_y_pos = door_destination_y_pos;
|
|
door_transition_flag |= 0x8000;
|
|
}
|
|
}
|
|
|
|
uint8 DoorTransition_Right(void) { // 0x80AE7E
|
|
uint16 v2 = door_transition_frame_counter;
|
|
AddToHiLo(&samus_x_pos, &samus_x_subpos, __PAIR32__(samus_door_transition_speed, samus_door_transition_subspeed));
|
|
samus_prev_x_pos = samus_x_pos;
|
|
layer1_x_pos += 4;
|
|
layer2_x_pos += 4;
|
|
UpdateScrollVarsUpdateMap();
|
|
door_transition_frame_counter = v2 + 1;
|
|
if (v2 != 63)
|
|
return 0;
|
|
UpdateScrollVarsUpdateMap();
|
|
return 1;
|
|
}
|
|
|
|
uint8 DoorTransition_Left(void) { // 0x80AEC2
|
|
uint16 v2 = door_transition_frame_counter;
|
|
AddToHiLo(&samus_x_pos, &samus_x_subpos, -IPAIR32(samus_door_transition_speed, samus_door_transition_subspeed));
|
|
samus_prev_x_pos = samus_x_pos;
|
|
layer1_x_pos -= 4;
|
|
layer2_x_pos -= 4;
|
|
UpdateScrollVarsUpdateMap();
|
|
door_transition_frame_counter = v2 + 1;
|
|
return v2 == 63;
|
|
}
|
|
|
|
uint8 DoorTransition_Down(void) { // 0x80AF02
|
|
uint16 v6 = door_transition_frame_counter;
|
|
if (door_transition_frame_counter) {
|
|
if (door_transition_frame_counter < 0x39) {
|
|
AddToHiLo(&samus_y_pos, &samus_y_subpos, __PAIR32__(samus_door_transition_speed, samus_door_transition_subspeed));
|
|
samus_prev_y_pos = samus_y_pos;
|
|
layer1_y_pos += 4;
|
|
layer2_y_pos += 4;
|
|
UpdateScrollVarsUpdateMap();
|
|
}
|
|
} else {
|
|
uint16 v5 = reg_BG1VOFS;
|
|
uint16 v4 = reg_BG2VOFS;
|
|
uint16 v3 = layer1_y_pos;
|
|
layer1_y_pos -= 15;
|
|
uint16 v2 = layer2_y_pos;
|
|
layer2_y_pos -= 15;
|
|
CalculateBgScrollAndLayerPositionBlocks();
|
|
UpdatePreviousLayerBlocks();
|
|
--previous_layer1_y_block;
|
|
--previous_layer2_y_block;
|
|
UpdateScrollVarsUpdateMap();
|
|
layer2_y_pos = v2;
|
|
layer1_y_pos = v3;
|
|
reg_BG2VOFS = v4;
|
|
reg_BG1VOFS = v5;
|
|
}
|
|
door_transition_frame_counter = v6 + 1;
|
|
if ((uint16)(v6 + 1) < 0x39)
|
|
return 0;
|
|
UpdateScrollVarsUpdateMap();
|
|
return 1;
|
|
}
|
|
|
|
uint8 DoorTransition_Up(void) { // 0x80AF89
|
|
uint16 v6 = door_transition_frame_counter;
|
|
if (door_transition_frame_counter) {
|
|
AddToHiLo(&samus_y_pos, &samus_y_subpos, -IPAIR32(samus_door_transition_speed, samus_door_transition_subspeed));
|
|
samus_prev_y_pos = samus_y_pos;
|
|
layer1_y_pos -= 4;
|
|
layer2_y_pos -= 4;
|
|
if (door_transition_frame_counter >= 5) {
|
|
UpdateScrollVarsUpdateMap();
|
|
} else {
|
|
reg_BG1HOFS = bg1_x_offset + layer1_x_pos;
|
|
reg_BG1VOFS = bg1_y_offset + layer1_y_pos;
|
|
reg_BG2HOFS = bg2_x_scroll + layer2_x_pos;
|
|
reg_BG2VOFS = bg2_y_scroll + layer2_y_pos;
|
|
}
|
|
} else {
|
|
uint16 v5 = reg_BG1VOFS;
|
|
uint16 v4 = reg_BG2VOFS;
|
|
uint16 v3 = layer1_y_pos;
|
|
layer1_y_pos -= 16;
|
|
uint16 v2 = layer2_y_pos;
|
|
layer2_y_pos -= 16;
|
|
CalculateBgScrollAndLayerPositionBlocks();
|
|
UpdatePreviousLayerBlocks();
|
|
++previous_layer1_y_block;
|
|
++previous_layer2_y_block;
|
|
UpdateScrollVarsUpdateMap();
|
|
layer2_y_pos = v2;
|
|
layer1_y_pos = v3;
|
|
reg_BG2VOFS = v4;
|
|
reg_BG1VOFS = v5;
|
|
}
|
|
door_transition_frame_counter = v6 + 1;
|
|
return v6 == 56;
|
|
}
|
|
|
|
void ConfigureMode7RotationMatrix(void) { // 0x80B0C2
|
|
if (irq_enable_mode7) {
|
|
if ((nmi_frame_counter_word & 7) == 0) {
|
|
reg_M7B = kSinCosTable8bit_Sext[((uint8)mode7_rotation_angle) + 64];
|
|
reg_M7C = -reg_M7B;
|
|
reg_M7A = kSinCosTable8bit_Sext[((uint8)(mode7_rotation_angle + 64)) + 64];
|
|
reg_M7D = reg_M7A;
|
|
++mode7_rotation_angle;
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint32 decompress_src;
|
|
|
|
static uint8 DecompNextByte() {
|
|
uint8 b = *RomPtr(decompress_src);
|
|
if ((decompress_src++ & 0xffff) == 0xffff)
|
|
decompress_src += 0x8000;
|
|
return b;
|
|
}
|
|
|
|
void DecompressToMem(uint32 src, uint8 *decompress_dst) { // 0x80B119
|
|
decompress_src = src;
|
|
|
|
int src_pos, dst_pos = 0;
|
|
while (1) {
|
|
int len;
|
|
uint8 cmd, b;
|
|
b = DecompNextByte();
|
|
if (b == 0xFF)
|
|
break;
|
|
if ((b & 0xE0) == 0xE0) {
|
|
cmd = (8 * b) & 0xE0;
|
|
len = ((b & 3) << 8 | DecompNextByte()) + 1;
|
|
} else {
|
|
cmd = b & 0xE0;
|
|
len = (b & 0x1F) + 1;
|
|
}
|
|
if (cmd & 0x80) {
|
|
uint8 want_xor = cmd & 0x20 ? 0xff : 0;
|
|
if (cmd >= 0xC0) {
|
|
src_pos = dst_pos - DecompNextByte();
|
|
} else {
|
|
src_pos = DecompNextByte();
|
|
src_pos += DecompNextByte() * 256;
|
|
}
|
|
do {
|
|
b = decompress_dst[src_pos++] ^ want_xor;
|
|
decompress_dst[dst_pos++] = b;
|
|
} while (--len);
|
|
} else {
|
|
switch (cmd) {
|
|
case 0x20:
|
|
b = DecompNextByte();
|
|
do {
|
|
decompress_dst[dst_pos++] = b;
|
|
} while (--len);
|
|
break;
|
|
case 0x40: {
|
|
b = DecompNextByte();
|
|
uint8 b2 = DecompNextByte();
|
|
do {
|
|
decompress_dst[dst_pos++] = b;
|
|
if (!--len)
|
|
break;
|
|
decompress_dst[dst_pos++] = b2;
|
|
} while (--len);
|
|
break;
|
|
}
|
|
case 0x60:
|
|
b = DecompNextByte();
|
|
do {
|
|
decompress_dst[dst_pos++] = b++;
|
|
} while (--len);
|
|
break;
|
|
default:
|
|
do {
|
|
b = DecompNextByte();
|
|
decompress_dst[dst_pos++] = b;
|
|
} while (--len);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint8 ReadPpuByte(uint16 addr) {
|
|
WriteRegWord(VMADDL, addr >> 1);
|
|
ReadRegWord(RDVRAML); // latch
|
|
uint16 data = ReadRegWord(RDVRAML);
|
|
return (addr & 1) ? GET_HIBYTE(data) : data;
|
|
}
|
|
|
|
void DecompressToVRAM(uint32 src, uint16 dst_addr) { // 0x80B271
|
|
decompress_src = src;
|
|
int src_pos, dst_pos = dst_addr;
|
|
while (1) {
|
|
int len;
|
|
uint8 b = DecompNextByte(), cmd;
|
|
if (b == 0xFF)
|
|
break;
|
|
if ((b & 0xE0) == 0xE0) {
|
|
cmd = (8 * b) & 0xE0;
|
|
len = ((b & 3) << 8 | DecompNextByte()) + 1;
|
|
} else {
|
|
cmd = b & 0xE0;
|
|
len = (b & 0x1F) + 1;
|
|
}
|
|
if (cmd & 0x80) {
|
|
uint8 want_xor = cmd & 0x20 ? 0xff : 0;
|
|
if (cmd >= 0xC0) {
|
|
src_pos = dst_pos - DecompNextByte();
|
|
} else {
|
|
src_pos = DecompNextByte();
|
|
src_pos += DecompNextByte() * 256;
|
|
src_pos += dst_addr;
|
|
}
|
|
do {
|
|
b = ReadPpuByte(src_pos++) ^ want_xor;
|
|
WriteRegWord(VMADDL, dst_pos >> 1);
|
|
WriteReg(VMDATAL + (dst_pos++ & 1), b);
|
|
} while (--len);
|
|
} else {
|
|
switch (cmd) {
|
|
case 0x20:
|
|
b = DecompNextByte();
|
|
do {
|
|
WriteReg(VMDATAL + (dst_pos++ & 1), b);
|
|
} while (--len);
|
|
break;
|
|
case 0x40: {
|
|
b = DecompNextByte();
|
|
uint8 b2 = DecompNextByte();
|
|
do {
|
|
WriteReg(VMDATAL + (dst_pos++ & 1), b);
|
|
if (!--len)
|
|
break;
|
|
WriteReg(VMDATAL + (dst_pos++ & 1), b2);
|
|
} while (--len);
|
|
break;
|
|
}
|
|
case 0x60:
|
|
b = DecompNextByte();
|
|
do {
|
|
WriteReg(VMDATAL + (dst_pos++ & 1), b++);
|
|
} while (--len);
|
|
break;
|
|
default:
|
|
do {
|
|
b = DecompNextByte();
|
|
WriteReg(VMDATAL + (dst_pos++ & 1), b++);
|
|
} while (--len);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void LoadFromLoadStation(void) { // 0x80C437
|
|
save_station_lockout_flag = 1;
|
|
const uint16 *v0 = (const uint16 *)RomPtr_80(kLoadStationLists[area_index] + 14 * load_station_index);
|
|
room_ptr = *v0;
|
|
door_def_ptr = v0[1];
|
|
door_bts = v0[2];
|
|
layer1_x_pos = v0[3];
|
|
bg1_x_offset = layer1_x_pos;
|
|
layer1_y_pos = v0[4];
|
|
bg1_y_offset = layer1_y_pos;
|
|
samus_y_pos = layer1_y_pos + v0[5];
|
|
samus_prev_y_pos = samus_y_pos;
|
|
samus_x_pos = v0[6] + layer1_x_pos + 128;
|
|
samus_prev_x_pos = samus_x_pos;
|
|
reg_BG1HOFS = 0;
|
|
reg_BG1VOFS = 0;
|
|
LOBYTE(area_index) = get_RoomDefHeader(room_ptr)->area_index_;
|
|
LOBYTE(debug_disable_minimap) = 0;
|
|
}
|
|
|
|
|
|
void SetElevatorsAsUsed(void) { // 0x80CD07
|
|
const uint8 *v0 = RomPtr_80(off_80CD46[area_index] + 4 * ((elevator_door_properties_orientation & 0xF) - 1));
|
|
used_save_stations_and_elevators[v0[0]] |= v0[1];
|
|
used_save_stations_and_elevators[v0[2]] |= v0[3];
|
|
}
|