ref: 1b95f8b2b540d45efb57b129840115b2aed6f666
dir: /dungeon.c/
#include "zelda_rtl.h" #include "snes/snes_regs.h" #include "variables.h" #include "dungeon.h" #include "nmi.h" #include "hud.h" #include "load_gfx.h" #include "overworld.h" #include "sprite.h" #include "ancilla.h" #include "ending.h" #include "player.h" #include "misc.h" #include "player_oam.h" #include "tagalong.h" #include "messaging.h" #include "assets.h" // todo: move to config static const uint16 kBossRooms[] = { 200, 51, 7, 32, 6, 90, 41, 144, 222, 164, 172, 13 }; static const uint8 kDungeonExit_From[12] = {200, 51, 7, 32, 6, 90, 41, 144, 222, 164, 172, 13}; static const uint8 kDungeonExit_To[12] = {201, 99, 119, 32, 40, 74, 89, 152, 14, 214, 219, 13}; static const uint16 kObjectSubtype1Params[] = { 0x3d8, 0x2e8, 0x2f8, 0x328, 0x338, 0x400, 0x410, 0x388, 0x390, 0x420, 0x42a, 0x434, 0x43e, 0x448, 0x452, 0x45c, 0x466, 0x470, 0x47a, 0x484, 0x48e, 0x498, 0x4a2, 0x4ac, 0x4b6, 0x4c0, 0x4ca, 0x4d4, 0x4de, 0x4e8, 0x4f2, 0x4fc, 0x506, 0x598, 0x600, 0x63c, 0x63c, 0x63c, 0x63c, 0x63c, 0x642, 0x64c, 0x652, 0x658, 0x65e, 0x664, 0x66a, 0x688, 0x694, 0x6a8, 0x6a8, 0x6a8, 0x6c8, 0x0, 0x78a, 0x7aa, 0xe26, 0x84a, 0x86a, 0x882, 0x8ca, 0x85a, 0x8fa, 0x91a, 0x920, 0x92a, 0x930, 0x936, 0x93c, 0x942, 0x948, 0x94e, 0x96c, 0x97e, 0x98e, 0x902, 0x99e, 0x9d8, 0x9d8, 0x9d8, 0x9fa, 0x156c, 0x1590, 0x1d86, 0x0, 0xa14, 0xa24, 0xa54, 0xa54, 0xa84, 0xa84, 0x14dc, 0x1500, 0x61e, 0xe52, 0x600, 0x3d8, 0x2c8, 0x2d8, 0x308, 0x318, 0x3e0, 0x3f0, 0x378, 0x380, 0x5fa, 0x648, 0x64a, 0x670, 0x67c, 0x6a8, 0x6a8, 0x6a8, 0x6c8, 0x0, 0x7aa, 0x7ca, 0x84a, 0x89a, 0x8b2, 0x90a, 0x926, 0x928, 0x912, 0x9f8, 0x1d7e, 0x0, 0xa34, 0xa44, 0xa54, 0xa6c, 0xa84, 0xa9c, 0x1524, 0x1548, 0x85a, 0x606, 0xe52, 0x5fa, 0x6a0, 0x6a2, 0xb12, 0xb14, 0x9b0, 0xb46, 0xb56, 0x1f52, 0x1f5a, 0x288, 0xe82, 0x1df2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d8, 0x3d8, 0x3d8, 0x3d8, 0x5aa, 0x5b2, 0x5b2, 0x5b2, 0x5b2, 0xe0, 0xe0, 0xe0, 0xe0, 0x110, 0x0, 0x0, 0x6a4, 0x6a6, 0xae6, 0xb06, 0xb0c, 0xb16, 0xb26, 0xb36, 0x1f52, 0x1f5a, 0x288, 0xeba, 0xe82, 0x1df2, 0x0, 0x0, 0x3d8, 0x510, 0x5aa, 0x5aa, 0x0, 0x168, 0xe0, 0x158, 0x100, 0x110, 0x178, 0x72a, 0x72a, 0x72a, 0x75a, 0x670, 0x670, 0x130, 0x148, 0x72a, 0x72a, 0x72a, 0x75a, 0xe0, 0x110, 0xf0, 0x110, 0x0, 0xab4, 0x8da, 0xade, 0x188, 0x1a0, 0x1b0, 0x1c0, 0x1d0, 0x1e0, 0x1f0, 0x200, 0x120, 0x2a8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; static const uint16 kObjectSubtype2Params[] = { 0xb66, 0xb86, 0xba6, 0xbc6, 0xc66, 0xc86, 0xca6, 0xcc6, 0xbe6, 0xc06, 0xc26, 0xc46, 0xce6, 0xd06, 0xd26, 0xd46, 0xd66, 0xd7e, 0xd96, 0xdae, 0xdc6, 0xdde, 0xdf6, 0xe0e, 0x398, 0x3a0, 0x3a8, 0x3b0, 0xe32, 0xe26, 0xea2, 0xe9a, 0xeca, 0xed2, 0xede, 0xede, 0xf1e, 0xf3e, 0xf5e, 0xf6a, 0xef6, 0xf72, 0xf92, 0xfa2, 0xfa2, 0x1088, 0x10a8, 0x10a8, 0x10c8, 0x10c8, 0x10c8, 0x10c8, 0xe52, 0x1108, 0x1108, 0x12a8, 0x1148, 0x1160, 0x1178, 0x1190, 0x1458, 0x1488, 0x2062, 0x2086, }; static const uint16 kObjectSubtype3Params[] = { 0x1614, 0x162c, 0x1654, 0xa0e, 0xa0c, 0x9fc, 0x9fe, 0xa00, 0xa02, 0xa04, 0xa06, 0xa08, 0xa0a, 0x0, 0xa10, 0xa12, 0x1dda, 0x1de2, 0x1dd6, 0x1dea, 0x15fc, 0x1dfa, 0x1df2, 0x1488, 0x1494, 0x149c, 0x14a4, 0x10e8, 0x10e8, 0x10e8, 0x11a8, 0x11c8, 0x11e8, 0x1208, 0x3b8, 0x3c0, 0x3c8, 0x3d0, 0x1228, 0x1248, 0x1268, 0x1288, 0x0, 0xe5a, 0xe62, 0x0, 0x0, 0xe82, 0xe8a, 0x14ac, 0x14c4, 0x10e8, 0x1614, 0x1614, 0x1614, 0x1614, 0x1614, 0x1614, 0x1cbe, 0x1cee, 0x1d1e, 0x1d4e, 0x1d8e, 0x1d96, 0x1d9e, 0x1da6, 0x1dae, 0x1db6, 0x1dbe, 0x1dc6, 0x1dce, 0x220, 0x260, 0x280, 0x1f3a, 0x1f62, 0x1f92, 0x1ff2, 0x2016, 0x1f42, 0xeaa, 0x1f4a, 0x1f52, 0x1f5a, 0x202e, 0x2062, 0x9b8, 0x9c0, 0x9c8, 0x9d0, 0xfa2, 0xfb2, 0xfc4, 0xff4, 0x1018, 0x1020, 0x15b4, 0x15d8, 0x20f6, 0xeba, 0x22e6, 0x22ee, 0x5da, 0x281e, 0x2ae0, 0x2d2a, 0x2f2a, 0x22f6, 0x2316, 0x232e, 0x2346, 0x235e, 0x2376, 0x23b6, 0x1e9a, 0x0, 0x2436, 0x149c, 0x24b6, 0x24e6, 0x2516, 0x1028, 0x1040, 0x1060, 0x1070, 0x1078, 0x1080, 0x0, }; static const uint16 kDoorTypeSrcData[] = { 0x2716, 0x272e, 0x272e, 0x2746, 0x2746, 0x2746, 0x2746, 0x2746, 0x2746, 0x275e, 0x275e, 0x275e, 0x275e, 0x2776, 0x278e, 0x27a6, 0x27be, 0x27be, 0x27d6, 0x27d6, 0x27ee, 0x2806, 0x2806, 0x281e, 0x2836, 0x2836, 0x2836, 0x2836, 0x284e, 0x2866, 0x2866, 0x2866, 0x2866, 0x287e, 0x2896, 0x28ae, 0x28c6, 0x28de, 0x28f6, 0x28f6, 0x28f6, 0x290e, 0x2926, 0x2958, 0x2978, 0x2990, 0x2990, 0x2990, 0x2990, 0x29a8, 0x29c0, 0x29d8, }; static const uint16 kDoorTypeSrcData2[] = { 0x29f0, 0x2a08, 0x2a08, 0x2a20, 0x2a20, 0x2a20, 0x2a20, 0x2a20, 0x2a20, 0x2a38, 0x2a38, 0x2a38, 0x2a38, 0x2a50, 0x2a68, 0x2a80, 0x2a98, 0x2a98, 0x2a98, 0x2a98, 0x2a98, 0x2ab0, 0x2ac8, 0x2ae0, 0x2af8, 0x2af8, 0x2af8, 0x2af8, 0x2b10, 0x2b28, 0x2b28, 0x2b28, 0x2b28, 0x2b40, 0x2b58, 0x2b70, 0x2b88, 0x2ba0, 0x2bb8, 0x2bb8, 0x2bb8, 0x2bd0, 0x2be8, 0x2c1a, 0x2c3a, 0x2c52, 0x2c6a, 0x2c6a, }; static const uint16 kDoorTypeSrcData3[] = { 0x2c6a, 0x2c82, 0x2c82, 0x2c9a, 0x2c9a, 0x2c9a, 0x2c9a, 0x2c9a, 0x2c9a, 0x2cb2, 0x2cb2, 0x2cb2, 0x2cb2, 0x2cca, 0x2ce2, 0x2cfa, 0x2cfa, 0x2cfa, 0x2cfa, 0x2cfa, 0x2cfa, 0x2d12, 0x2d12, 0x2d2a, 0x2d42, 0x2d42, 0x2d42, 0x2d42, 0x2d5a, 0x2d72, 0x2d72, 0x2d72, 0x2d72, 0x2d8a, 0x2da2, 0x2dba, 0x2dd2, 0x2dea, 0x2e02, 0x2e02, 0x2e02, 0x2e1a, 0x2e32, 0x2e32, 0x2e52, 0x2e6a, 0x2e6a, 0x2e6a, }; static const uint16 kDoorTypeSrcData4[] = { 0x2e6a, 0x2e82, 0x2e82, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2e9a, 0x2eb2, 0x2eb2, 0x2eb2, 0x2eb2, 0x2eca, 0x2ee2, 0x2efa, 0x2efa, 0x2efa, 0x2efa, 0x2efa, 0x2efa, 0x2f12, 0x2f12, 0x2f2a, 0x2f42, 0x2f42, 0x2f42, 0x2f42, 0x2f5a, 0x2f72, 0x2f72, 0x2f72, 0x2f72, 0x2f8a, 0x2fa2, 0x2fba, 0x2fd2, 0x2fea, 0x3002, 0x3002, 0x3002, 0x301a, 0x3032, 0x3032, 0x3052, 0x306a, 0x306a, }; static const uint16 kDoorPositionToTilemapOffs_Up[] = { 0x21c, 0x23c, 0x25c, 0x39c, 0x3bc, 0x3dc, 0x121c, 0x123c, 0x125c, 0x139c, 0x13bc, 0x13dc }; static const uint16 kDoorPositionToTilemapOffs_Down[] = { 0xd1c, 0xd3c, 0xd5c, 0xb9c, 0xbbc, 0xbdc, 0x1d1c, 0x1d3c, 0x1d5c, 0x1b9c, 0x1bbc, 0x1bdc }; static const uint16 kDoorPositionToTilemapOffs_Left[] = { 0x784, 0xf84, 0x1784, 0x78a, 0xf8a, 0x178a, 0x7c4, 0xfc4, 0x17c4, 0x7ca, 0xfca, 0x17ca }; static const uint16 kDoorPositionToTilemapOffs_Right[] = { 0x7b4, 0xfb4, 0x17b4, 0x7ae, 0xfae, 0x17ae, 0x7f4, 0xff4, 0x17f4, 0x7ee, 0xfee, 0x17ee }; static const int8 kSpiralTab1[] = { 0, 1, 1, -1, 1, 1, 1, 1 }; static const int8 kTeleportPitLevel1[] = { 0, 1, 1 }; static const int8 kTeleportPitLevel2[] = { 0, 0, 1 }; static const uint8 kDoorTypeRemap[] = { 0, 2, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 80, 0, 80, 80, 96, 98, 100, 102, 82, 90, 80, 82, 84, 86, 0, 80, 80, 0, 0, 0, 64, 88, 88, 0, 88, 88, 0, 0, }; static const int8 kStaircaseTab2[] = { 12, 32, 48, 56, 72, -44, -40, -64, -64, -88, 12, 24, 40, 48, 64, -28, -40, -56, -64, -80, }; static const int8 kStaircaseTab3[] = { 4, -4, 4, -4 }; static const int8 kStaircaseTab4[] = { 52, 52, 59, 58 }; static const int8 kStaircaseTab5[] = { 32, -64, 32, -32 }; static const uint8 kMovingWall_Sizes0[4] = { 5, 7, 11, 15 }; static const uint8 kMovingWall_Sizes1[4] = { 8, 16, 24, 32 }; static const uint8 kWatergateLayout[17] = { 0x1b, 0xa1, 0xc9, 0x51, 0xa1, 0xc9, 0x92, 0xa1, 0xc9, 0xa1, 0x33, 0xc9, 0xa1, 0x72, 0xc9, 0xff, 0xff, }; static const uint16 kChestOpenMasks[] = { 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000 }; const uint8 kLayoutQuadrantFlags[] = { 0xF, 0xF, 0xF, 0xF, 0xB, 0xB, 7, 7, 0xF, 0xB, 0xF, 7, 0xB, 0xF, 7, 0xF, 0xE, 0xD, 0xE, 0xD, 0xF, 0xF, 0xE, 0xD, 0xE, 0xD, 0xF, 0xF, 0xA, 9, 6, 5 }; static const uint8 kQuadrantVisitingFlags[] = { 8, 4, 2, 1, 0xC, 0xC, 3, 3, 0xA, 5, 0xA, 5, 0xF, 0xF, 0xF, 0xF }; #define XY(x, y) ((y)*64+(x)) static const uint8 kDungeon_MinigameChestPrizes1[8] = { 0x40, 0x41, 0x34, 0x42, 0x43, 0x44, 0x27, 0x17 }; static const uint8 kDungeon_RupeeChestMinigamePrizes[32] = { 0x47, 0x34, 0x46, 0x34, 0x46, 0x46, 0x34, 0x47, 0x46, 0x47, 0x34, 0x46, 0x47, 0x34, 0x46, 0x47, 0x34, 0x47, 0x41, 0x47, 0x41, 0x41, 0x47, 0x34, 0x41, 0x34, 0x47, 0x41, 0x34, 0x47, 0x41, 0x34, }; static const int8 kDungeon_QueryIfTileLiftable_x[4] = { 7, 7, -3, 16 }; static const int8 kDungeon_QueryIfTileLiftable_y[4] = { 3, 24, 14, 14 }; static const uint16 kDungeon_QueryIfTileLiftable_rv[16] = { 0x5252, 0x5050, 0x5454, 0x0, 0x2323 }; static const uint16 kDoor_BlastWallUp_Dsts[] = { 0xd8a, 0xdaa, 0xdca, 0x2b6, 0xab6, 0x12b6 }; #define adjacent_doors_flags (*(uint16*)(g_ram+0x1100)) #define adjacent_doors ((uint16*)(g_ram+0x1110)) static const DungPalInfo kDungPalinfos[41] = { { 0, 0, 3, 1}, { 2, 0, 3, 1}, { 4, 0, 10, 1}, { 6, 0, 1, 7}, {10, 2, 2, 7}, { 4, 4, 3, 10}, {12, 5, 8, 20}, {14, 0, 3, 10}, { 2, 0, 15, 20}, {10, 2, 0, 7}, { 2, 0, 15, 12}, { 6, 0, 6, 7}, { 0, 0, 14, 18}, {18, 5, 5, 11}, {18, 0, 2, 12}, {16, 5, 10, 7}, {16, 0, 16, 12}, {22, 7, 2, 7}, {22, 0, 7, 15}, { 8, 0, 4, 12}, { 8, 0, 4, 9}, { 4, 0, 3, 1}, {20, 0, 4, 4}, {20, 0, 20, 12}, {24, 5, 7, 11}, {24, 6, 16, 12}, {26, 5, 8, 20}, {26, 2, 0, 7}, { 6, 0, 3, 10}, {28, 0, 3, 1}, {30, 0, 11, 17}, { 4, 0, 11, 17}, {14, 0, 0, 2}, {32, 8, 19, 13}, {10, 0, 3, 10}, {20, 0, 4, 4}, {26, 2, 2, 7}, {26, 10, 0, 0}, { 0, 0, 3, 2}, {14, 0, 3, 7}, {26, 5, 5, 11}, }; // these are not used by the code, but needed for the comparison with the real rom to work. static const uint8 kDungeon_DrawObjectOffsets_BG1[33] = { 0, 0x20, 0x7e, 2, 0x20, 0x7e, 4, 0x20, 0x7e, 6, 0x20, 0x7e, 0x80, 0x20, 0x7e, 0x82, 0x20, 0x7e, 0x84, 0x20, 0x7e, 0x86, 0x20, 0x7e, 0, 0x21, 0x7e, 0x80, 0x21, 0x7e, 0, 0x22, 0x7e, }; static const uint8 kDungeon_DrawObjectOffsets_BG2[33] = { 0, 0x40, 0x7e, 2, 0x40, 0x7e, 4, 0x40, 0x7e, 6, 0x40, 0x7e, 0x80, 0x40, 0x7e, 0x82, 0x40, 0x7e, 0x84, 0x40, 0x7e, 0x86, 0x40, 0x7e, 0, 0x41, 0x7e, 0x80, 0x41, 0x7e, 0, 0x42, 0x7e, }; static const uint16 kUploadBgSrcs[] = { 0x0, 0x1000, 0x0, 0x40, 0x40, 0x1040, 0x1000, 0x1040, 0x1000, 0x0, 0x40, 0x0, 0x1040, 0x40, 0x1040, 0x1000 }; static const uint8 kUploadBgDsts[] = { 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 }; static const uint16 kTileAttrsByDoor[] = { 0x8080, 0x8484, 0x0, 0x101, 0x8484, 0x8e8e, 0x0, 0x0, 0x8888, 0x8e8e, 0x8080, 0x8080, 0x8282, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8282, 0x8e8e, 0x8080, 0x8282, 0x8080, 0x8080, 0x8080, 0x8282, 0x8282, 0x8080, 0x8080, 0x8080, 0x8484, 0x8484, 0x8686, 0x8888, 0x8686, 0x8686, 0x8080, 0x8080, }; static PlayerHandlerFunc *const kDungeon_Effect_Handler[28] = { &LayerEffect_Nothing, &LayerEffect_Nothing, &LayerEffect_Scroll, &LayerEffect_WaterRapids, &LayerEffect_Trinexx, &LayerEffect_Agahnim2, &LayerEffect_InvisibleFloor, &LayerEffect_Ganon, }; static const int16 kPushBlockMoveDistances[] = { -0x100, 0x100, -0x4, 0x4 }; static HandlerFuncK *const kDungTagroutines[] = { &Dung_TagRoutine_0x00, &RoomTag_NorthWestTrigger, &Dung_TagRoutine_0x2A, &Dung_TagRoutine_0x2B, &Dung_TagRoutine_0x2C, &Dung_TagRoutine_0x2D, &Dung_TagRoutine_0x2E, &Dung_TagRoutine_0x2F, &Dung_TagRoutine_0x30, &RoomTag_QuadrantTrigger, &RoomTag_RoomTrigger, &RoomTag_NorthWestTrigger, &Dung_TagRoutine_0x2A, &Dung_TagRoutine_0x2B, &Dung_TagRoutine_0x2C, &Dung_TagRoutine_0x2D, &Dung_TagRoutine_0x2E, &Dung_TagRoutine_0x2F, &Dung_TagRoutine_0x30, &RoomTag_QuadrantTrigger, &RoomTag_RoomTrigger_BlockDoor, &RoomTag_PrizeTriggerDoorDoor, &RoomTag_SwitchTrigger_HoldDoor, &RoomTag_SwitchTrigger_ToggleDoor, &RoomTag_WaterOff, &RoomTag_WaterOn, &RoomTag_WaterGate, &Dung_TagRoutine_0x1B, &RoomTag_MovingWall_East, &RoomTag_MovingWall_West, &RoomTag_MovingWallTorchesCheck, &RoomTag_MovingWallTorchesCheck, &RoomTag_Switch_ExplodingWall, &RoomTag_Holes0, &RoomTag_ChestHoles0, &Dung_TagRoutine_0x23, &RoomTag_Holes2, &RoomTag_GetHeartForPrize, &RoomTag_KillRoomBlock, &RoomTag_TriggerChest, &RoomTag_PullSwitchExplodingWall, &RoomTag_NorthWestTrigger, &Dung_TagRoutine_0x2A, &Dung_TagRoutine_0x2B, &Dung_TagRoutine_0x2C, &Dung_TagRoutine_0x2D, &Dung_TagRoutine_0x2E, &Dung_TagRoutine_0x2F, &Dung_TagRoutine_0x30, &RoomTag_QuadrantTrigger, &RoomTag_RoomTrigger, &RoomTag_TorchPuzzleDoor, &Dung_TagRoutine_0x34, &Dung_TagRoutine_0x35, &Dung_TagRoutine_0x36, &Dung_TagRoutine_0x37, &RoomTag_Agahnim, &Dung_TagRoutine_0x39, &Dung_TagRoutine_0x3A, &Dung_TagRoutine_0x3B, &RoomTag_PushBlockForChest, &RoomTag_GanonDoor, &RoomTag_TorchPuzzleChest, &RoomTag_RekillableBoss, }; static const uint16 kDoorAnimUpSrc[] = { 0x306a, 0x306a, 0x3082, 0x309a, 0x30b2 }; static const uint16 kDoorAnimDownSrc[] = { 0x30b2, 0x30ca, 0x30e2, 0x30fa, 0x3112 }; static const uint16 kDoorAnimLeftSrc[] = { 0x3112, 0x312a, 0x3142, 0x315a, 0x3172 }; static const uint16 kDoorAnimRightSrc[] = { 0x3172, 0x318a, 0x31a2, 0x31ba, 0x31D2 }; static PlayerHandlerFunc *const kDungeon_IntraRoomTrans[8] = { &DungeonTransition_Subtile_PrepTransition, &DungeonTransition_Subtile_ApplyFilter, &DungeonTransition_Subtile_ResetShutters, &DungeonTransition_ScrollRoom, &DungeonTransition_FindSubtileLanding, &Dungeon_IntraRoomTrans_State5, &DungeonTransition_Subtile_ApplyFilter, &DungeonTransition_Subtile_TriggerShutters, }; static PlayerHandlerFunc *const kDungeon_InterRoomTrans[16] = { &Module07_02_00_InitializeTransition, &Module07_02_01_LoadNextRoom, &Module07_02_FadedFilter, &Dungeon_InterRoomTrans_State3, &Dungeon_InterRoomTrans_State4, &Dungeon_InterRoomTrans_notDarkRoom, &Dungeon_InterRoomTrans_State4, &Dungeon_InterRoomTrans_State7, &DungeonTransition_ScrollRoom, &Dungeon_InterRoomTrans_State9, &Dungeon_InterRoomTrans_State10, &Dungeon_InterRoomTrans_State9, &Dungeon_InterRoomTrans_State12, &Dungeon_InterRoomTrans_State13, &Module07_02_FadedFilter, &Dungeon_InterRoomTrans_State15, }; static PlayerHandlerFunc *const kDungeon_Submodule_7_DownFloorTrans[18] = { &Module07_07_00_HandleMusicAndResetRoom, &ApplyPaletteFilter_bounce, &Dungeon_InitializeRoomFromSpecial, &DungeonTransition_TriggerBGC34UpdateAndAdvance, &DungeonTransition_TriggerBGC56UpdateAndAdvance, &DungeonTransition_LoadSpriteGFX, &Module07_07_06_SyncBG1and2, &Dungeon_InterRoomTrans_State4, &Dungeon_InterRoomTrans_notDarkRoom, &Dungeon_InterRoomTrans_State4, &Dungeon_InterRoomTrans_notDarkRoom, &Dungeon_InterRoomTrans_State4, &Dungeon_InterRoomTrans_notDarkRoom, &Dungeon_InterRoomTrans_State4, &Dungeon_Staircase14, &Module07_07_0F_FallingFadeIn, &Module07_07_10_LandLinkFromFalling, &Module07_07_11_CacheRoomAndSetMusic, }; static PlayerHandlerFunc *const kWatergateFuncs[6] = { &FloodDam_PrepTiles_init, &Watergate_Main_State1, &Watergate_Main_State1, &Watergate_Main_State1, &FloodDam_Expand, &FloodDam_Fill, }; static const int8 kSpiralStaircaseX[] = { -28, -28, 24, 24 }; static const int8 kSpiralStaircaseY[] = { 16, -10, -10, -32 }; static PlayerHandlerFunc *const kDungeon_SpiralStaircase[20] = { &Module07_0E_00_InitPriorityAndScreens, &Module07_0E_01_HandleMusicAndResetProps, &Module07_0E_02_ApplyFilterIf, &Dungeon_InitializeRoomFromSpecial, &DungeonTransition_TriggerBGC34UpdateAndAdvance, &DungeonTransition_TriggerBGC56UpdateAndAdvance, &DungeonTransition_LoadSpriteGFX, &Dungeon_SyncBackgroundsFromSpiralStairs, &Dungeon_InterRoomTrans_State4, &Dungeon_InterRoomTrans_notDarkRoom, &Dungeon_InterRoomTrans_State4, &Dungeon_SpiralStaircase11, &Dungeon_SpiralStaircase12, &Dungeon_SpiralStaircase11, &Dungeon_SpiralStaircase12, &Dungeon_DoubleApplyAndIncrementGrayscale, &Dungeon_AdvanceThenSetBossMusicUnorthodox, &Dungeon_SpiralStaircase17, &Dungeon_SpiralStaircase18, &Module07_0E_13_SetRoomAndLayerAndCache, }; static PlayerHandlerFunc *const kDungeon_Submodule_F[2] = { &Module07_0F_00_InitSpotlight, &Module07_0F_01_OperateSpotlight, }; static PlayerHandlerFunc *const kDungeon_StraightStaircase[2] = { &Module07_10_00_InitStairs, &Module07_10_01_ClimbStairs, }; static PlayerHandlerFunc *const kDungeon_StraightStaircaseDown[2] = { &Module07_08_00_InitStairs, &Module07_08_01_ClimbStairs, }; static PlayerHandlerFunc *const kDungeon_StraightStairs[19] = { &Module07_11_00_PrepAndReset, &Module07_11_01_FadeOut, &Module07_11_02_LoadAndPrepRoom, &Module07_11_03_FilterAndLoadBGChars, &Module07_11_04_FilterDoBGAndResetSprites, &Dungeon_SpiralStaircase11, &Dungeon_SpiralStaircase12, &Dungeon_SpiralStaircase11, &Dungeon_SpiralStaircase12, &Module07_11_09_LoadSpriteGraphics, &Module07_11_0A_ScrollCamera, &Module07_11_0B_PrepDestination, &Dungeon_InterRoomTrans_State4, &Dungeon_InterRoomTrans_notDarkRoom, &Dungeon_InterRoomTrans_State4, &Dungeon_DoubleApplyAndIncrementGrayscale, &Module07_11_19_SetSongAndFilter, &Module07_11_11_KeepSliding, &ResetThenCacheRoomEntryProperties, }; static PlayerHandlerFunc *const kDungeon_Teleport[15] = { &ResetTransitionPropsAndAdvance_ResetInterface, &Module07_15_01_ApplyMosaicAndFilter, &Dungeon_InitializeRoomFromSpecial, &DungeonTransition_LoadSpriteGFX, &Module07_15_04_SyncRoomPropsAndBuildOverlay, &Dungeon_InterRoomTrans_State4, &Dungeon_InterRoomTrans_notDarkRoom, &Dungeon_InterRoomTrans_State4, &Dungeon_InterRoomTrans_notDarkRoom, &Dungeon_InterRoomTrans_State4, &Dungeon_InterRoomTrans_notDarkRoom, &Dungeon_InterRoomTrans_State4, &Dungeon_Staircase14, &Module07_15_0E_FadeInFromWarp, &Module07_15_0F_FinalizeAndCacheEntry, }; static PlayerHandlerFunc *const kDungeonSubmodules[31] = { &Module07_00_PlayerControl, &Module07_01_SubtileTransition, &Module07_02_SupertileTransition, &Module07_03_OverlayChange, &Module07_04_UnlockDoor, &Module07_05_ControlShutters, &Module07_06_FatInterRoomStairs, &Module07_07_FallingTransition, &Module07_08_NorthIntraRoomStairs, &Module07_09_OpenCrackedDoor, &Module07_0A_ChangeBrightness, &Module07_0B_DrainSwampPool, &Module07_0C_FloodSwampWater, &Module07_0D_FloodDam, &Module07_0E_SpiralStairs, &Module07_0F_LandingWipe, &Module07_10_SouthIntraRoomStairs, &Module07_11_StraightInterroomStairs, &Module07_11_StraightInterroomStairs, &Module07_11_StraightInterroomStairs, &Module07_14_RecoverFromFall, &Module07_15_WarpPad, &Module07_16_UpdatePegs, &Module07_17_PressurePlate, &Module07_18_RescuedMaiden, &Module07_19_MirrorFade, &Module07_1A_RoomDraw_OpenTriforceDoor_bounce, }; const uint8 kDungAnimatedTiles[24] = { 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5f, 0x5d, 0x5f, 0x5f, 0x5e, 0x5f, 0x5e, 0x5e, 0x5d, 0x5d, 0x5e, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, }; uint16 *DstoPtr(uint16 d) { return (uint16 *)&(g_ram[dung_line_ptrs_row0 + d * 2]); } void Object_Fill_Nx1(int n, const uint16 *src, uint16 *dst) { int t = src[0]; do *dst++ = t; while (--n); } void Object_Draw_5x4(const uint16 *src, uint16 *dst) { int n = 5; do { dst[XY(0, 0)] = src[0]; dst[XY(1, 0)] = src[1]; dst[XY(2, 0)] = src[2]; dst[XY(3, 0)] = src[3]; dst += XY(0, 1), src += 4; } while (--n); } void Object_Draw_4x2_BothBgs(const uint16 *src, uint16 dsto) { dung_bg1[dsto + XY(0, 0)] = dung_bg2[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(1, 0)] = dung_bg2[dsto + XY(1, 0)] = src[1]; dung_bg1[dsto + XY(2, 0)] = dung_bg2[dsto + XY(2, 0)] = src[2]; dung_bg1[dsto + XY(3, 0)] = dung_bg2[dsto + XY(3, 0)] = src[3]; dung_bg1[dsto + XY(0, 1)] = dung_bg2[dsto + XY(0, 1)] = src[4]; dung_bg1[dsto + XY(1, 1)] = dung_bg2[dsto + XY(1, 1)] = src[5]; dung_bg1[dsto + XY(2, 1)] = dung_bg2[dsto + XY(2, 1)] = src[6]; dung_bg1[dsto + XY(3, 1)] = dung_bg2[dsto + XY(3, 1)] = src[7]; } void Object_ChestPlatform_Helper(const uint16 *src, int dsto) { dung_bg2[dsto] = src[0]; int n = src[3]; for (int i = dung_draw_width_indicator; i--; dsto++) dung_bg2[1 + dsto] = n; dung_bg2[1 + dsto] = src[6]; dung_bg2[2 + dsto] = dung_bg2[3 + dsto] = dung_bg2[4 + dsto] = dung_bg2[5 + dsto] = src[9]; dung_bg2[6 + dsto] = src[12]; n = src[15]; for (int i = dung_draw_width_indicator; i--; dsto++) dung_bg2[7 + dsto] = n; dung_bg2[7 + dsto] = src[18]; } void Object_Hole(const uint16 *src, uint16 *dst) { Object_SizeAtoAplus15(4); int w = dung_draw_width_indicator; for (int i = 0; i < w; i++) Object_Fill_Nx1(w, src, dst + XY(0, i)); // fill top/bottom src = SrcPtr(0x63c); dst[XY(0, 0)] = src[0]; Object_Fill_Nx1(w - 2, src + 1, dst + XY(1, 0)); dst[XY(w - 1, 0)] = src[2]; dst[XY(0, w - 1)] = src[3]; Object_Fill_Nx1(w - 2, src + 4, dst + XY(1, w - 1)); dst[XY(w - 1, w - 1)] = src[5]; // fill left/right edge src = SrcPtr(0x648); for (int i = 1; i < w - 1; i++) { dst[XY(0, i)] = src[0]; dst[XY(w - 1, i)] = src[1]; } } // dsto is half the value of Y void LoadType1ObjectSubtype1(uint8 idx, uint16 *dst, uint16 dsto) { uint16 param1 = kObjectSubtype1Params[idx]; const uint16 *src = SrcPtr(param1); int n; switch (idx) { case 0x0: // RoomDraw_Rightwards2x2_1to15or32 - Ceiling case 0xb8: case 0xb9: // B8 - Blue Switch Block [L-R] RoomDraw_GetObjectSize_1to15or32(); do { RoomDraw_Rightwards2x2(src, dst), dst += XY(2, 0); } while (--dung_draw_width_indicator); break; case 0x1: case 0x2: // RoomDraw_Rightwards2x4_1to15or26 - [N]Wall Horz: [L-R] case 0xb6: case 0xb7: // B6 - [N]Wall Decor: 1/2 [L-R] RoomDraw_GetObjectSize_1to15or26(); do { RoomDraw_Object_Nx4(2, src, dst), dst += XY(2, 0); } while (--dung_draw_width_indicator); break; case 0x3: case 0x4: // RoomDraw_Rightwards2x4spaced4_1to16 - 03 - [N]Wall Horz: (LOW) [L-R] RoomDraw_GetObjectSize_1to16(); do { dung_bg1[dsto + XY(0, 0)] = dung_bg2[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(0, 1)] = dung_bg2[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = dung_bg2[dsto + XY(0, 2)] = src[2]; dung_bg1[dsto + XY(0, 3)] = dung_bg2[dsto + XY(0, 3)] = src[3]; dung_bg1[dsto + XY(1, 0)] = dung_bg2[dsto + XY(1, 0)] = src[4]; dung_bg1[dsto + XY(1, 1)] = dung_bg2[dsto + XY(1, 1)] = src[5]; dung_bg1[dsto + XY(1, 2)] = dung_bg2[dsto + XY(1, 2)] = src[6]; dung_bg1[dsto + XY(1, 3)] = dung_bg2[dsto + XY(1, 3)] = src[7]; dsto += XY(2, 0); } while (--dung_draw_width_indicator); break; case 0x5: case 0x6: // RoomDraw_Rightwards2x4spaced4_1to16_BothBG - 05 - [N]Wall Column [L-R] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Object_Nx4(2, src, dst), dst += XY(6, 0); } while (--dung_draw_width_indicator); break; case 0x7: case 0x8: case 0x53: // RoomDraw_Rightwards2x2_1to16 - 07 - [N]Wall Pit [L-R] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Rightwards2x2(src, dst), dst += XY(2, 0); } while (--dung_draw_width_indicator); break; case 0x9: case 0x0c: case 0x0d: case 0x10: case 0x11: case 0x14: // 09 - / Wall Wood Bot (HIGH) [NW] Object_SizeAtoAplus15(6); do { RoomDraw_DrawObject2x2and1(src, dst), dst += XY(1, -1); } while (--dung_draw_width_indicator); break; case 0x0a: case 0x0b: case 0x0e: case 0x0f: case 0x12: case 0x13: // 12 - \ Wall Tile2 Bot (HIGH) [SW] Object_SizeAtoAplus15(6); do { RoomDraw_DrawObject2x2and1(src, dst), dst += XY(1, 1); } while (--dung_draw_width_indicator); break; case 0x15: case 0x18: case 0x19: case 0x1C: case 0x1D: case 0x20: // 15 - / Wall Tile Top (LOW)[NW] Object_SizeAtoAplus15(6); do { dung_bg1[dsto + XY(0, 0)] = dung_bg2[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(0, 1)] = dung_bg2[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = dung_bg2[dsto + XY(0, 2)] = src[2]; dung_bg1[dsto + XY(0, 3)] = dung_bg2[dsto + XY(0, 3)] = src[3]; dung_bg1[dsto + XY(0, 4)] = dung_bg2[dsto + XY(0, 4)] = src[4]; dsto -= 63; } while (--dung_draw_width_indicator); break; case 0x16: case 0x17: case 0x1A: case 0x1B: case 0x1E: case 0x1F: // 16 - \ Wall Tile Top (LOW)[SW] Object_SizeAtoAplus15(6); do { dung_bg1[dsto + XY(0, 0)] = dung_bg2[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(0, 1)] = dung_bg2[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = dung_bg2[dsto + XY(0, 2)] = src[2]; dung_bg1[dsto + XY(0, 3)] = dung_bg2[dsto + XY(0, 3)] = src[3]; dung_bg1[dsto + XY(0, 4)] = dung_bg2[dsto + XY(0, 4)] = src[4]; dsto += 65; } while (--dung_draw_width_indicator); break; case 0x21: // 21 - Mini Stairs [L-R] dung_draw_width_indicator = (dung_draw_width_indicator << 2 | dung_draw_height_indicator) * 2 + 1; RoomDraw_1x3_rightwards(2, src, dst), dst += XY(2, 0); do { RoomDraw_1x3_rightwards(1, src + 3, dst), dst += XY(1, 0); } while (--dung_draw_width_indicator); RoomDraw_1x3_rightwards(1, src + 6, dst); break; case 0x22: { // 22 - Horz: Rail Thin [L-R] Object_SizeAtoAplus15(2); if ((dst[0] & 0x3ff) != 0xe2) dst[0] = src[0]; n = src[1]; do *++dst = n; while (--dung_draw_width_indicator); dst[1] = src[2]; break; } case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: // 23 - Pit [N]Edge [L-R] case 0x3f: case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: // 3F - Water Edge [L-R] case 0x45: case 0x46: case 0xb3: case 0xb4: RoomDraw_GetObjectSize_1to16(); n = dst[0] & 0x3ff; if (n != 0x1db && n != 0x1a6 && n != 0x1dd && n != 0x1fc) dst[0] = src[0]; n = src[1]; do *++dst = n; while (--dung_draw_width_indicator); dst[1] = src[2]; break; case 0x2f: // 2F - Rail Wall [L-R] Object_SizeAtoAplus15(10); n = *src++; if ((dst[0] & 0x3ff) != 0xe2) { dst[XY(0, 0)] = src[0]; dst[XY(1, 0)] = src[1]; dst[XY(1, 1)] = dst[XY(0, 1)] = n; dst += 2; } src += 2; do { dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = n; } while (dst++, --dung_draw_width_indicator); src++; dst[XY(0, 0)] = src[0]; dst[XY(1, 0)] = src[1]; dst[XY(1, 1)] = dst[XY(0, 1)] = n; break; case 0x30: // 30 - Rail Wall [L-R] Object_SizeAtoAplus15(10); n = *src++; if ((dst[XY(0, 1)] & 0x3ff) != 0xe2) { dst[XY(0, 0)] = dst[XY(1, 0)] = n; dst[XY(0, 1)] = src[0]; dst[XY(1, 1)] = src[1]; dst += 2; } src += 2; do { dst[XY(0, 0)] = n; dst[XY(0, 1)] = src[0]; } while (dst++, --dung_draw_width_indicator); src++; dst[XY(0, 0)] = dst[XY(1, 0)] = n; dst[XY(0, 1)] = src[0]; dst[XY(1, 1)] = src[1]; break; case 0x31: case 0x32: // 31 - Unused -empty case 0x35: case 0x54: case 0x57:case 0x58:case 0x59:case 0x5A: break; case 0x33: // 33 - Red Carpet Floor [L-R] case 0xb2: case 0xba: // B2 - Floor? [L-R] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_4x4(src, dst), dst += XY(4, 0); } while (--dung_draw_width_indicator); break; case 0x34: // 34 - Red Carpet Floor Trim [L-R] Object_SizeAtoAplus15(4); n = src[0]; do *dst++ = n; while (--dung_draw_width_indicator); break; case 0x36: case 0x37: // 36 - [N]Curtain [L-R] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_4x4(src, dst), dst += XY(6, 0); } while (--dung_draw_width_indicator); break; case 0x38: // 38 - Statue [L-R] src = (uint16 *)((uint8 *)src - param1 + 0xe26); RoomDraw_GetObjectSize_1to16(); do { RoomDraw_1x3_rightwards(2, src, dst), dst += XY(4, 0); } while (--dung_draw_width_indicator); break; case 0x39: case 0x3d: // 39 - Column [L-R] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Object_Nx4(2, src, dst), dst += XY(6, 0); } while (--dung_draw_width_indicator); break; case 0x3a: case 0x3b: // 3A - [N]Wall Decor: [L-R] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_1x3_rightwards(4, src, dst), dst += XY(8, 0); } while (--dung_draw_width_indicator); break; case 0x3c: // 3C - Double Chair [L-R] RoomDraw_GetObjectSize_1to16(); do { const uint16 *src = SrcPtr(0x8ca); RoomDraw_Rightwards2x2(src + 0, dst); RoomDraw_Rightwards2x2(src + 4, dst + XY(0, 6)); dst += 4; } while (--dung_draw_width_indicator); break; case 0x3e: case 0x4b: // 3E - [N]Wall Column [L-R] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Rightwards2x2(src, dst), dst += XY(14, 0); } while (--dung_draw_width_indicator); break; case 0x47: // 47 - Unused Waterfall [L-R] RoomDraw_GetObjectSize_1to16(); dung_draw_width_indicator <<= 1; dst = RoomDraw_DrawObject2x2and1(src, dst) + 1; do { RoomDraw_DrawObject2x2and1(src + 5, dst); } while (dst++, --dung_draw_width_indicator); RoomDraw_DrawObject2x2and1(src + 10, dst); break; case 0x48: RoomDraw_GetObjectSize_1to16(); dung_draw_width_indicator <<= 1; RoomDraw_1x3_rightwards(1, src, dst), dst += XY(1, 0); do { dst[XY(0, 0)] = src[3]; dst[XY(0, 1)] = src[4]; dst[XY(0, 2)] = src[5]; } while (dst++, --dung_draw_width_indicator); RoomDraw_1x3_rightwards(1, src + 6, dst); break; case 0x49: case 0x4A: // RoomDraw_RightwardsFloorTile4x2_1to16 ; 49 - N/A RoomDraw_GetObjectSize_1to16(); RoomDraw_Downwards4x2VariableSpacing(4, src, dst); break; case 0x4c: // 4C - Bar [L-R] RoomDraw_GetObjectSize_1to16(); dung_draw_width_indicator <<= 1; dst = RoomDraw_RightwardBarSegment(src, dst) + 1; do { dst = RoomDraw_RightwardBarSegment(src + 3, dst) + 1; } while (--dung_draw_width_indicator); dst = RoomDraw_RightwardBarSegment(src + 6, dst) + 1; break; case 0x4d: case 0x4e: case 0x4f: // 4C - Bar [L-R] RoomDraw_GetObjectSize_1to16(); RoomDraw_Object_Nx4(1, src, dst), dst += XY(1, 0); do { RoomDraw_Object_Nx4(2, src + 4, dst), dst += XY(2, 0); } while (--dung_draw_width_indicator); RoomDraw_RightwardShelfEnd(src + 12, dst); break; case 0x50: // 50 - Cane Ride [L-R] Object_SizeAtoAplus15(2); n = src[0]; do *dst++ = n; while (--dung_draw_width_indicator); break; case 0x51: case 0x52: // 51 - [N]Canon Hole [L-R] case 0x5B: case 0x5C: RoomDraw_GetObjectSize_1to16(); RoomDraw_1x3_rightwards(2, src, dst), dst += XY(2, 0); while (--dung_draw_width_indicator) RoomDraw_1x3_rightwards(2, src + 6, dst), dst += XY(2, 0); RoomDraw_1x3_rightwards(2, src + 12, dst); break; case 0x55: case 0x56: // 55 - [N]Wall Torches [L-R] RoomDraw_GetObjectSize_1to16(); RoomDraw_Downwards4x2VariableSpacing(12, src, dst); break; case 0x5D: // 5D - Large Horz: Rail [L-R] RoomDraw_GetObjectSize_1to16(); dung_draw_width_indicator++; RoomDraw_1x3_rightwards(2, src, dst), dst += XY(2, 0); do { RoomDraw_RightwardBarSegment(src + 6, dst), dst += XY(1, 0); } while (--dung_draw_width_indicator); RoomDraw_1x3_rightwards(2, src + 9, dst); break; case 0x5E: // 5E - Block [L-R] case 0xbb: // BB - N/A RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Rightwards2x2(src, dst), dst += XY(4, 0); } while (--dung_draw_width_indicator); break; case 0x5f: { // 5F - Long Horz: Rail [L-R] Object_SizeAtoAplus15(21); if ((dst[0] & 0x3ff) != 0xe2) dst[0] = src[0]; n = src[1]; do *++dst = n; while (--dung_draw_width_indicator); dst[1] = src[2]; break; } case 0x60: // 60 - Ceiling [U-D] case 0x92: case 0x93: // 92 - Blue Peg Block [U-D] RoomDraw_GetObjectSize_1to15or32(); do { RoomDraw_Rightwards2x2(src, dst), dst += XY(0, 2); } while (--dung_draw_width_indicator); break; case 0x61: case 0x62: case 0x90: case 0x91: // 61 - [W]Wall Vert: [U-D] RoomDraw_GetObjectSize_1to15or26(); RoomDraw_Downwards4x2VariableSpacing(2 * 64, src, dst); break; case 0x63: case 0x64: // RoomDraw_Downwards4x2_1to16_BothBG - 63 - [W]Wall Vert: (LOW) [U-D] RoomDraw_GetObjectSize_1to16(); do { dung_bg1[dsto + XY(0, 0)] = dung_bg2[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(1, 0)] = dung_bg2[dsto + XY(1, 0)] = src[1]; dung_bg1[dsto + XY(2, 0)] = dung_bg2[dsto + XY(2, 0)] = src[2]; dung_bg1[dsto + XY(3, 0)] = dung_bg2[dsto + XY(3, 0)] = src[3]; dung_bg1[dsto + XY(0, 1)] = dung_bg2[dsto + XY(0, 1)] = src[4]; dung_bg1[dsto + XY(1, 1)] = dung_bg2[dsto + XY(1, 1)] = src[5]; dung_bg1[dsto + XY(2, 1)] = dung_bg2[dsto + XY(2, 1)] = src[6]; dung_bg1[dsto + XY(3, 1)] = dung_bg2[dsto + XY(3, 1)] = src[7]; dsto += XY(0, 2); } while (--dung_draw_width_indicator); break; case 0x65: case 0x66: // 65 - [W]Wall Column [U-D] RoomDraw_GetObjectSize_1to16(); RoomDraw_Downwards4x2VariableSpacing(6 * 64, src, dst); break; case 0x67: case 0x68: // 67 - [W]Wall Pit [U-D] case 0x7d: // 7D - Pipe Ride [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Rightwards2x2(src, dst), dst += XY(0, 2); } while (--dung_draw_width_indicator); break; case 0x69: // 69 - Vert: Rail Thin [U-D] Object_SizeAtoAplus15(2); if ((dst[0] & 0x3ff) != 0xe3) dst[0] = src[0]; n = src[1]; do { dst += 64; *dst = n; } while (--dung_draw_width_indicator); dst[64] = src[2]; break; case 0x6a: case 0x6b: // 6A - [W]Pit Edge [U-D] case 0x79: case 0x7a: // 79 - Water Edge [U-D] case 0x8d: case 0x8e: // 8D - [W]Edge [U-D] RoomDraw_GetObjectSize_1to16(); do { dst[0] = src[0], dst += XY(0, 1); } while (--dung_draw_width_indicator); break; case 0x6c: // 6C - [W]Rail Wall [U-D] Object_SizeAtoAplus15(10); n = *src++; if ((dst[0] & 0x3ff) != 0xe3) { dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(1, 0)] = dst[XY(1, 1)] = n; dst += XY(0, 2); } src += 2; do { dst[XY(0, 0)] = src[0]; dst[XY(1, 0)] = n; dst += XY(0, 1); } while (--dung_draw_width_indicator); src += 1; dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(1, 0)] = dst[XY(1, 1)] = n; break; case 0x6d: // 6D - [E]Rail Wall [U-D] Object_SizeAtoAplus15(10); n = *src++; if ((dst[XY(1, 0)] & 0x3ff) != 0xe3) { dst[XY(0, 0)] = dst[XY(0, 1)] = n; dst[XY(1, 0)] = src[0]; dst[XY(1, 1)] = src[1]; dst += XY(0, 2); } src += 2; do { dst[XY(0, 0)] = n; dst[XY(1, 0)] = src[0]; dst += XY(0, 1); } while (--dung_draw_width_indicator); src += 1; dst[XY(0, 0)] = dst[XY(0, 1)] = n; dst[XY(1, 0)] = src[0]; dst[XY(1, 1)] = src[1]; break; case 0x6e: case 0x6f: // unused case 0x72: case 0x7e: break; case 0x70: case 0x94: // 70 - Red Floor/Wire Floor [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_4x4(src, dst), dst += XY(0, 4); } while (--dung_draw_width_indicator); break; case 0x71: // 71 - Red Carpet Floor Trim [U-D] Object_SizeAtoAplus15(4); do { *dst = src[0], dst += XY(0, 1); } while (--dung_draw_width_indicator); break; case 0x73: case 0x74: // 73 - [W]Curtain [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_4x4(src, dst), dst += XY(0, 6); } while (--dung_draw_width_indicator); break; case 0x75: case 0x87: // 75 - Column [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Object_Nx4(2, src, dst), dst += XY(0, 6); } while (--dung_draw_width_indicator); break; case 0x76: case 0x77: // 76 - [W]Wall Decor: [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Object_Nx4(3, src, dst), dst += XY(0, 8); } while (--dung_draw_width_indicator); break; case 0x78: case 0x7b: // 78 - [W]Wall Top Column [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Rightwards2x2(src, dst), dst += XY(0, 14); } while (--dung_draw_width_indicator); break; case 0x7c: // 7C - Cane Ride [U-D] RoomDraw_GetObjectSize_1to16(); dung_draw_width_indicator += 1; do { dst[0] = src[0], dst += XY(0, 1); } while (--dung_draw_width_indicator); break; case 0x7f: case 0x80: // 7F - [W]Wall Torches [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Object_Nx4(2, src, dst), dst += XY(0, 12); } while (--dung_draw_width_indicator); break; case 0x81: case 0x82: case 0x83: case 0x84: // 81 - [W]Wall Decor: [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Object_Nx4(3, src, dst), dst += XY(0, 6); } while (--dung_draw_width_indicator); break; case 0x85: case 0x86: // 85 - [W]Wall Canon Hole [U-D] RoomDraw_GetObjectSize_1to16(); Object_Draw_3x2(src, dst), dst += XY(0, 2); while (--dung_draw_width_indicator) Object_Draw_3x2(src + 6, dst), dst += XY(0, 2); Object_Draw_3x2(src + 12, dst); break; case 0x88: // 88 - Large Vert: Rail [U-D] RoomDraw_GetObjectSize_1to16(); RoomDraw_Rightwards2x2(src, dst), dst += XY(0, 2), src += 4; do { dst[XY(0, 0)] = src[0]; dst[XY(1, 0)] = src[1]; dst += XY(0, 1); } while (--dung_draw_width_indicator); RoomDraw_1x3_rightwards(2, src + 2, dst); break; case 0x89: // 89 - Block Vert: [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_Rightwards2x2(src, dst), dst += XY(0, 4); } while (--dung_draw_width_indicator); break; case 0x8a: // 8A - Long Vert: Rail [U-D] Object_SizeAtoAplus15(21); if ((dst[0] & 0x3ff) != 0xe3) dst[0] = src[0]; n = src[1]; do { dst += XY(0, 1); *dst = n; } while (--dung_draw_width_indicator); dst[XY(0, 1)] = src[2]; break; case 0x8b: case 0x8c: // 8B - [W]Vert: Jump Edge [U-D] Object_SizeAtoAplus15(8); do { dst[0] = src[0], dst += XY(0, 1); } while (--dung_draw_width_indicator); break; case 0x8f: // 8F - N/A Object_SizeAtoAplus15(2); dung_draw_width_indicator <<= 1; dst[XY(0, 0)] = src[0], dst[XY(1, 0)] = src[1]; do { dst[XY(0, 1)] = src[2], dst[XY(1, 1)] = src[3], dst += XY(0, 1); } while (--dung_draw_width_indicator); break; case 0x95: // 95 - Fake Pot [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_SinglePot(src, dst, dsto); dst += XY(0, 2), dsto += XY(0, 2); } while (--dung_draw_width_indicator); break; case 0x96: // 96 - Hammer Peg Block [U-D] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_HammerPegSingle(src, dst, dsto); dst += XY(0, 2), dsto += XY(0, 2); } while (--dung_draw_width_indicator); break; case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: case 0xad: case 0xae: case 0xaf: case 0xbe: case 0xbf: break; case 0xa0: // A0 - / Ceiling [NW] case 0xa5: case 0xa9: // A5 - / Ceiling [Trans][NW] Object_SizeAtoAplus15(4); do { Object_Fill_Nx1(dung_draw_width_indicator, src, dst), dst += XY(0, 1); } while (--dung_draw_width_indicator); break; case 0xa1: // A1 - \ Ceiling [SW] case 0xa6: case 0xaa: // A6 - \ Ceiling [Trans][SW] Object_SizeAtoAplus15(4); n = 1; do { Object_Fill_Nx1(n++, src, dst), dst += XY(0, 1); } while (--dung_draw_width_indicator); break; case 0xa2: // A2 - \ Ceiling [NE] case 0xa7: case 0xab: // A7 - \ Ceiling [Trans][NE] Object_SizeAtoAplus15(4); do { Object_Fill_Nx1(dung_draw_width_indicator, src, dst), dst += XY(1, 1); } while (--dung_draw_width_indicator); break; case 0xa3: // A3 - / Ceiling [SE] case 0xa8: case 0xac: // A8 - / Ceiling [Trans][SE] Object_SizeAtoAplus15(4); do { Object_Fill_Nx1(dung_draw_width_indicator, src, dst), dst += XY(1, -1); } while (--dung_draw_width_indicator); break; case 0xa4: // A4 - Hole [4-way] Object_Hole(src, dst); break; case 0xb0: case 0xb1: // B0 - [S]Horz: Jump Edge [L-R] Object_SizeAtoAplus15(8); Object_Fill_Nx1(dung_draw_width_indicator, src, dst); break; case 0xb5: // B5 - N/A RoomDraw_GetObjectSize_1to16(); do { src = SrcPtr(0xb16); RoomDraw_Object_Nx4(2, src, dst), dst += XY(2, 0); } while (--dung_draw_width_indicator); break; case 0xbc: // BC - fake pots [L-R] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_SinglePot(src, dst, dsto); dst += XY(2, 0), dsto += XY(2, 0); } while (--dung_draw_width_indicator); break; case 0xbd: // BD - Hammer Pegs [L-R] RoomDraw_GetObjectSize_1to16(); do { RoomDraw_HammerPegSingle(src, dst, dsto); dst += XY(2, 0), dsto += XY(2, 0); } while (--dung_draw_width_indicator); break; case 0xc0: case 0xc2: // C0 - Ceiling Large [4-way] n = src[0]; for (int y = dung_draw_height_indicator; y-- >= 0; ) { uint16 *dst_org = dst; for (int x = dung_draw_width_indicator; x-- >= 0; dst += XY(4, 0)) { dst[XY(0, 0)] = dst[XY(1, 0)] = dst[XY(2, 0)] = dst[XY(3, 0)] = n; dst[XY(0, 1)] = dst[XY(1, 1)] = dst[XY(2, 1)] = dst[XY(3, 1)] = n; dst[XY(0, 2)] = dst[XY(1, 2)] = dst[XY(2, 2)] = dst[XY(3, 2)] = n; dst[XY(0, 3)] = dst[XY(1, 3)] = dst[XY(2, 3)] = dst[XY(3, 3)] = n; } dst = dst_org + XY(0, 4); } break; case 0xc1: { // C1 - Chest Pedastal [4-way] dung_draw_width_indicator += 4; dung_draw_height_indicator += 1; // draw upper part uint16 *dsto = dst; RoomDraw_1x3_rightwards(3, src, dst), src += 9, dst += XY(3, 0); for (int i = dung_draw_width_indicator; i--; ) RoomDraw_1x3_rightwards(2, src, dst), dst += XY(2, 0); RoomDraw_1x3_rightwards(3, src + 6, dst), src += 6 + 9; // draw center part dst = dsto + XY(0, 3); for (int i = dung_draw_height_indicator; i--; ) { uint16 *dt = dst; Object_Draw_3x2(src, dt), dt += XY(3, 0); for (int j = dung_draw_width_indicator; j--; ) RoomDraw_Rightwards2x2(src + 6, dt), dt += XY(2, 0); Object_Draw_3x2(src + 10, dt); dst += XY(0, 2); } dsto = dst; src += 6 + 4 + 6; RoomDraw_1x3_rightwards(3, src, dst), src += 9, dst += XY(3, 0); for (int i = dung_draw_width_indicator; i--; ) RoomDraw_1x3_rightwards(2, src, dst), dst += XY(2, 0); RoomDraw_1x3_rightwards(3, src + 6, dst), src += 6 + 9; src = SrcPtr(0x590); RoomDraw_Rightwards2x2(src, dsto + XY(dung_draw_width_indicator + 2, -(dung_draw_height_indicator + 1))); break; } case 0xc3: // C3 - Falling Edge Mask [4-way] case 0xd7: // D7 - overlay tile? [4-way] dung_draw_width_indicator++; dung_draw_height_indicator++; n = *src; do { uint16 *d = dst; for (int i = dung_draw_width_indicator; i--; d += XY(3, 0)) { d[XY(0, 0)] = d[XY(1, 0)] = d[XY(2, 0)] = n; d[XY(0, 1)] = d[XY(1, 1)] = d[XY(2, 1)] = n; d[XY(0, 2)] = d[XY(1, 2)] = d[XY(2, 2)] = n; } dst += XY(0, 3); } while (--dung_draw_height_indicator); break; case 0xc4: // C4 - Doorless Room Transition src = SrcPtr(dung_floor_2_filler_tiles); goto fill_floor; case 0xdb: // C4 - DB - Floor2 [4-way] src = SrcPtr(dung_floor_1_filler_tiles); goto fill_floor; case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xd1: case 0xd2: case 0xd9: case 0xdf: case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: fill_floor: dung_draw_width_indicator++; dung_draw_height_indicator++; do { RoomDraw_A_Many32x32Blocks(dung_draw_width_indicator, src, dst); dst += XY(0, 4); } while (--dung_draw_height_indicator); break; case 0xcd: { // CD - Moving Wall Right [4-way] if (!RoomDraw_CheckIfWallIsMoved()) return; dung_hdr_collision_2_mirror++; int size0 = kMovingWall_Sizes0[dung_draw_width_indicator]; int size1 = kMovingWall_Sizes1[dung_draw_height_indicator]; MovingWall_FillReplacementBuffer(dsto - size1 - 1); moving_wall_var2 = dung_draw_height_indicator * 2; src = SrcPtr(0x3d8); uint16 *dst1 = dst - size1; do { uint16 *dst2 = dst1; dst2[XY(0, 0)] = src[0]; int n1 = size0 * 2 + 4; do { dst2[XY(0, 1)] = src[1]; dst2 += XY(0, 1); } while (--n1); dst2[XY(0, 1)] = src[2]; dst1++; } while (--size1); src = SrcPtr(0x72a); RoomDraw_1x3_rightwards(3, src, dst); dst += XY(0, 3); do { Object_Draw_3x2(src + 9, dst); } while (dst += XY(0, 2), --size0); RoomDraw_1x3_rightwards(3, src + 9 + 6, dst); break; } case 0xce: { // CE - Moving Wall Left [4-way] if (!RoomDraw_CheckIfWallIsMoved()) return; dung_hdr_collision_2_mirror++; src = SrcPtr(0x75a); int size1 = kMovingWall_Sizes1[dung_draw_height_indicator]; int size0 = kMovingWall_Sizes0[dung_draw_width_indicator]; moving_wall_var2 = dung_draw_height_indicator * 2; MovingWall_FillReplacementBuffer(dsto + 3 + size1); uint16 *dst1 = dst; RoomDraw_1x3_rightwards(3, src, dst1); dst1 += XY(0, 3); int n = size0; do { Object_Draw_3x2(src + 9, dst1); dst1 += XY(0, 2); } while (--n); RoomDraw_1x3_rightwards(3, src + 15, dst1); src = SrcPtr(0x3d8); dst1 = dst + XY(3, 0); do { uint16 *dst2 = dst1; dst2[XY(0, 0)] = src[0]; int n1 = size0 * 2 + 4; do { dst2[XY(0, 1)] = src[1]; dst2 += XY(0, 1); } while (--n1); dst2[XY(0, 1)] = src[2]; dst1++; } while (--size1); break; } case 0xd8: { // loads of lava/water hdma stuff dung_draw_width_indicator += 2; water_hdma_var3 = (dung_draw_width_indicator << 4); dung_draw_height_indicator += 2; water_hdma_var2 = (dung_draw_height_indicator << 4); water_hdma_var4 = water_hdma_var2 - 24; water_hdma_var0 = (dsto & 0x3f) << 3; water_hdma_var0 += (dung_draw_width_indicator << 4) + dung_loade_bgoffs_h_copy; water_hdma_var1 = (dsto & 0xfc0) >> 3; water_hdma_var1 += (dung_draw_height_indicator << 4) + dung_loade_bgoffs_v_copy; if (dung_savegame_state_bits & 0x800) { dung_hdr_tag[1] = 0; dung_hdr_bg2_properties = 0; dung_num_interpseudo_upnorth_stairs = dung_num_inroom_upnorth_stairs_water; dung_some_stairs_unk4 = dung_num_activated_water_ladders; dung_num_activated_water_ladders = 0; dung_num_inroom_upnorth_stairs_water = 0; dung_num_stairs_wet = dung_num_inroom_upsouth_stairs_water; dung_num_inroom_upsouth_stairs_water = 0; dsto += (dung_draw_width_indicator - 1) << 1; dsto += (dung_draw_height_indicator - 1) << 7; DrawWaterThing(&dung_bg2[dsto], SrcPtr(0x1438)); } else { src = SrcPtr(0x110); do { RoomDraw_A_Many32x32Blocks(dung_draw_width_indicator, src, dst); dst += XY(0, 4); } while (--dung_draw_height_indicator); } break; } case 0xda: { // water hdma stuff dung_draw_width_indicator += 2; water_hdma_var3 = (dung_draw_width_indicator << 4) - 24; dung_draw_height_indicator += 2; water_hdma_var4 = (dung_draw_height_indicator << 4) - 8; water_hdma_var2 = water_hdma_var4 - 24; water_hdma_var5 = 0; water_hdma_var0 = (dsto & 0x3f) << 3; water_hdma_var0 += (dung_draw_width_indicator << 4) + dung_loade_bgoffs_h_copy; water_hdma_var1 = (dsto & 0xfc0) >> 3; water_hdma_var1 += (dung_draw_height_indicator << 4) + dung_loade_bgoffs_v_copy - 8; if (dung_savegame_state_bits & 0x800) { dung_hdr_tag[1] = 0; } else { dung_hdr_bg2_properties = 0; dung_num_interpseudo_upnorth_stairs = dung_num_inroom_upnorth_stairs_water; dung_some_stairs_unk4 = dung_num_activated_water_ladders; dung_num_activated_water_ladders = 0; dung_num_inroom_upnorth_stairs_water = 0; dung_num_stairs_wet = dung_num_inroom_upsouth_stairs_water; dung_num_inroom_upsouth_stairs_water = 0; } int n = dung_draw_height_indicator * 2 - 1; src = SrcPtr(0x110); do { uint16 *dst2 = dst; int j = dung_draw_width_indicator; do { dst[XY(0, 0)] = src[0]; dst[XY(1, 0)] = src[1]; dst[XY(2, 0)] = src[2]; dst[XY(3, 0)] = src[3]; dst[XY(0, 1)] = src[4]; dst[XY(1, 1)] = src[5]; dst[XY(2, 1)] = src[6]; dst[XY(3, 1)] = src[7]; dst += 4; } while (--j); dst = dst2 + XY(0, 2); } while (--n); break; } case 0xdc: { // DC - Chest Platform? [4-way] dsto |= (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); dung_draw_width_indicator++; dung_draw_height_indicator = dung_draw_height_indicator * 2 + 5; src = SrcPtr(0xAB4); do { Object_ChestPlatform_Helper(src, dsto), dsto += XY(0, 1); } while (--dung_draw_height_indicator); Object_ChestPlatform_Helper(src + 1, dsto), dsto += XY(0, 1); Object_ChestPlatform_Helper(src + 2, dsto), dsto += XY(0, 1); break; } case 0xdd: // DD - Table / Rock [4-way] dung_draw_width_indicator++; dung_draw_height_indicator = dung_draw_height_indicator * 2 + 1; Object_Table_Helper(src, dst), dst += XY(0, 1); do { Object_Table_Helper(src + 4, dst), dst += XY(0, 1); } while (--dung_draw_height_indicator); Object_Table_Helper(src + 8, dst), dst += XY(0, 1); Object_Table_Helper(src + 12, dst), dst += XY(0, 1); break; case 0xde: // DE - Spike Block [4-way] dung_draw_width_indicator++; dung_draw_height_indicator++; do { int n = dung_draw_width_indicator; uint16 *dst1 = dst; do { RoomDraw_Rightwards2x2(src, dst1), dst1 += XY(2, 0); } while (--n); dst += XY(0, 2); } while (--dung_draw_height_indicator); break; case 0xcb: case 0xcc: case 0xcf: case 0xd0: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: assert(0); break; default: assert(0); } } void Object_DrawNx3_BothBgs(int n, const uint16 *src, int dsto) { do { dung_bg1[dsto + XY(0, 0)] = dung_bg2[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(0, 1)] = dung_bg2[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = dung_bg2[dsto + XY(0, 2)] = src[2]; src += 3, dsto += 1; } while (--n); } void LoadType1ObjectSubtype2(uint8 idx, uint16 *dst, uint16 dsto) { uint16 params = kObjectSubtype2Params[idx]; const uint16 *src = SrcPtr(params); int i; switch (idx) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: // 00 - Wall Outer Corner (HIGH) [NW] case 0x1c: case 0x24: case 0x25: case 0x29: RoomDraw_Object_Nx4(4, src, dst); break; case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: // 08 - Wall Outer Corner (LOW) [NW] Object_DrawNx4_BothBgs(4, src, dsto); break; case 0x10: case 0x11: case 0x12: case 0x13: // 10 - Wall S-Bend (LOW) [N1] Object_DrawNx4_BothBgs(3, src, dsto); break; case 0x14: case 0x15: case 0x16: case 0x17: // 14 - Wall S-Bend (LOW) [W1] Object_DrawNx3_BothBgs(4, src, dsto); break; case 0x18: case 0x19: case 0x1a: case 0x1b: // 18 - Wall Pit Corner (Lower) [NW] case 0x27: case 0x2b: case 0x34: RoomDraw_Rightwards2x2(src, dst); break; case 0x1d: case 0x21: case 0x26: // 1D - Statue RoomDraw_1x3_rightwards(2, src, dst); break; case 0x1e: // 1E - Star Tile Off RoomDraw_Rightwards2x2(src, dst); break; case 0x1f: // 1F - Star Tile On i = dung_num_star_shaped_switches >> 1; dung_num_star_shaped_switches += 2; star_shaped_switches_tile[i] = (dsto | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000)); RoomDraw_Rightwards2x2(src, dst); break; case 0x20: // 20 - Torch Lit dung_num_lit_torches++; RoomDraw_Rightwards2x2(src, dst); break; case 0x22: case 0x28: // 22 - Weird Bed Object_Draw_5x4(src, dst); break; case 0x23: // 23 - Table RoomDraw_1x3_rightwards(4, src, dst); break; case 0x2a: // 2A - Wall Painting dung_draw_width_indicator = 1; RoomDraw_Downwards4x2VariableSpacing(1, src, dst); break; case 0x2c: // 2C - ??? RoomDraw_1x3_rightwards(6, src, dst); break; case 0x2d: // 2D - Floor Stairs Up (room) i = dung_num_inter_room_upnorth_stairs >> 1; dung_inter_starcases[i] = (dsto | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000)); dung_num_inter_room_upnorth_stairs = dung_num_wall_upnorth_spiral_stairs = dung_num_wall_upnorth_spiral_stairs_2 = dung_num_inter_room_upnorth_straight_stairs = dung_num_inter_room_upsouth_straight_stairs = dung_num_inter_room_southdown_stairs = dung_num_wall_downnorth_spiral_stairs = dung_num_wall_downnorth_spiral_stairs_2 = dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_inter_room_upnorth_stairs + 2; RoomDraw_4x4(SrcPtr(0x1088), dst); break; case 0x2e: // 2E - Floor Stairs Down (room) case 0x2f: // 2F - Floor Stairs Down2 (room) i = dung_num_inter_room_southdown_stairs >> 1; dung_inter_starcases[i] = (dsto | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000)); dung_num_inter_room_southdown_stairs = dung_num_wall_downnorth_spiral_stairs = dung_num_wall_downnorth_spiral_stairs_2 = dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_inter_room_southdown_stairs + 2; RoomDraw_4x4(SrcPtr(0x10A8), dst); break; case 0x30: // 30 - Stairs [N](unused) assert(0); break; case 0x31: // 31 - Stairs [N](layer) i = dung_num_inroom_southdown_stairs >> 1; dung_stairs_table_1[i] = dsto; dung_num_inroom_southdown_stairs = dung_num_water_ladders = dung_some_stairs_unk4 = dung_num_inroom_southdown_stairs + 2; Object_DrawNx4_BothBgs(4, src, dsto); break; case 0x32: // 32 - Stairs [N](layer) non_submerged: i = dung_num_interpseudo_upnorth_stairs >> 1; dung_stairs_table_1[i] = dsto; dung_num_interpseudo_upnorth_stairs = dung_num_water_ladders = dung_some_stairs_unk4 = dung_num_interpseudo_upnorth_stairs + 2; RoomDraw_4x4(src, dst); break; case 0x33: // 33 - Stairs Submerged [N](layer) if (dung_hdr_tag[1] == 27 && !(save_dung_info[dungeon_room_index] & 0x100)) { dung_hdr_bg2_properties = 0; src = SrcPtr(0x10C8); goto non_submerged; } else { i = dung_num_inroom_upnorth_stairs_water >> 1; dung_stairs_table_1[i] = dsto; dung_num_inroom_upnorth_stairs_water = dung_num_activated_water_ladders = dung_num_inroom_upnorth_stairs_water + 2; RoomDraw_4x4(SrcPtr(0x10C8), dst); } break; case 0x35: // 35 - Water Ladder if (dung_hdr_tag[1] == 27 && !(save_dung_info[dungeon_room_index] & 0x100)) goto inactive_water_ladder; dung_stairs_table_1[dung_num_activated_water_ladders >> 1] = dsto; dung_num_activated_water_ladders += 2; dung_draw_width_indicator = 1; RoomDraw_Downwards4x2VariableSpacing(1, SrcPtr(0x1108), dst); break; case 0x36: // 36 - Water Ladder Inactive inactive_water_ladder: dung_stairs_table_1[dung_num_water_ladders >> 1] = dsto; dung_some_stairs_unk4 = (dung_num_water_ladders += 2); Object_Draw_4x2_BothBgs(SrcPtr(0x1108), dsto); break; case 0x37: // 37 - Water Gate Large if (!(dung_savegame_state_bits & 0x800)) { RoomDraw_Object_Nx4(10, src, dst); watergate_var1 = 0xf; watergate_pos = dsto * 2; } else { RoomDraw_Object_Nx4(10, SrcPtr(0x13e8), dst); uint16 bak0 = dung_load_ptr; uint16 bak1 = dung_load_ptr_offs; uint8 bak2 = dung_load_ptr_bank; RoomTag_OperateWaterFlooring(); dung_load_ptr_bank = bak2; dung_load_ptr_offs = bak1; dung_load_ptr = bak0; } break; case 0x38: // 38 - Door Staircase Up R i = dung_num_wall_upnorth_spiral_stairs >> 1; dung_inter_starcases[i] = (dsto - 0x40) | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); dung_num_wall_upnorth_spiral_stairs = dung_num_wall_upnorth_spiral_stairs_2 = dung_num_inter_room_upnorth_straight_stairs = dung_num_inter_room_upsouth_straight_stairs = dung_num_inter_room_southdown_stairs = dung_num_wall_downnorth_spiral_stairs = dung_num_wall_downnorth_spiral_stairs_2 = dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_wall_upnorth_spiral_stairs + 2; RoomDraw_1x3_rightwards(4, SrcPtr(0x1148), dst); dung_bg2[dsto - 1] |= 0x2000; dung_bg2[dsto + 4] |= 0x2000; break; case 0x39: // 39 - Door Staircase Down L i = dung_num_wall_downnorth_spiral_stairs >> 1; dung_inter_starcases[i] = (dsto - 0x40) | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); dung_num_wall_downnorth_spiral_stairs = dung_num_wall_downnorth_spiral_stairs_2 = dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_wall_downnorth_spiral_stairs + 2; RoomDraw_1x3_rightwards(4, SrcPtr(0x1160), dst); dung_bg2[dsto - 1] |= 0x2000; dung_bg2[dsto + 4] |= 0x2000; break; case 0x3a: // 3A - Door Staircase Up R (Lower) i = dung_num_wall_upnorth_spiral_stairs_2 >> 1; dung_inter_starcases[i] = (dsto - 0x40) | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); dung_num_wall_upnorth_spiral_stairs_2 = dung_num_inter_room_upnorth_straight_stairs = dung_num_inter_room_upsouth_straight_stairs = dung_num_inter_room_southdown_stairs = dung_num_wall_downnorth_spiral_stairs = dung_num_wall_downnorth_spiral_stairs_2 = dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_wall_upnorth_spiral_stairs_2 + 2; RoomDraw_1x3_rightwards(4, SrcPtr(0x1178), dst); dung_bg1[dsto - 1] |= 0x2000; dung_bg1[dsto + 4] |= 0x2000; break; case 0x3b: // 3B - Door Staircase Down L (Lower) i = dung_num_wall_downnorth_spiral_stairs_2 >> 1; dung_inter_starcases[i] = (dsto - 0x40) | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); dung_num_wall_downnorth_spiral_stairs_2 = dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_wall_downnorth_spiral_stairs_2 + 2; RoomDraw_1x3_rightwards(4, SrcPtr(0x1190), dst); dung_bg1[dsto - 1] |= 0x2000; dung_bg1[dsto + 4] |= 0x2000; break; case 0x3c: // 3C - Sanctuary Wall for (int i = 0; i < 6; i++) { dung_bg2[dsto + 0] = dung_bg2[dsto + 4] = dung_bg2[dsto + 8] = dung_bg2[dsto + 14] = dung_bg2[dsto + 18] = dung_bg2[dsto + 22] = src[0]; dung_bg2[dsto + 1] = dung_bg2[dsto + 5] = dung_bg2[dsto + 9] = dung_bg2[dsto + 15] = dung_bg2[dsto + 19] = dung_bg2[dsto + 23] = src[0] | 0x4000; dung_bg2[dsto + 2] = dung_bg2[dsto + 6] = dung_bg2[dsto + 16] = dung_bg2[dsto + 20] = src[6]; dung_bg2[dsto + 3] = dung_bg2[dsto + 7] = dung_bg2[dsto + 17] = dung_bg2[dsto + 21] = src[6] | 0x4000; dsto += XY(0, 1); src++; } RoomDraw_1x3_rightwards(4, src + 6, dst + 10); break; case 0x3e: // 3E - Church Pew RoomDraw_1x3_rightwards(6, src, dst); break; case 0x3f: { // 3F - used in hole at the smithy dwarves dsto |= (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); dst = &dung_bg2[dsto]; for (int i = 0; i < 8; i++) { dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(0, 2)] = src[2]; dst[XY(0, 3)] = src[3]; dst[XY(0, 4)] = src[4]; dst[XY(0, 5)] = src[5]; dst[XY(0, 6)] = src[6]; dst += XY(1, 0); src += 7; } break; } default: assert(0); } } void Object_BombableFloorHelper(uint16 a, const uint16 *src, const uint16 *src_below, uint16 *dst, uint16 dsto) { int i = dung_misc_objs_index >> 1; dung_replacement_tile_state[i] = a; dung_misc_objs_index += 2; dung_object_pos_in_objdata[i] = dung_load_ptr_offs; dung_object_tilemap_pos[i] = dsto * 2 | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x2000); replacement_tilemap_UL[i] = src_below[0]; replacement_tilemap_LL[i] = src_below[1]; replacement_tilemap_UR[i] = src_below[2]; replacement_tilemap_LR[i] = src_below[3]; RoomDraw_Rightwards2x2(src, dst); } void LoadType1ObjectSubtype3(uint8 idx, uint16 *dst, uint16 dsto) { uint16 params = kObjectSubtype3Params[idx]; const uint16 *src = SrcPtr(params); int i; switch (idx) { case 0x00: // 00 - Water Face Closed if (dung_hdr_tag[1] == 27) { if (save_dung_info[dungeon_room_index] & 0x100) goto water_face_open; } else if (dung_hdr_tag[1] == 25) { if (dung_savegame_state_bits & 0x800) goto water_face_open; } word_7E047C = dsto * 2; RoomDraw_WaterHoldingObject(3, src, dst); break; case 0x01: // 01 - Waterfall Face water_face_open: RoomDraw_WaterHoldingObject(5, SrcPtr(0x162c), dst); break; case 0x02: // 02 - Waterfall Face Longer RoomDraw_WaterHoldingObject(7, src, dst); break; case 0x03: case 0x0e: // 03 - Cane Ride Spawn [?]Block dung_unk6++; dst[0] = src[0]; break; case 0x04: case 0x05: case 0x06: case 0x07: // 04 - Cane Ride Node [4-way] case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0f: dst[0] = src[0]; break; case 0x0d: case 0x17: { // 0D - Prison Cell src = SrcPtr(0x1488); dsto |= (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); uint16 *d = &dung_bg2[dsto], *dd = d; for (int i = 0; i < 5; i++, d++) { d[XY(2, 0)] = d[XY(9, 0)] = src[1]; d[XY(2, 1)] = src[2]; d[XY(9, 1)] = src[2] | 0x4000; d[XY(2, 2)] = src[4]; d[XY(9, 2)] = src[4] | 0x4000; d[XY(2, 3)] = src[5]; d[XY(9, 3)] = src[5] | 0x4000; } dd[XY(0, 0)] = src[0]; dd[XY(15, 0)] = src[0] | 0x4000; dd[XY(1, 0)] = dd[XY(7, 0)] = dd[XY(8, 0)] = dd[XY(14, 0)] = src[1]; dd[XY(1, 2)] = src[3]; dd[XY(14, 2)] = src[3] | 0x4000; break; } case 0x10: case 0x11: case 0x13: case 0x1a: case 0x22: case 0x23: case 0x24: case 0x25: case 0x3e: case 0x3f: case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x49: case 0x4a: case 0x4f: case 0x50: case 0x51: case 0x52: case 0x53: case 0x56: case 0x57: case 0x58: case 0x59: case 0x5e: case 0x5f: case 0x63: case 0x64: case 0x65: case 0x75: case 0x7c: case 0x7d: case 0x7e: RoomDraw_Rightwards2x2(src, dst); break; case 0x12: // 12 - Rupee Floor if (dung_savegame_state_bits & 0x1000) return; src = SrcPtr(0x1dd6); dst = &dung_bg2[dsto | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000)]; for (int i = 0; i < 3; i++) { dst[XY(0, 0)] = dst[XY(0, 3)] = dst[XY(0, 6)] = src[0]; dst[XY(0, 1)] = dst[XY(0, 4)] = dst[XY(0, 7)] = src[1]; dst += 2; } break; case 0x14: case 0x4E: // 14 - Down Warp Door case 0x67: case 0x68: case 0x6c: case 0x6d: case 0x79: RoomDraw_1x3_rightwards(4, src, dst); break; case 0x15: // 15 - Kholdstare Shell - BG2 if (dung_savegame_state_bits & 0x8000) return; src = SrcPtr(0x1dfa); RoomDraw_SomeBigDecors(10, src, dsto); break; case 0x16: // 16 - Single Hammer Peg RoomDraw_HammerPegSingle(src, dst, dsto); break; case 0x18: // 18 - Cell Lock i = dung_num_bigkey_locks_x2 >> 1; dung_num_bigkey_locks_x2 += 2; if (!(dung_savegame_state_bits & kChestOpenMasks[i])) { dung_chest_locations[i] = dsto * 2; RoomDraw_Rightwards2x2(SrcPtr(0x1494), dst); } else { dung_chest_locations[i] = 0; } break; case 0x19: { // 19 - Chest if (main_module_index == 26) return; i = dung_num_chests_x2 >> 1; dung_num_bigkey_locks_x2 = (dung_num_chests_x2 += 2); int h = -1; if (dung_hdr_tag[0] == 0x27 || dung_hdr_tag[0] == 0x3c || dung_hdr_tag[0] == 0x3e || dung_hdr_tag[0] >= 0x29 && dung_hdr_tag[0] < 0x33) h = 0; else if (dung_hdr_tag[1] == 0x27 || dung_hdr_tag[1] == 0x3c || dung_hdr_tag[1] == 0x3e || dung_hdr_tag[1] >= 0x29 && dung_hdr_tag[1] < 0x33) h = 1; dung_chest_locations[i] = 2 * (dsto | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000)); if (!(dung_savegame_state_bits & kChestOpenMasks[i])) { if (h >= 0) { if (!(dung_savegame_state_bits & kChestOpenMasks[h])) return; dung_hdr_tag[h] = 0; } RoomDraw_Rightwards2x2(SrcPtr(0x149c), dst); } else { dung_chest_locations[i] = 0; if (h >= 0) dung_hdr_tag[h] = 0; RoomDraw_Rightwards2x2(SrcPtr(0x14a4), dst); } break; } case 0x1b: // 1B - Stair dung_stairs_table_1[dung_num_stairs_1 >> 1] = dsto; dung_num_stairs_1 += 2; stair1b: for (int i = 0; i < 4; i++) { dung_bg1[dsto + XY(0, 0)] = dung_bg2[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(0, 1)] = dung_bg2[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = dung_bg2[dsto + XY(0, 2)] = src[2]; dung_bg1[dsto + XY(0, 3)] = dung_bg2[dsto + XY(0, 3)] = src[3]; src += 4, dsto += 1; } break; case 0x1c: // 1C - Stair [S](Layer) dung_stairs_table_2[dung_num_stairs_2 >> 1] = dsto; dung_num_stairs_2 += 2; goto stair1b; case 0x1d: // 1D - Stair Wet [S](Layer) stairs_wet: dung_stairs_table_2[dung_num_stairs_wet >> 1] = dsto; dung_num_stairs_wet += 2; RoomDraw_4x4(src, dst); break; case 0x1e: // 1E - Staircase going Up(Up) dung_inter_starcases[dung_num_inter_room_upnorth_straight_stairs >> 1] = dsto; dung_num_inter_room_upnorth_straight_stairs = dung_num_inter_room_upsouth_straight_stairs = dung_num_inter_room_southdown_stairs = dung_num_wall_downnorth_spiral_stairs = dung_num_wall_downnorth_spiral_stairs_2 = dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_inter_room_upnorth_straight_stairs + 2; RoomDraw_Object_Nx4(4, src, dst); break; case 0x1f: // 1F - Staircase Going Down (Up) dung_inter_starcases[dung_num_inter_room_downnorth_straight_stairs >> 1] = dsto; dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_inter_room_downnorth_straight_stairs + 2; RoomDraw_Object_Nx4(4, src, dst); break; case 0x20: // 20 - Staircase Going Up (Down) dung_inter_starcases[dung_num_inter_room_upsouth_straight_stairs >> 1] = dsto; dung_num_inter_room_upsouth_straight_stairs = dung_num_inter_room_southdown_stairs = dung_num_wall_downnorth_spiral_stairs = dung_num_wall_downnorth_spiral_stairs_2 = dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_inter_room_upsouth_straight_stairs + 2; RoomDraw_Object_Nx4(4, src, dst); break; case 0x21: // 21 - Staircase Going Down (Down) dung_inter_starcases[dung_num_inter_room_downsouth_straight_stairs >> 1] = dsto; dung_num_inter_room_downsouth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs + 2; RoomDraw_Object_Nx4(4, src, dst); break; case 0x26: // 26 - Staircase Going Up (Lower) i = dung_num_inter_room_upnorth_straight_stairs >> 1; dung_inter_starcases[i] = dsto | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); dung_num_inter_room_upnorth_straight_stairs = dung_num_inter_room_upsouth_straight_stairs = dung_num_inter_room_southdown_stairs = dung_num_wall_downnorth_spiral_stairs = dung_num_wall_downnorth_spiral_stairs_2 = dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_inter_room_upnorth_straight_stairs + 2; door26: for (int i = 0; i < 4; i++) { dung_bg1[dsto] = dung_bg2[dsto] = src[0]; dung_bg1[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = src[2]; dung_bg1[dsto + XY(0, 3)] = src[3]; src += 4, dsto++; } dsto += XY(-4, -4); copy_door_bg2: dung_bg2[dsto + XY(0, 0)] |= 0x2000; dung_bg2[dsto + XY(0, 1)] |= 0x2000; dung_bg2[dsto + XY(0, 2)] |= 0x2000; dung_bg2[dsto + XY(0, 3)] |= 0x2000; break; case 0x27: // 27 - Staircase Going Up (Lower) i = dung_num_inter_room_downnorth_straight_stairs >> 1; dung_inter_starcases[i] = dsto | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_inter_room_downnorth_straight_stairs + 2; goto door26; case 0x28: // 28 - Staircase Going Down (Lower) i = dung_num_inter_room_upsouth_straight_stairs >> 1; dung_inter_starcases[i] = dsto | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); dung_num_inter_room_upsouth_straight_stairs = dung_num_inter_room_southdown_stairs = dung_num_wall_downnorth_spiral_stairs = dung_num_wall_downnorth_spiral_stairs_2 = dung_num_inter_room_downnorth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs = dung_num_inter_room_upsouth_straight_stairs + 2; door28: for (int i = 0; i < 4; i++) { dung_bg1[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = src[2]; dung_bg1[dsto + XY(0, 3)] = dung_bg2[dsto + XY(0, 3)] = src[3]; src += 4, dsto++; } dsto += XY(-4, 4); goto copy_door_bg2; case 0x29: // 29 - Staircase Going Down (Lower) i = dung_num_inter_room_downsouth_straight_stairs >> 1; dung_inter_starcases[i] = dsto | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000); dung_num_inter_room_downsouth_straight_stairs = dung_num_inter_room_downsouth_straight_stairs + 2; goto door28; case 0x2a: // 2A - Dark Room BG2 Mask RoomDraw_SingleLampCone(0x514, 0x16dc); RoomDraw_SingleLampCone(0x554, 0x17f6); RoomDraw_SingleLampCone(0x1514, 0x1914); RoomDraw_SingleLampCone(0x1554, 0x1a2a); break; case 0x2b: // 2B - Staircase Going Down (Lower) not really DrawBigGraySegment(0x1010, src, dst, dsto); break; case 0x2c: // 2C - Large Pick Up Block DrawBigGraySegment(0x2020, SrcPtr(0xe62), dst, dsto); DrawBigGraySegment(0x2121, SrcPtr(0xe6a), dst + XY(2, 0), dsto + XY(2, 0)); DrawBigGraySegment(0x2222, SrcPtr(0xe72), dst + XY(0, 2), dsto + XY(0, 2)); DrawBigGraySegment(0x2323, SrcPtr(0xe7a), dst + XY(2, 2), dsto + XY(2, 2)); break; case 0x2d: { // 2D - Agahnim Altar src = SrcPtr(0x1b4a); uint16 *d = &dung_bg2[dsto]; for (int j = 0; j < 14; j++) { i = src[0], d[0] = i, d[13] = i | 0x4000; i = src[14], d[1] = d[2] = i, d[11] = d[12] = i ^ 0x4000; i = src[28], d[3] = i, d[10] = i ^ 0x4000; i = src[42], d[4] = i, d[9] = i ^ 0x4000; i = src[56], d[5] = i, d[8] = i ^ 0x4000; i = src[70], d[6] = i, d[7] = i ^ 0x4000; src++, d += 64; } break; } case 0x2e: // 2E - Agahnim Room RoomDraw_AgahnimsWindows(dsto); break; case 0x2f: // 2F - Pot RoomDraw_SinglePot(src, dst, dsto); break; case 0x30: // 30 - ?? DrawBigGraySegment(0x1212, src, dst, dsto); break; case 0x31: // 31 - Big Chest i = dung_num_chests_x2; dung_chest_locations[i >> 1] = dsto * 2 | 0x8000 | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x2000); if (dung_savegame_state_bits & kChestOpenMasks[i >> 1]) { dung_chest_locations[i >> 1] = 0; dung_num_chests_x2 = dung_num_bigkey_locks_x2 = i + 2; RoomDraw_1x3_rightwards(4, SrcPtr(0x14c4), dst); } else { dung_num_chests_x2 = dung_num_bigkey_locks_x2 = i + 2; RoomDraw_1x3_rightwards(4, SrcPtr(0x14ac), dst); } break; case 0x32: // 32 - Big Chest Open RoomDraw_1x3_rightwards(4, src, dst); break; case 0x33: // 33 - Stairs Submerged [S](layer) if (dung_hdr_tag[1] == 27) { if (!(save_dung_info[dungeon_room_index] & 0x100)) { dung_hdr_bg2_properties = 0; goto stairs_wet; } CGWSEL_copy = 2; CGADSUB_copy = 0x62; } dung_stairs_table_2[dung_num_inroom_upsouth_stairs_water >> 1] = dsto; dung_num_inroom_upsouth_stairs_water += 2; RoomDraw_4x4(src, dst); break; case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: assert(0); break; case 0x3a: case 0x3b: // 3A - Pipe Ride Mouth [S] RoomDraw_1x3_rightwards(4, src, dst); RoomDraw_1x3_rightwards(4, src + 12, dst + XY(0, 3)); break; case 0x3c: case 0x3d: case 0x5c: // 3C - Pipe Ride Mouth [E] RoomDraw_Object_Nx4(6, src, dst); break; case 0x47: // 47 - Bomb Floor RoomDraw_BombableFloor(src, dst, dsto); break; case 0x48: case 0x66: case 0x6b: case 0x7a: // 48 - Fake Bomb Floor RoomDraw_4x4(src, dst); break; case 0x4b: case 0x76: case 0x77: RoomDraw_1x3_rightwards(8, src, dst); break; case 0x4c: RoomDraw_SomeBigDecors(6, SrcPtr(0x1f92), dsto); break; case 0x4d: case 0x5d: // 5D - Forge RoomDraw_1x3_rightwards(6, src, dst); break; case 0x54: RoomDraw_FortuneTellerRoom(dsto); break; case 0x55: case 0x5b: // 5B - Water Troof dst[XY(0, 0)] = src[0]; dst[XY(1, 0)] = src[1]; dst[XY(2, 0)] = src[2]; for (int i = 0; i < 3; i++) { dst[XY(0, 1)] = src[3]; dst[XY(1, 1)] = src[4]; dst[XY(2, 1)] = src[5]; dst += XY(0, 1); } dst[XY(0, 1)] = src[6]; dst[XY(1, 1)] = src[7]; dst[XY(2, 1)] = src[8]; break; case 0x5a: // 5A - Plate on Table RoomDraw_WaterHoldingObject(2, src, dst); break; case 0x60: case 0x61: // 60 - Left/Right Warp Door RoomDraw_1x3_rightwards(3, src, dst); RoomDraw_1x3_rightwards(3, src + 9, dst + XY(0, 3)); break; case 0x62: { // 62 ?? src = SrcPtr(0x20f6); uint16 *d = &dung_bg1[dsto]; for (int i = 0; i < 22; i++) { d[XY(0, 0)] = src[0]; d[XY(0, 1)] = src[1]; d[XY(0, 2)] = src[2]; d[XY(0, 3)] = src[3]; d[XY(0, 4)] = src[4]; d[XY(0, 5)] = src[5]; d[XY(0, 6)] = src[6]; d[XY(0, 7)] = src[7]; d[XY(0, 8)] = src[8]; d[XY(0, 9)] = src[9]; d[XY(0, 10)] = src[10]; d += XY(1, 0), src += 11; } d -= XY(1, 0) * 22; src = SrcPtr(0x22da); for (int i = 0; i < 3; i++) { d[XY(9, 11)] = src[0]; d[XY(9, 12)] = src[3]; d += XY(1, 0), src += 1; } break; } case 0x69: case 0x6a: case 0x6e: case 0x6f: // 69 - Left Crack Wall RoomDraw_Object_Nx4(3, src, dst); break; case 0x70: // 70 - Window Light RoomDraw_4x4(src, dst + XY(0, 0)); RoomDraw_4x4(SrcPtr(0x2376), dst + XY(0, 2)); RoomDraw_4x4(SrcPtr(0x2396), dst + XY(0, 6)); break; case 0x71: // 71 - Floor Light Blind BG2 if (!(save_dung_info[101] & 0x100)) return; Object_Draw8x8(src, dst); break; case 0x72: // 72 - TrinexxShell Boss Goo/Shell BG2 if (dung_savegame_state_bits & 0x8000) return; RoomDraw_SomeBigDecors(10, src, dsto); break; case 0x73: // 73 - Entire floor is pit, Bg2 Full Mask RoomDraw_FloorChunks(SrcPtr(0xe0)); break; case 0x74: // 74 - Boss Entrance Object_Draw8x8(src, dst); break; case 0x78: // Triforce RoomDraw_4x4(src, dst); RoomDraw_4x4(src + 16, dst + XY(-2, 4)); RoomDraw_4x4(src + 16, dst + XY(2, 4)); break; case 0x7b: // 7B - Vitreous Boss? RoomDraw_A_Many32x32Blocks(5, src, dst); RoomDraw_A_Many32x32Blocks(5, src, dst + XY(0, 4)); break; default: assert(0); } } void RoomBounds_AddA(RoomBounds *r) { r->a0 += 0x100; r->a1 += 0x100; } void RoomBounds_AddB(RoomBounds *r) { r->b0 += 0x200; r->b1 += 0x200; } void RoomBounds_SubB(RoomBounds *r) { r->b0 -= 0x200; r->b1 -= 0x200; } void RoomBounds_SubA(RoomBounds *r) { r->a0 -= 0x100; r->a1 -= 0x100; } void Dungeon_StartInterRoomTrans_Left() { link_quadrant_x ^= 1; Dungeon_AdjustQuadrant(); RoomBounds_SubA(&room_bounds_x); Dung_SaveDataForCurrentRoom(); DungeonTransition_AdjustCamera_X(link_quadrant_x ^ 1); HandleEdgeTransition_AdjustCameraBoundaries(3); submodule_index++; if (link_quadrant_x) { RoomBounds_SubB(&room_bounds_x); BYTE(dungeon_room_index_prev) = dungeon_room_index; if ((link_tile_below & 0xcf) == 0x89) { dungeon_room_index = dung_hdr_travel_destinations[3]; Dungeon_AdjustForTeleportDoors(dungeon_room_index + 1, 0xff); } else { if ((uint8)dungeon_room_index != (uint8)dungeon_room_index2) { BYTE(dungeon_room_index_prev) = dungeon_room_index2; Dungeon_AdjustAfterSpiralStairs(); } dungeon_room_index--; } submodule_index += 1; if (room_transitioning_flags & 1) { link_is_on_lower_level ^= 1; link_is_on_lower_level_mirror = link_is_on_lower_level; } if (room_transitioning_flags & 2) { cur_palace_index_x2 ^= 2; } } room_transitioning_flags = 0; quadrant_fullsize_y = (dung_blastwall_flag_y || (kLayoutQuadrantFlags[composite_of_layout_and_quadrant] & (link_quadrant_y ? 8 : 4)) == 0) ? 2 : 0; } void Dung_StartInterRoomTrans_Left_Plus() { link_x_coord -= 8; Dungeon_StartInterRoomTrans_Left(); } void Dungeon_StartInterRoomTrans_Up() { link_quadrant_y ^= 2; Dungeon_AdjustQuadrant(); RoomBounds_SubA(&room_bounds_y); Dung_SaveDataForCurrentRoom(); DungeonTransition_AdjustCamera_Y(link_quadrant_y ^ 2); HandleEdgeTransition_AdjustCameraBoundaries(1); submodule_index++; if (link_quadrant_y) { RoomBounds_SubB(&room_bounds_y); BYTE(dungeon_room_index_prev) = dungeon_room_index; if (link_tile_below == 0x8e) { Dung_HandleExitToOverworld(); return; } if (dungeon_room_index == 0) { SaveDungeonKeys(); main_module_index = 25; submodule_index = 0; subsubmodule_index = 0; return; } if (BYTE(dungeon_room_index2) == BYTE(dungeon_room_index)) { BYTE(dungeon_room_index_prev) = BYTE(dungeon_room_index2); Dungeon_AdjustAfterSpiralStairs(); } BYTE(dungeon_room_index) -= 0x10; submodule_index += 1; if (room_transitioning_flags & 1) { link_is_on_lower_level ^= 1; link_is_on_lower_level_mirror = link_is_on_lower_level; } if (room_transitioning_flags & 2) { cur_palace_index_x2 ^= 2; } } room_transitioning_flags = 0; quadrant_fullsize_x = (dung_blastwall_flag_x || (kLayoutQuadrantFlags[composite_of_layout_and_quadrant] & (link_quadrant_x ? 2 : 1)) == 0) ? 2 : 0; } void Dungeon_StartInterRoomTrans_Down() { link_quadrant_y ^= 2; Dungeon_AdjustQuadrant(); RoomBounds_AddA(&room_bounds_y); Dung_SaveDataForCurrentRoom(); DungeonTransition_AdjustCamera_Y(link_quadrant_y); HandleEdgeTransition_AdjustCameraBoundaries(0); submodule_index++; if (!link_quadrant_y) { RoomBounds_AddB(&room_bounds_y); BYTE(dungeon_room_index_prev) = dungeon_room_index; if (link_tile_below == 0x8e) { Dung_HandleExitToOverworld(); return; } if ((uint8)dungeon_room_index != (uint8)dungeon_room_index2) { BYTE(dungeon_room_index_prev) = dungeon_room_index2; Dungeon_AdjustAfterSpiralStairs(); } BYTE(dungeon_room_index) += 16; submodule_index += 1; if (room_transitioning_flags & 1) { link_is_on_lower_level ^= 1; link_is_on_lower_level_mirror = link_is_on_lower_level; } if (room_transitioning_flags & 2) { cur_palace_index_x2 ^= 2; } } room_transitioning_flags = 0; quadrant_fullsize_x = (dung_blastwall_flag_x || (kLayoutQuadrantFlags[composite_of_layout_and_quadrant] & (link_quadrant_x ? 2 : 1)) == 0) ? 2 : 0; } void Dungeon_Store2x2(uint16 pos, uint16 t0, uint16 t1, uint16 t2, uint16 t3, uint8 attr) { uint16 *dst = &vram_upload_data[vram_upload_offset >> 1]; dst[2] = t0; dst[5] = t1; dst[8] = t2; dst[11] = t3; overworld_tileattr[pos] = t0; overworld_tileattr[pos + 64] = t1; overworld_tileattr[pos + 1] = t2; overworld_tileattr[pos + 65] = t3; dung_bg2_attr_table[pos] = attr; dung_bg2_attr_table[pos + 64] = attr; dung_bg2_attr_table[pos + 1] = attr; dung_bg2_attr_table[pos + 65] = attr; dst[0] = Dungeon_MapVramAddr(pos + 0); dst[3] = Dungeon_MapVramAddr(pos + 64); dst[6] = Dungeon_MapVramAddr(pos + 1); dst[9] = Dungeon_MapVramAddr(pos + 65); dst[1] = 0x100; dst[4] = 0x100; dst[7] = 0x100; dst[10] = 0x100; dst[12] = 0xffff; vram_upload_offset += 24; nmi_load_bg_from_vram = 1; } uint16 Dungeon_MapVramAddr(uint16 pos) { pos *= 2; return swap16(((pos & 0x40) << 4) | ((pos & 0x303f) >> 1) | ((pos & 0xf80) >> 2)); } uint16 Dungeon_MapVramAddrNoSwap(uint16 pos) { pos *= 2; return ((pos & 0x40) << 4) | ((pos & 0x303f) >> 1) | ((pos & 0xf80) >> 2); } void Door_Up_EntranceDoor(uint16 dsto) { // NOTE: This don't pass the right value to RoomDraw_FlagDoorsAndGetFinalType assert(0); } void Door_Down_EntranceDoor(uint16 dsto) { // NOTE: This don't pass the right value to RoomDraw_FlagDoorsAndGetFinalType assert(0); } void Door_Left_EntranceDoor(uint16 dsto) { // NOTE: This don't pass the right value to RoomDraw_FlagDoorsAndGetFinalType assert(0); } void Door_Right_EntranceDoor(uint16 dsto) { // NOTE: This don't pass the right value to RoomDraw_FlagDoorsAndGetFinalType assert(0); } void Door_Draw_Helper4(uint8 door_type, uint16 dsto) { int t = RoomDraw_FlagDoorsAndGetFinalType(1, door_type, dsto), new_type; if (t & 0x100) return; if ((new_type = kDoorType_Regular, t == kDoorType_1E || t == kDoorType_36) || (new_type = kDoorType_ShuttersTwoWay, t == kDoorType_38)) { int i = (dung_cur_door_idx >> 1) - 1; door_type_and_slot[i] = (i << 8) | new_type; t = new_type; } const uint16 *src = SrcPtr(kDoorTypeSrcData2[t >> 1]); uint16 *dst = DstoPtr(dsto); for (int i = 0; i < 4; i++) { dst[XY(0, 1)] = src[0]; dst[XY(0, 2)] = src[1]; dst[XY(0, 3)] = src[2]; dst++, src += 3; } } const uint16 *GetRoomDoorInfo(int room) { return (uint16 *)(kDungeonRoom + kDungeonRoomDoorOffs[room]); } const uint8 *GetRoomHeaderPtr(int room) { return kDungeonRoomHeaders + kDungeonRoomHeadersOffs[room]; } const uint8 *GetDefaultRoomLayout(int i) { return kDungeonRoomDefault + kDungeonRoomDefaultOffs[i]; } const uint8 *GetDungeonRoomLayout(int i) { return kDungeonRoom + kDungeonRoomOffs[i]; } static inline void WriteAttr1(int j, uint16 attr) { dung_bg1_attr_table[j + 0] = attr; dung_bg1_attr_table[j + 1] = attr >> 8; } static inline void WriteAttr2(int j, uint16 attr) { dung_bg2_attr_table[j + 0] = attr; dung_bg2_attr_table[j + 1] = attr >> 8; } void Dung_TagRoutine_0x22_0x3B(int k, uint8 j) { if (dung_savegame_state_bits & 0x100) { dung_hdr_tag[k] = 0; dung_overlay_to_load = j; dung_load_ptr_offs = 0; subsubmodule_index = 0; sound_effect_2 = 0x1b; submodule_index = 3; } } void Sprite_HandlePushedBlocks_One(int i) { Oam_AllocateFromRegionB(4); int y = (uint8)pushedblocks_y_lo[i] | (uint8)pushedblocks_y_hi[i] << 8; int x = (uint8)pushedblocks_x_lo[i] | (uint8)pushedblocks_x_hi[i] << 8; y -= BG2VOFS_copy2 + 1; x -= BG2HOFS_copy2; if (pushedblocks_some_index < 3) { uint8 *oam = &g_ram[oam_cur_ptr]; oam[0] = x; oam[1] = y; oam[2] = 12; oam[3] = 0x20; g_ram[oam_ext_cur_ptr] = 2; } } void Object_Draw_DoorLeft_3x4(uint16 src, int door) { const uint16 *s = SrcPtr(src); uint16 *dst = &dung_bg2[dung_door_tilemap_address[door] >> 1]; for (int i = 0; i < 3; i++) { dst[XY(0, 0)] = s[0]; dst[XY(0, 1)] = s[1]; dst[XY(0, 2)] = s[2]; dst[XY(0, 3)] = s[3]; dst += 1, s += 4; } } void Object_Draw_DoorRight_3x4(uint16 src, int door) { const uint16 *s = SrcPtr(src); uint16 *dst = &dung_bg2[dung_door_tilemap_address[door] >> 1]; for (int i = 0; i < 3; i++) { dst[XY(1, 0)] = s[0]; dst[XY(1, 1)] = s[1]; dst[XY(1, 2)] = s[2]; dst[XY(1, 3)] = s[3]; dst += 1, s += 4; } } void Dungeon_OpeningLockedDoor_Combined(bool skip_anim) { uint8 ctr = 2; int m, k, dma_ptr; if (skip_anim) { door_animation_step_indicator = 16; goto step12; } door_animation_step_indicator++; if (door_animation_step_indicator != 4) { if (door_animation_step_indicator != 12) goto middle; step12: m = kUpperBitmasks[dung_bg2_attr_table[dung_cur_door_pos] & 7]; dung_door_opened_incl_adjacent |= m; dung_door_opened |= m; ctr = 4; } door_open_closed_counter = ctr; k = dung_bg2_attr_table[dung_cur_door_pos] & 0xf; dma_ptr = DrawDoorOpening_Step1(k, 0); Dungeon_PrepOverlayDma_nextPrep(dma_ptr, dung_door_tilemap_address[k]); sound_effect_2 = 21; nmi_copy_packets_flag = 1; middle: if (door_animation_step_indicator == 16) { Dungeon_LoadToggleDoorAttr_OtherEntry(dung_bg2_attr_table[dung_cur_door_pos] & 0xf); if (dung_bg2_attr_table[dung_cur_door_pos] >= 0xf0) { k = dung_bg2_attr_table[dung_cur_door_pos] & 0xf; uint8 door_type = door_type_and_slot[k]; if (door_type >= kDoorType_StairMaskLocked0 && door_type <= kDoorType_StairMaskLocked3) DrawCompletelyOpenDoor(); } submodule_index = 0; } } const DungPalInfo *GetDungPalInfo(int idx) { return &kDungPalinfos[idx]; } uint16 Dungeon_GetTeleMsg(int room) { return kDungeonRoomTeleMsg[room]; } uint8 GetEntranceMusicTrack(int entrance) { return kEntranceData_musicTrack[entrance]; } bool Dungeon_IsPitThatHurtsPlayer() { for (int i = kDungeonPitsHurtPlayer_SIZE / 2 - 1; i >= 0; i--) { if (kDungeonPitsHurtPlayer[i] == dungeon_room_index) return true; } return false; } void Dungeon_PrepareNextRoomQuadrantUpload() { // 80913f int ofs = (overworld_screen_transition & 0xf) + dung_cur_quadrant_upload; uint16 *src = &dung_bg2[kUploadBgSrcs[ofs] / 2]; int p = 0; do { UploadVram_32x32 *d = (UploadVram_32x32 *)&g_ram[0x1000 + p * 2]; do { d->row[0].col[0] = src[XY(0, 0)]; d->row[0].col[1] = src[XY(1, 0)]; d->row[1].col[0] = src[XY(0, 1)]; d->row[1].col[1] = src[XY(1, 1)]; d->row[2].col[0] = src[XY(0, 2)]; d->row[2].col[1] = src[XY(1, 2)]; d->row[3].col[0] = src[XY(0, 3)]; d->row[3].col[1] = src[XY(1, 3)]; d = (UploadVram_32x32 *)((uint16 *)d + 2); src += 2, p += 2; } while (p & 0x1f); src += 224; p += 128 - 32; } while (p != 0x400); dung_cur_quadrant_upload += 4; BYTE(nmi_load_target_addr) = kUploadBgDsts[ofs]; nmi_subroutine_index = 1; nmi_disable_core_updates = 1; } void WaterFlood_BuildOneQuadrantForVRAM() { // 8091c4 // It never seems to be 25 here, so skip updating water stuff assert(dung_hdr_tag[0] != 25); TileMapPrep_NotWaterOnTag(); } void TileMapPrep_NotWaterOnTag() { // 8091d3 int ofs = (overworld_screen_transition & 0xf) + dung_cur_quadrant_upload; uint16 *src = &dung_bg1[kUploadBgSrcs[ofs] / 2]; int p = 0; do { UploadVram_32x32 *d = (UploadVram_32x32 *)&g_ram[0x1000 + p * 2]; do { d->row[0].col[0] = src[XY(0, 0)]; d->row[0].col[1] = src[XY(1, 0)]; d->row[1].col[0] = src[XY(0, 1)]; d->row[1].col[1] = src[XY(1, 1)]; d->row[2].col[0] = src[XY(0, 2)]; d->row[2].col[1] = src[XY(1, 2)]; d->row[3].col[0] = src[XY(0, 3)]; d->row[3].col[1] = src[XY(1, 3)]; d = (UploadVram_32x32 *)((uint16 *)d + 2); src += 2, p += 2; } while (p & 0x1f); src += 224; p += 128 - 32; } while (p != 0x400); BYTE(nmi_load_target_addr) = kUploadBgDsts[ofs] + 0x10; nmi_subroutine_index = 1; nmi_disable_core_updates = 1; } void OrientLampLightCone() { // 80f567 static const uint16 kOrientLampBgTab0[] = { 0, 256, 0, 256 }; static const uint16 kOrientLampBgTab1[] = { 0, 0, 256, 256 }; static const int16 kOrientLampBgTab2[] = { 52, -2, 56, 6 }; static const int16 kOrientLampBgTab3[] = { 64, 64, 82, -176 }; static const int16 kOrientLampBgTab4[] = { 128, 384, 160, 160 }; if (!hdr_dungeon_dark_with_lantern || submodule_index == 20) return; uint8 a = link_direction_facing >> 1, idx = a; if (is_standing_in_doorway) { idx = (is_standing_in_doorway & 0xfe); if (idx) { if (a < 2) idx += ((uint8)(link_x_coord + 8) >= 0x80); else idx = a; } else { if (a >= 2) idx += ((uint8)link_y_coord >= 0x80); else idx = a; } } if (idx < 2) { BG1HOFS_copy2 = BG2HOFS_copy2 - (link_x_coord - 0x77) + kOrientLampBgTab0[idx]; uint16 t = BG2VOFS_copy2 - (link_y_coord - 0x58) + kOrientLampBgTab1[idx] + kOrientLampBgTab2[idx] + kOrientLampBgTab3[idx]; if ((int16)t < 0) t = 0; if (t > kOrientLampBgTab4[idx]) t = kOrientLampBgTab4[idx]; BG1VOFS_copy2 = t - kOrientLampBgTab3[idx]; } else { BG1VOFS_copy2 = BG2VOFS_copy2 - (link_y_coord - 0x72) + kOrientLampBgTab1[idx]; uint16 t = BG2HOFS_copy2 - (link_x_coord - 0x58) + kOrientLampBgTab0[idx] + kOrientLampBgTab2[idx] + kOrientLampBgTab3[idx]; if ((int16)t < 0) t = 0; if (t > kOrientLampBgTab4[idx]) t = kOrientLampBgTab4[idx]; BG1HOFS_copy2 = t - kOrientLampBgTab3[idx]; } } void PrepareDungeonExitFromBossFight() { // 80f945 SavePalaceDeaths(); SaveDungeonKeys(); dung_savegame_state_bits |= 0x8000; Dungeon_FlagRoomData_Quadrants(); int j = FindInByteArray(kDungeonExit_From, BYTE(dungeon_room_index), countof(kDungeonExit_From)); assert(j >= 0); BYTE(dungeon_room_index) = kDungeonExit_To[j]; if (BYTE(dungeon_room_index) == 0x20) { sram_progress_indicator = 3; save_ow_event_info[2] |= 0x20; savegame_is_darkworld ^= 0x40; Sprite_LoadGraphicsProperties_light_world_only(); Ancilla_TerminateSelectInteractives(0); link_disable_sprite_damage = 0; button_b_frames = 0; button_mask_b_y = 0; link_force_hold_sword_up = 0; flag_is_link_immobilized = 1; saved_module_for_menu = 8; main_module_index = 21; submodule_index = 0; subsubmodule_index = 0; } else if (BYTE(dungeon_room_index) == 0xd) { main_module_index = 24; submodule_index = 0; overworld_map_state = 0; CGADSUB_copy = 0x20; } else { if (j >= 3) { music_control = 0xf1; music_unk1 = 0xf1; main_module_index = 22; } else { main_module_index = 19; } saved_module_for_menu = 8; submodule_index = 0; subsubmodule_index = 0; } } void SavePalaceDeaths() { // 80f9dd int j = BYTE(cur_palace_index_x2); deaths_per_palace[j >> 1] = death_save_counter; if (j != 8) death_save_counter = 0; } void Dungeon_LoadRoom() { // 81873a Dungeon_LoadHeader(); dung_unk6 = 0; dung_hdr_collision_2_mirror = dung_hdr_collision_2; dung_hdr_collision_2_mirror_PADDING = dung_hdr_tag[0]; dung_some_subpixel[0] = 0x30; dung_some_subpixel[1] = 0xff; dung_floor_move_flags = 0; word_7E0420 = 0; dung_floor_x_vel = dung_floor_y_vel = 0; dung_floor_x_offs = dung_floor_y_offs = 0; invisible_door_dir_and_index_x2 = 0xffff; dung_blastwall_flag_x = dung_blastwall_flag_y = 0; dung_unk_blast_walls_2 = dung_unk_blast_walls_3 = 0; water_hdma_var5 = 0; dung_num_toggle_floor = 0; dung_num_toggle_palace = 0; dung_unk2 = 0; dung_cur_quadrant_upload = 0; dung_num_inter_room_upnorth_stairs = 0; dung_num_inter_room_southdown_stairs = 0; dung_num_inroom_upnorth_stairs = 0; dung_num_inroom_southdown_stairs = 0; dung_num_interpseudo_upnorth_stairs = 0; dung_num_inroom_upnorth_stairs_water = 0; dung_num_activated_water_ladders = 0; dung_num_water_ladders = 0; dung_some_stairs_unk4 = 0; dung_num_stairs_1 = 0; dung_num_stairs_2 = 0; dung_num_stairs_wet = 0; dung_num_inroom_upsouth_stairs_water = 0; dung_num_wall_upnorth_spiral_stairs = 0; dung_num_wall_downnorth_spiral_stairs = 0; dung_num_wall_upnorth_spiral_stairs_2 = 0; dung_num_wall_downnorth_spiral_stairs_2 = 0; dung_num_inter_room_upnorth_straight_stairs = 0; dung_num_inter_room_upsouth_straight_stairs = 0; dung_num_inter_room_downnorth_straight_stairs = 0; dung_num_inter_room_downsouth_straight_stairs = 0; dung_exit_door_addresses[0] = 0; dung_exit_door_addresses[1] = 0; dung_exit_door_addresses[2] = 0; dung_exit_door_addresses[3] = 0; dung_exit_door_count = 0; dung_door_switch_triggered = 0; dung_num_star_shaped_switches = 0; dung_misc_objs_index = 0; dung_index_of_torches = 0; dung_num_chests_x2 = 0; dung_num_bigkey_locks_x2 = 0; dung_unk5 = 0; dung_cur_door_idx = 0; for (int i = 0; i < 16; i++) { dung_door_tilemap_address[i] = 0; door_type_and_slot[i] = 0; dung_door_direction[i] = 0; dung_torch_timers[i] = 0; dung_replacement_tile_state[i] = 0; dung_object_pos_in_objdata[i] = 0; dung_object_tilemap_pos[i] = 0; } const uint8 *cur_p0 = GetDungeonRoomLayout(dungeon_room_index); dung_load_ptr_offs = 0; RoomDraw_DrawFloors(cur_p0); uint16 old_offs = dung_load_ptr_offs; dung_layout_and_starting_quadrant = cur_p0[dung_load_ptr_offs]; const uint8 *cur_p1 = GetDefaultRoomLayout(dung_layout_and_starting_quadrant >> 2); dung_load_ptr_offs = 0; RoomDraw_DrawAllObjects(cur_p1); dung_load_ptr_offs = old_offs + 1; RoomDraw_DrawAllObjects(cur_p0); // Draw Layer 1 objects to BG2 dung_load_ptr_offs += 2; memcpy(&dung_line_ptrs_row0, kDungeon_DrawObjectOffsets_BG2, 33); RoomDraw_DrawAllObjects(cur_p0); // Draw Layer 2 objects to BG2 dung_load_ptr_offs += 2; memcpy(&dung_line_ptrs_row0, kDungeon_DrawObjectOffsets_BG1, 33); RoomDraw_DrawAllObjects(cur_p0); // Draw Layer 3 objects to BG2 for (dung_load_ptr_offs = 0; dung_load_ptr_offs != 0x18C; dung_load_ptr_offs += 4) { MovableBlockData m = movable_block_datas[dung_load_ptr_offs >> 2]; if (m.room == dungeon_room_index) DrawObjects_PushableBlock(m.tilemap, dung_load_ptr_offs); } uint16 t; dung_index_of_torches = dung_index_of_torches_start = dung_misc_objs_index; int i = 0; do { if (dung_torch_data[i >> 1] == dungeon_room_index) { i += 2; do { t = dung_torch_data[i >> 1]; i += 2; DrawObjects_LightableTorch(t, i - 2); } while (dung_torch_data[i >> 1] != 0xffff); break; } i += 2; do { t = dung_torch_data[i >> 1]; i += 2; } while (t != 0xffff); } while (i != 0x120); dung_load_ptr_offs = 0x120; } void RoomDraw_DrawAllObjects(const uint8 *level_data) { // 8188e4 for (;;) { dung_draw_width_indicator = dung_draw_height_indicator = 0; uint16 d = WORD(level_data[dung_load_ptr_offs]); if (d == 0xffff) return; if (d == 0xfff0) break; RoomData_DrawObject(d, level_data); } for (;;) { dung_load_ptr_offs += 2; uint16 d = WORD(level_data[dung_load_ptr_offs]); if (d == 0xffff) return; RoomData_DrawObject_Door(d); } } void RoomData_DrawObject_Door(uint16 a) { // 818916 uint8 door_type = a >> 8; uint8 position = a >> 4 & 0xf; switch (a & 3) { case 0: RoomDraw_Door_North(door_type, position); break; case 1: RoomDraw_Door_South(door_type, position); break; case 2: RoomDraw_Door_West(door_type, position); break; case 3: RoomDraw_Door_East(door_type, position); break; } } void RoomData_DrawObject(uint16 r0, const uint8 *level_data) { // 81893c uint16 offs = dung_load_ptr_offs; uint8 idx = level_data[offs + 2]; dung_load_ptr_offs = offs + 3; if ((r0 & 0xfc) != 0xfc) { dung_draw_width_indicator = (r0 & 3); dung_draw_height_indicator = (r0 >> 8) & 3; uint8 x = (uint8)r0 >> 2; uint8 y = (r0 >> 10); uint16 dst = y * 64 + x; if (idx < 0xf8) { LoadType1ObjectSubtype1(idx, DstoPtr(dst), dst); } else { idx = (idx & 7) << 4 | ((r0 >> 8) & 3) << 2 | (r0 & 3); LoadType1ObjectSubtype3(idx, DstoPtr(dst), dst); } } else { uint8 x = (r0 & 3) << 4 | (r0 >> 12) & 0xf; uint8 y = ((r0 >> 8) & 0xf) << 2 | (idx >> 6); uint16 dst = y * 64 + x; LoadType1ObjectSubtype2(idx & 0x3f, DstoPtr(dst), dst); } } void RoomDraw_DrawFloors(const uint8 *level_data) { // 8189dc memcpy(&dung_line_ptrs_row0, kDungeon_DrawObjectOffsets_BG2, 33); uint8 ft = level_data[dung_load_ptr_offs++]; dung_floor_1_filler_tiles = ft & 0xf0; RoomDraw_FloorChunks(SrcPtr(dung_floor_1_filler_tiles)); memcpy(&dung_line_ptrs_row0, kDungeon_DrawObjectOffsets_BG1, 33); dung_floor_2_filler_tiles = (ft & 0xf) << 4; RoomDraw_FloorChunks(SrcPtr(dung_floor_2_filler_tiles)); } void RoomDraw_FloorChunks(const uint16 *src) { // 818a1f static const uint16 kDungeon_QuadrantOffsets[] = { 0x0, 0x40, 0x1000, 0x1040 }; for (int i = 0; i < 4; i++) { uint16 *dst = DstoPtr(kDungeon_QuadrantOffsets[i] / 2); for (int j = 0; j < 8; j++) { RoomDraw_A_Many32x32Blocks(8, src, dst); dst += XY(0, 4); } } } void RoomDraw_A_Many32x32Blocks(int n, const uint16 *src, uint16 *dst) { // 818a44 do { // draw 4x2 twice for (int i = 0; i < 2; i++) { dst[XY(0, 0)] = src[0]; dst[XY(1, 0)] = src[1]; dst[XY(2, 0)] = src[2]; dst[XY(3, 0)] = src[3]; dst[XY(0, 1)] = src[4]; dst[XY(1, 1)] = src[5]; dst[XY(2, 1)] = src[6]; dst[XY(3, 1)] = src[7]; dst += XY(0, 2); } dst += XY(4, -4); } while (--n); } void RoomDraw_1x3_rightwards(int n, const uint16 *src, uint16 *dst) { // 818d80 do { dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(0, 2)] = src[2]; dst++, src += 3; } while (--n); } bool RoomDraw_CheckIfWallIsMoved() { // 819298 dung_some_subpixel[0] = dung_some_subpixel[1] = 0; dung_floor_move_flags = 0; int i; if ((i = 0, dung_hdr_tag[0] >= 0x1c && dung_hdr_tag[0] < 0x20) || (i = 1, dung_hdr_tag[1] >= 0x1c && dung_hdr_tag[1] < 0x20)) { if (dung_savegame_state_bits & (0x1000 >> i)) { dung_hdr_collision = 0; dung_hdr_tag[i] = 0; dung_hdr_bg2_properties = 0; return false; } } return true; } void MovingWall_FillReplacementBuffer(int dsto) { // 8192d1 for (int i = 0; i < 64; i++) moving_wall_arr1[i] = 0x1ec; moving_wall_var1 = (dsto & 0x1f) | (dsto & 0x20 ? 0x400 : 0) | 0x1000; } void Object_Table_Helper(const uint16 *src, uint16 *dst) { // 8193f7 int n = dung_draw_width_indicator; dst[0] = src[0]; do { dst[1] = src[1]; dst[2] = src[2]; dst += 2; } while (--n); dst[1] = src[3]; } void DrawWaterThing(uint16 *dst, const uint16 *src) { // 8195a0 for (int i = 3; i >= 0; i--) { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3]; dst += XY(0, 1), src += 4; } } void RoomDraw_4x4(const uint16 *src, uint16 *dst) { // 8197ed RoomDraw_Object_Nx4(4, src, dst); } void RoomDraw_Object_Nx4(int n, const uint16 *src, uint16 *dst) { // 8197f0 do { dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(0, 2)] = src[2]; dst[XY(0, 3)] = src[3]; src += 4; dst += XY(1, 0); } while (--n); } void Object_DrawNx4_BothBgs(int n, const uint16 *src, int dsto) { // 819819 do { dung_bg1[dsto + XY(0, 0)] = dung_bg2[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(0, 1)] = dung_bg2[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = dung_bg2[dsto + XY(0, 2)] = src[2]; dung_bg1[dsto + XY(0, 3)] = dung_bg2[dsto + XY(0, 3)] = src[3]; src += 4, dsto += 1; } while (--n); } void RoomDraw_Rightwards2x2(const uint16 *src, uint16 *dst) { // 819895 dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(1, 0)] = src[2]; dst[XY(1, 1)] = src[3]; } void Object_Draw_3x2(const uint16 *src, uint16 *dst) { // 819d04 dst[XY(0, 0)] = src[0]; dst[XY(1, 0)] = src[1]; dst[XY(2, 0)] = src[2]; dst[XY(0, 1)] = src[3]; dst[XY(1, 1)] = src[4]; dst[XY(2, 1)] = src[5]; } void RoomDraw_WaterHoldingObject(int n, const uint16 *src, uint16 *dst) { // 819d6f do { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3]; src += 4; dst += XY(0, 1); } while (--n); } void RoomDraw_SomeBigDecors(int n, const uint16 *src, uint16 dsto) { // 819da2 uint16 *dst = &dung_bg2[dsto | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x1000)]; for (int i = 0; i < 8; i++) { for (int j = 0; j < n; j++) dst[j] = src[j]; dst += 64, src += n; } } void RoomDraw_SingleLampCone(uint16 a, uint16 y) { // 819e06 const uint16 *src = SrcPtr(y); uint16 *dst = &dung_bg1[a / 2]; for (int i = 0; i < 12; i++) { for (int j = 0; j < 12; j++) *dst++ = *src++; dst += 64 - 12; } } void RoomDraw_AgahnimsWindows(uint16 dsto) { // 819ea3 const uint16 *src; uint16 *d = &dung_bg2[dsto]; src = SrcPtr(0x1BF2); for (int i = 0; i < 6; i++) { d[XY(7, 4)] = d[XY(13, 4)] = d[XY(19, 4)] = src[0]; d[XY(7, 5)] = d[XY(13, 5)] = d[XY(19, 5)] = src[1]; d[XY(7, 6)] = d[XY(13, 6)] = d[XY(19, 6)] = src[2]; d[XY(7, 7)] = d[XY(13, 7)] = d[XY(19, 7)] = src[3]; src += 4, d += XY(1, 0); } d -= 6; src = SrcPtr(0x1c22); for (int i = 0; i < 5; i++) { int j = src[0]; d[XY(2, 10)] = d[XY(3, 9)] = d[XY(4, 8)] = d[XY(5, 7)] = d[XY(6, 6)] = d[XY(7, 5)] = d[XY(8, 4)] = j; d[XY(23, 4)] = d[XY(24, 5)] = d[XY(25, 6)] = d[XY(26, 7)] = d[XY(27, 8)] = d[XY(28, 9)] = d[XY(29, 10)] = j | 0x4000; src++, d += XY(0, 1); } d -= XY(0, 1) * 5; src = SrcPtr(0x1c2c); for (int i = 0; i < 6; i++) { int j = src[0]; d[XY(2, 11)] = d[XY(2, 17)] = d[XY(2, 23)] = j; d[XY(29, 11)] = d[XY(29, 17)] = d[XY(29, 23)] = j | 0x4000; j = src[1]; d[XY(3, 11)] = d[XY(3, 17)] = d[XY(3, 23)] = j; d[XY(28, 11)] = d[XY(28, 17)] = d[XY(28, 23)] = j | 0x4000; j = src[2]; d[XY(4, 11)] = d[XY(4, 17)] = d[XY(4, 23)] = j; d[XY(27, 11)] = d[XY(27, 17)] = d[XY(27, 23)] = j | 0x4000; j = src[3]; d[XY(5, 11)] = d[XY(5, 17)] = d[XY(5, 23)] = j; d[XY(26, 11)] = d[XY(26, 17)] = d[XY(26, 23)] = j | 0x4000; src += 4, d += XY(0, 1); } d -= XY(0, 1) * 6; src = SrcPtr(0x1c5c); for (int i = 0; i < 6; i++) { d[XY(12, 9)] = d[XY(18, 9)] = src[0]; d[XY(12, 10)] = d[XY(18, 10)] = src[6]; src += 1, d += XY(1, 0); } d -= XY(1, 0) * 6; src = SrcPtr(0x1c74); for (int i = 0; i < 6; i++) { d[XY(7, 14)] = d[XY(7, 20)] = src[0]; d[XY(8, 14)] = d[XY(8, 20)] = src[1]; src += 2, d += XY(0, 1); } d -= XY(0, 1) * 6; src = SrcPtr(0x1c8c); for (int i = 0; i < 5; i++) { d[XY(7, 9)] = src[0]; d[XY(7, 10)] = src[1]; d[XY(7, 11)] = src[2]; d[XY(7, 12)] = src[3]; d[XY(7, 13)] = src[4]; src += 5, d += XY(1, 0); } d -= XY(1, 0) * 5; for (int i = 0; i < 4; i++) { d[XY(14, 28)] |= 0x2000; d[XY(14, 29)] |= 0x2000; d += XY(1, 0); } } void RoomDraw_FortuneTellerRoom(uint16 dsto) { // 81a095 const uint16 *src = SrcPtr(0x202e), *src_org = src; uint16 *d = &dung_bg2[dsto]; int j; for (int i = 0; i < 6; i++) { d[XY(1, 0)] = d[XY(2, 0)] = d[XY(1, 1)] = d[XY(2, 1)] = src[0]; d[XY(1, 2)] = (j = src[1]); d[XY(2, 2)] = j | 0x4000; d += XY(2, 0); } d -= XY(2, 0) * 6; for (int i = 0; i < 3; i++) { d[XY(0, 3)] = d[XY(2, 3)] = d[XY(10, 3)] = d[XY(12, 3)] = (j = src[2]); d[XY(1, 3)] = d[XY(3, 3)] = d[XY(11, 3)] = d[XY(13, 3)] = j | 0x4000; d[XY(4, 3)] = d[XY(6, 3)] = d[XY(8, 3)] = (j = src[5]); d[XY(5, 3)] = d[XY(7, 3)] = d[XY(9, 3)] = j | 0x4000; src++, d += XY(0, 1); } d -= XY(0, 1) * 3; d[XY(0, 0)] = d[XY(0, 1)] = (j = src[5]); d[XY(13, 0)] = d[XY(13, 1)] = j | 0x4000; d[XY(0, 2)] = (j = src[6]); d[XY(13, 2)] = j | 0x4000; src = src_org; for (int i = 0; i < 4; i++) { d[XY(3, 10)] = (j = src[10]); d[XY(10, 10)] = j ^ 0x4000; d[XY(4, 10)] = (j = src[14]); d[XY(9, 10)] = j ^ 0x4000; d[XY(5, 10)] = (j = src[18]); d[XY(8, 10)] = j ^ 0x4000; d[XY(6, 10)] = (j = src[22]); d[XY(7, 10)] = j ^ 0x4000; src++, d += XY(0, 1); } } void Object_Draw8x8(const uint16 *src, uint16 *dst) { // 81a7dc RoomDraw_4x4(src, dst + XY(0, 0)); RoomDraw_4x4(src + 16, dst + XY(4, 0)); RoomDraw_4x4(src + 32, dst + XY(0, 4)); RoomDraw_4x4(src + 48, dst + XY(4, 4)); } void RoomDraw_Door_North(int type, int pos_enum) { // 81a81c uint16 dsto = kDoorPositionToTilemapOffs_Up[pos_enum] / 2; if (type == kDoorType_LgExplosion) RoomDraw_Door_ExplodingWall(pos_enum); else if (type == kDoorType_PlayerBgChange) RoomDraw_MarkLayerToggleDoor(dsto - 0xfe / 2); else if (type == kDoorType_Slashable) RoomDraw_NorthCurtainDoor(dsto); else if (type == kDoorType_EntranceDoor) Door_Up_EntranceDoor(dsto); else if (type == kDoorType_ThroneRoom) RoomDraw_MarkDungeonToggleDoor(dsto - 0xfe / 2); else if (type == kDoorType_Regular2) { RoomDraw_MakeDoorPartsHighPriority_Y(dsto & (0xF07F / 2)); RoomDraw_NormalRangedDoors_North(type, dsto, pos_enum); } else if (type == kDoorType_ExitToOw) { dung_exit_door_addresses[dung_exit_door_count >> 1] = dsto * 2; dung_exit_door_count += 2; } else if (type == kDoorType_WaterfallTunnel) { RoomDraw_NormalRangedDoors_North(type, dsto, pos_enum); Door_PrioritizeCurDoor(); } else if (type >= kDoorType_StairMaskLocked0 && type <= kDoorType_StairMaskLocked3) { Door_Up_StairMaskLocked(type, dsto); } else if (type >= kDoorType_RegularDoor33) RoomDraw_HighRangeDoor_North(type, dsto, pos_enum); else RoomDraw_NormalRangedDoors_North(type, dsto, pos_enum); } void Door_Up_StairMaskLocked(uint8 door_type, uint16 dsto) { // 81a892 int i = dung_cur_door_idx >> 1; dung_door_direction[i] = 0; dung_door_tilemap_address[i] = dsto * 2; door_type_and_slot[i] = i << 8 | door_type; if (dung_door_opened_incl_adjacent & kUpperBitmasks[i & 7]) { dung_cur_door_idx += 2; return; } if (door_type < kDoorType_StairMaskLocked2) { RoomDraw_OneSidedShutters_North(door_type, dsto); return; } uint8 t = RoomDraw_FlagDoorsAndGetFinalType(0, door_type, dsto); const uint16 *src = SrcPtr(kDoorTypeSrcData[t >> 1]); for (int i = 0; i < 4; i++) { dung_bg1[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = src[2]; dsto++, src += 3; } Door_PrioritizeCurDoor(); } void Door_PrioritizeCurDoor() { // 81a8fa dung_door_tilemap_address[(dung_cur_door_idx >> 1) - 1] |= 0x2000; } void RoomDraw_NormalRangedDoors_North(uint8 door_type, uint16 dsto, int pos_enum) { // 81a90f if (pos_enum >= 6) { uint16 bak = dung_cur_door_idx; dung_cur_door_idx |= 0x10; RoomDraw_CheckIfLowerLayerDoors_Y(door_type, kDoorPositionToTilemapOffs_Down[pos_enum - 6] / 2); dung_cur_door_idx = bak; } RoomDraw_OneSidedShutters_North(door_type, dsto); } void RoomDraw_OneSidedShutters_North(uint8 door_type, uint16 dsto) { // 81a932 int t = RoomDraw_FlagDoorsAndGetFinalType(0, door_type, dsto); if (t & 0x100) return; // Remap type if (t == 54 || t == 56) { int new_type = (t == 54) ? kDoorType_ShuttersTwoWay : kDoorType_Regular; int i = (dung_cur_door_idx >> 1) - 1; door_type_and_slot[i] = (i << 8) | new_type; t = new_type; } const uint16 *src = SrcPtr(kDoorTypeSrcData[t >> 1]); uint16 *dst = DstoPtr(dsto); for (int i = 0; i < 4; i++) { dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(0, 2)] = src[2]; dst++, src += 3; } } void RoomDraw_Door_South(int type, int pos_enum) { // 81a984 uint16 dsto = kDoorPositionToTilemapOffs_Down[pos_enum] / 2; if (type == kDoorType_PlayerBgChange) RoomDraw_MarkLayerToggleDoor(dsto + XY(1, 4)); else if (type == kDoorType_EntranceDoor) Door_Down_EntranceDoor(dsto); else if (type == kDoorType_ThroneRoom) RoomDraw_MarkDungeonToggleDoor(dsto + XY(1, 4)); else if (type == kDoorType_ExitToOw) { dung_exit_door_addresses[dung_exit_door_count >> 1] = dsto * 2; dung_exit_door_count += 2; } else if (type >= kDoorType_RegularDoor33) { RoomDraw_OneSidedLowerShutters_South(type, dsto); } else if (type == kDoorType_EntranceLarge) { RoomDraw_FlagDoorsAndGetFinalType(1, type, dsto); RoomDraw_SomeBigDecors(10, SrcPtr(0x2656), dsto + XY(-3, -4)); } else if (type == kDoorType_EntranceLarge2) { dsto |= 0x1000; RoomDraw_FlagDoorsAndGetFinalType(1, type, dsto); dsto += XY(-3, -4); RoomDraw_SomeBigDecors(10, SrcPtr(0x2656), dsto); dsto += -0x1000 + XY(0, 7); for (int i = 0; i < 10; i++) { dung_bg2[dsto] = dung_bg1[dsto] | 0x2000; dsto += 1; } } else if (type == kDoorType_EntranceCave || type == kDoorType_EntranceCave2) { if (type == kDoorType_EntranceCave2) RoomDraw_MakeDoorPartsHighPriority_Y(dsto + XY(0, 4)); RoomDraw_FlagDoorsAndGetFinalType(1, type, dsto); RoomDraw_4x4(SrcPtr(0x26f6), DstoPtr(dsto)); } else if (type == kDoorType_4) { uint16 dsto_org = dsto; dsto |= 0x1000; RoomDraw_MakeDoorPartsHighPriority_Y(dsto + XY(0, 4)); RoomDraw_FlagDoorsAndGetFinalType(1, type, dsto); RoomDraw_4x4(SrcPtr(0x26f6), DstoPtr(dsto)); for (int i = 0; i < 4; i++) { dung_bg2[dsto_org + XY(0, 3)] = dung_bg1[dsto_org + XY(0, 3)] | 0x2000; dsto_org += 1; } } else { RoomDraw_CheckIfLowerLayerDoors_Y(type, dsto); } } void RoomDraw_CheckIfLowerLayerDoors_Y(uint8 door_type, uint16 dsto) { // 81aa66 if (door_type == kDoorType_Regular2) { RoomDraw_MakeDoorPartsHighPriority_Y(dsto + XY(0, 4)); Door_Draw_Helper4(door_type, dsto); } else if (door_type == kDoorType_WaterfallTunnel) { Door_Draw_Helper4(door_type, dsto); Door_PrioritizeCurDoor(); } else { Door_Draw_Helper4(door_type, dsto); } } void RoomDraw_Door_West(int type, int pos_enum) { // 81aad7 uint16 dsto = kDoorPositionToTilemapOffs_Left[pos_enum] / 2; if (type == kDoorType_PlayerBgChange) RoomDraw_MarkLayerToggleDoor(dsto + XY(-2, 1)); else if (type == kDoorType_EntranceDoor) Door_Left_EntranceDoor(dsto); else if (type == kDoorType_ThroneRoom) RoomDraw_MarkDungeonToggleDoor(dsto + XY(-2, 1)); else if (type == kDoorType_Regular2) { RoomDraw_MakeDoorPartsHighPriority_X(dsto & ~0x1f); RoomDraw_NormalRangedDoors_West(type, dsto, pos_enum); } else if (type == kDoorType_WaterfallTunnel) { RoomDraw_NormalRangedDoors_West(type, dsto, pos_enum); Door_PrioritizeCurDoor(); } else if (type < kDoorType_RegularDoor33) { RoomDraw_NormalRangedDoors_West(type, dsto, pos_enum); } else { RoomDraw_HighRangeDoor_West(type, dsto, pos_enum); } } void RoomDraw_NormalRangedDoors_West(uint8 door_type, uint16 dsto, int pos_enum) { // 81ab1f if (pos_enum >= 6) { uint16 bak = dung_cur_door_idx; dung_cur_door_idx |= 0x10; RoomDraw_NormalRangedDoors_East(door_type, kDoorPositionToTilemapOffs_Right[pos_enum - 6] / 2); dung_cur_door_idx = bak; } int t = RoomDraw_FlagDoorsAndGetFinalType(2, door_type, dsto), new_type; if (t & 0x100) return; if ((new_type = kDoorType_ShuttersTwoWay, t == kDoorType_36) || (new_type = kDoorType_Regular, t == kDoorType_38)) { int i = (dung_cur_door_idx >> 1) - 1; door_type_and_slot[i] = (i << 8) | new_type; t = new_type; } const uint16 *src = SrcPtr(kDoorTypeSrcData3[t >> 1]); uint16 *dst = DstoPtr(dsto); for (int i = 0; i < 3; i++) { dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(0, 2)] = src[2]; dst[XY(0, 3)] = src[3]; dst++, src += 4; } } void RoomDraw_Door_East(int type, int pos_enum) { // 81ab99 uint16 dsto = kDoorPositionToTilemapOffs_Right[pos_enum] / 2; if (type == kDoorType_PlayerBgChange) RoomDraw_MarkLayerToggleDoor(dsto + XY(4, 1)); else if (type == kDoorType_EntranceDoor) Door_Right_EntranceDoor(dsto); else if (type == kDoorType_ThroneRoom) RoomDraw_MarkDungeonToggleDoor(dsto + XY(4, 1)); else if (type < kDoorType_RegularDoor33) { RoomDraw_NormalRangedDoors_East(type, dsto); } else { RoomDraw_OneSidedLowerShutters_East(type, dsto); } } void RoomDraw_NormalRangedDoors_East(uint8 door_type, uint16 dsto) { // 81abc8 if (door_type == kDoorType_Regular2) RoomDraw_MakeDoorPartsHighPriority_X(dsto + XY(4, 0)); if (door_type == kDoorType_WaterfallTunnel) { RoomDraw_OneSidedShutters_East(door_type, dsto); Door_PrioritizeCurDoor(); } else { RoomDraw_OneSidedShutters_East(door_type, dsto); } } void RoomDraw_OneSidedShutters_East(uint8 door_type, uint16 dsto) { // 81abe2 int t = RoomDraw_FlagDoorsAndGetFinalType(3, door_type, dsto), new_type; if (t & 0x100) return; if ((new_type = kDoorType_Regular, t == kDoorType_36) || (new_type = kDoorType_ShuttersTwoWay, t == kDoorType_38)) { int i = (dung_cur_door_idx >> 1) - 1; door_type_and_slot[i] = (i << 8) | new_type; t = new_type; } const uint16 *src = SrcPtr(kDoorTypeSrcData4[t >> 1]); uint16 *dst = DstoPtr(dsto) + 1; for (int i = 0; i < 3; i++) { dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(0, 2)] = src[2]; dst[XY(0, 3)] = src[3]; dst++, src += 4; } } void RoomDraw_NorthCurtainDoor(uint16 dsto) { // 81ac3b int rv = RoomDraw_FlagDoorsAndGetFinalType(0, kDoorType_Slashable, dsto); if (rv & 0x100) { RoomDraw_4x4(SrcPtr(0x78a), DstoPtr(dsto)); } else { RoomDraw_4x4(SrcPtr(kDoorTypeSrcData[rv >> 1]), DstoPtr(dsto)); } } void RoomDraw_Door_ExplodingWall(int pos_enum) { // 81ac70 uint16 dsto = kDoor_BlastWallUp_Dsts[pos_enum] / 2; int i = dung_cur_door_idx >> 1; dung_door_tilemap_address[i] = 2 * (dsto + 10); door_type_and_slot[i] = i << 8 | kDoorType_LgExplosion; if (!(dung_door_opened_incl_adjacent & kUpperBitmasks[i & 7])) { dung_door_direction[i] = 0; dung_cur_door_idx += 2; return; } int slot = dung_hdr_tag[0] != 0x20 && dung_hdr_tag[0] != 0x25 && dung_hdr_tag[0] != 0x28; dung_hdr_tag[slot] = 0; quadrant_fullsize_y = 2; dung_blastwall_flag_y = 1; RoomDraw_ExplodingWallSegment(SrcPtr(kDoorTypeSrcData2[42]), dsto); dung_cur_door_idx += 2; dung_unk2 |= 0x200; RoomDraw_ExplodingWallSegment(SrcPtr(kDoorTypeSrcData[42]), dsto + XY(0, 6)); } void RoomDraw_ExplodingWallSegment(const uint16 *src, uint16 dsto) { // 81ace4 RoomDraw_ExplodingWallColumn(src, DstoPtr(dsto)); src += 12, dsto += 2; int n = src[0]; uint16 *d = &dung_bg2[dsto]; dung_draw_width_indicator = 18; do { d[XY(0, 0)] = d[XY(0, 1)] = d[XY(0, 2)] = n; d[XY(0, 3)] = d[XY(0, 4)] = d[XY(0, 5)] = n; d++; } while (--dung_draw_width_indicator); RoomDraw_ExplodingWallColumn(src + 1, DstoPtr(dsto + 18)); } void RoomDraw_ExplodingWallColumn(const uint16 *src, uint16 *dst) { // 81ad25 for (int i = 0; i < 6; i++) { dst[0] = src[0]; dst[1] = src[6]; dst += XY(0, 1), src += 1; } } void RoomDraw_HighRangeDoor_North(uint8 door_type, uint16 dsto, int pos_enum) { // 81ad41 if (pos_enum >= 6 && door_type != kDoorType_WarpRoomDoor) { uint16 bak = dung_cur_door_idx; dung_cur_door_idx |= 0x10; RoomDraw_OneSidedLowerShutters_South(door_type, kDoorPositionToTilemapOffs_Down[pos_enum - 6] / 2); dung_cur_door_idx = bak; } uint8 t = RoomDraw_FlagDoorsAndGetFinalType(0, door_type, dsto); if (t == kDoorType_ShutterTrapUR || t == kDoorType_ShutterTrapDL) { int new_type = (t == kDoorType_ShutterTrapUR) ? kDoorType_RegularDoor33 : kDoorType_Shutter; int i = (dung_cur_door_idx >> 1) - 1; door_type_and_slot[i] = (i << 8) | new_type; t = new_type; } uint16 dsto_org = dsto; const uint16 *src = SrcPtr(kDoorTypeSrcData[t >> 1]); for (int i = 0; i < 4; i++) { dung_bg2[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = src[2]; dsto++, src += 3; } if (door_type != kDoorType_WarpRoomDoor) RoomDraw_MakeDoorHighPriority_North(dsto_org); Door_PrioritizeCurDoor(); } void RoomDraw_OneSidedLowerShutters_South(uint8 door_type, uint16 dsto) { // 81add4 uint8 t = RoomDraw_FlagDoorsAndGetFinalType(1, door_type, dsto); if (t == kDoorType_ShutterTrapUR || t == kDoorType_ShutterTrapDL) { int new_type = (t == kDoorType_ShutterTrapUR) ? kDoorType_Shutter : kDoorType_RegularDoor33; int i = (dung_cur_door_idx >> 1) - 1; door_type_and_slot[i] = (i << 8) | new_type; t = new_type; } uint16 dsto_org = dsto; const uint16 *src = SrcPtr(kDoorTypeSrcData2[t >> 1]); for (int i = 0; i < 4; i++) { dung_bg1[dsto + XY(0, 1)] = src[0]; dung_bg1[dsto + XY(0, 2)] = src[1]; dung_bg2[dsto + XY(0, 3)] = src[2]; dsto++, src += 3; } RoomDraw_MakeDoorHighPriority_South(dsto_org + XY(0, 4)); Door_PrioritizeCurDoor(); } void RoomDraw_HighRangeDoor_West(uint8 door_type, uint16 dsto, int pos_enum) { // 81ae40 if (pos_enum >= 6) { uint16 bak = dung_cur_door_idx; dung_cur_door_idx |= 0x10; RoomDraw_OneSidedLowerShutters_East(door_type, kDoorPositionToTilemapOffs_Right[pos_enum - 6] / 2); dung_cur_door_idx = bak; } uint8 t = RoomDraw_FlagDoorsAndGetFinalType(2, door_type, dsto), new_type; if ((new_type = kDoorType_Shutter, t == kDoorType_ShutterTrapUR) || (new_type = kDoorType_RegularDoor33, t == kDoorType_ShutterTrapDL)) { int i = (dung_cur_door_idx >> 1) - 1; door_type_and_slot[i] = (i << 8) | new_type; t = new_type; } const uint16 *src = SrcPtr(kDoorTypeSrcData3[t >> 1]); uint16 dsto_org = dsto; dung_bg2[dsto + XY(0, 0)] = src[0]; dung_bg2[dsto + XY(0, 1)] = src[1]; dung_bg2[dsto + XY(0, 2)] = src[2]; dung_bg2[dsto + XY(0, 3)] = src[3]; dsto++, src += 4; for (int i = 0; i < 2; i++) { dung_bg1[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(0, 1)] = src[1]; dung_bg1[dsto + XY(0, 2)] = src[2]; dung_bg1[dsto + XY(0, 3)] = src[3]; dsto++, src += 4; } RoomDraw_MakeDoorHighPriority_West(dsto_org); Door_PrioritizeCurDoor(); } void RoomDraw_OneSidedLowerShutters_East(uint8 door_type, uint16 dsto) { // 81aef0 uint8 t = RoomDraw_FlagDoorsAndGetFinalType(3, door_type, dsto), new_type; if ((new_type = kDoorType_RegularDoor33, t == kDoorType_ShutterTrapUR) || (new_type = kDoorType_Shutter, t == kDoorType_ShutterTrapDL)) { int i = (dung_cur_door_idx >> 1) - 1; door_type_and_slot[i] = (i << 8) | new_type; t = new_type; } uint16 dst_org = dsto; const uint16 *src = SrcPtr(kDoorTypeSrcData4[t >> 1]); for (int i = 0; i < 2; i++) { dung_bg1[dsto + XY(1, 0)] = src[0]; dung_bg1[dsto + XY(1, 1)] = src[1]; dung_bg1[dsto + XY(1, 2)] = src[2]; dung_bg1[dsto + XY(1, 3)] = src[3]; dsto++, src += 4; } dung_bg2[dsto + XY(1, 0)] = src[0]; dung_bg2[dsto + XY(1, 1)] = src[1]; dung_bg2[dsto + XY(1, 2)] = src[2]; dung_bg2[dsto + XY(1, 3)] = src[3]; RoomDraw_MakeDoorHighPriority_East(dst_org + XY(4, 0)); Door_PrioritizeCurDoor(); } void RoomDraw_MakeDoorHighPriority_North(uint16 dsto) { // 81af8b uint16 dsto_org = dsto; dsto &= 0xF07F >> 1; do { dung_bg2[dsto + 0] |= 0x2000; dung_bg2[dsto + 1] |= 0x2000; dung_bg2[dsto + 2] |= 0x2000; dung_bg2[dsto + 3] |= 0x2000; dsto += XY(0, 1); } while (dsto != dsto_org); } void RoomDraw_MakeDoorHighPriority_South(uint16 dsto) { // 81afd4 do { dung_bg2[dsto + 0] |= 0x2000; dung_bg2[dsto + 1] |= 0x2000; dung_bg2[dsto + 2] |= 0x2000; dung_bg2[dsto + 3] |= 0x2000; dsto += XY(0, 1); } while (dsto & 0x7c0); } void RoomDraw_MakeDoorHighPriority_West(uint16 dsto) { // 81b017 uint16 dsto_org = dsto; dsto &= 0xffe0; do { dung_bg2[dsto + XY(0, 0)] |= 0x2000; dung_bg2[dsto + XY(0, 1)] |= 0x2000; dung_bg2[dsto + XY(0, 2)] |= 0x2000; dung_bg2[dsto + XY(0, 3)] |= 0x2000; dsto += XY(1, 0); } while (dsto != dsto_org); } void RoomDraw_MakeDoorHighPriority_East(uint16 dsto) { // 81b05c uint16 *d = &dung_bg2[dsto]; do { d[XY(0, 0)] |= 0x2000; d[XY(0, 1)] |= 0x2000; d[XY(0, 2)] |= 0x2000; d[XY(0, 3)] |= 0x2000; d += XY(1, 0), dsto += 1; } while (dsto & 0x1f); } void RoomDraw_MarkDungeonToggleDoor(uint16 dsto) { // 81b092 dung_toggle_palace_pos[dung_num_toggle_palace >> 1] = dsto; dung_num_toggle_palace += 2; } void RoomDraw_MarkLayerToggleDoor(uint16 dsto) { // 81b09f dung_toggle_floor_pos[dung_num_toggle_floor >> 1] = dsto; dung_num_toggle_floor += 2; } void RoomDraw_GetObjectSize_1to16() { // 81b0ac dung_draw_width_indicator = (dung_draw_width_indicator << 2 | dung_draw_height_indicator) + 1; dung_draw_height_indicator = 0; } void Object_SizeAtoAplus15(uint8 a) { // 81b0af dung_draw_width_indicator = (dung_draw_width_indicator << 2 | dung_draw_height_indicator) + a; dung_draw_height_indicator = 0; } void RoomDraw_GetObjectSize_1to15or26() { // 81b0be uint16 x = dung_draw_width_indicator << 2 | dung_draw_height_indicator; dung_draw_width_indicator = x ? x : 26; } void RoomDraw_GetObjectSize_1to15or32() { // 81b0cc uint16 x = dung_draw_width_indicator << 2 | dung_draw_height_indicator; dung_draw_width_indicator = x ? x : 32; } // returns 0x100 on inverse carry int RoomDraw_FlagDoorsAndGetFinalType(uint8 direction, uint8 door_type, uint16 dsto) { // 81b0da int slot = dung_cur_door_idx >> 1; dung_door_direction[slot] = direction; dung_door_tilemap_address[slot] = dsto * 2; door_type_and_slot[slot] = slot << 8 | door_type; uint8 door_type_remapped = door_type; if ((slot & 7) < 4 && (dung_door_opened_incl_adjacent & kUpperBitmasks[slot & 7])) { if ((door_type == kDoorType_ShuttersTwoWay || door_type == kDoorType_Shutter) && dung_flag_trapdoors_down) goto dont_mark_opened; door_type_remapped = kDoorTypeRemap[door_type >> 1]; if (door_type != kDoorType_ShuttersTwoWay && door_type != kDoorType_Shutter && door_type >= kDoorType_InvisibleDoor && door_type != kDoorType_RegularDoor33 && door_type != kDoorType_WarpRoomDoor) dung_door_opened |= kUpperBitmasks[slot]; } dont_mark_opened: dung_cur_door_idx = slot * 2 + 2; if (door_type_remapped == kDoorType_Slashable || door_type_remapped == kDoorType_WaterfallTunnel) return 0x100 | door_type_remapped; if (door_type != kDoorType_InvisibleDoor) return door_type_remapped; invisible_door_dir_and_index_x2 = (slot << 8 | direction) * 2; // if (direction * 2 == link_direction_facing || ((direction * 2) ^ 2) == link_direction_facing) // return door_type_remapped; dung_door_opened_incl_adjacent |= kUpperBitmasks[slot]; return kDoorType_Regular; } void RoomDraw_MakeDoorPartsHighPriority_Y(uint16 dsto) { // 81b1a4 uint16 *d = &dung_bg2[dsto]; for (int i = 0; i < 7; i++) { d[XY(0, 0)] |= 0x2000; d[XY(1, 0)] |= 0x2000; d[XY(2, 0)] |= 0x2000; d[XY(3, 0)] |= 0x2000; d += XY(0, 1); } } void RoomDraw_MakeDoorPartsHighPriority_X(uint16 dsto) { // 81b1e7 uint16 *d = &dung_bg2[dsto]; for (int i = 0; i < 5; i++) { d[XY(0, 0)] |= 0x2000; d[XY(0, 1)] |= 0x2000; d[XY(0, 2)] |= 0x2000; d[XY(0, 3)] |= 0x2000; d += XY(1, 0); } } void RoomDraw_Downwards4x2VariableSpacing(int increment, const uint16 *src, uint16 *dst) { // 81b220 do { dst[XY(0, 0)] = src[0]; dst[XY(1, 0)] = src[1]; dst[XY(2, 0)] = src[2]; dst[XY(3, 0)] = src[3]; dst[XY(0, 1)] = src[4]; dst[XY(1, 1)] = src[5]; dst[XY(2, 1)] = src[6]; dst[XY(3, 1)] = src[7]; dst += increment; } while (--dung_draw_width_indicator); } uint16 *RoomDraw_DrawObject2x2and1(const uint16 *src, uint16 *dst) { // 81b279 dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(0, 2)] = src[2]; dst[XY(0, 3)] = src[3]; dst[XY(0, 4)] = src[4]; return dst; } uint16 *RoomDraw_RightwardShelfEnd(const uint16 *src, uint16 *dst) { // 81b2e1 dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(0, 2)] = src[2]; dst[XY(0, 3)] = src[3]; return dst; } uint16 *RoomDraw_RightwardBarSegment(const uint16 *src, uint16 *dst) { // 81b2f6 dst[XY(0, 0)] = src[0]; dst[XY(0, 1)] = src[1]; dst[XY(0, 2)] = src[2]; return dst; } void DrawBigGraySegment(uint16 a, const uint16 *src, uint16 *dst, uint16 dsto) { // 81b33a int i = dung_misc_objs_index >> 1; dung_replacement_tile_state[i] = a; dung_misc_objs_index += 2; dung_object_pos_in_objdata[i] = dung_load_ptr_offs; dung_object_tilemap_pos[i] = dsto * 2 | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x2000); replacement_tilemap_UL[i] = dst[XY(0, 0)]; replacement_tilemap_LL[i] = dst[XY(0, 1)]; replacement_tilemap_UR[i] = dst[XY(1, 0)]; replacement_tilemap_LR[i] = dst[XY(1, 1)]; RoomDraw_Rightwards2x2(src, dst); } void RoomDraw_SinglePot(const uint16 *src, uint16 *dst, uint16 dsto) { // 81b395 int i = dung_misc_objs_index >> 1; dung_misc_objs_index += 2; dung_replacement_tile_state[i] = 0x1111; dung_object_pos_in_objdata[i] = dung_load_ptr_offs; dung_object_tilemap_pos[i] = (dsto * 2) | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x2000); replacement_tilemap_UL[i] = 0x0d0e; replacement_tilemap_LL[i] = 0x0d1e; replacement_tilemap_UR[i] = 0x4d0e; replacement_tilemap_LR[i] = 0x4d1e; if (savegame_is_darkworld) src = SrcPtr(0xe92); RoomDraw_Rightwards2x2(src, dst); } void RoomDraw_BombableFloor(const uint16 *src, uint16 *dst, uint16 dsto) { // 81b3e1 if (dungeon_room_index == 101 && (dung_savegame_state_bits & 0x1000)) { dung_draw_width_indicator = 0; dung_draw_height_indicator = 0; Object_Hole(SrcPtr(0x5aa), dst); return; } src = SrcPtr(0x220); const uint16 *src_below = SrcPtr(0x5ba); Object_BombableFloorHelper(0x3030, src, src_below, dst, dsto); Object_BombableFloorHelper(0x3131, src + 4, src_below + 4, dst + XY(2, 0), dsto + XY(2, 0)); Object_BombableFloorHelper(0x3232, src + 8, src_below + 8, dst + XY(0, 2), dsto + XY(0, 2)); Object_BombableFloorHelper(0x3333, src + 12, src_below + 12, dst + XY(2, 2), dsto + XY(2, 2)); } void RoomDraw_HammerPegSingle(const uint16 *src, uint16 *dst, uint16 dsto) { // 81b493 int i = dung_misc_objs_index >> 1; dung_misc_objs_index += 2; dung_replacement_tile_state[i] = 0x4040; dung_object_pos_in_objdata[i] = dung_load_ptr_offs; dung_object_tilemap_pos[i] = (dsto * 2) | (dung_line_ptrs_row0 != 0x4000 ? 0 : 0x2000); replacement_tilemap_UL[i] = 0x19d8; replacement_tilemap_LL[i] = 0x19d9; replacement_tilemap_UR[i] = 0x59d8; replacement_tilemap_LR[i] = 0x59d9; RoomDraw_Rightwards2x2(src, dst); } void DrawObjects_PushableBlock(uint16 dsto_x2, uint16 slot) { // 81b4d6 int x = dung_misc_objs_index >> 1; dung_misc_objs_index += 2; dung_replacement_tile_state[x] = 0; dung_object_pos_in_objdata[x] = slot; dung_object_tilemap_pos[x] = dsto_x2; uint16 *dst = DstoPtr((dsto_x2 >> 1) & 0x1fff); replacement_tilemap_UL[x] = dst[XY(0, 0)]; replacement_tilemap_LL[x] = dst[XY(0, 1)]; replacement_tilemap_UR[x] = dst[XY(1, 0)]; replacement_tilemap_LR[x] = dst[XY(1, 1)]; RoomDraw_Rightwards2x2(SrcPtr(0xe52), dst); } void DrawObjects_LightableTorch(uint16 dsto_x2, uint16 slot) { // 81b509 int x = dung_index_of_torches >> 1; dung_index_of_torches += 2; dung_object_tilemap_pos[x] = dsto_x2; dung_object_pos_in_objdata[x] = slot; uint16 src_img = 0xec2; uint16 *dst = DstoPtr((dsto_x2 >> 1) & 0x1fff); if (dsto_x2 & 0x8000) { src_img = 0xeca; if (dung_num_lit_torches < 3) dung_num_lit_torches++; } RoomDraw_Rightwards2x2(SrcPtr(src_img), dst); } void Dungeon_LoadHeader() { // 81b564 dung_flag_statechange_waterpuzzle = 0; dung_flag_somaria_block_switch = 0; dung_flag_movable_block_was_pushed = 0; static const int16 kAdjustment[] = { 256, -256 }; if (submodule_index == 0) { dung_loade_bgoffs_h_copy = BG2HOFS_copy2 & ~0x1FF; dung_loade_bgoffs_v_copy = BG2VOFS_copy2 & ~0x1FF; } else if (submodule_index == 21 || submodule_index < 18 && submodule_index >= 6) { dung_loade_bgoffs_h_copy = (BG2HOFS_copy2 + 0x20) & ~0x1FF; dung_loade_bgoffs_v_copy = (BG2VOFS_copy2 + 0x20) & ~0x1FF; } else { if (((link_direction & 0xf) >> 1) < 2) { dung_loade_bgoffs_h_copy = (BG2HOFS_copy2 + kAdjustment[(link_direction & 0xf) >> 1]) & ~0x1FF; dung_loade_bgoffs_v_copy = (BG2VOFS_copy2 + 0x20) & ~0x1FF; } else { dung_loade_bgoffs_h_copy = (BG2HOFS_copy2 + 0x20) & ~0x1FF; dung_loade_bgoffs_v_copy = (BG2VOFS_copy2 + kAdjustment[(link_direction & 0xf) >> 3]) & ~0x1FF; } } const uint8 *hdr_ptr = GetRoomHeaderPtr(dungeon_room_index); dung_bg2_properties_backup = dung_hdr_bg2_properties; dung_hdr_bg2_properties = hdr_ptr[0] >> 5; dung_hdr_collision = (hdr_ptr[0] >> 2) & 7; dung_want_lights_out_copy = dung_want_lights_out; dung_want_lights_out = hdr_ptr[0] & 1; const DungPalInfo *dpi = &kDungPalinfos[hdr_ptr[1]]; dung_hdr_palette_1 = dpi->pal0; overworld_palette_sp0 = dpi->pal1; sprite_aux1_palette = dpi->pal2; sprite_aux2_palette = dpi->pal3; aux_tile_theme_index = hdr_ptr[2]; sprite_graphics_index = hdr_ptr[3] + 0x40; dung_hdr_collision_2 = hdr_ptr[4]; dung_hdr_tag[0] = hdr_ptr[5]; dung_hdr_tag[1] = hdr_ptr[6]; dung_hdr_hole_teleporter_plane = hdr_ptr[7] & 3; dung_hdr_staircase_plane[0] = (hdr_ptr[7] >> 2) & 3; dung_hdr_staircase_plane[1] = (hdr_ptr[7] >> 4) & 3; dung_hdr_staircase_plane[2] = (hdr_ptr[7] >> 6) & 3; dung_hdr_staircase_plane[3] = hdr_ptr[8] & 3; dung_hdr_travel_destinations[0] = hdr_ptr[9]; dung_hdr_travel_destinations[1] = hdr_ptr[10]; dung_hdr_travel_destinations[2] = hdr_ptr[11]; dung_hdr_travel_destinations[3] = hdr_ptr[12]; dung_hdr_travel_destinations[4] = hdr_ptr[13]; dung_flag_trapdoors_down = 1; dung_overlay_to_load = 0; dung_index_x3 = dungeon_room_index * 3; uint16 x = save_dung_info[dungeon_room_index]; dung_door_opened = x & 0xf000; dung_door_opened_incl_adjacent = dung_door_opened | 0xf00; dung_savegame_state_bits = (x & 0xff0) << 4; dung_quadrants_visited = x & 0xf; const uint16 *dp = GetRoomDoorInfo(dungeon_room_index); int i = 0; for (; dp[i] != 0xffff; i++) dung_door_tilemap_address[i] = dp[i]; dung_door_tilemap_address[i] = 0; if (((dungeon_room_index - 1) & 0xf) != 0xf) Dungeon_CheckAdjacentRoomsForOpenDoors(18, dungeon_room_index - 1); if (((dungeon_room_index + 1) & 0xf) != 0) Dungeon_CheckAdjacentRoomsForOpenDoors(12, dungeon_room_index + 1); if (dungeon_room_index - 16 >= 0) Dungeon_CheckAdjacentRoomsForOpenDoors(6, dungeon_room_index - 16); if (dungeon_room_index + 16 < 0x140) Dungeon_CheckAdjacentRoomsForOpenDoors(0, dungeon_room_index + 16); } void Dungeon_CheckAdjacentRoomsForOpenDoors(int idx, int room) { // 81b759 static const uint16 kLookup[] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x61, 0x71, 0x81, 0x91, 0xa1, 0xb1, 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x63, 0x73, 0x83, 0x93, 0xa3, 0xb3, }; static const uint16 kLookup2[] = { 0x61, 0x71, 0x81, 0x91, 0xa1, 0xb1, 0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x63, 0x73, 0x83, 0x93, 0xa3, 0xb3, 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, }; Dungeon_LoadAdjacentRoomDoors(room); int i, j; uint16 a; for (i = 0; i != 8 && (a = adjacent_doors[i]) != 0xffff; i++) { a &= 0xff; j = idx; if (a == kLookup[j] || a == kLookup[++j] || a == kLookup[++j] || a == kLookup[++j] || a == kLookup[++j] || a == kLookup[++j]) { uint8 rev = kLookup2[j]; for (j = 0; j != 8; j++) { if ((uint8)dung_door_tilemap_address[j] == rev) { uint8 k = dung_door_tilemap_address[j] >> 8; if (k == 0x30) break; if (k == 0x44 || k == 0x18) { // trapdoor if (room != dungeon_room_index_prev) break; dung_flag_trapdoors_down = 0; } else { // not trapdoor if (!(adjacent_doors_flags & kUpperBitmasks[i])) break; } dung_door_opened_incl_adjacent |= kUpperBitmasks[j]; break; } } } } } void Dungeon_LoadAdjacentRoomDoors(int room) { // 81b7ef const uint16 *dp = GetRoomDoorInfo(room); adjacent_doors_flags = (save_dung_info[room] & 0xf000) | 0xf00; for (int i = 0; ; i++) { uint16 a = dp[i]; adjacent_doors[i] = a; if (a == 0xffff) break; if ((a & 0xff00) == 0x4000 || (a & 0xff00) < 0x200) adjacent_doors_flags |= kUpperBitmasks[i]; } } void Dungeon_LoadAttribute_Selectable() { // 81b8b4 switch (overworld_map_state) { case 0: // Dungeon_LoadBasicAttribute overworld_map_state = 1; dung_draw_width_indicator = dung_draw_height_indicator = 0; case 1: Dungeon_LoadBasicAttribute_full(0x40); break; case 2: Dungeon_LoadObjectAttribute(); break; case 3: Dungeon_LoadDoorAttribute(); break; case 4: overworld_map_state = 5; if (orange_blue_barrier_state) Dungeon_FlipCrystalPegAttribute(); break; case 5: break; default: assert(0); } } void Dungeon_LoadAttributeTable() { // 81b8bf dung_draw_width_indicator = dung_draw_height_indicator = 0; Dungeon_LoadBasicAttribute_full(0x1000); Dungeon_LoadObjectAttribute(); Dungeon_LoadDoorAttribute(); if (orange_blue_barrier_state) Dungeon_FlipCrystalPegAttribute(); overworld_map_state = 0; } void Dungeon_LoadBasicAttribute_full(uint16 loops) { // 81b8f3 do { int i = dung_draw_width_indicator / 2; uint8 a0 = attributes_for_tile[dung_bg2[i] & 0x3ff]; if (a0 >= 0x10 && a0 < 0x1c) a0 |= (dung_bg2[i] >> 14); // vflip/hflip uint8 a1 = attributes_for_tile[dung_bg2[i + 1] & 0x3ff]; if (a1 >= 0x10 && a1 < 0x1c) a1 |= (dung_bg2[i + 1] >> 14); // vflip/hflip int j = dung_draw_height_indicator; dung_bg2_attr_table[j] = a0; dung_bg2_attr_table[j + 1] = a1; dung_draw_height_indicator = j + 2; dung_draw_width_indicator += 4; } while (--loops); if (dung_draw_height_indicator == 0x2000) overworld_map_state++; } void Dungeon_LoadObjectAttribute() { // 81b967 for (int i = 0; i != dung_num_star_shaped_switches; i += 2) { int j = star_shaped_switches_tile[i >> 1]; WriteAttr2(j + XY(0, 0), 0x3b3b); WriteAttr2(j + XY(0, 1), 0x3b3b); } int i = 0, t = 0x3030; for (; i != dung_num_inter_room_upnorth_stairs; i += 2, t += 0x101) { int j = dung_inter_starcases[i >> 1]; WriteAttr2(j + XY(1, 2), 0); WriteAttr2(j + XY(1, 0), 0x2626); WriteAttr2(j + XY(1, 1), t); } for (; i != dung_num_wall_upnorth_spiral_stairs; i += 2, t += 0x101) { int j = dung_inter_starcases[i >> 1]; WriteAttr2(j + XY(1, 0), 0x5e5e); WriteAttr2(j + XY(1, 2), 0x5e5e); WriteAttr2(j + XY(1, 3), 0x5e5e); WriteAttr2(j + XY(1, 1), t); } for (; i != dung_num_wall_upnorth_spiral_stairs_2; i += 2, t += 0x101) { int j = dung_inter_starcases[i >> 1]; WriteAttr2(j + XY(1, 0), 0x5f5f); WriteAttr2(j + XY(1, 2), 0x5f5f); WriteAttr2(j + XY(1, 3), 0x5f5f); WriteAttr2(j + XY(1, 1), t); } for (; i != dung_num_inter_room_upnorth_straight_stairs; i += 2, t += 0x101) { int j = dung_inter_starcases[i >> 1]; WriteAttr2(j + XY(1, 0), 0x3838); WriteAttr2(j + XY(1, 2), 0); WriteAttr2(j + XY(1, 3), 0); WriteAttr2(j + XY(1, 1), t); } for (; i != dung_num_inter_room_upsouth_straight_stairs; i += 2, t += 0x101) { int j = dung_inter_starcases[i >> 1]; WriteAttr2(j + XY(1, 0), 0); WriteAttr2(j + XY(1, 1), 0); WriteAttr2(j + XY(1, 2), t); WriteAttr2(j + XY(1, 3), 0x3939); } t = (t & 0x707) | 0x3434; for (; i != dung_num_inter_room_southdown_stairs; i += 2, t += 0x101) { int j = dung_inter_starcases[i >> 1]; WriteAttr2(j + XY(1, 2), t); WriteAttr2(j + XY(1, 3), 0x2626); } for (; i != dung_num_wall_downnorth_spiral_stairs; i += 2, t += 0x101) { int j = dung_inter_starcases[i >> 1]; WriteAttr2(j + XY(1, 0), 0x5e5e); WriteAttr2(j + XY(1, 1), t); WriteAttr2(j + XY(1, 2), 0x5e5e); WriteAttr2(j + XY(1, 3), 0x5e5e); } for (; i != dung_num_wall_downnorth_spiral_stairs_2; i += 2, t += 0x101) { int j = dung_inter_starcases[i >> 1]; WriteAttr2(j + XY(1, 0), 0x5f5f); WriteAttr2(j + XY(1, 1), t); WriteAttr2(j + XY(1, 2), 0x5f5f); WriteAttr2(j + XY(1, 3), 0x5f5f); } for (; i != dung_num_inter_room_downnorth_straight_stairs; i += 2, t += 0x101) { int j = dung_inter_starcases[i >> 1]; WriteAttr2(j + XY(1, 0), 0x3838); WriteAttr2(j + XY(1, 1), t); WriteAttr2(j + XY(1, 2), 0); WriteAttr2(j + XY(1, 3), 0); } for (; i != dung_num_inter_room_downsouth_straight_stairs; i += 2, t += 0x101) { int j = dung_inter_starcases[i >> 1]; WriteAttr2(j + XY(1, 0), 0); WriteAttr2(j + XY(1, 1), 0); WriteAttr2(j + XY(1, 2), t); WriteAttr2(j + XY(1, 3), 0x3939); } i = 0; int type = 0, iend = dung_num_inroom_upnorth_stairs; uint16 attr = 0x1f1f; if (iend == 0) { type = 1, attr = 0x1e1e; iend = dung_num_inroom_southdown_stairs; if (iend == 0) { type = 2, attr = 0x1d1d; iend = dung_num_interpseudo_upnorth_stairs; if (iend == 0) goto skip3; } } kind_of_in_room_staircase = type; for (; i != iend; i += 2) { int j = dung_stairs_table_1[i >> 1]; WriteAttr2(j + XY(0, 0), 0x02); WriteAttr1(j + XY(0, 3), 0x02); WriteAttr2(j + XY(2, 0), 0x0200); WriteAttr1(j + XY(2, 3), 0x0200); WriteAttr2(j + XY(0, 1), 0x01); WriteAttr1(j + XY(0, 2), 0x01); WriteAttr2(j + XY(2, 1), 0x0100); // todo: use 8-bit write? WriteAttr1(j + XY(2, 2), 0x0100); WriteAttr2(j + XY(1, 1), attr); WriteAttr1(j + XY(1, 1), attr); WriteAttr2(j + XY(1, 2), attr); WriteAttr1(j + XY(1, 2), attr); } skip3: if (i != dung_some_stairs_unk4) { kind_of_in_room_staircase = 2; for (; i != dung_some_stairs_unk4; i += 2) { int j = dung_stairs_table_1[i >> 1]; WriteAttr2(j + XY(0, 0), 0xa03); WriteAttr1(j + XY(0, 0), 0xa03); WriteAttr2(j + XY(2, 0), 0x30a); WriteAttr1(j + XY(2, 0), 0x30a); WriteAttr2(j + XY(0, 1), 0x803); WriteAttr2(j + XY(2, 1), 0x308); } } i = 0; if (i != dung_num_inroom_upnorth_stairs_water) { kind_of_in_room_staircase = 2; for (; i != dung_num_inroom_upnorth_stairs_water; i += 2) { int j = dung_stairs_table_1[i >> 1]; WriteAttr2(j + XY(0, 0), 0x003); WriteAttr2(j + XY(2, 0), 0x300); WriteAttr1(j + XY(0, 0), 0xa03); WriteAttr1(j + XY(2, 0), 0x30a); WriteAttr2(j + XY(0, 1), 0x808); WriteAttr2(j + XY(2, 1), 0x808); } } if (i != dung_num_activated_water_ladders) { kind_of_in_room_staircase = 2; for (; i != dung_num_activated_water_ladders; i += 2) { int j = dung_stairs_table_1[i >> 1]; WriteAttr2(j + XY(0, 0), 0x003); WriteAttr2(j + XY(2, 0), 0x300); WriteAttr1(j + XY(0, 0), 0xa03); WriteAttr1(j + XY(2, 0), 0x30a); } } for (i = 0, t = 0x7070; i != dung_misc_objs_index; i += 2, t += 0x101) { uint16 k = dung_replacement_tile_state[i >> 1]; if ((k & 0xf0) != 0x30) { int j = (dung_object_tilemap_pos[i >> 1] & 0x3fff) >> 1; WriteAttr2(j + XY(0, 0), t); WriteAttr2(j + XY(0, 1), t); } } if (i != dung_index_of_torches) { for (t = 0xc0c0; i != dung_index_of_torches; i += 2, t = (t & 0xefef) + 0x101) { int j = (dung_object_tilemap_pos[i >> 1] & 0x3fff) >> 1; WriteAttr2(j + XY(0, 0), t); WriteAttr2(j + XY(0, 1), t); } dung_index_of_torches = 0; } t = 0x5858, i = 0; if (dung_num_chests_x2) { if (dung_hdr_tag[0] == 0x27 || dung_hdr_tag[0] == 0x3c || dung_hdr_tag[0] == 0x3e || dung_hdr_tag[0] >= 0x29 && dung_hdr_tag[0] < 0x33) goto no_big_key_locks; if (dung_hdr_tag[1] == 0x27 || dung_hdr_tag[1] == 0x3c || dung_hdr_tag[1] == 0x3e || dung_hdr_tag[1] >= 0x29 && dung_hdr_tag[1] < 0x33) goto no_big_key_locks; for (; i != dung_num_chests_x2; i += 2, t += 0x101) { int k = dung_chest_locations[i >> 1]; if (k != 0) { int j = (k & 0x7fff) >> 1; WriteAttr2(j + XY(0, 0), t); WriteAttr2(j + XY(0, 1), t); if (k & 0x8000) { dung_chest_locations[i >> 1] = k & 0x7fff; WriteAttr2(j + XY(2, 1), t); WriteAttr2(j + XY(0, 2), t); WriteAttr2(j + XY(2, 2), t); } } } } for (; i != dung_num_bigkey_locks_x2; i += 2, t += 0x101) { int k = dung_chest_locations[i >> 1]; dung_chest_locations[i >> 1] = k | 0x8000; int j = (k & 0x7fff) >> 1; WriteAttr2(j + XY(0, 0), t); WriteAttr2(j + XY(0, 1), t); } no_big_key_locks: i = 0; type = 0, iend = dung_num_stairs_1; attr = 0x3f3f; if (iend == 0) { type = 1, attr = 0x3e3e; iend = dung_num_stairs_2; if (iend == 0) { type = 2, attr = 0x3d3d; iend = dung_num_stairs_wet; if (iend == 0) goto skip7; } } kind_of_in_room_staircase = type; for (i = 0; i != iend; i += 2) { int j = dung_stairs_table_2[i >> 1]; WriteAttr1(j + XY(0, 0), 0x02); WriteAttr2(j + XY(0, 3), 0x02); WriteAttr1(j + XY(0, 1), 0x01); WriteAttr2(j + XY(0, 2), 0x01); WriteAttr1(j + XY(2, 0), 0x0200); WriteAttr2(j + XY(2, 3), 0x0200); WriteAttr1(j + XY(2, 1), 0x0100); // todo: use 8-bit write? WriteAttr2(j + XY(2, 2), 0x0100); WriteAttr1(j + XY(1, 1), attr); WriteAttr2(j + XY(1, 1), attr); WriteAttr1(j + XY(1, 2), attr); WriteAttr2(j + XY(1, 2), attr); } skip7: if (dung_num_inroom_upsouth_stairs_water) { kind_of_in_room_staircase = 2; for (i = 0; i != dung_num_inroom_upsouth_stairs_water; i += 2) { int j = dung_stairs_table_2[i >> 1]; WriteAttr1(j + XY(0, 3), 0xa03); WriteAttr1(j + XY(2, 3), 0x30a); WriteAttr2(j + XY(0, 3), 0x003); WriteAttr2(j + XY(2, 3), 0x300); WriteAttr2(j + XY(0, 2), 0x808); WriteAttr2(j + XY(2, 2), 0x808); } } overworld_map_state += 1; } void Dungeon_LoadDoorAttribute() { // 81be17 for (int i = 0; i != 16; i++) { if (dung_door_tilemap_address[i]) Dungeon_LoadSingleDoorAttribute(i); } Dungeon_LoadSingleDoorTileAttribute(); ChangeDoorToSwitch(); overworld_map_state += 1; } void Dungeon_LoadSingleDoorAttribute(int k) { // 81be35 assert(k >= 0 && k < 16); uint8 t = door_type_and_slot[k] & 0xfe, dir; uint16 attr; int i, j; if (t == kDoorType_Regular || t == kDoorType_EntranceDoor || t == kDoorType_ExitToOw || t == kDoorType_EntranceLarge || t == kDoorType_EntranceCave) goto alpha; if (t == kDoorType_EntranceLarge2 || t == kDoorType_EntranceCave2 || t == kDoorType_4 || t == kDoorType_Regular2 || t == kDoorType_WaterfallTunnel) goto beta; if (t == kDoorType_LgExplosion) return; if (t >= kDoorType_RegularDoor33) { if (t == kDoorType_RegularDoor33 || t == kDoorType_WarpRoomDoor) goto beta; if (dung_door_opened_incl_adjacent & kUpperBitmasks[k]) goto beta; j = dung_door_tilemap_address[k] >> 1; attr = (0xf0 + k) * 0x101; WriteAttr2(j + XY(1, 1), attr); WriteAttr2(j + XY(1, 2), attr); return; } i = (t == kDoorType_ShuttersTwoWay || t == kDoorType_Shutter) ? k : k & 7; if (!(dung_door_opened_incl_adjacent & kUpperBitmasks[i])) { j = dung_door_tilemap_address[k] >> 1; attr = (0xf0 + k) * 0x101; WriteAttr2(j + XY(1, 1), attr); WriteAttr2(j + XY(1, 2), attr); return; } alpha: if (t >= kDoorType_StairMaskLocked0 && t <= kDoorType_StairMaskLocked3) return; attr = kTileAttrsByDoor[t >> 1]; dir = dung_door_direction[k] & 3; if (dir == 0) { uint16 a = dung_door_tilemap_address[k]; if (a == dung_exit_door_addresses[0] || a == dung_exit_door_addresses[1] || a == dung_exit_door_addresses[2] || a == dung_exit_door_addresses[3]) attr = 0x8e8e; j = (a >> 1) & ~0x7c0; WriteAttr2(j + XY(1, 0), attr); WriteAttr2(j + XY(1, 1), attr); WriteAttr2(j + XY(1, 2), attr); WriteAttr2(j + XY(1, 3), attr); WriteAttr2(j + XY(1, 4), attr); WriteAttr2(j + XY(1, 5), attr); WriteAttr2(j + XY(1, 6), attr); WriteAttr2(j + XY(1, 7), 0); } else if (dir == 1) { uint16 a = dung_door_tilemap_address[k]; if (t == kDoorType_EntranceLarge || t == kDoorType_EntranceCave || a == dung_exit_door_addresses[0] || a == dung_exit_door_addresses[1] || a == dung_exit_door_addresses[2] || a == dung_exit_door_addresses[3]) attr = 0x8e8e; j = a >> 1; WriteAttr2(j + XY(1, 1), attr); WriteAttr2(j + XY(1, 2), attr); WriteAttr2(j + XY(1, 3), attr); WriteAttr2(j + XY(1, 4), attr); WriteAttr2(j + XY(1, 5), attr); } else if (dir == 2) { j = (dung_door_tilemap_address[k] >> 1) & ~0x1f; WriteAttr2(j + XY(0, 1), attr + 0x101); WriteAttr2(j + XY(2, 1), attr + 0x101); WriteAttr2(j + XY(0, 2), attr + 0x101); WriteAttr2(j + XY(2, 2), attr + 0x101); WriteAttr2(j + XY(4, 1), (attr + 0x101) & 0xff); WriteAttr2(j + XY(4, 2), (attr + 0x101) & 0xff); } else { j = (dung_door_tilemap_address[k] >> 1); WriteAttr2(j + XY(2, 1), attr + 0x101); WriteAttr2(j + XY(4, 1), attr + 0x101); WriteAttr2(j + XY(2, 2), attr + 0x101); WriteAttr2(j + XY(4, 2), attr + 0x101); WriteAttr2(j + XY(0, 1), (attr + 0x101) & 0xff00); WriteAttr2(j + XY(0, 2), (attr + 0x101) & 0xff00); } return; beta: attr = kTileAttrsByDoor[t >> 1]; dir = dung_door_direction[k] & 3; if (dir == 0) { j = (dung_door_tilemap_address[k] >> 1) & ~0x7c0; WriteAttr2(j + XY(1, 0), attr); WriteAttr2(j + XY(1, 1), attr); WriteAttr2(j + XY(1, 2), attr); WriteAttr2(j + XY(1, 3), attr); WriteAttr2(j + XY(1, 4), attr); WriteAttr2(j + XY(1, 5), attr); WriteAttr2(j + XY(1, 6), attr); WriteAttr2(j + XY(1, 7), attr); WriteAttr2(j + XY(1, 8), attr); WriteAttr2(j + XY(1, 9), attr); } else if (dir == 1) { uint16 a = dung_door_tilemap_address[k] & 0x1fff; if (t == kDoorType_EntranceLarge2 || t == kDoorType_EntranceCave2 || t == kDoorType_4 || a == dung_exit_door_addresses[0] || a == dung_exit_door_addresses[1] || a == dung_exit_door_addresses[2] || a == dung_exit_door_addresses[3]) attr = 0x8e8e; j = dung_door_tilemap_address[k] >> 1; WriteAttr2(j + XY(1, 1), attr); WriteAttr2(j + XY(1, 2), attr); WriteAttr2(j + XY(1, 3), attr); WriteAttr2(j + XY(1, 4), attr); WriteAttr2(j + XY(1, 5), attr); WriteAttr2(j + XY(1, 6), attr); WriteAttr2(j + XY(1, 7), attr); WriteAttr2(j + XY(1, 8), attr); } else if (dir == 2) { j = (dung_door_tilemap_address[k] >> 1) & ~0x1f; WriteAttr2(j + XY(0, 1), attr + 0x101); WriteAttr2(j + XY(2, 1), attr + 0x101); WriteAttr2(j + XY(4, 1), attr + 0x101); WriteAttr2(j + XY(6, 1), attr + 0x101); WriteAttr2(j + XY(0, 2), attr + 0x101); WriteAttr2(j + XY(2, 2), attr + 0x101); WriteAttr2(j + XY(4, 2), attr + 0x101); WriteAttr2(j + XY(6, 2), attr + 0x101); } else { j = ((dung_door_tilemap_address[k] >> 1) + 1); WriteAttr2(j + XY(0, 1), attr + 0x101); WriteAttr2(j + XY(2, 1), attr + 0x101); WriteAttr2(j + XY(4, 1), attr + 0x101); WriteAttr2(j + XY(6, 1), attr + 0x101); WriteAttr2(j + XY(0, 2), attr + 0x101); WriteAttr2(j + XY(2, 2), attr + 0x101); WriteAttr2(j + XY(4, 2), attr + 0x101); WriteAttr2(j + XY(6, 2), attr + 0x101); } } void Door_LoadBlastWallAttr(int k) { // 81bfc1 int j = dung_door_tilemap_address[k] >> 1; if (!(dung_door_direction[k] & 2)) { for (int n = 12; n; n--) { WriteAttr2(j + XY(0, 0), 0x102); for (int i = 2; i < 20; i += 2) WriteAttr2(j + XY(i, 0), 0x0); WriteAttr2(j + XY(20, 0), 0x201); j += XY(0, 1); } } else { for (int n = 5; n; n--) { WriteAttr2(j + XY(0, 0), 0x101); WriteAttr2(j + XY(0, 21), 0x101); WriteAttr2(j + XY(0, 1), 0x202); WriteAttr2(j + XY(0, 20), 0x202); for (int i = 2; i < 20; i++) WriteAttr2(j + XY(0, i), 0x0); j += XY(2, 0); } } } void ChangeDoorToSwitch() { // 81c1ba assert(dung_unk5 == 0); } void Dungeon_FlipCrystalPegAttribute() { // 81c22a for (int i = 0xfff; i >= 0; i--) { if ((dung_bg2_attr_table[i] & ~1) == 0x66) dung_bg2_attr_table[i] ^= 1; if ((dung_bg1_attr_table[i] & ~1) == 0x66) dung_bg1_attr_table[i] ^= 1; } } void Dungeon_HandleRoomTags() { // 81c2fd if (!flag_skip_call_tag_routines) { Dungeon_DetectStaircase(); g_ram[14] = 0; kDungTagroutines[dung_hdr_tag[0]](0); g_ram[14] = 1; kDungTagroutines[dung_hdr_tag[1]](1); } flag_skip_call_tag_routines = 0; } void Dung_TagRoutine_0x00(int k) { // 81c328 } void Dungeon_DetectStaircase() { // 81c329 int k = link_direction & 12; if (!k) return; static const int8 kBuggyLookup[] = { 7, 24, 8, 8, 0, 0, -1, 17 }; int pos = ((link_y_coord + kBuggyLookup[k >> 1]) & 0x1f8) << 3; pos |= (link_x_coord & 0x1f8) >> 3; pos |= (link_is_on_lower_level ? 0x1000 : 0); uint8 at = dung_bg2_attr_table[pos + (k == 4 ? 0x80 : 0)]; if (!(at == 0x26 || at == 0x38 || at == 0x39 || at == 0x5e || at == 0x5f)) return; uint8 attr2 = dung_bg2_attr_table[pos + XY(0, 1)]; if ((attr2 & 0xf8) != 0x30) return; if (link_state_bits & 0x80) { link_y_coord = link_y_coord_prev; return; } which_staircase_index = attr2; which_staircase_index_PADDING = pos >> 8; // residual dungeon_room_index_prev = dungeon_room_index; Dungeon_FlagRoomData_Quadrants(); if (at == 0x38 || at == 0x39) { staircase_var1 = 0x20; if (at == 0x38) Dungeon_StartInterRoomTrans_Up(); else Dungeon_StartInterRoomTrans_Down(); } int j = (which_staircase_index & 3); BYTE(dungeon_room_index) = dung_hdr_travel_destinations[j + 1]; cur_staircase_plane = dung_hdr_staircase_plane[j]; byte_7E0492 = (link_is_on_lower_level || link_is_on_lower_level_mirror) ? 2 : 0; subsubmodule_index = 0; bitmask_of_dragstate = 0; link_delay_timer_spin_attack = 0; button_mask_b_y = 0; button_b_frames = 0; link_cant_change_direction &= ~1; if (at == 0x26) { submodule_index = 6; sound_effect_1 = (cur_staircase_plane < 0x34 ? 22 : 24); // wtf? } else if (at == 0x38 || at == 0x39) { submodule_index = (at == 0x38) ? 18 : 19; link_timer_push_get_tired = 7; } else { UsedForStraightInterRoomStaircase(); submodule_index = 14; } } void RoomTag_NorthWestTrigger(int k) { // 81c432 if (!(link_x_coord & 0x100) && !(link_y_coord & 0x100)) RoomTag_QuadrantTrigger(k); } void Dung_TagRoutine_0x2A(int k) { // 81c438 if ((link_x_coord & 0x100) && !(link_y_coord & 0x100)) RoomTag_QuadrantTrigger(k); } void Dung_TagRoutine_0x2B(int k) { // 81c43e if (!(link_x_coord & 0x100) && (link_y_coord & 0x100)) RoomTag_QuadrantTrigger(k); } void Dung_TagRoutine_0x2C(int k) { // 81c444 if ((link_x_coord & 0x100) && (link_y_coord & 0x100)) RoomTag_QuadrantTrigger(k); } void Dung_TagRoutine_0x2D(int k) { // 81c44a if (!(link_x_coord & 0x100)) RoomTag_QuadrantTrigger(k); } void Dung_TagRoutine_0x2E(int k) { // 81c450 if (link_x_coord & 0x100) RoomTag_QuadrantTrigger(k); } void Dung_TagRoutine_0x2F(int k) { // 81c456 if (!(link_y_coord & 0x100)) RoomTag_QuadrantTrigger(k); } void Dung_TagRoutine_0x30(int k) { // 81c45c if (link_y_coord & 0x100) RoomTag_QuadrantTrigger(k); } void RoomTag_QuadrantTrigger(int k) { // 81c461 uint8 tag = dung_hdr_tag[k]; if (tag >= 0xb) { if (tag >= 0x29) { if (Sprite_CheckIfScreenIsClear()) RoomTag_OperateChestReveal(k); } else { uint8 a = (dung_flag_movable_block_was_pushed ^ 1); if (a != BYTE(dung_flag_trapdoors_down)) { BYTE(dung_flag_trapdoors_down) = a; sound_effect_2 = 37; submodule_index = 5; dung_cur_door_pos = 0; door_animation_step_indicator = 0; } } } else { if (Sprite_CheckIfScreenIsClear()) Dung_TagRoutine_TrapdoorsUp(); } } void Dung_TagRoutine_TrapdoorsUp() { // 81c49e if (dung_flag_trapdoors_down) { dung_flag_trapdoors_down = 0; dung_cur_door_pos = 0; door_animation_step_indicator = 0; sound_effect_2 = 0x1b; submodule_index = 5; } } void RoomTag_RoomTrigger(int k) { // 81c4bf if (dung_hdr_tag[k] == 10) { if (Sprite_CheckIfRoomIsClear()) Dung_TagRoutine_TrapdoorsUp(); } else { if (Sprite_CheckIfRoomIsClear()) RoomTag_OperateChestReveal(k); } } void RoomTag_RekillableBoss(int k) { // 81c4db if (Sprite_CheckIfRoomIsClear()) { flag_block_link_menu = 0; dung_hdr_tag[1] = 0; } } void RoomTag_RoomTrigger_BlockDoor(int k) { // 81c4e7 if (dung_flag_statechange_waterpuzzle && dung_flag_trapdoors_down) { dung_flag_trapdoors_down = 0; dung_cur_door_pos = 0; door_animation_step_indicator = 0; submodule_index = 5; } } // Used for bosses void RoomTag_PrizeTriggerDoorDoor(int k) { // 81c508 int t = savegame_is_darkworld ? link_has_crystals : link_which_pendants; if (t & kDungeonCrystalPendantBit[BYTE(cur_palace_index_x2) >> 1]) { dung_flag_trapdoors_down = 0; dung_cur_door_pos = 0; door_animation_step_indicator = 0; submodule_index = 5; dung_hdr_tag[k] = 0; } } void RoomTag_SwitchTrigger_HoldDoor(int k) { // 81c541 uint16 i = -2, v; uint8 tmp; for (;;) { i += 2; if (i == dung_index_of_torches_start) break; if (dung_replacement_tile_state[i >> 1] == 5) { v = related_to_trapdoors_somehow; if (v != 0xffff) goto shortcut; break; } } v = !dung_flag_somaria_block_switch && !dung_flag_statechange_waterpuzzle && !RoomTag_CheckForPressedSwitch(&tmp); shortcut: if (v != dung_flag_trapdoors_down) { dung_flag_trapdoors_down = v; dung_cur_door_pos = 0; door_animation_step_indicator = 0; if (v == 0) sound_effect_2 = 0x25; submodule_index = 5; } } void RoomTag_SwitchTrigger_ToggleDoor(int k) { // 81c599 uint8 attr; if (!dung_door_switch_triggered) { if (RoomTag_MaybeCheckShutters(&attr)) { dung_cur_door_pos = 0; door_animation_step_indicator = 0; sound_effect_2 = 0x25; PushPressurePlate(attr); dung_flag_trapdoors_down ^= 1; dung_door_switch_triggered = 1; } } else { if (!RoomTag_MaybeCheckShutters(&attr)) dung_door_switch_triggered = 0; } } void PushPressurePlate(uint8 attr) { // 81c5cf submodule_index = 5; if (attr == 0x23 || !word_7E04B6) return; saved_module_for_menu = submodule_index; submodule_index = 23; subsubmodule_index = 32; link_y_coord += 2; if ((WORD(dung_bg2_attr_table[word_7E04B6]) & 0xfe00) != 0x2400) word_7E04B6++; Dungeon_UpdateTileMapWithCommonTile((word_7E04B6 & 0x3f) << 3, (word_7E04B6 >> 3) & 0x1f8, 0x10); } void RoomTag_TorchPuzzleDoor(int k) { // 81c629 int j = 0; for (int i = 0; i < 16; i++) if (dung_object_tilemap_pos[i] & 0x8000) j++; int down = (j < 4); if (down != dung_flag_trapdoors_down) { dung_flag_trapdoors_down = down; dung_cur_door_pos = 0; door_animation_step_indicator = 0; sound_effect_2 = 0x1b; submodule_index = 5; } } void RoomTag_Switch_ExplodingWall(int k) { // 81c67a uint8 yv; if (!RoomTag_MaybeCheckShutters(&yv)) return; Dung_TagRoutine_BlastWallStuff(k); } void RoomTag_PullSwitchExplodingWall(int k) { // 81c685 if (!dung_flag_statechange_waterpuzzle) return; Dung_TagRoutine_BlastWallStuff(k); } void Dung_TagRoutine_BlastWallStuff(int k) { // 81c68c static const uint8 kBlastWall_Tab0[5] = { 4, 6, 0, 0, 2 }; static const uint16 kBlastWall_Tab1[5] = { 0, 0xa, 0, 0, 0x280 }; dung_hdr_tag[k] = 0; int j = -1; do { j++; } while ((door_type_and_slot[j] & ~1) != 0x30); dung_unk_blast_walls_3 = j * 2; int i = ((link_y_coord >> 8 & 1) + 1) * 2; if (dung_door_direction[j] & 2) i = (link_x_coord >> 8 & 1); messaging_buf[0x1c / 2] = kBlastWall_Tab0[i]; j = dung_door_tilemap_address[j] + kBlastWall_Tab1[i]; messaging_buf[0x1a / 2] = (j & 0x7e) * 4 + dung_loade_bgoffs_h_copy; messaging_buf[0x18 / 2] = ((j & 0x1f80) >> 4) + dung_loade_bgoffs_v_copy; sound_effect_2 = 27; BYTE(dung_unk_blast_walls_2) = 1; AncillaAdd_BlastWall(); } // Used for bosses void RoomTag_GetHeartForPrize(int k) { // 81c709 static const uint8 kBossFinishedFallingItem[13] = { 0, 0, 1, 2, 0, 6, 6, 6, 6, 6, 3, 6, 6 }; if (!(dung_savegame_state_bits & 0x8000)) return; int t = savegame_is_darkworld ? link_has_crystals : link_which_pendants; if (!(t & kDungeonCrystalPendantBit[BYTE(cur_palace_index_x2) >> 1])) { byte_7E04C2 = 128; if (Ancilla_SpawnFallingPrize(kBossFinishedFallingItem[BYTE(cur_palace_index_x2) >> 1]) < 0) return; // Zelda bugfix. Price won't spawn if we're out of ancillas } dung_hdr_tag[k] = 0; } void RoomTag_Agahnim(int k) { // 81c74e if (!(save_ow_event_info[0x5b] & 0x20) && dung_savegame_state_bits & 0x8000) { Palette_RevertTranslucencySwap(); dung_hdr_tag[0] = 0; PrepareDungeonExitFromBossFight(); } } void RoomTag_GanonDoor(int tagidx) { // 81c767 for (int k = 15; k >= 0; k--) { if (sprite_state[k] == 4 || !(sprite_flags4[k] & 64) && sprite_state[k]) return; } if (link_player_handler_state != kPlayerState_FallingIntoHole) { flag_is_link_immobilized = 26; submodule_index = 26; subsubmodule_index = 0; dung_hdr_tag[0] = 0; link_force_hold_sword_up = 1; button_mask_b_y = 0; button_b_frames = 0; R16 = 0x364; } } void RoomTag_KillRoomBlock(int k) { // 81c7a2 if (link_x_coord & 0x100 && link_y_coord & 0x100) { if (Sprite_CheckIfScreenIsClear()) { sound_effect_2 = 0x1b; dung_hdr_tag[k] = 0; } } } void RoomTag_PushBlockForChest(int k) { // 81c7c2 if (!nmi_load_bg_from_vram && dung_flag_movable_block_was_pushed) RoomTag_OperateChestReveal(k); } void RoomTag_TriggerChest(int k) { // 81c7cc uint8 attr; if (!countdown_for_blink && RoomTag_MaybeCheckShutters(&attr)) RoomTag_OperateChestReveal(k); } void RoomTag_OperateChestReveal(int k) { // 81c7d8 dung_hdr_tag[k] = 0; vram_upload_offset = 0; WORD(overworld_map_state) = 0; uint16 attr = 0x5858; do { int pos = dung_chest_locations[WORD(overworld_map_state) >> 1] >> 1 & 0x1fff; WORD(dung_bg2_attr_table[pos + XY(0, 0)]) = attr; WORD(dung_bg2_attr_table[pos + XY(0, 1)]) = attr; attr += 0x101; const uint16 *src = SrcPtr(0x149c); dung_bg2[pos + XY(0, 0)] = src[0]; dung_bg2[pos + XY(0, 1)] = src[1]; dung_bg2[pos + XY(1, 0)] = src[2]; dung_bg2[pos + XY(1, 1)] = src[3]; uint16 yy = WORD(overworld_map_state); uint16 *dst = &vram_upload_data[vram_upload_offset >> 1]; dst[0] = RoomTag_BuildChestStripes(XY(0, 0) * 2, yy); dst[3] = RoomTag_BuildChestStripes(XY(0, 1) * 2, yy); dst[6] = RoomTag_BuildChestStripes(XY(1, 0) * 2, yy); dst[9] = RoomTag_BuildChestStripes(XY(1, 1) * 2, yy); dst[2] = src[0]; dst[5] = src[1]; dst[8] = src[2]; dst[11] = src[3]; dst[1] = 0x100; dst[4] = 0x100; dst[7] = 0x100; dst[10] = 0x100; dst[12] = 0xffff; vram_upload_offset += 24; WORD(overworld_map_state) += 2; } while (WORD(overworld_map_state) != dung_num_chests_x2); WORD(overworld_map_state) = 0; sound_effect_2 = 26; nmi_load_bg_from_vram = 1; } void RoomTag_TorchPuzzleChest(int k) { // 81c8ae int j = 0; for (int i = 0; i < 16; i++) if (dung_object_tilemap_pos[i] & 0x8000) j++; if (j >= 4) RoomTag_OperateChestReveal(k); } void RoomTag_MovingWall_East(int k) { // 81c8d4 static const int16 kMovingWall_Tab1[8] = { -63, -127, -191, -255, -71, -135, -199, -263 }; if (!dung_floor_move_flags) { RoomTag_MovingWallTorchesCheck(k); dung_floor_x_vel = 0; } else { flag_unk1 = 1; RoomTag_MovingWallShakeItUp(k); dung_floor_x_vel = MovingWall_MoveALittle(); } dung_floor_x_offs -= dung_floor_x_vel; BG1HOFS_copy2 = BG2HOFS_copy2 + dung_floor_x_offs; if (dung_floor_x_vel) { if (dung_floor_x_offs < (uint16)kMovingWall_Tab1[moving_wall_var2 >> 1] && dung_floor_x_offs < (uint16)kMovingWall_Tab1[RoomTag_AdvanceGiganticWall(k) >> 1]) { sound_effect_2 = 0x1b; sound_effect_ambient = 5; dung_hdr_tag[k] = 0; flag_is_link_immobilized = 0; flag_unk1 = 0; bg1_x_offset = bg1_y_offset = 0; } nmi_subroutine_index = 5; nmi_load_target_addr = (moving_wall_var1 - ((-dung_floor_x_offs & 0x1f8) >> 3)) & 0x141f; } } void RoomTag_MovingWallShakeItUp(int k) { // 81c969 int i = frame_counter & 1; bg1_x_offset = i ? -1 : 1; bg1_y_offset = -bg1_x_offset; if (!dung_hdr_tag[k]) bg1_x_offset = bg1_y_offset = 0; } void RoomTag_MovingWall_West(int k) { // 81c98b static const uint16 kMovingWall_Tab0[8] = { 0x42, 0x82, 0xc2, 0x102, 0x4a, 0x8a, 0xca, 0x10a }; if (!dung_floor_move_flags) { RoomTag_MovingWallTorchesCheck(k); dung_floor_x_vel = 0; } else { flag_unk1 = 1; RoomTag_MovingWallShakeItUp(k); dung_floor_x_vel = MovingWall_MoveALittle(); } dung_floor_x_offs += dung_floor_x_vel; BG1HOFS_copy2 = BG2HOFS_copy2 + dung_floor_x_offs; if (dung_floor_x_vel) { if (dung_floor_x_offs >= kMovingWall_Tab0[moving_wall_var2 >> 1] && dung_floor_x_offs >= kMovingWall_Tab0[RoomTag_AdvanceGiganticWall(k) >> 1]) { sound_effect_2 = 0x1b; sound_effect_ambient = 5; dung_hdr_tag[k] = 0; flag_is_link_immobilized = 0; flag_unk1 = 0; bg1_x_offset = bg1_y_offset = 0; } nmi_subroutine_index = 5; nmi_load_target_addr = moving_wall_var1 + ((dung_floor_x_offs & 0x1f8) >> 3); if (nmi_load_target_addr & 0x1020) nmi_load_target_addr = (nmi_load_target_addr & 0x1020) ^ 0x420; } } void RoomTag_MovingWallTorchesCheck(int k) { // 81ca17 if (!dung_flag_statechange_waterpuzzle) { int count = 0; for (int i = 0; i < 16; i++) count += (dung_object_tilemap_pos[i] & 0x8000) != 0; if (count < 4) return; } dung_floor_move_flags++; WORD(dung_flag_statechange_waterpuzzle) = 0; dung_savegame_state_bits |= 0x1000 >> k; sound_effect_ambient = 7; flag_is_link_immobilized = 1; flag_unk1 = 1; } int MovingWall_MoveALittle() { // 81ca66 int t = dung_some_subpixel[1] + 0x22; dung_some_subpixel[1] = t; return t >> 8; } int RoomTag_AdvanceGiganticWall(int k) { // 81ca75 int i = moving_wall_var2; if (dung_hdr_tag[k] < 0x20) { dung_hdr_collision = 0; TM_copy = 0x16; i += 8; } return i; } void RoomTag_WaterOff(int k) { // 81ca94 if (dung_flag_statechange_waterpuzzle) { W12SEL_copy = 3; W34SEL_copy = 0; WOBJSEL_copy = 0; TMW_copy = 22; TSW_copy = 1; turn_on_off_water_ctr = 1; AdjustWaterHDMAWindow(); submodule_index = 11; palette_filter_countdown = 0; darkening_or_lightening_screen = 0; mosaic_target_level = 31; flag_update_cgram_in_nmi++; dung_hdr_tag[1] = 0; dung_savegame_state_bits |= 0x800; dung_flag_statechange_waterpuzzle = 0; int dsto = ((water_hdma_var1 & 0x1ff) - 0x10) << 3 | ((water_hdma_var0 & 0x1ff) - 0x10) >> 3; DrawWaterThing(&dung_bg2[dsto], SrcPtr(0x1438)); Dungeon_PrepOverlayDma_nextPrep(0, dsto * 2); sound_effect_2 = 0x1b; sound_effect_1 = 0x2e; nmi_copy_packets_flag = 1; } } void RoomTag_WaterOn(int k) { // 81cb1a if (dung_flag_statechange_waterpuzzle) { sound_effect_2 = 0x1b; sound_effect_1 = 0x2f; submodule_index = 12; subsubmodule_index = 0; BYTE(dung_floor_y_offs) = 1; dung_hdr_tag[1] = 0; dung_savegame_state_bits |= 0x800; dung_flag_statechange_waterpuzzle = 0; dung_cur_quadrant_upload = 0; } } void RoomTag_WaterGate(int k) { // 81cb49 if (dung_savegame_state_bits & 0x800 || !dung_flag_statechange_waterpuzzle) return; submodule_index = 13; subsubmodule_index = 0; dung_hdr_tag[1] = 0; dung_savegame_state_bits |= 0x800; dung_flag_statechange_waterpuzzle = 0; BYTE(water_hdma_var2) = 0; BYTE(spotlight_var4) = 0; W12SEL_copy = 3; W34SEL_copy = 0; WOBJSEL_copy = 0; TMW_copy = 0x16; TSW_copy = 1; CGWSEL_copy = 2; CGADSUB_copy = 0x62; save_ow_event_info[0x3b] |= 32; save_ow_event_info[0x7b] |= 32; save_dung_info[0x28] |= 0x100; RoomTag_OperateWaterFlooring(); water_hdma_var0 = ((watergate_pos & 0x7e) << 2) + (dung_draw_width_indicator * 16 + dung_loade_bgoffs_h_copy + 40); word_7E0678 = spotlight_y_upper = (watergate_pos & 0x1f80) >> 4; water_hdma_var1 = word_7E0678 + dung_loade_bgoffs_v_copy; water_hdma_var3 = 0; sound_effect_2 = 0x1b; sound_effect_1 = 0x2f; } void Dung_TagRoutine_0x1B(int k) { // 81cbff // empty } void RoomTag_Holes0(int k) { // 81cc00 Dung_TagRoutine_Func2(1); } void Dung_TagRoutine_0x23(int k) { // 81cc04 Dung_TagRoutine_Func2(3); } void Dung_TagRoutine_0x34(int k) { // 81cc08 Dung_TagRoutine_Func2(6); } void Dung_TagRoutine_0x35(int k) { // 81cc0c Dung_TagRoutine_Func2(8); } void Dung_TagRoutine_0x36(int k) { // 81cc10 Dung_TagRoutine_Func2(10); } void Dung_TagRoutine_0x37(int k) { // 81cc14 Dung_TagRoutine_Func2(12); } void Dung_TagRoutine_0x39(int k) { // 81cc18 Dung_TagRoutine_Func2(14); } void Dung_TagRoutine_0x3A(int k) { // 81cc1c Dung_TagRoutine_Func2(16); } void Dung_TagRoutine_Func2(uint8 av) { // 81cc1e uint8 yv; if (!dung_overlay_to_load) dung_overlay_to_load = av; if (RoomTag_CheckForPressedSwitch(&yv) && (av += yv) != dung_overlay_to_load) { dung_overlay_to_load = av; dung_load_ptr_offs = 0; subsubmodule_index = 0; sound_effect_2 = 27; submodule_index = 3; byte_7E04BC ^= 1; Dungeon_RestoreStarTileChr(); } } void RoomTag_ChestHoles0(int k) { // 81cc5b Dung_TagRoutine_0x22_0x3B(k, 0x0); } void Dung_TagRoutine_0x3B(int k) { // 81cc62 Dung_TagRoutine_0x22_0x3B(k, 0x12); } void RoomTag_Holes2(int k) { // 81cc89 uint8 yv; if (!RoomTag_CheckForPressedSwitch(&yv)) return; dung_hdr_tag[k] = 0; dung_overlay_to_load = 5; dung_load_ptr_offs = 0; subsubmodule_index = 0; sound_effect_2 = 0x1b; submodule_index = 3; } void RoomTag_OperateWaterFlooring() { // 81cc95 dung_load_ptr_offs = 0; const uint8 *layoutsrc = kWatergateLayout; for (;;) { dung_draw_width_indicator = 0; dung_draw_height_indicator = 0; uint16 t = WORD(*layoutsrc); if (t == 0xffff) break; dung_draw_width_indicator = (t & 3) + 1; dung_draw_height_indicator = (t >> 8 & 3) + 1; dung_load_ptr_offs += 3, layoutsrc += 3; const uint16 *src = SrcPtr(0x110); int dsto2 = (t & 0xfc) >> 2 | (t >> 10) << 6; do { int dsto = dsto2; int n = dung_draw_width_indicator; do { int nn = 2; do { dung_bg1[dsto + XY(0, 0)] = src[0]; dung_bg1[dsto + XY(1, 0)] = src[1]; dung_bg1[dsto + XY(2, 0)] = src[2]; dung_bg1[dsto + XY(3, 0)] = src[3]; dung_bg1[dsto + XY(0, 1)] = src[4]; dung_bg1[dsto + XY(1, 1)] = src[5]; dung_bg1[dsto + XY(2, 1)] = src[6]; dung_bg1[dsto + XY(3, 1)] = src[7]; dsto += XY(0, 2); } while (--nn); dsto += XY(4, -4); } while (--n); dsto2 += XY(0, 4); } while (--dung_draw_height_indicator); } } bool RoomTag_MaybeCheckShutters(uint8 *attr_out) { // 81cd39 int p, t; word_7E04B6 = 0; if (flag_is_link_immobilized || link_auxiliary_state) return false; p = RoomTag_GetTilemapCoords(); t = WORD(dung_bg2_attr_table[p]); if (t == 0x2323 || t == 0x2424) goto done; t = WORD(dung_bg2_attr_table[p += 64]); if (t == 0x2323 || t == 0x2424) goto done; t = WORD(dung_bg2_attr_table[p -= 63]); if (t == 0x2323 || t == 0x2424) goto done; t = WORD(dung_bg2_attr_table[p += 64]); if (t == 0x2323 || t == 0x2424) goto done; return false; done: if (t != WORD(dung_bg2_attr_table[p + 64])) return false; *attr_out = t; word_7E04B6 = p; return true; } int RoomTag_GetTilemapCoords() { // 81cda5 return ((link_x_coord - 1) & 0x1f8) >> 3 | ((link_y_coord + 14) & 0x1f8) << 3 | (link_is_on_lower_level ? 0x1000 : 0); } bool RoomTag_CheckForPressedSwitch(uint8 *y_out) { // 81cdcc int p, t; word_7E04B6 = 0; if (flag_is_link_immobilized || link_auxiliary_state) return false; p = RoomTag_GetTilemapCoords(); t = WORD(dung_bg2_attr_table[p]); if (t == 0x2323 || t == 0x3a3a || t == 0x3b3b) goto done; t = WORD(dung_bg2_attr_table[p += 64]); if (t == 0x2323 || t == 0x3a3a || t == 0x3b3b) goto done; t = WORD(dung_bg2_attr_table[p -= 63]); if (t == 0x2323 || t == 0x3a3a || t == 0x3b3b) goto done; t = WORD(dung_bg2_attr_table[p += 64]); if (t == 0x2323 || t == 0x3a3a || t == 0x3b3b) goto done; return false; done: if (t != WORD(dung_bg2_attr_table[p + 64])) return false; *y_out = (t == 0x3b3b); word_7E04B6 = p; return true; } void Dungeon_ProcessTorchesAndDoors() { // 81ce70 static const int16 kDungLinkOffs1X[] = { 0, 0, -1, 17 }; static const int16 kDungLinkOffs1Y[] = { 7, 24, 8, 8 }; static const uint16 kDungLinkOffs1Pos[] = { 0x2, 0x2, 0x80, 0x80 }; if ((frame_counter & 3) == 0 && !flag_custom_spell_anim_active) { for (int i = 0; i != 16; i++) { if (dung_torch_timers[i] && !--dung_torch_timers[i]) { byte_7E0333 = 0xc0 + i; Dungeon_ExtinguishTorch(); } } } if (!flag_is_link_immobilized) { int dir = link_direction_facing >> 1; int pos = ((link_y_coord + kDungLinkOffs1Y[dir]) & 0x1f8) << 3; pos |= ((link_x_coord + kDungLinkOffs1X[dir]) & 0x1f8) >> 3; pos |= (link_is_on_lower_level ? 0x1000 : 0); if ((dung_bg2_attr_table[pos] & 0xf0) == 0xf0 || (dung_bg2_attr_table[pos += kDungLinkOffs1Pos[dir]] & 0xf0) == 0xf0) { int k = dung_bg2_attr_table[pos] & 0xf; dung_which_key_x2 = 2 * k; if ((dung_door_direction[k] & 3) != dir) goto not_openable; uint8 door_type = door_type_and_slot[k] & 0xfe; if (door_type == kDoorType_BreakableWall) { if (link_is_running && link_dash_ctr < 63) { dung_cur_door_pos = pos; int db = AncillaAdd_DoorDebris(); if (db >= 0) { door_debris_direction[db] = dung_door_direction[k] & 3; door_debris_x[db] = dung_loade_bgoffs_h_copy + (dung_door_tilemap_address[k] & 0x7e) * 4; door_debris_y[db] = dung_loade_bgoffs_v_copy + ((dung_door_tilemap_address[k] & 0x1f80) >> 4); } sound_effect_2 = 27; submodule_index = 9; Sprite_RepelDash(); return; } } else if (door_type == kDoorType_1E) { door_animation_step_indicator = 0; dung_cur_door_pos = pos; if (link_bigkey & kUpperBitmasks[cur_palace_index_x2 >> 1]) goto has_key_for_door; if (!big_key_door_message_triggered) { big_key_door_message_triggered = 1; dialogue_message_index = 0x7a; Main_ShowTextMessage(); } } else if (door_type >= kDoorType_SmallKeyDoor && door_type < 0x2c && door_type != 0x2a && link_num_keys != 0) { link_num_keys -= 1; has_key_for_door: door_animation_step_indicator = 0; dung_cur_door_pos = pos; submodule_index = 4; static const uint8 kOpenDoorPanning[] = { 0x0, 0x0, 0x80, 0x40 }; sound_effect_2 = 20 | kOpenDoorPanning[dung_door_direction[k] & 3]; return; } } else { not_openable: big_key_door_message_triggered = 0; } } if (!(invisible_door_dir_and_index_x2 & 0x80) && !is_standing_in_doorway && (link_x_coord >> 8) == 0xc) { uint8 dir = invisible_door_dir_and_index_x2; int j = (invisible_door_dir_and_index_x2 >> 8) >> 1; uint16 m = dung_door_opened_incl_adjacent; if (dir != link_direction_facing && (dir ^ 2) == link_direction_facing) m |= kUpperBitmasks[j]; else m &= ~kUpperBitmasks[j]; if (m != dung_door_opened_incl_adjacent) { dung_door_opened_incl_adjacent = m; DrawEyeWatchDoor(j); Dungeon_PrepOverlayDma_nextPrep(0, dung_door_tilemap_address[j]); Dungeon_LoadToggleDoorAttr_OtherEntry(j); nmi_copy_packets_flag = 1; sound_effect_2 = 21; return; } } if (!(button_mask_b_y & 0x80) || button_b_frames != 4) return; int pos = ((link_y_coord + (int8)player_oam_y_offset) & 0x1f8) << 3; pos |= ((link_x_coord + (int8)player_oam_x_offset) & 0x1f8) >> 3; uint8 attr, y; #define is_6c_fx(yv,x) (y=yv, ((attr = (dung_bg2_attr_table[x] & 0xfc)) == 0x6c || (attr & 0xf0) == 0xf0)) if (!(is_6c_fx(0x41, pos) || is_6c_fx(0x40, pos += 1) || is_6c_fx(1, pos += 63) || is_6c_fx(0, pos += 1))) return; int addr; if (attr == 0x6c) { if (y & 0x40 && (dung_bg2_attr_table[pos -= 64] & 0xfc) != 0x6c) pos += 64; if (y & 1 && (dung_bg2_attr_table[pos -= 1] & 0xfc) != 0x6c) pos += 1; attr = dung_bg2_attr_table[pos]; WriteAttr2(pos + XY(0, 0), 0x202); WriteAttr2(pos + XY(0, 1), 0x202); static const uint16 kSrcTiles1[] = { 0x7ea, 0x80a, 0x80a, 0x82a }; addr = (pos - XY(1, 1)) * 2; RoomDraw_Object_Nx4(4, SrcPtr(kSrcTiles1[attr & 3]), &dung_bg2[addr >> 1]); } else { dung_cur_door_pos = pos; int k = attr & 0xf; uint8 door_type = door_type_and_slot[k]; if (door_type != kDoorType_Slashable) return; sound_effect_2 = 27; addr = dung_door_tilemap_address[k]; dung_door_opened_incl_adjacent |= kUpperBitmasks[k]; dung_door_opened |= kUpperBitmasks[k]; door_open_closed_counter = 0; dung_cur_door_idx = k * 2; dung_which_key_x2 = k * 2; RoomDraw_Object_Nx4(4, SrcPtr(kDoorTypeSrcData[0x56 / 2]), &dung_bg2[addr >> 1]); Dungeon_LoadToggleDoorAttr_OtherEntry(k); } Dungeon_PrepOverlayDma_nextPrep(0, addr); sound_effect_1 = 30 | CalculateSfxPan_Arbitrary((addr & 0x7f) * 2); nmi_copy_packets_flag = 1; } void Bomb_CheckForDestructibles(uint16 x, uint16 y, uint8 r14) { // 81d1f4 if (main_module_index != 7) { Overworld_BombTiles32x32(x, y); return; } int k = ((y & 0x1f8) << 3 | (x & 0x1f8) >> 3) - 0x82; uint8 a; for (int i = 2; i >= 0; i--) { a = dung_bg2_attr_table[k]; if (a == 0x62) { handle_62: if (dungeon_room_index == 0x65) dung_savegame_state_bits |= 0x1000; Point16U pt; printf("Wtf is R6\n"); ThievesAttic_DrawLightenedHole(0, 0, &pt); sound_effect_2 = 0x1b; return; } if ((a & 0xf0) == 0xf0) { int j; handle_f0: j = a & 0xf; a = door_type_and_slot[j] & 0xfe; if (a != kDoorType_BreakableWall && a != 0x2A && a != 0x2E) return; dung_cur_door_pos = k; door_debris_x[r14] = ((dung_door_tilemap_address[j] & 0x7e) << 2) + dung_loade_bgoffs_h_copy; door_debris_y[r14] = ((dung_door_tilemap_address[j] & 0x1f80) >> 4) + dung_loade_bgoffs_v_copy; door_debris_direction[r14] = dung_door_direction[j] & 3; sound_effect_2 = 0x1b; submodule_index = 9; return; } a = dung_bg2_attr_table[k += 2]; if (a == 0x62) goto handle_62; if ((a & 0xf0) == 0xf0) goto handle_f0; a = dung_bg2_attr_table[k += 2]; if (a == 0x62) goto handle_62; if ((a & 0xf0) == 0xf0) goto handle_f0; k += 0x7c; } } int DrawDoorOpening_Step1(int door, int dma_ptr) { // 81d2e8 dung_cur_door_idx = door * 2; dung_which_key_x2 = door * 2; switch (dung_door_direction[door] & 3) { case 0: return DoorDoorStep1_North(door, dma_ptr); case 1: return DoorDoorStep1_South(door, dma_ptr); case 2: return DoorDoorStep1_West(door, dma_ptr); case 3: return DoorDoorStep1_East(door, dma_ptr); } return 0; } void DrawShutterDoorSteps(int door) { // 81d311 dung_cur_door_idx = door * 2; dung_which_key_x2 = door * 2; switch (dung_door_direction[door] & 3) { case 0: GetDoorDrawDataIndex_North_clean_door_index(door); break; case 1: GetDoorDrawDataIndex_South_clean_door_index(door); break; case 2: GetDoorDrawDataIndex_West_clean_door_index(door); break; case 3: GetDoorDrawDataIndex_East_clean_door_index(door); break; } } void DrawEyeWatchDoor(int door) { // 81d33a dung_cur_door_idx = door * 2; dung_which_key_x2 = door * 2; switch (dung_door_direction[door] & 3) { case 0: DrawDoorToTileMap_North(door, door); break; case 1: DrawDoorToTileMap_South(door, door); break; case 2: DrawDoorToTileMap_West(door, door); break; case 3: DrawDoorToTileMap_East(door, door); break; } } void Door_BlastWallExploding_Draw(int dsto) { // 81d373 uint16 *dst = &dung_bg2[dsto]; const uint16 *src = SrcPtr(0x31ea); ClearExplodingWallFromTileMap_ClearOnePair(dst, src); dst += 2; uint16 v = src[24]; for (int n = dung_unk_blast_walls_2 - 1; n; n--) { for (int j = 0; j < 12; j++) dst[XY(0, j)] = v; dst++; } ClearExplodingWallFromTileMap_ClearOnePair(dst, src + 25); } void OperateShutterDoors() { // 81d38f int anim_dst = 0; uint8 y = 2; if (++door_animation_step_indicator != 4) { y = dung_flag_trapdoors_down ? 0 : 4; if (door_animation_step_indicator != 8) goto getout; } door_open_closed_counter = y; for (dung_cur_door_pos = 0; dung_cur_door_pos != 0x18; dung_cur_door_pos += 2) { int j = dung_cur_door_pos >> 1; uint8 door_type = door_type_and_slot[j] & 0xfe; if (door_type != kDoorType_Shutter && door_type != kDoorType_ShuttersTwoWay) continue; int mask = kUpperBitmasks[j]; if (!dung_flag_trapdoors_down) { if (dung_door_opened_incl_adjacent & mask) continue; if (door_animation_step_indicator == 8) { sound_effect_2 = 21; dung_door_opened_incl_adjacent ^= mask; } } else { if (!(dung_door_opened_incl_adjacent & mask)) continue; if (door_animation_step_indicator == 8) { sound_effect_2 = 22; dung_door_opened_incl_adjacent ^= mask; } } DrawShutterDoorSteps(j); anim_dst = Dungeon_PrepOverlayDma_nextPrep(anim_dst, dung_door_tilemap_address[j]); if (door_animation_step_indicator == 8) Dungeon_LoadToggleDoorAttr_OtherEntry(j); } dung_cur_door_pos -= 2; if (anim_dst != 0) { nmi_disable_core_updates = nmi_copy_packets_flag = 1; getout: if (BYTE(door_animation_step_indicator) != 0x10) return; } submodule_index = 0; nmi_copy_packets_flag = 0; } void OpenCrackedDoor() { // 81d469 Dungeon_OpeningLockedDoor_Combined(true); } void Dungeon_LoadToggleDoorAttr_OtherEntry(int door) { // 81d51c Dungeon_LoadSingleDoorAttribute(door); Dungeon_LoadSingleDoorTileAttribute(); } void Dungeon_LoadSingleDoorTileAttribute() { // 81d51f for (int i = 0; i != dung_num_toggle_floor; i += 2) { int j = dung_toggle_floor_pos[i >> 1]; if ((dung_bg2_attr_table[j] & 0xf0) == 0x80) { uint16 attr = *(uint16 *)&dung_bg2_attr_table[j]; WriteAttr2(j + XY(0, 0), attr | 0x1010); WriteAttr2(j + XY(0, 1), attr | 0x1010); } else { uint16 attr = *(uint16 *)&dung_bg1_attr_table[j]; WriteAttr1(j + XY(0, 0), attr | 0x1010); WriteAttr1(j + XY(0, 1), attr | 0x1010); } } for (int i = 0; i != dung_num_toggle_palace; i += 2) { int j = dung_toggle_palace_pos[i >> 1]; if ((dung_bg2_attr_table[j] & 0xf0) == 0x80) { uint16 attr = *(uint16 *)&dung_bg2_attr_table[j]; WriteAttr2(j + XY(0, 0), attr | 0x2020); WriteAttr2(j + XY(0, 1), attr | 0x2020); } else { uint16 attr = *(uint16 *)&dung_bg1_attr_table[j]; WriteAttr1(j + XY(0, 0), attr | 0x2020); WriteAttr1(j + XY(0, 1), attr | 0x2020); } } } void DrawCompletelyOpenDoor() { // 81d5aa uint16 t; int i; for (i = 0, t = 0x3030; i != dung_num_inter_room_upnorth_stairs; i += 2, t += 0x101) {} for (; i != dung_num_wall_upnorth_spiral_stairs; i += 2, t += 0x101) { int pos = dung_inter_starcases[i >> 1]; WriteAttr2(pos + XY(1, 0), 0x5e5e); WriteAttr2(pos + XY(1, 1), t); WriteAttr2(pos + XY(1, 2), 0); WriteAttr2(pos + XY(1, 3), 0); } for (; i != dung_num_wall_upnorth_spiral_stairs_2; i += 2, t += 0x101) { int pos = dung_inter_starcases[i >> 1]; WriteAttr2(pos + XY(1, 0), 0x5f5f); WriteAttr2(pos + XY(1, 1), t); WriteAttr2(pos + XY(1, 2), 0); WriteAttr2(pos + XY(1, 3), 0); } for (; i != dung_num_inter_room_upnorth_straight_stairs; i += 2, t += 0x101) {} for (; i != dung_num_inter_room_upsouth_straight_stairs; i += 2, t += 0x101) {} t = (t & 0x707) | 0x3434; for (; i != dung_num_inter_room_southdown_stairs; i += 2, t += 0x101) {} for (; i != dung_num_wall_downnorth_spiral_stairs; i += 2, t += 0x101) { int pos = dung_inter_starcases[i >> 1]; WriteAttr2(pos + XY(1, 0), 0x5e5e); WriteAttr2(pos + XY(1, 1), t); WriteAttr2(pos + XY(1, 2), 0); WriteAttr2(pos + XY(1, 3), 0); } for (; i != dung_num_wall_downnorth_spiral_stairs_2; i += 2, t += 0x101) { int pos = dung_inter_starcases[i >> 1]; WriteAttr2(pos + XY(1, 0), 0x5f5f); WriteAttr2(pos + XY(1, 1), t); WriteAttr2(pos + XY(1, 2), 0); WriteAttr2(pos + XY(1, 3), 0); } } void Dungeon_ClearAwayExplodingWall() { // 81d6c1 flag_is_link_immobilized = 6; flag_unk1 = 6; if (BYTE(messaging_buf[0]) != 6) return; word_7E045E = 0; g_ram[12] = 0; door_animation_step_indicator = 0; dung_cur_door_idx = dung_unk_blast_walls_3; int dsto = (dung_door_tilemap_address[dung_unk_blast_walls_3 >> 1] -= 2) >> 1; Door_BlastWallExploding_Draw(dsto); ClearAndStripeExplodingWall(dsto); WORD(nmi_disable_core_updates) = 0xffff; dung_unk_blast_walls_2 += 2; if (dung_unk_blast_walls_2 == 21) { int m = kUpperBitmasks[dung_unk_blast_walls_3 >> 1]; dung_door_opened_incl_adjacent |= m; dung_door_opened |= m; if (dung_door_direction[dung_unk_blast_walls_3 >> 1] & 2) { dung_blastwall_flag_x = 1; quadrant_fullsize_x = 2; } else { dung_blastwall_flag_y = 1; quadrant_fullsize_y = 2; } WORD(quadrant_fullsize_x_cached) = WORD(quadrant_fullsize_x); Door_LoadBlastWallAttr(dung_unk_blast_walls_3 >> 1); dung_unk_blast_walls_2 = 0; dung_unk_blast_walls_3 = 0; Dungeon_FlagRoomData_Quadrants(); flag_is_link_immobilized = 0; flag_unk1 = 0; } nmi_copy_packets_flag = 3; } uint16 Dungeon_CheckForAndIDLiftableTile() { // 81d748 uint16 x = (link_x_coord + kDungeon_QueryIfTileLiftable_x[link_direction_facing >> 1]) & 0x1f8; uint16 y = (link_y_coord + kDungeon_QueryIfTileLiftable_y[link_direction_facing >> 1]) & 0x1f8; uint16 xy = (y << 3) | (x >> 3) | (link_is_on_lower_level ? 0x1000 : 0x0); uint8 attr = dung_bg2_attr_table[xy]; if ((attr & 0xf0) != 0x70) return 0xffff; // clc uint16 rt = dung_replacement_tile_state[attr & 0xf]; if (rt == 0) return 0xffff; if ((rt & 0xf0f0) == 0x2020) return 0x55; return kDungeon_QueryIfTileLiftable_rv[rt & 0xf]; } void Dungeon_PushBlock_Handler() { // 81d81b while (dung_misc_objs_index != dung_index_of_torches_start) { int k = dung_misc_objs_index >> 1; int st = dung_replacement_tile_state[k]; if (st == 1) { RoomDraw_16x16Single(k * 2); dung_object_tilemap_pos[k] += kPushBlockMoveDistances[push_block_direction >> 1]; dung_replacement_tile_state[k] = 2; } else if (st == 2) { PushBlock_Slide(k * 2); if (dung_replacement_tile_state[dung_misc_objs_index >> 1] == 3) { PushBlock_CheckForPit(dung_misc_objs_index); dung_replacement_tile_state[dung_misc_objs_index >> 1]++; } } else if (st == 4) { PushBlock_HandleFalling(k * 2); } dung_misc_objs_index += 2; } } void RoomDraw_16x16Single(uint8 index) { // 81d828 index >>= 1; uint16 pos = (dung_object_tilemap_pos[index] & 0x3fff) >> 1; Dungeon_Store2x2(pos, replacement_tilemap_UL[index], replacement_tilemap_LL[index], replacement_tilemap_UR[index], replacement_tilemap_LR[index], attributes_for_tile[replacement_tilemap_LR[index] & 0x3ff]); } void PushBlock_CheckForPit(uint8 y) { // 81d8d4 y >>= 1; if (!(dung_object_tilemap_pos[y] & 0x4000)) dung_flag_movable_block_was_pushed ^= 1; int p = (dung_object_tilemap_pos[y] & 0x3fff) >> 1; uint8 attr = dung_bg2_attr_table[p]; if (attr == 0x20) { // fall into pit sound_effect_1 = 0x20; int k = dung_object_pos_in_objdata[y] >> 2; movable_block_datas[k].room = dung_hdr_travel_destinations[0]; movable_block_datas[k].tilemap = dung_object_tilemap_pos[y]; return; } int i = (index_of_changable_dungeon_objs[1] - 1) == y; index_of_changable_dungeon_objs[i] = 0; if (attr == 0x23) { related_to_trapdoors_somehow = dung_flag_trapdoors_down ^ 1; dung_replacement_tile_state[y] = 4; } else { dung_replacement_tile_state[y] = 0xffff; } Dungeon_Store2x2(p, 0x922, 0x932, 0x923, 0x933, 0x27); } uint8 Dungeon_LiftAndReplaceLiftable(Point16U *pt) { // 81d9ec uint16 x = link_x_coord + kDungeon_QueryIfTileLiftable_x[link_direction_facing >> 1]; uint16 y = link_y_coord + kDungeon_QueryIfTileLiftable_y[link_direction_facing >> 1]; pt->x = x; pt->y = y; R16 = y; R18 = x; x &= 0x1f8; y &= 0x1f8; uint16 xy = (y << 3) | (x >> 3) | (link_is_on_lower_level ? 0x1000 : 0x0); uint8 attr = dung_bg2_attr_table[xy]; assert((attr & 0x70) == 0x70); attr &= 0xf; uint16 rt = dung_replacement_tile_state[attr]; if ((rt & 0xf0f0) == 0x1010) { dung_misc_objs_index = attr * 2; RevealPotItem(xy, dung_object_tilemap_pos[attr]); RoomDraw_16x16Single(dung_misc_objs_index); ManipBlock_Something(pt); return kDungeon_QueryIfTileLiftable_rv[rt & 0xf]; } else if ((rt & 0xf0f0) == 0x2020) { return ThievesAttic_DrawLightenedHole(xy, (attr - (rt & 0xf)) * 2, pt); } else { return 0; } return 0; } uint8 ThievesAttic_DrawLightenedHole(uint16 pos6, uint16 a, Point16U *pt) { // 81da71 dung_misc_objs_index = a; RevealPotItem(pos6, dung_object_tilemap_pos[a >> 1]); RoomDraw_16x16Single(a); RoomDraw_16x16Single(a + 2); RoomDraw_16x16Single(a + 4); RoomDraw_16x16Single(a + 6); ManipBlock_Something(pt); return 0x55; } uint8 HandleItemTileAction_Dungeon(uint16 x, uint16 y) { // 81dabb if (!(link_item_in_hand & 2)) { if (!(enhanced_features0 & kFeatures0_BreakPotsWithSword) || button_b_frames == 0 || link_sword_type == 1) return 0; } uint16 pos = (y & 0x1f8) * 8 + x + (link_is_on_lower_level ? 0x1000 : 0); uint16 tile = dung_bg2_attr_table[pos]; if ((tile & 0xf0) == 0x70) { uint16 tile2 = dung_replacement_tile_state[tile & 0xf]; if ((tile2 & 0xf0f0) == 0x4040) { // Hammer peg if (!(link_item_in_hand & 2)) return 0; // only hammers on pegs dung_misc_objs_index = (tile & 0xf) * 2; RoomDraw_16x16Single(dung_misc_objs_index); sound_effect_1 = 0x11; } else if ((tile2 & 0xf0f0) == 0x1010) { // Pot dung_misc_objs_index = (tile & 0xf) * 2; RevealPotItem(pos, dung_object_tilemap_pos[tile & 0xf]); RoomDraw_16x16Single(dung_misc_objs_index); Point16U pt; ManipBlock_Something(&pt); BYTE(dung_secrets_unk1) |= 0x80; Sprite_SpawnImmediatelySmashedTerrain(1, pt.x, pt.y); AncillaAdd_BushPoof(pt.x, pt.y); // return value wtf? } } return 0; } void ManipBlock_Something(Point16U *pt) { // 81db41 uint16 pos = dung_object_tilemap_pos[dung_misc_objs_index >> 1]; pt->x = (link_x_coord & 0xfe00) | ((pos & 0x007e) << 2); pt->y = (link_y_coord & 0xfe00) | ((pos & 0x1f80) >> 4); } void RevealPotItem(uint16 pos6, uint16 pos4) { // 81e6b2 BYTE(dung_secrets_unk1) = 0; const uint8 *src_ptr = kDungeonSecrets + WORD(kDungeonSecrets[dungeon_room_index * 2]); int index = 0; for (;;) { uint16 test_pos = *(uint16 *)src_ptr; if (test_pos == 0xffff) return; assert(!(test_pos & 0x8000)); if (test_pos == pos4) break; src_ptr += 3; index++; } uint8 data = src_ptr[2]; if (data == 0) return; if (data < 0x80) { if (data != 8) { uint16 mask = 1 << index; uint16 *pr = &pots_revealed_in_room[dungeon_room_index]; if (*pr & mask) return; *pr |= mask; } BYTE(dung_secrets_unk1) |= data; } else if (data != 0x88) { int j = dung_bg2_attr_table[pos6] & 0xf; int k = (j - (dung_replacement_tile_state[j] & 0xf)); dung_misc_objs_index = 2 * k; sound_effect_2 = 0x1b; const uint16 *src = SrcPtr(0x5ba); for (int i = 0; i < 4; i++, k++, src += 4) { replacement_tilemap_UL[k] = src[0]; replacement_tilemap_LL[k] = src[1]; replacement_tilemap_UR[k] = src[2]; replacement_tilemap_LR[k] = src[3]; } } else { int k = dung_misc_objs_index >> 1; replacement_tilemap_UL[k] = 0xD0B; replacement_tilemap_LL[k] = 0xD1B; replacement_tilemap_UR[k] = 0x4D0B; replacement_tilemap_LR[k] = 0x4D1B; } } void Dungeon_UpdateTileMapWithCommonTile(int x, int y, uint8 v) { // 81e7a9 if (v == 8) Dungeon_PrepSpriteInducedDma(x + 16, y, v + 2); Dungeon_PrepSpriteInducedDma(x, y, v); nmi_load_bg_from_vram = 1; } void Dungeon_PrepSpriteInducedDma(int x, int y, uint8 v) { // 81e7df static const uint16 kPrepSpriteInducedDma_Srcs[10] = { 0xe0, 0xade, 0x5aa, 0x198, 0x210, 0x218, 0x1f3a, 0xeaa, 0xeb2, 0x140 }; int pos = ((y + 1) & 0x1f8) << 3 | (x & 0x1f8) >> 3; const uint16 *src = SrcPtr(kPrepSpriteInducedDma_Srcs[v >> 1]); uint16 *dst = &vram_upload_data[vram_upload_offset >> 1]; dst[0] = Dungeon_MapVramAddr(pos + 0); dst[3] = Dungeon_MapVramAddr(pos + 64); dst[6] = Dungeon_MapVramAddr(pos + 1); dst[9] = Dungeon_MapVramAddr(pos + 65); uint8 attr = attributes_for_tile[src[3] & 0x3ff]; dung_bg2_attr_table[pos + XY(0, 0)] = attr; dung_bg2_attr_table[pos + XY(0, 1)] = attr; dung_bg2_attr_table[pos + XY(1, 0)] = attr; dung_bg2_attr_table[pos + XY(1, 1)] = attr; dung_bg2[pos + XY(0, 0)] = dst[2] = src[0]; dung_bg2[pos + XY(0, 1)] = dst[5] = src[1]; dung_bg2[pos + XY(1, 0)] = dst[8] = src[2]; dung_bg2[pos + XY(1, 1)] = dst[11] = src[3]; dst[1] = 0x100; dst[4] = 0x100; dst[7] = 0x100; dst[10] = 0x100; dst[12] = 0xffff; vram_upload_offset += 24; } void Dungeon_DeleteRupeeTile(uint16 x, uint16 y) { // 81e8bd int pos = (y & 0x1f8) * 8 | (x & 0x1f8) >> 3; uint16 *dst = &vram_upload_data[vram_upload_offset >> 1]; dst[2] = 0x190f; dst[5] = 0x190f; dung_bg2[pos + XY(0, 0)] = 0x190f; dung_bg2[pos + XY(0, 1)] = 0x190f; uint16 attr = attributes_for_tile[0x190f & 0x3ff] * 0x101; WORD(dung_bg2_attr_table[pos + XY(0, 0)]) = attr; WORD(dung_bg2_attr_table[pos + XY(0, 1)]) = attr; dst[0] = Dungeon_MapVramAddr(pos + XY(0, 0)); dst[3] = Dungeon_MapVramAddr(pos + XY(0, 1)); dst[1] = 0x100; dst[4] = 0x100; dst[6] = 0xffff; vram_upload_offset += 24; dung_savegame_state_bits |= 0x1000; nmi_load_bg_from_vram = 1; } // This doesn't return exactly like the original // Also returns in scratch_0 uint8 OpenChestForItem(uint8 tile, int *chest_position) { // 81eb66 static const uint16 kChestOpenMasks[] = { 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000 }; if (tile == 0x63) return OpenMiniGameChest(chest_position); int chest_idx = tile - 0x58, chest_idx_org = chest_idx; uint16 loc = dung_chest_locations[chest_idx], pos, chest_room; uint8 data = 0xff; const uint16 *ptr; if (loc >= 0x8000) { // big key lock if (!(link_bigkey & kUpperBitmasks[cur_palace_index_x2 >> 1])) { dialogue_message_index = 0x7a; Main_ShowTextMessage(); return 0xff; } else { dung_savegame_state_bits |= kChestOpenMasks[chest_idx]; sound_effect_1 = 0x29; sound_effect_2 = 0x15; pos = (loc & 0x7fff) >> 1; ptr = SrcPtr(dung_floor_2_filler_tiles); overworld_tileattr[pos + 0] = ptr[0]; overworld_tileattr[pos + 64] = ptr[1]; overworld_tileattr[pos + 1] = ptr[2]; overworld_tileattr[pos + 65] = ptr[3]; goto afterStoreCrap; } } else { const uint8 *chest_data; int i; chest_data = kDungeonRoomChests; for (i = 0; i < kDungeonRoomChests_SIZE; i += 3, chest_data += 3) { chest_room = *(uint16 *)chest_data; if ((chest_room & 0x7fff) == dungeon_room_index && --chest_idx < 0) { data = chest_data[2]; if (chest_room & 0x8000) { if (!(link_bigkey & kUpperBitmasks[cur_palace_index_x2 >> 1])) { dialogue_message_index = 0x7a; Main_ShowTextMessage(); return 0xff; } dung_savegame_state_bits |= kChestOpenMasks[chest_idx_org]; OpenBigChest(loc, chest_position); return data; } else { dung_savegame_state_bits |= kChestOpenMasks[chest_idx_org]; ptr = SrcPtr(0x14A4); pos = loc >> 1; overworld_tileattr[pos + 0] = ptr[0]; overworld_tileattr[pos + 64] = ptr[1]; overworld_tileattr[pos + 1] = ptr[2]; overworld_tileattr[pos + 65] = ptr[3]; uint8 attr; afterStoreCrap: attr = (loc < 0x8000) ? 0x27 : 0x00; dung_bg2_attr_table[pos + 0] = attr; dung_bg2_attr_table[pos + 64] = attr; dung_bg2_attr_table[pos + 1] = attr; dung_bg2_attr_table[pos + 65] = attr; uint16 *dst = &vram_upload_data[vram_upload_offset >> 1]; dst[0] = Dungeon_MapVramAddr(pos + 0); dst[3] = Dungeon_MapVramAddr(pos + 64); dst[6] = Dungeon_MapVramAddr(pos + 1); dst[9] = Dungeon_MapVramAddr(pos + 65); dst[2] = ptr[0]; dst[5] = ptr[1]; dst[8] = ptr[2]; dst[11] = ptr[3]; dst[1] = 0x100; dst[4] = 0x100; dst[7] = 0x100; dst[10] = 0x100; dst[12] = 0xffff; vram_upload_offset += 24; nmi_load_bg_from_vram = 1; Dungeon_FlagRoomData_Quadrants(); if (sound_effect_2 == 0) sound_effect_2 = 14; *chest_position = loc & 0x7fff; return data; } } } return 0xff; } } void OpenBigChest(uint16 loc, int *chest_position) { // 81ed05 uint16 pos = loc >> 1; const uint16 *src = SrcPtr(0x14C4); for (int i = 0; i < 4; i++) { dung_bg2[pos + XY(i, 0)] = src[0]; dung_bg2[pos + XY(i, 1)] = src[1]; dung_bg2[pos + XY(i, 2)] = src[2]; src += 3; } Dungeon_PrepOverlayDma_nextPrep(0, loc); *chest_position = (loc + 2); WORD(dung_bg2_attr_table[pos + XY(0, 0)]) = 0x2727; WORD(dung_bg2_attr_table[pos + XY(2, 0)]) = 0x2727; WORD(dung_bg2_attr_table[pos + XY(0, 1)]) = 0x2727; WORD(dung_bg2_attr_table[pos + XY(2, 1)]) = 0x2727; WORD(dung_bg2_attr_table[pos + XY(0, 2)]) = 0x2727; WORD(dung_bg2_attr_table[pos + XY(2, 2)]) = 0x2727; Dungeon_FlagRoomData_Quadrants(); sound_effect_2 = 14; nmi_copy_packets_flag = 1; byte_7E0B9E = 1; } uint8 OpenMiniGameChest(int *chest_position) { // 81edab int t; if (minigame_credits == 0) { dialogue_message_index = 0x163; Main_ShowTextMessage(); return 0xff; } if (minigame_credits == 255) { dialogue_message_index = 0x162; Main_ShowTextMessage(); return 0xff; } minigame_credits--; int pos = ((link_y_coord - 4) & 0x1f8) * 8; pos |= ((link_x_coord + 7) & 0x1f8) >> 3; if (WORD(dung_bg2_attr_table[pos]) != 0x6363) { pos--; if (WORD(dung_bg2_attr_table[pos]) != 0x6363) pos += 2; } *chest_position = pos * 2; WORD(dung_bg2_attr_table[pos + XY(0, 0)]) = 0x202; WORD(dung_bg2_attr_table[pos + XY(0, 1)]) = 0x202; const uint16 *src = SrcPtr(0x14A4); int pos_wrong = pos + XY(0, 2); // zelda bug? dung_bg2[pos_wrong + XY(0, 0)] = src[0]; dung_bg2[pos_wrong + XY(0, 1)] = src[1]; dung_bg2[pos_wrong + XY(1, 0)] = src[2]; dung_bg2[pos_wrong + XY(1, 1)] = src[3]; // The orig asm code seems to access invalid vram here because it indexes by 0x14a4 uint16 *dst = &vram_upload_data[vram_upload_offset >> 1]; dst[0] = Dungeon_MapVramAddr(pos + 0); dst[3] = Dungeon_MapVramAddr(pos + 64); dst[6] = Dungeon_MapVramAddr(pos + 1); dst[9] = Dungeon_MapVramAddr(pos + 65); dst[2] = src[0]; dst[5] = src[1]; dst[8] = src[2]; dst[11] = src[3]; dst[1] = 0x100; dst[4] = 0x100; dst[7] = 0x100; dst[10] = 0x100; dst[12] = 0xffff; vram_upload_offset += 24; uint8 rv; uint16 r16 = some_menu_ctr; t = GetRandomNumber(); if (BYTE(dungeon_room_index) == 0) { t = t & 0xf; rv = kDungeon_RupeeChestMinigamePrizes[t & 0xf]; } else if (BYTE(dungeon_room_index) == 0x18) { t = 0x10 + (t & 0xf); rv = kDungeon_RupeeChestMinigamePrizes[0x10 + (t & 0xf)]; } else { t &= 7; if (t >= 2 && t == r16) { t = (t + 1) & 7; } if (t == 7) { if (dung_savegame_state_bits & 0x4000) { t = 0; } else { dung_savegame_state_bits |= 0x4000; } } rv = kDungeon_MinigameChestPrizes1[t]; } some_menu_ctr = t; nmi_load_bg_from_vram = 1; sound_effect_2 = 14; return rv; } uint16 RoomTag_BuildChestStripes(uint16 pos, uint16 y) { // 81ef0f pos += dung_chest_locations[y >> 1]; return swap16(((pos & 0x40) << 4) | ((pos & 0x303f) >> 1) | ((pos & 0xf80) >> 2)); } void Dungeon_SetAttrForActivatedWaterOff() { // 81ef93 CGWSEL_copy = 2; CGADSUB_copy = 0x32; zelda_ppu_write(TS, 0); TS_copy = 0; W12SEL_copy = 0; dung_hdr_collision = 0; WORD(TMW_copy) = 0; for (int j = 0; j != dung_num_inroom_upnorth_stairs_water; j += 2) { int dsto = dung_stairs_table_1[j >> 1]; WriteAttr2(dsto + XY(1, 1), 0x1d1d); WriteAttr2(dsto + XY(1, 2), 0x1d1d); } for (int j = 0; j != dung_num_inroom_upsouth_stairs_water; j += 2) { int dsto = dung_stairs_table_2[j >> 1]; WriteAttr2(dsto + XY(1, 1), 0x1d1d); WriteAttr2(dsto + XY(1, 2), 0x1d1d); } flag_update_cgram_in_nmi++; subsubmodule_index++; } void Dungeon_FloodSwampWater_PrepTileMap() { // 81f046 WaterFlood_BuildOneQuadrantForVRAM(); dung_cur_quadrant_upload += 4; if (++subsubmodule_index == 6) { dung_cur_quadrant_upload = 0; subsubmodule_index = 0; submodule_index = 0; } } void Dungeon_AdjustWaterVomit(const uint16 *src, int depth) { // 81f0c9 int dsto = (word_7E047C >> 1) + XY(0, 2); uint16 *dst = &dung_bg2[dsto]; do { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3]; dst += XY(0, 1), src += 4; } while (--depth); uint16 *vram = vram_upload_data; for (int i = 0; i < 4; i++) { uint16 *dst = &dung_bg2[dsto]; vram[0] = Dungeon_MapVramAddr(dsto); vram[1] = 0x980; vram[2] = dst[XY(0, 0)]; vram[3] = dst[XY(0, 1)]; vram[4] = dst[XY(0, 2)]; vram[5] = dst[XY(0, 3)]; vram[6] = dst[XY(0, 4)]; vram += 7, dsto++; } vram[0] = 0xffff; nmi_load_bg_from_vram = 1; } void Dungeon_SetAttrForActivatedWater() { // 81f237 WORD(TMW_copy) = 0; for (int j = 0; j != dung_num_interpseudo_upnorth_stairs; j += 2) { int dsto = dung_stairs_table_1[j >> 1]; WriteAttr2(dsto + 0, 0x003); WriteAttr2(dsto + 2, 0x300); WriteAttr1(dsto + 0, 0xa03); WriteAttr1(dsto + 2, 0x30a); WriteAttr2(dsto + XY(0, 1), 0x808); WriteAttr2(dsto + XY(2, 1), 0x808); WriteAttr1(dsto + XY(0, 1), 0x808); WriteAttr1(dsto + XY(2, 1), 0x808); WriteAttr1(dsto + XY(0, 2), 0x808); WriteAttr1(dsto + XY(2, 2), 0x808); WriteAttr1(dsto + XY(0, 3), 0x808); WriteAttr1(dsto + XY(2, 3), 0x808); } for (int j = 0; j != dung_num_stairs_wet; j += 2) { int dsto = dung_stairs_table_2[j >> 1]; WriteAttr2(dsto + XY(0, 3), 0x003); WriteAttr2(dsto + XY(2, 3), 0x300); WriteAttr1(dsto + XY(0, 3), 0xa03); WriteAttr1(dsto + XY(2, 3), 0x30a); WriteAttr2(dsto + XY(0, 2), 0x808); WriteAttr2(dsto + XY(2, 2), 0x808); WriteAttr1(dsto + XY(0, 0), 0x808); WriteAttr1(dsto + XY(2, 0), 0x808); WriteAttr1(dsto + XY(0, 1), 0x808); WriteAttr1(dsto + XY(2, 1), 0x808); WriteAttr1(dsto + XY(0, 2), 0x808); WriteAttr1(dsto + XY(2, 2), 0x808); } submodule_index = 0; nmi_boolean = 0; // wtf subsubmodule_index = 0; } void FloodDam_Expand() { // 81f30c watergate_var1++; water_hdma_var3 = watergate_var1 >> 1; uint8 r0 = water_hdma_var3 - 8; BYTE(spotlight_y_upper) = word_7E0678; BYTE(spotlight_var4) += 1; BYTE(water_hdma_var2) = spotlight_var4 + r0; if (watergate_var1 & 0xf) return; if (watergate_var1 == 64) subsubmodule_index++; static const uint16 kWatergateSrcs1[] = { 0x12f8, 0x1348, 0x1398, 0x13e8 }; RoomDraw_Object_Nx4(10, SrcPtr(kWatergateSrcs1[(watergate_var1 >> 4) - 1]), &dung_bg2[watergate_pos >> 1]); int pos = watergate_pos; int n = 3; int dma_ptr = 0; do { dma_ptr = Dungeon_PrepOverlayDma_watergate(dma_ptr, pos, 0x881, 4); pos += 6; } while (--n); nmi_copy_packets_flag = 1; } void FloodDam_PrepTiles_init() { // 81f3a7 dung_cur_quadrant_upload = 0; overworld_screen_transition = 0; WaterFlood_BuildOneQuadrantForVRAM(); dung_cur_quadrant_upload += 4; subsubmodule_index++; } void Watergate_Main_State1() { // 81f3aa overworld_screen_transition = 0; WaterFlood_BuildOneQuadrantForVRAM(); dung_cur_quadrant_upload += 4; subsubmodule_index++; } void FloodDam_Fill() { // 81f3bd BYTE(water_hdma_var2)++; uint8 t = water_hdma_var2 + spotlight_y_upper; if (t >= 225) { dung_cur_quadrant_upload = 0; submodule_index = 0; subsubmodule_index = 0; TMW_copy = 0; TSW_copy = 0; IrisSpotlight_ResetTable(); } } void Ganon_ExtinguishTorch_adjust_translucency() { // 81f496 Palette_AssertTranslucencySwap(); byte_7E0333 = 0xc0; Dungeon_ExtinguishTorch(); } void Ganon_ExtinguishTorch() { // 81f4a1 byte_7E0333 = 193; Dungeon_ExtinguishTorch(); } void Dungeon_ExtinguishTorch() { // 81f4a6 int y = (byte_7E0333 & 0xf) * 2 + dung_index_of_torches_start; uint16 r8 = (dung_object_tilemap_pos[y >> 1] &= 0x7fff); dung_torch_data[(dung_object_pos_in_objdata[y >> 1] & 0xff) >> 1] = r8; r8 &= 0x3fff; RoomDraw_AdjustTorchLightingChange(r8, 0xec2, r8); nmi_copy_packets_flag = 1; if (dung_want_lights_out && dung_num_lit_torches != 0 && --dung_num_lit_torches < 3) { if (dung_num_lit_torches == 0) TS_copy = 1; overworld_fixed_color_plusminus = kLitTorchesColorPlus[dung_num_lit_torches]; submodule_index = 10; subsubmodule_index = 0; } dung_torch_timers[byte_7E0333 & 0xf] = 0; byte_7E0333 = 0; } void SpiralStairs_MakeNearbyWallsHighPriority_Entering() { // 81f528 int pos = dung_inter_starcases[which_staircase_index & 3] - 4; word_7E048C = pos * 2; uint16 *dst = &dung_bg2[pos]; for (int i = 0; i < 5; i++) { dst[XY(0, 0)] |= 0x2000; dst[XY(0, 1)] |= 0x2000; dst[XY(0, 2)] |= 0x2000; dst[XY(0, 3)] |= 0x2000; dst += 1; } int dp = Dungeon_PrepOverlayDma_nextPrep(0, pos * 2); Dungeon_PrepOverlayDma_nextPrep(dp, pos * 2 + 8); nmi_copy_packets_flag = 1; } void SpiralStairs_MakeNearbyWallsLowPriority() { // 81f585 int pos = word_7E048C >> 1; uint16 *dst = &dung_bg2[pos]; for (int i = 0; i < 5; i++) { dst[XY(0, 0)] &= ~0x2000; dst[XY(0, 1)] &= ~0x2000; dst[XY(0, 2)] &= ~0x2000; dst[XY(0, 3)] &= ~0x2000; dst += 1; } int dp = Dungeon_PrepOverlayDma_nextPrep(0, pos * 2); Dungeon_PrepOverlayDma_nextPrep(dp, pos * 2 + 8); nmi_copy_packets_flag = 1; } void ClearAndStripeExplodingWall(uint16 dsto) { // 81f811 static const uint16 kBlastWall_Tab2[16] = { 4, 8, 0xc, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800 }; uint16 r6 = 0x80; uint16 r14 = 0; uint16 r10 = dung_unk_blast_walls_2 + 3; uint16 r2 = 0; if (!sign16(r10 - 8)) { r2 = r10 - 6; r14 = 1; r10 = 3; } if (!(dung_door_direction[dung_cur_door_idx >> 1] & 2)) r6++; uint16 *uvdata = &uvram.data[0]; for (;;) { const uint16 *bg2 = &dung_bg2[dsto]; do { uint16 vram_addr = Dungeon_MapVramAddrNoSwap(dsto); uvdata[0] = vram_addr; uvdata[1] = r6 | 0xa00; uvdata[2] = bg2[XY(0, 0)]; uvdata[3] = bg2[XY(0, 1)]; uvdata[4] = bg2[XY(0, 2)]; uvdata[5] = bg2[XY(0, 3)]; uvdata[6] = bg2[XY(0, 4)]; uvdata[7] = vram_addr + 0x4a0; uvdata[8] = r6 | 0xe00; uvdata[9] = bg2[XY(0, 5)]; uvdata[10] = bg2[XY(0, 6)]; uvdata[11] = bg2[XY(0, 7)]; uvdata[12] = bg2[XY(0, 8)]; uvdata[13] = bg2[XY(0, 9)]; uvdata[14] = bg2[XY(0, 10)]; uvdata[15] = bg2[XY(0, 11)]; dsto++, bg2++, uvdata += 16; } while (--r10); if (!r14) break; r14--; dsto += kBlastWall_Tab2[(r2 >> 1) + ((r6 & 1) ? 0 : 8) - 1] >> 1; r10 = 3; } uvdata[0] = 0xffff; } void Dungeon_DrawRoomOverlay(const uint8 *src) { // 81f967 for (;;) { dung_draw_width_indicator = 0; dung_draw_height_indicator = 0; uint16 a = WORD(*src); if (a == 0xffff) break; uint16 *p = &dung_bg2[(src[0] >> 2) | (src[1] >> 2) << 6]; uint8 type = src[2]; if (type == 0xa4) { p[XY(0, 1)] = p[XY(1, 1)] = p[XY(2, 1)] = p[XY(3, 1)] = p[XY(0, 2)] = p[XY(1, 2)] = p[XY(2, 2)] = p[XY(3, 2)] = SrcPtr(0x5aa)[0]; p[XY(0, 0)] = p[XY(1, 0)] = p[XY(2, 0)] = p[XY(3, 0)] = SrcPtr(0x63c)[1]; p[XY(0, 3)] = p[XY(1, 3)] = p[XY(2, 3)] = p[XY(3, 3)] = SrcPtr(0x642)[1]; } else { const uint16 *sp = SrcPtr(dung_floor_2_filler_tiles); p[XY(0, 0)] = p[XY(2, 0)] = p[XY(0, 2)] = p[XY(2, 2)] = sp[0]; p[XY(1, 0)] = p[XY(3, 0)] = p[XY(1, 2)] = p[XY(3, 2)] = sp[1]; p[XY(0, 1)] = p[XY(2, 1)] = p[XY(0, 3)] = p[XY(2, 3)] = sp[4]; p[XY(1, 1)] = p[XY(3, 1)] = p[XY(1, 3)] = p[XY(3, 3)] = sp[5]; } src += 3; } } void GetDoorDrawDataIndex_North_clean_door_index(int door) { // 81fa4a GetDoorDrawDataIndex_North(door, door); } int DoorDoorStep1_North(int door, int dma_ptr) { // 81fa54 int pos = dung_door_tilemap_address[door]; if ((pos & 0x1fff) >= kDoorPositionToTilemapOffs_Up[6]) { pos -= 0x500; if ((door_type_and_slot[door] & 0xfe) >= 0x42) pos -= 0x300; GetDoorDrawDataIndex_South(door ^ 8, door & 7); dma_ptr = Dungeon_PrepOverlayDma_nextPrep(dma_ptr, pos); Dungeon_LoadSingleDoorAttribute(door ^ 8); } GetDoorDrawDataIndex_North(door, door & 7); return dma_ptr; } void GetDoorDrawDataIndex_North(int door, int r4_door) { // 81faa0 uint8 door_type = door_type_and_slot[door] & 0xfe; int x = door_open_closed_counter; if (x == 0 || x == 4) { DrawDoorToTileMap_North(door, r4_door); return; } x += (door_type == kDoorType_StairMaskLocked2 || door_type == kDoorType_StairMaskLocked3 || door_type >= 0x42) ? 4 : 0; x += (door_type == kDoorType_ShuttersTwoWay || door_type == kDoorType_Shutter) ? 2 : 0; // assert(x < 8); Object_Draw_DoorUp_4x3(kDoorAnimUpSrc[x >> 1], door); } void DrawDoorToTileMap_North(int door, int r4_door) { // 81fad7 Object_Draw_DoorUp_4x3(kDoorTypeSrcData[GetDoorGraphicsIndex(door, r4_door) >> 1], door); } void Object_Draw_DoorUp_4x3(uint16 src, int door) { // 81fae3 const uint16 *s = SrcPtr(src); uint16 *dst = &dung_bg2[dung_door_tilemap_address[door] >> 1]; for (int i = 0; i < 4; i++) { dst[XY(0, 0)] = s[0]; dst[XY(0, 1)] = s[1]; dst[XY(0, 2)] = s[2]; dst += 1, s += 3; } } void GetDoorDrawDataIndex_South_clean_door_index(int door) { // 81fb0b GetDoorDrawDataIndex_South(door, door); } int DoorDoorStep1_South(int door, int dma_ptr) { // 81fb15 int pos = dung_door_tilemap_address[door]; if ((pos & 0x1fff) < kDoorPositionToTilemapOffs_Down[9]) { pos += 0x500; if ((door_type_and_slot[door] & 0xfe) >= 0x42) pos += 0x300; GetDoorDrawDataIndex_North(door ^ 8, door & 7); dma_ptr = Dungeon_PrepOverlayDma_nextPrep(dma_ptr, pos); Dungeon_LoadSingleDoorAttribute(door ^ 8); } GetDoorDrawDataIndex_South(door, door & 7); return dma_ptr; } void GetDoorDrawDataIndex_South(int door, int r4_door) { // 81fb61 uint8 door_type = door_type_and_slot[door] & 0xfe; int x = door_open_closed_counter; if (x == 0 || x == 4) { DrawDoorToTileMap_South(door, r4_door); return; } x += (door_type >= 0x42) ? 4 : 0; x += (door_type == kDoorType_ShuttersTwoWay || door_type == kDoorType_Shutter) ? 2 : 0; // assert(x < 8); Object_Draw_DoorDown_4x3(kDoorAnimDownSrc[x >> 1], door); } void DrawDoorToTileMap_South(int door, int r4_door) { // 81fb8e Object_Draw_DoorDown_4x3(kDoorTypeSrcData2[GetDoorGraphicsIndex(door, r4_door) >> 1], door); } void Object_Draw_DoorDown_4x3(uint16 src, int door) { // 81fb9b const uint16 *s = SrcPtr(src); uint16 *dst = &dung_bg2[dung_door_tilemap_address[door] >> 1]; for (int i = 0; i < 4; i++) { dst[XY(0, 1)] = s[0]; dst[XY(0, 2)] = s[1]; dst[XY(0, 3)] = s[2]; dst += 1, s += 3; } } void GetDoorDrawDataIndex_West_clean_door_index(int door) { // 81fbc2 GetDoorDrawDataIndex_West(door, door); } int DoorDoorStep1_West(int door, int dma_ptr) { // 81fbcc int pos = dung_door_tilemap_address[door]; if ((pos & 0x7ff) >= kDoorPositionToTilemapOffs_Left[6]) { pos -= 16; if ((door_type_and_slot[door] & 0xfe) >= 0x42) pos -= 12; GetDoorDrawDataIndex_East(door ^ 8, door & 7); dma_ptr = Dungeon_PrepOverlayDma_nextPrep(dma_ptr, pos); Dungeon_LoadSingleDoorAttribute(door ^ 8); } GetDoorDrawDataIndex_West(door, door & 7); return dma_ptr; } void GetDoorDrawDataIndex_West(int door, int r4_door) { // 81fc18 uint8 door_type = door_type_and_slot[door] & 0xfe; int x = door_open_closed_counter; if (x == 0 || x == 4) { DrawDoorToTileMap_West(door, r4_door); return; } x += (door_type >= 0x42) ? 4 : 0; x += (door_type == kDoorType_ShuttersTwoWay || door_type == kDoorType_Shutter) ? 2 : 0; Object_Draw_DoorLeft_3x4(kDoorAnimLeftSrc[x >> 1], door); } void DrawDoorToTileMap_West(int door, int r4_door) { // 81fc45 Object_Draw_DoorLeft_3x4(kDoorTypeSrcData3[GetDoorGraphicsIndex(door, r4_door) >> 1], door); } void GetDoorDrawDataIndex_East_clean_door_index(int door) { // 81fc80 GetDoorDrawDataIndex_East(door, door); } int DoorDoorStep1_East(int door, int dma_ptr) { // 81fc8a int pos = dung_door_tilemap_address[door]; if ((pos & 0x7ff) < kDoorPositionToTilemapOffs_Right[6]) { pos += 16; if ((door_type_and_slot[door] & 0xfe) >= 0x42) pos += 12; GetDoorDrawDataIndex_West(door ^ 8, door & 7); dma_ptr = Dungeon_PrepOverlayDma_nextPrep(dma_ptr, pos); Dungeon_LoadSingleDoorAttribute(door ^ 8); } GetDoorDrawDataIndex_East(door, door & 7); return dma_ptr; } void GetDoorDrawDataIndex_East(int door, int r4_door) { // 81fcd6 uint8 door_type = door_type_and_slot[door] & 0xfe; int x = door_open_closed_counter; if (x == 0 || x == 4) { DrawDoorToTileMap_East(door, r4_door); return; } x += (door_type >= 0x42) ? 4 : 0; x += (door_type == kDoorType_ShuttersTwoWay || door_type == kDoorType_Shutter) ? 2 : 0; Object_Draw_DoorRight_3x4(kDoorAnimRightSrc[x >> 1], door); } void DrawDoorToTileMap_East(int door, int r4_door) { // 81fd03 Object_Draw_DoorRight_3x4(kDoorTypeSrcData4[GetDoorGraphicsIndex(door, r4_door) >> 1], door); } uint8 GetDoorGraphicsIndex(int door, int r4_door) { // 81fd79 uint8 door_type = door_type_and_slot[door] & 0xfe; if (dung_door_opened_incl_adjacent & kUpperBitmasks[r4_door]) door_type = kDoorTypeRemap[door_type >> 1]; return door_type; } void ClearExplodingWallFromTileMap_ClearOnePair(uint16 *dst, const uint16 *src) { // 81fddb for (int i = 2; i != 0; i--) { for (int j = 0; j < 12; j++) dst[XY(0, j)] = src[j]; dst++; src += 12; } } void Dungeon_DrawRoomOverlay_Apply(int p) { // 81fe41 for (int j = 0; j < 4; j++, p += 64) { for (int i = 0; i < 4; i++) { uint16 t = dung_bg2[p + i] & 0x3fe; dung_bg2_attr_table[p + i] = (t == 0xee || t == 0xfe) ? 0 : 0x20; } } } void ApplyGrayscaleFixed_Incremental() { // 81feb0 uint8 a = COLDATA_copy0 & 0x1f; if (a == overworld_fixed_color_plusminus) return; a += (a < overworld_fixed_color_plusminus) ? 1 : -1; Dungeon_ApproachFixedColor_variable(a); } void Dungeon_ApproachFixedColor_variable(uint8 a) { // 81fec1 COLDATA_copy0 = a | 0x20; COLDATA_copy1 = a | 0x40; COLDATA_copy2 = a | 0x80; } void Module_PreDungeon() { // 82821e sound_effect_ambient = 5; sound_effect_1 = 0; dungeon_room_index = 0; dungeon_room_index_prev = 0; dung_savegame_state_bits = 0; agahnim_pal_setting[0] = agahnim_pal_setting[1] = agahnim_pal_setting[2] = 0; agahnim_pal_setting[3] = agahnim_pal_setting[4] = agahnim_pal_setting[5] = 0; Dungeon_LoadEntrance(); uint8 d = cur_palace_index_x2; link_num_keys = (d != 0xff) ? link_keys_earned_per_dungeon[d == 2 ? 0 : (d >> 1)] : 0xff; Hud_Rebuild(); dung_num_lit_torches = 0; hdr_dungeon_dark_with_lantern = 0; Dungeon_LoadAndDrawRoom(); Dungeon_LoadCustomTileAttr(); DecompressAnimatedDungeonTiles(kDungAnimatedTiles[main_tile_theme_index]); Dungeon_LoadAttributeTable(); misc_sprites_graphics_index = 10; InitializeTilesets(); palette_sp6 = 10; Dungeon_LoadPalettes(); if (link_is_bunny_mirror | link_is_bunny) LoadGearPalettes_bunny(); dung_loade_bgoffs_h_copy = (dungeon_room_index & 0xf) << 9; dung_loade_bgoffs_v_copy = swap16((dungeon_room_index & 0xff0) >> 3); if (dungeon_room_index == 0x104 && sram_progress_flags & 0x10) WORD(dung_want_lights_out) = 0; SetAndSaveVisitedQuadrantFlags(); CGWSEL_copy = 2; CGADSUB_copy = 0xb3; uint8 x = dung_num_lit_torches; if (!dung_want_lights_out) { x = 3; CGADSUB_copy = dung_hdr_bg2_properties == 7 ? 0x32 : dung_hdr_bg2_properties == 4 ? 0x62 : 0x20; } overworld_fixed_color_plusminus = kLitTorchesColorPlus[x]; Dungeon_ApproachFixedColor_variable(overworld_fixed_color_plusminus); BYTE(palette_filter_countdown) = 0x1f; mosaic_target_level = 0; BYTE(darkening_or_lightening_screen) = 2; overworld_palette_aux_or_main = 0; link_speed_modifier = 0; button_mask_b_y = 0; button_b_frames = 0; Dungeon_ResetTorchBackgroundAndPlayer(); Link_CheckBunnyStatus(); ResetThenCacheRoomEntryProperties(); if (follower_indicator == 13) { follower_indicator = 0; super_bomb_indicator_unk2 = 0; Hud_RemoveSuperBombIndicator(); } BGMODE_copy = 9; Follower_Initialize(); Sprite_ResetAll(); Dungeon_ResetSprites(); byte_7E02F0 = 0; flag_skip_call_tag_routines++; if (!sram_progress_indicator && !(sram_progress_flags & 0x10)) { COLDATA_copy0 = 0x30; COLDATA_copy1 = 0x50; COLDATA_copy2 = 0x80; dung_want_lights_out = dung_want_lights_out_copy = 0; Link_TuckIntoBed(); } saved_module_for_menu = 7; main_module_index = 7; submodule_index = 15; Dungeon_LoadSongBankIfNeeded(); Module_PreDungeon_setAmbientSfx(); } void Module_PreDungeon_setAmbientSfx() { // 82838c if (sram_progress_indicator < 2) { sound_effect_ambient = 5; if (!sign8(dung_cur_floor) && dungeon_room_index != 2 && dungeon_room_index != 18) sound_effect_ambient = 3; } } void LoadOWMusicIfNeeded() { // 82854c if (!flag_which_music_type) return; zelda_snes_dummy_write(NMITIMEN, 0); zelda_snes_dummy_write(HDMAEN, 0); flag_which_music_type = 0; LoadOverworldSongs(); zelda_snes_dummy_write(NMITIMEN, 0x81); } void Module07_Dungeon() { // 8287a2 Dungeon_HandleLayerEffect(); kDungeonSubmodules[submodule_index](); // When having the somaria on door button and exiting in skull woods, // don't overwrite submodule_index if (enhanced_features0 & kFeatures0_MiscBugFixes && main_module_index != 7) goto skip; dung_misc_objs_index = 0; Dungeon_PushBlock_Handler(); if (submodule_index) goto skip; Graphics_LoadChrHalfSlot(); Dungeon_HandleCamera(); if (submodule_index) goto skip; Dungeon_HandleRoomTags(); if (submodule_index) goto skip; Dungeon_ProcessTorchesAndDoors(); if (dung_unk_blast_walls_2) Dungeon_ClearAwayExplodingWall(); if (!is_standing_in_doorway) Dungeon_TryScreenEdgeTransition(); skip: OrientLampLightCone(); int bg2x = BG2HOFS_copy2; int bg2y = BG2VOFS_copy2; int bg1x = BG1HOFS_copy2; int bg1y = BG1VOFS_copy2; BG2HOFS_copy2 = BG2HOFS_copy = bg2x + bg1_x_offset; BG2VOFS_copy2 = BG2VOFS_copy = bg2y + bg1_y_offset; BG1HOFS_copy2 = BG1HOFS_copy = bg1x + bg1_x_offset; BG1VOFS_copy2 = BG1VOFS_copy = bg1y + bg1_y_offset; if (dung_hdr_collision_2_mirror) { BG1HOFS_copy2 = BG1HOFS_copy = bg1x = BG2HOFS_copy2 + dung_floor_x_offs; BG1VOFS_copy2 = BG1VOFS_copy = bg1y = BG2VOFS_copy2 + dung_floor_y_offs; } Sprite_Dungeon_DrawAllPushBlocks(); Sprite_Main(); BG2HOFS_copy2 = bg2x; BG2VOFS_copy2 = bg2y; BG1HOFS_copy2 = bg1x; BG1VOFS_copy2 = bg1y; LinkOam_Main(); Hud_RefillLogic(); Hud_FloorIndicator(); } void Dungeon_TryScreenEdgeTransition() { // 82885e int dir; if (link_y_vel != 0) { int y = (link_y_coord & 0x1ff); if ((dir = 3, y < 4) || (dir = 2, y >= 476)) goto trigger_trans; } if (link_x_vel != 0) { int y = (link_x_coord & 0x1ff); if ((dir = 1, y < 8) || (dir = 0, y >= 489)) goto trigger_trans; } return; trigger_trans: if (!Link_CheckForEdgeScreenTransition() && main_module_index == 7) { Dungeon_HandleEdgeTransitionMovement(dir); if (main_module_index == 7) submodule_index = 2; } } void Dungeon_HandleEdgeTransitionMovement(int dir) { // 8288c5 static const uint8 kLimitDirectionOnOneAxis[] = { 0x3, 0x3, 0xc, 0xc }; link_direction &= kLimitDirectionOnOneAxis[dir]; switch (dir) { case 0: Dungeon_StartInterRoomTrans_Right(); break; case 1: Dungeon_StartInterRoomTrans_Left(); break; case 2: Dungeon_StartInterRoomTrans_Down(); break; case 3: Dungeon_StartInterRoomTrans_Up(); break; default: assert(0); } } void Module07_00_PlayerControl() { // 8288de if (!(flag_custom_spell_anim_active | flag_is_link_immobilized | flag_block_link_menu)) { if (filtered_joypad_H & 0x10) { // start overworld_map_state = 0; submodule_index = 1; saved_module_for_menu = main_module_index; main_module_index = 14; return; } else if (DidPressButtonForMap()) { // x if ((uint8)cur_palace_index_x2 != 0xff && (uint8)dungeon_room_index) { overworld_map_state = 0; submodule_index = 3; saved_module_for_menu = main_module_index; main_module_index = 14; return; } } else if (joypad1H_last & 0x20) { // select if (sram_progress_indicator) { overworld_map_state = 0; DisplaySelectMenu(); return; } } Hud_HandleItemSwitchInputs(); } Link_Main(); } void Module07_01_SubtileTransition() { // 82897c link_y_coord_prev = link_y_coord; link_x_coord_prev = link_x_coord; Link_HandleMovingAnimation_FullLongEntry(); kDungeon_IntraRoomTrans[subsubmodule_index](); } void DungeonTransition_Subtile_ResetShutters() { // 828995 BYTE(dung_flag_trapdoors_down) = 0; BYTE(door_animation_step_indicator) = 7; uint8 bak = submodule_index; OperateShutterDoors(); submodule_index = bak; BYTE(palette_filter_countdown) = 31; mosaic_target_level = 0; subsubmodule_index++; } void DungeonTransition_Subtile_PrepTransition() { // 8289b6 darkening_or_lightening_screen = 0; palette_filter_countdown = 0; mosaic_target_level = 31; unused_config_gfx = 0; dung_flag_somaria_block_switch = 0; dung_flag_statechange_waterpuzzle = 0; subsubmodule_index++; } void DungeonTransition_Subtile_ApplyFilter() { // 8289d8 if (!dung_want_lights_out) { subsubmodule_index++; return; } ApplyPaletteFilter_bounce(); if (BYTE(palette_filter_countdown)) ApplyPaletteFilter_bounce(); } void DungeonTransition_Subtile_TriggerShutters() { // 8289f0 ResetThenCacheRoomEntryProperties(); if (!BYTE(dung_flag_trapdoors_down)) { BYTE(dung_flag_trapdoors_down)++; BYTE(dung_cur_door_pos) = 0; BYTE(door_animation_step_indicator) = 0; submodule_index = 5; } } void Module07_02_SupertileTransition() { // 828a26 link_y_coord_prev = link_y_coord; link_x_coord_prev = link_x_coord; if (subsubmodule_index != 0) { if (subsubmodule_index >= 7) Graphics_IncrementalVRAMUpload(); Dungeon_LoadAttribute_Selectable(); } Link_HandleMovingAnimation_FullLongEntry(); kDungeon_InterRoomTrans[subsubmodule_index](); } void Module07_02_00_InitializeTransition() { // 828a4f uint8 bak = hdr_dungeon_dark_with_lantern; ResetTransitionPropsAndAdvanceSubmodule(); hdr_dungeon_dark_with_lantern = bak; } void Module07_02_01_LoadNextRoom() { // 828a5b Dungeon_LoadRoom(); ResetStarTileGraphics(); LoadTransAuxGFX_sprite(); subsubmodule_index++; overworld_map_state = 0; BYTE(dungeon_room_index2) = BYTE(dungeon_room_index); Dungeon_ResetSprites(); if (!hdr_dungeon_dark_with_lantern) MirrorBg1Bg2Offs(); hdr_dungeon_dark_with_lantern = 0; } void Dungeon_InterRoomTrans_State3() { // 828a87 if (dung_want_lights_out | dung_want_lights_out_copy) TS_copy = 0; Dungeon_AdjustForRoomLayout(); LoadNewSpriteGFXSet(); MirrorBg1Bg2Offs(); WaterFlood_BuildOneQuadrantForVRAM(); subsubmodule_index++; } void Dungeon_InterRoomTrans_State10() { // 828aa5 if (dung_want_lights_out | dung_want_lights_out_copy) ApplyPaletteFilter_bounce(); Dungeon_InterRoomTrans_notDarkRoom(); } void Dungeon_SpiralStaircase11() { // 828aaf ApplyPaletteFilter_bounce(); WaterFlood_BuildOneQuadrantForVRAM(); subsubmodule_index++; } void Dungeon_InterRoomTrans_notDarkRoom() { // 828ab3 WaterFlood_BuildOneQuadrantForVRAM(); subsubmodule_index++; } void Dungeon_InterRoomTrans_State9() { // 828aba if (dung_want_lights_out | dung_want_lights_out_copy) ApplyPaletteFilter_bounce(); Dungeon_InterRoomTrans_State4(); } void Dungeon_SpiralStaircase12() { // 828ac4 ApplyPaletteFilter_bounce(); Dungeon_PrepareNextRoomQuadrantUpload(); subsubmodule_index++; } void Dungeon_InterRoomTrans_State4() { // 828ac8 Dungeon_PrepareNextRoomQuadrantUpload(); subsubmodule_index++; } void Dungeon_InterRoomTrans_State12() { // 828acf if (submodule_index == 2) { if (overworld_map_state != 5) return; SubtileTransitionCalculateLanding(); if (dung_want_lights_out | dung_want_lights_out_copy) ApplyPaletteFilter_bounce(); } subsubmodule_index++; Dungeon_ResetTorchBackgroundAndPlayer(); } void Dungeon_Staircase14() { // 828aed subsubmodule_index++; Dungeon_ResetTorchBackgroundAndPlayer(); } void Dungeon_ResetTorchBackgroundAndPlayer() { // 828aef uint8 ts = kSpiralTab1[dung_hdr_bg2_properties], tm = 0x16; if (sign8(ts)) tm = 0x17, ts = 0; if (dung_hdr_bg2_properties == 2) ts = 3; TM_copy = tm; TS_copy = ts; Hud_RestoreTorchBackground(); Dungeon_ResetTorchBackgroundAndPlayerInner(); } void Dungeon_ResetTorchBackgroundAndPlayerInner() { // 828b0c Ancilla_TerminateSelectInteractives(0); if (link_is_running && !(enhanced_features0 & kFeatures0_TurnWhileDashing)) { link_auxiliary_state = 0; link_incapacitated_timer = 0; link_actual_vel_z = 0xff; g_ram[0xc7] = 0xff; link_delay_timer_spin_attack = 0; link_speed_setting = 0; swimcoll_var5[0] &= ~0xff; link_is_running = 0; link_player_handler_state = 0; } } void Dungeon_InterRoomTrans_State7() { // 828b2e BG1HOFS_copy2 = BG2HOFS_copy2; BG1VOFS_copy2 = BG2VOFS_copy2; if (dungeon_room_index != 54 && dungeon_room_index != 56) { uint16 y = kSpiralTab1[dung_hdr_bg2_properties] ? 0x116 : 0x16; if (y != (TM_copy | TS_copy << 8) && (TM_copy == 0x17 || (TM_copy | TS_copy) != 0x17)) TM_copy = y, TS_copy = y >> 8; } DungeonTransition_RunFiltering(); } void DungeonTransition_RunFiltering() { // 828b67 if (dung_want_lights_out | dung_want_lights_out_copy) { overworld_fixed_color_plusminus = kLitTorchesColorPlus[dung_want_lights_out ? dung_num_lit_torches : 3]; Dungeon_ApproachFixedColor_variable(overworld_fixed_color_plusminus); mosaic_target_level = 0; } Dungeon_HandleTranslucencyAndPalette(); } void Module07_02_FadedFilter() { // 828b92 if (dung_want_lights_out | dung_want_lights_out_copy) { ApplyPaletteFilter_bounce(); if (BYTE(palette_filter_countdown)) ApplyPaletteFilter_bounce(); } else { subsubmodule_index++; } } void Dungeon_InterRoomTrans_State15() { // 828bae ResetThenCacheRoomEntryProperties(); if (!BYTE(dung_flag_trapdoors_down) && (BYTE(dungeon_room_index) != 172 || dung_savegame_state_bits & 0x3000)) { BYTE(dung_flag_trapdoors_down) = 1; BYTE(dung_cur_door_pos) = 0; BYTE(door_animation_step_indicator) = 0; submodule_index = 5; } Dungeon_PlayMusicIfDefeated(); } void Dungeon_PlayMusicIfDefeated() { // 828bd7 uint8 x = 0x14; if (dungeon_room_index != 18) { x = 0x10; if (dungeon_room_index != 2) { if (FindInWordArray(kBossRooms, dungeon_room_index, countof(kBossRooms)) < 0) return; if (Sprite_CheckIfScreenIsClear()) return; x = 0x15; } } music_control = x; } void Module07_03_OverlayChange() { // 828c05 const uint8 *overlay_p = kDungeonRoomOverlay + kDungeonRoomOverlayOffs[dung_overlay_to_load]; Dungeon_DrawRoomOverlay(overlay_p); int dst_pos = 0; for (;;) { uint16 a = WORD(*overlay_p); if (a == 0xffff) break; int p = (overlay_p[0] >> 2) | (overlay_p[1] >> 2) << 6; dst_pos = Dungeon_PrepOverlayDma_nextPrep(dst_pos, p * 2); Dungeon_DrawRoomOverlay_Apply(p); overlay_p += 3; } nmi_copy_packets_flag = 1; submodule_index = 0; } void Module07_04_UnlockDoor() { // 828c0a Dungeon_OpeningLockedDoor_Combined(false); } void Module07_05_ControlShutters() { // 828c0f OperateShutterDoors(); } void Module07_06_FatInterRoomStairs() { // 828c14 if (subsubmodule_index >= 3) Dungeon_LoadAttribute_Selectable(); if (subsubmodule_index >= 13) { Graphics_IncrementalVRAMUpload(); if (!staircase_var1) goto table; if (staircase_var1-- == 0x10) link_speed_modifier = 2; link_direction = which_staircase_index & 4 ? 4 : 8; Link_HandleVelocity(); Dungeon_HandleCamera(); } Link_HandleMovingAnimation_FullLongEntry(); table: switch (subsubmodule_index) { case 0: ResetTransitionPropsAndAdvance_ResetInterface(); break; case 1: ApplyPaletteFilter_bounce(); if (BYTE(palette_filter_countdown)) ApplyPaletteFilter_bounce(); break; case 2: Dungeon_InitializeRoomFromSpecial(); break; case 3: DungeonTransition_TriggerBGC34UpdateAndAdvance(); break; case 4: DungeonTransition_TriggerBGC56UpdateAndAdvance(); break; case 5: DungeonTransition_LoadSpriteGFX(); break; case 6: DungeonTransition_AdjustForFatStairScroll(); break; case 7: Dungeon_InterRoomTrans_State4(); break; case 8: Dungeon_InterRoomTrans_notDarkRoom(); break; case 9: Dungeon_InterRoomTrans_State4(); break; case 10: Dungeon_SpiralStaircase11(); break; case 11: Dungeon_SpiralStaircase12(); break; case 12: Dungeon_SpiralStaircase11(); break; case 13: Dungeon_SpiralStaircase12(); break; case 14: Dungeon_DoubleApplyAndIncrementGrayscale(); break; case 15: Dungeon_Staircase14(); break; case 16: if (!(BYTE(darkening_or_lightening_screen) | BYTE(palette_filter_countdown)) && overworld_map_state == 5) ResetThenCacheRoomEntryProperties(); break; } } void Module07_0E_01_HandleMusicAndResetProps() { // 828c78 if ((dungeon_room_index == 7 || dungeon_room_index == 23 && music_unk1 != 17) && !(link_which_pendants & 1)) music_control = 0xf1; staircase_var1 = (which_staircase_index & 4) ? 106 : 88; overworld_map_state = 0; ResetTransitionPropsAndAdvanceSubmodule(); } void ResetTransitionPropsAndAdvance_ResetInterface() { // 828ca9 overworld_map_state = 0; ResetTransitionPropsAndAdvanceSubmodule(); } void ResetTransitionPropsAndAdvanceSubmodule() { // 828cac WORD(mosaic_level) = 0; darkening_or_lightening_screen = 0; palette_filter_countdown = 0; mosaic_target_level = 31; unused_config_gfx = 0; dung_num_lit_torches = 0; if (hdr_dungeon_dark_with_lantern) { CGWSEL_copy = 0x02; CGADSUB_copy = 0xB3; } hdr_dungeon_dark_with_lantern = 0; Dungeon_ResetTorchBackgroundAndPlayerInner(); Overworld_CopyPalettesToCache(); subsubmodule_index += 1; } void Dungeon_InitializeRoomFromSpecial() { // 828ce2 Dungeon_AdjustAfterSpiralStairs(); Dungeon_LoadRoom(); ResetStarTileGraphics(); LoadTransAuxGFX(); Dungeon_LoadCustomTileAttr(); BYTE(dungeon_room_index2) = BYTE(dungeon_room_index); Follower_Initialize(); subsubmodule_index += 1; } void DungeonTransition_LoadSpriteGFX() { // 828d10 LoadNewSpriteGFXSet(); Dungeon_ResetSprites(); DungeonTransition_RunFiltering(); } void DungeonTransition_AdjustForFatStairScroll() { // 828d1b MirrorBg1Bg2Offs(); Dungeon_AdjustForRoomLayout(); uint8 ts = kSpiralTab1[dung_hdr_bg2_properties]; uint8 tm = 0x16; if (sign8(ts)) tm = 0x17, ts = 0; TM_copy = tm; TS_copy = ts; link_speed_modifier = 1; if (which_staircase_index & 4) { dung_cur_floor--; staircase_var1 = 32; sound_effect_1 = 0x19; } else { dung_cur_floor++; staircase_var1 = 48; sound_effect_1 = 0x17; } sound_effect_2 = 0x24; Dungeon_PlayBlipAndCacheQuadrantVisits(); Dungeon_InterRoomTrans_notDarkRoom(); } void ResetThenCacheRoomEntryProperties() { // 828d71 overworld_map_state = 0; subsubmodule_index = 0; overworld_screen_transition = 0; submodule_index = 0; dung_flag_statechange_waterpuzzle = 0; dung_flag_movable_block_was_pushed = 0; CacheCameraProperties(); } void DungeonTransition_TriggerBGC34UpdateAndAdvance() { // 828e0f PrepTransAuxGfx(); nmi_subroutine_index = nmi_disable_core_updates = 9; subsubmodule_index += 1; } void DungeonTransition_TriggerBGC56UpdateAndAdvance() { // 828e1d nmi_subroutine_index = nmi_disable_core_updates = 10; subsubmodule_index += 1; } void Module07_07_FallingTransition() { // 828e27 if (subsubmodule_index >= 6) { Graphics_IncrementalVRAMUpload(); Dungeon_LoadAttribute_Selectable(); ApplyGrayscaleFixed_Incremental(); } kDungeon_Submodule_7_DownFloorTrans[subsubmodule_index](); } void Module07_07_00_HandleMusicAndResetRoom() { // 828e63 if (dungeon_room_index == 0x10 || dungeon_room_index == 7 || dungeon_room_index == 0x17) music_control = 0xf1; ResetTransitionPropsAndAdvance_ResetInterface(); } void Module07_07_06_SyncBG1and2() { // 828e80 MirrorBg1Bg2Offs(); Dungeon_AdjustForRoomLayout(); uint8 ts = kSpiralTab1[dung_hdr_bg2_properties]; uint8 tm = 0x16; if (sign8(ts)) tm = 0x17, ts = 0; TM_copy = tm; TS_copy = ts; WaterFlood_BuildOneQuadrantForVRAM(); subsubmodule_index++; } void Module07_07_0F_FallingFadeIn() { // 828ea1 ApplyPaletteFilter_bounce(); if (BYTE(darkening_or_lightening_screen)) return; HIBYTE(tiledetect_which_y_pos[0]) = HIBYTE(link_y_coord) + (BYTE(link_y_coord) >= BYTE(tiledetect_which_y_pos[0])); Dungeon_SetBossMusicUnorthodox(); if (BYTE(dungeon_room_index) == 0x89 || BYTE(dungeon_room_index) == 0x4f) return; if (BYTE(dungeon_room_index) == 0xA7) { hud_floor_changed_timer = 0; dung_cur_floor = 1; return; } dung_cur_floor--; Dungeon_PlayBlipAndCacheQuadrantVisits(); } void Dungeon_PlayBlipAndCacheQuadrantVisits() { // 828ec9 hud_floor_changed_timer = 1; sound_effect_2 = 36; SetAndSaveVisitedQuadrantFlags(); } void Module07_07_10_LandLinkFromFalling() { // 828ee0 HandleDungeonLandingFromPit(); if (submodule_index) return; submodule_index = 7; subsubmodule_index = 17; load_chr_halfslot_even_odd = 1; Graphics_LoadChrHalfSlot(); } void Module07_07_11_CacheRoomAndSetMusic() { // 828efa if (overworld_map_state == 5) { ResetThenCacheRoomEntryProperties(); Dungeon_PlayMusicIfDefeated(); Graphics_LoadChrHalfSlot(); } } // straight staircase going down when walking south void Module07_08_NorthIntraRoomStairs() { // 828f0c uint8 t = staircase_var1; if (t) { staircase_var1--; if (t == 20) link_speed_modifier = 2; Link_HandleVelocity(); ApplyLinksMovementToCamera(); Dungeon_HandleCamera(); Link_HandleMovingAnimation_FullLongEntry(); } kDungeon_StraightStaircaseDown[subsubmodule_index](); } void Module07_08_00_InitStairs() { // 828f35 draw_water_ripples_or_grass = 0; uint8 v1 = 0x3c, sfx = 25; if (link_direction & 8) { v1 = 0x38, sfx = 23; link_is_on_lower_level_mirror = 0; if ((uint8)kind_of_in_room_staircase != 2) link_is_on_lower_level = 0; } staircase_var1 = v1; sound_effect_1 = sfx; link_speed_modifier = 1; subsubmodule_index++; } void Module07_08_01_ClimbStairs() { // 828f5f if (staircase_var1) return; if (link_direction & 4) { link_is_on_lower_level_mirror = 1; if ((uint8)kind_of_in_room_staircase != 2) link_is_on_lower_level = 1; } subsubmodule_index = 0; overworld_screen_transition = 0; submodule_index = 0; SetAndSaveVisitedQuadrantFlags(); } // straight staircase going up when walking south void Module07_10_SouthIntraRoomStairs() { // 828f88 uint8 t = staircase_var1; if (t) { staircase_var1--; if (t == 20) link_speed_modifier = 2; Link_HandleVelocity(); ApplyLinksMovementToCamera(); Dungeon_HandleCamera(); Link_HandleMovingAnimation_FullLongEntry(); } kDungeon_StraightStaircase[subsubmodule_index](); } void Module07_10_00_InitStairs() { // 828fb1 uint8 v1 = 0x3c, sfx = 25; if (link_direction & 4) { v1 = 0x38, sfx = 23; link_is_on_lower_level_mirror ^= 1; if ((uint8)kind_of_in_room_staircase != 2) link_is_on_lower_level ^= 1; } staircase_var1 = v1; sound_effect_1 = sfx; link_speed_modifier = 1; subsubmodule_index++; } void Module07_10_01_ClimbStairs() { // 828fe1 if (staircase_var1) return; if (link_direction & 8) { link_is_on_lower_level_mirror ^= 1; if ((uint8)kind_of_in_room_staircase != 2) link_is_on_lower_level ^= 1; } subsubmodule_index = 0; overworld_screen_transition = 0; submodule_index = 0; SetAndSaveVisitedQuadrantFlags(); } void Module07_09_OpenCrackedDoor() { // 82900f OpenCrackedDoor(); } // Used when lighting a lamp void Module07_0A_ChangeBrightness() { // 829014 OrientLampLightCone(); ApplyGrayscaleFixed_Incremental(); if ((COLDATA_copy0 & 0x1f) != overworld_fixed_color_plusminus) return; submodule_index = 0; subsubmodule_index = 0; } void Module07_0B_DrainSwampPool() { // 82902d static const int8 kTurnOffWater_Tab0[16] = { -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1 }; switch (subsubmodule_index) { case 0: { if (!(turn_on_off_water_ctr & 7)) { int k = (turn_on_off_water_ctr >> 2) & 3; if (water_hdma_var2 == water_hdma_var4) { Dungeon_SetAttrForActivatedWaterOff(); return; } water_hdma_var2 += kTurnOffWater_Tab0[k]; water_hdma_var3 += kTurnOffWater_Tab0[k]; } turn_on_off_water_ctr++; AdjustWaterHDMAWindow(); break; } case 1: { uint16 v = SrcPtr(0x1e0)[0]; for (int i = 0; i < 0x1000; i++) dung_bg1[i] = v; dung_cur_quadrant_upload = 0; subsubmodule_index++; break; } case 2: case 3: case 4: case 5: Dungeon_FloodSwampWater_PrepTileMap(); break; } } void Module07_0C_FloodSwampWater() { // 82904a int k; static const int8 kTurnOnWater_Tab2[4] = { 1, 1, 1, -1 }; static const int8 kTurnOnWater_Tab1[4] = { 1, 2, 1, -1 }; static const int8 kTurnOnWater_Tab0[4] = { 1, -1, 1, -1 }; switch (subsubmodule_index) { case 0: case 1: case 2: case 3: Dungeon_FloodSwampWater_PrepTileMap(); break; case 4: case 5: case 6: case 7: case 8: if (!--turn_on_off_water_ctr) { turn_on_off_water_ctr = 4; int depth = ++subsubmodule_index - 4; water_hdma_var3 = 8; water_hdma_var5 = 0; water_hdma_var2 = 0x30; Dungeon_AdjustWaterVomit(SrcPtr(0x1654 + 0x10), depth); } break; case 9: W12SEL_copy = 3; W34SEL_copy = 0; WOBJSEL_copy = 0; TMW_copy = 22; TSW_copy = 1; TS_copy = 1; CGWSEL_copy = 2; CGADSUB_copy = 98; turn_on_off_water_ctr = 0; subsubmodule_index++; // fall through case 10: { k = (turn_on_off_water_ctr & 3); uint16 r0 = 0x688 - BG2VOFS_copy2 - 0x24; water_hdma_var3 += kTurnOnWater_Tab0[k]; water_hdma_var5 += kTurnOnWater_Tab1[k]; if (water_hdma_var5 >= r0) { dung_hdr_bg2_properties = 7; subsubmodule_index++; } turn_on_off_water_ctr++; spotlight_y_lower = 0x688 - BG2VOFS_copy2 - water_hdma_var2; spotlight_y_upper = spotlight_y_lower + water_hdma_var5; AdjustWaterHDMAWindow_X(spotlight_y_upper); break; } case 11: { if (!(turn_on_off_water_ctr & 7)) { k = (turn_on_off_water_ctr >> 2) & 3; if (water_hdma_var2 == water_hdma_var4) { Dungeon_SetAttrForActivatedWater(); return; } water_hdma_var2 += kTurnOnWater_Tab2[k]; water_hdma_var3 += kTurnOnWater_Tab2[k]; uint16 a = water_hdma_var4 - water_hdma_var2; if (a == 0 || a == 8) Dungeon_AdjustWaterVomit(SrcPtr(a == 0 ? 0x16b4 : 0x168c), 5); } turn_on_off_water_ctr++; AdjustWaterHDMAWindow(); break; } } } void Module07_0D_FloodDam() { // 82904f FloodDam_PrepFloodHDMA(); kWatergateFuncs[subsubmodule_index](); } void Module07_0E_SpiralStairs() { // 829054 if (subsubmodule_index >= 7) { Graphics_IncrementalVRAMUpload(); Dungeon_LoadAttribute_Selectable(); } HandleLinkOnSpiralStairs(); kDungeon_SpiralStaircase[subsubmodule_index](); } void Dungeon_DoubleApplyAndIncrementGrayscale() { // 829094 ApplyPaletteFilter_bounce(); ApplyPaletteFilter_bounce(); ApplyGrayscaleFixed_Incremental(); } void Module07_0E_02_ApplyFilterIf() { // 8290a1 if (staircase_var1 < 9) { ApplyPaletteFilter_bounce(); if (palette_filter_countdown) ApplyPaletteFilter_bounce(); } if (staircase_var1 != 0) { staircase_var1--; return; } tagalong_var5 = link_visibility_status = 12; } void Dungeon_SyncBackgroundsFromSpiralStairs() { // 8290c7 if (follower_indicator == 6 && BYTE(dungeon_room_index) == 100) follower_indicator = 0; uint8 bak = link_is_on_lower_level; link_y_coord += which_staircase_index & 4 ? 48 : -48; link_is_on_lower_level = kTeleportPitLevel2[cur_staircase_plane]; SpiralStairs_MakeNearbyWallsHighPriority_Exiting(); link_is_on_lower_level = bak; link_y_coord += which_staircase_index & 4 ? -48 : 48; BG1HOFS_copy2 = BG2HOFS_copy2; BG1VOFS_copy2 = BG2VOFS_copy2; Dungeon_AdjustForRoomLayout(); uint8 ts = kSpiralTab1[dung_hdr_bg2_properties], tm = 0x16; if (sign8(ts)) tm = 0x17, ts = 0; if (dung_hdr_bg2_properties == 2) ts = 3; TM_copy = tm; TS_copy = ts; dung_cur_floor += (which_staircase_index & 4) ? -1 : 1; staircase_var1 = 24; Dungeon_PlayBlipAndCacheQuadrantVisits(); Hud_RestoreTorchBackground(); Dungeon_InterRoomTrans_notDarkRoom(); } void Dungeon_AdvanceThenSetBossMusicUnorthodox() { // 82915b Dungeon_ResetTorchBackgroundAndPlayerInner(); staircase_var1 = 0x38; subsubmodule_index++; Dungeon_SetBossMusicUnorthodox(); } void Dungeon_SetBossMusicUnorthodox() { // 829165 uint8 x = 0x1c; if (dungeon_room_index != 16) { x = 0x15; if (dungeon_room_index != 7) { x = 0x11; if (dungeon_room_index != 23 || music_unk1 == 17) return; } if (music_unk1 != 0xf1 && (link_which_pendants & 1)) return; } music_control = x; } void Dungeon_SpiralStaircase17() { // 82919b SpiralStairs_FindLandingSpot(); if (!--staircase_var1) { staircase_var1 = which_staircase_index & 4 ? 10 : 24; subsubmodule_index++; } } void Dungeon_SpiralStaircase18() { // 8291b5 SpiralStairs_FindLandingSpot(); if (!--staircase_var1) { subsubmodule_index++; overworld_map_state = 0; } } void Module07_0E_00_InitPriorityAndScreens() { // 8291c4 SpiralStairs_MakeNearbyWallsHighPriority_Entering(); if (link_is_on_lower_level) { TM_copy &= 0xf; TS_copy |= 0x10; link_is_on_lower_level = 3; } subsubmodule_index++; } void Module07_0E_13_SetRoomAndLayerAndCache() { // 8291dd link_is_on_lower_level_mirror = kTeleportPitLevel1[cur_staircase_plane]; link_is_on_lower_level = kTeleportPitLevel2[cur_staircase_plane]; TM_copy |= 0x10; TS_copy &= 0xf; if (!(which_staircase_index & 4)) SpiralStairs_MakeNearbyWallsLowPriority(); BYTE(dungeon_room_index2) = BYTE(dungeon_room_index); ResetThenCacheRoomEntryProperties(); } void RepositionLinkAfterSpiralStairs() { // 82921a link_visibility_status = 0; tagalong_var5 = 0; int i = (cur_staircase_plane == 0 && byte_7E0492 != 0) ? 1 : 0; i += (which_staircase_index & 4) ? 2 : 0; link_x_coord += kSpiralStaircaseX[i]; link_y_coord += kSpiralStaircaseY[i]; if (TM_copy & 0x10) { if (cur_staircase_plane == 2) { link_is_on_lower_level = 3; TM_copy &= 0xf; TS_copy |= 0x10; if (byte_7E0492 != 2) link_y_coord += 24; } Follower_Initialize(); } else { if (cur_staircase_plane != 2) { TM_copy |= 0x10; TS_copy &= 0xf; if (byte_7E0492 != 2) link_y_coord -= 24; } Follower_Initialize(); } } void SpiralStairs_MakeNearbyWallsHighPriority_Exiting() { // 8292b1 if (which_staircase_index & 4) return; int lf = (word_7E048C + 8) & 0x7f; int x = 0, p; while ((((p = dung_inter_starcases[x]) * 2) & 0x7f) != lf) x++; p -= 4; word_7E048C = p * 2; uint16 *dst = &dung_bg2[p]; for (int i = 0; i < 5; i++) { dst[XY(0, 0)] |= 0x2000; dst[XY(0, 1)] |= 0x2000; dst[XY(0, 2)] |= 0x2000; dst[XY(0, 3)] |= 0x2000; dst += 1; } } void Module07_0F_LandingWipe() { // 82931d kDungeon_Submodule_F[subsubmodule_index](); Link_HandleMovingAnimation_FullLongEntry(); LinkOam_Main(); } void Module07_0F_00_InitSpotlight() { // 82932d Spotlight_open(); subsubmodule_index++; } void Module07_0F_01_OperateSpotlight() { // 829334 Sprite_Main(); IrisSpotlight_ConfigureTable(); if (!submodule_index) { W12SEL_copy = 0; W34SEL_copy = 0; WOBJSEL_copy = 0; TMW_copy = 0; TSW_copy = 0; subsubmodule_index = 0; if (buffer_for_playing_songs != 0xff) music_control = buffer_for_playing_songs; } } // This is used for straight inter room stairs for example stairs to throne room in first dung void Module07_11_StraightInterroomStairs() { // 829357 if (subsubmodule_index >= 3) Dungeon_LoadAttribute_Selectable(); if (subsubmodule_index >= 13) Graphics_IncrementalVRAMUpload(); if (staircase_var1) { if (staircase_var1-- == 16) link_speed_modifier = 2; link_direction = (submodule_index == 18) ? 8 : 4; Link_HandleVelocity(); } Link_HandleMovingAnimation_FullLongEntry(); kDungeon_StraightStairs[subsubmodule_index](); } void Module07_11_00_PrepAndReset() { // 8293bb if (link_is_running) { link_is_running = 0; link_speed_setting = 2; } sound_effect_1 = (which_staircase_index & 4) ? 24 : 22; if (dungeon_room_index == 48 || dungeon_room_index == 64) music_control = 0xf1; ResetTransitionPropsAndAdvance_ResetInterface(); } void Module07_11_01_FadeOut() { // 8293ed if (staircase_var1 < 9) { ApplyPaletteFilter_bounce(); if (BYTE(palette_filter_countdown) == 23) subsubmodule_index++; } } void Module07_11_02_LoadAndPrepRoom() { // 829403 ApplyPaletteFilter_bounce(); Dungeon_LoadRoom(); Dungeon_RestoreStarTileChr(); LoadTransAuxGFX(); Dungeon_LoadCustomTileAttr(); Dungeon_AdjustForRoomLayout(); Follower_Initialize(); subsubmodule_index++; } void Module07_11_03_FilterAndLoadBGChars() { // 829422 ApplyPaletteFilter_bounce(); DungeonTransition_TriggerBGC34UpdateAndAdvance(); } void Module07_11_04_FilterDoBGAndResetSprites() { // 82942a ApplyPaletteFilter_bounce(); DungeonTransition_TriggerBGC56UpdateAndAdvance(); BYTE(dungeon_room_index2) = BYTE(dungeon_room_index); Dungeon_ResetSprites(); } void Module07_11_0B_PrepDestination() { // 82943b uint8 ts = kSpiralTab1[dung_hdr_bg2_properties], tm = 0x16; if (sign8(ts)) tm = 0x17, ts = 0; TM_copy = tm; TS_copy = ts; link_speed_modifier = 1; dung_cur_floor += (which_staircase_index & 4) ? -1 : 1; staircase_var1 = (which_staircase_index & 4) ? 0x32 : 0x3c; sound_effect_1 = (which_staircase_index & 4) ? 25 : 23; uint8 r0 = 0; if (link_is_on_lower_level) { link_y_coord += (submodule_index == 18) ? -32 : 32; r0++; } link_is_on_lower_level_mirror = kTeleportPitLevel1[cur_staircase_plane]; link_is_on_lower_level = kTeleportPitLevel2[cur_staircase_plane]; if (link_is_on_lower_level) { link_y_coord += (submodule_index == 18) ? -32 : 32; r0++; } if (!r0) { if (submodule_index == 18) { link_y_coord += (which_staircase_index & 4) ? -24 : -8; } else { link_y_coord += 12; } } Dungeon_PlayBlipAndCacheQuadrantVisits(); Hud_RestoreTorchBackground(); Dungeon_InterRoomTrans_notDarkRoom(); } void Module07_11_09_LoadSpriteGraphics() { // 8294e0 ApplyPaletteFilter_bounce(); subsubmodule_index--; LoadNewSpriteGFXSet(); Dungeon_HandleTranslucencyAndPalette(); } void Module07_11_19_SetSongAndFilter() { // 8294ed if (overworld_map_state == 5 && !BYTE(darkening_or_lightening_screen)) { subsubmodule_index++; if (dungeon_room_index == 48) music_control = 0x1c; else if (dungeon_room_index == 64) music_control = 0x10; } ApplyGrayscaleFixed_Incremental(); } void Module07_11_11_KeepSliding() { // 829518 if (staircase_var1 == 0) subsubmodule_index++; else ApplyGrayscaleFixed_Incremental(); } void Module07_14_RecoverFromFall() { // 829520 switch (subsubmodule_index) { case 0: Module07_14_00_ScrollCamera(); break; case 1: RecoverPositionAfterDrowning(); break; } } void Module07_14_00_ScrollCamera() { // 82952a for (int i = 0; i < 2; i++) { if (BG2HOFS_copy2 != BG2HOFS_copy2_cached) BG2HOFS_copy2 += BG2HOFS_copy2 < BG2HOFS_copy2_cached ? 1 : -1; if (BG2VOFS_copy2 != BG2VOFS_copy2_cached) BG2VOFS_copy2 += BG2VOFS_copy2 < BG2VOFS_copy2_cached ? 1 : -1; } if (BG2HOFS_copy2 == BG2HOFS_copy2_cached && BG2VOFS_copy2 == BG2VOFS_copy2_cached) subsubmodule_index++; if (!hdr_dungeon_dark_with_lantern) MirrorBg1Bg2Offs(); } void Module07_15_WarpPad() { // 82967a if (subsubmodule_index >= 3) { Graphics_IncrementalVRAMUpload(); Dungeon_LoadAttribute_Selectable(); } kDungeon_Teleport[subsubmodule_index](); } void Module07_15_01_ApplyMosaicAndFilter() { // 8296ac ConditionalMosaicControl(); MOSAIC_copy = mosaic_level | 3; ApplyPaletteFilter_bounce(); } void Module07_15_04_SyncRoomPropsAndBuildOverlay() { // 8296ba ApplyGrayscaleFixed_Incremental(); if (dungeon_room_index == 0x17) dung_cur_floor = 4; MirrorBg1Bg2Offs(); Dungeon_AdjustForRoomLayout(); uint8 ts = kSpiralTab1[dung_hdr_bg2_properties], tm = 0x16; if (sign8(ts)) tm = 0x17, ts = 0; TM_copy = tm; TS_copy = ts; WaterFlood_BuildOneQuadrantForVRAM(); subsubmodule_index++; } void Module07_15_0E_FadeInFromWarp() { // 8296ec if (palette_filter_countdown & 1 && mosaic_level != 0) mosaic_level -= 0x10; BGMODE_copy = 9; MOSAIC_copy = mosaic_level | 3; ApplyPaletteFilter_bounce(); } void Module07_15_0F_FinalizeAndCacheEntry() { // 82970f if (overworld_map_state == 5) { SetAndSaveVisitedQuadrantFlags(); submodule_index = 0; ResetThenCacheRoomEntryProperties(); } } void Module07_16_UpdatePegs() { // 82972a if (++subsubmodule_index & 3) return; switch (subsubmodule_index >> 2) { case 0: case 1: Module07_16_UpdatePegs_Step1(); break; case 2: Module07_16_UpdatePegs_Step2(); break; case 3: RecoverPegGFXFromMapping(); break; case 4: Dungeon_FlipCrystalPegAttribute(); subsubmodule_index = 0; submodule_index = 0; break; } } void Module07_17_PressurePlate() { // 8297c8 if (--subsubmodule_index) return; link_y_coord -= 2; Dungeon_UpdateTileMapWithCommonTile((word_7E04B6 & 0x3f) << 3, (word_7E04B6 >> 3) & 0x1f8, 0xe); submodule_index = saved_module_for_menu; } void Module07_18_RescuedMaiden() { // 82980a switch (subsubmodule_index) { case 0: PaletteFilter_RestoreBGSubstractiveStrict(); main_palette_buffer[0] = main_palette_buffer[32]; if (BYTE(darkening_or_lightening_screen) != 255) return; for (int i = 0; i < 0x1000; i++) dung_bg2[i] = dung_bg1[i] = 0x1ec; bg1_y_offset = 0; bg1_x_offset = 0; dung_floor_x_offs = 0; dung_floor_y_offs = 0; overworld_screen_transition = 0; dung_cur_quadrant_upload = 0; subsubmodule_index++; break; case 1: { static const uint16 kCrystal_Tab0[7] = { 0x1618, 0x1658, 0x1658, 0x1618, 0x658, 0x1618, 0x1658 }; PaletteFilter_Crystal(); TS_copy = 1; flag_is_link_immobilized = 2; int j = FindInWordArray(kBossRooms, dungeon_room_index, countof(kBossRooms)) - 4; uint16 *dst = &dung_bg1[kCrystal_Tab0[j] >> 1]; for (int n = 0, t = 0; n != 4; n++) { for (int i = 0; i != 8; i++, t++) { dst[i + XY(0, 0)] = 0x1f80 | t; dst[i + XY(0, 4)] = 0x1f88 | t; } t += 8, dst += XY(0, 1); } subsubmodule_index++; break; } case 2: case 4: case 6: case 8: Dungeon_InterRoomTrans_notDarkRoom(); break; case 3: case 5: case 7: case 9: Dungeon_InterRoomTrans_State4(); break; case 10: is_nmi_thread_active++; Polyhedral_InitializeThread(); CrystalCutscene_Initialize(); submodule_index = 0; subsubmodule_index = 0; break; } } void Module07_19_MirrorFade() { // 8298f7 // When using mirror Overworld_ResetMosaic_alwaysIncrease(); if (!--INIDISP_copy) { main_module_index = 5; submodule_index = 0; nmi_load_bg_from_vram = 0; last_music_control = music_unk1; if (overworld_palette_swap_flag) Palette_RevertTranslucencySwap(); } } void Module07_1A_RoomDraw_OpenTriforceDoor_bounce() { // 829916 static const uint16 kOpenGanonDoor_Tab[4] = { 0x2556, 0x2596, 0x25d6, 0x2616 }; flag_is_link_immobilized = 1; if (R16 != 0) { if (--BYTE(R16) || --HIBYTE(R16)) return; sound_effect_ambient = 21; link_force_hold_sword_up = 0; link_cant_change_direction = 0; } flag_is_link_immobilized = 0; if (++subsubmodule_index & 3) return; const uint16 *src = SrcPtr(kOpenGanonDoor_Tab[(subsubmodule_index - 4) >> 2]); uint16 *dst = &dung_bg2[0]; for (int i = 0; i < 8; i++) { dst[XY(44, 3)] = src[0]; dst[XY(44, 4)] = src[1]; dst[XY(44, 5)] = src[2]; dst[XY(44, 6)] = src[3]; dst += XY(1, 0), src += 4; } Dungeon_PrepOverlayDma_watergate(0, 0x1d8, 0x881, 8); if (subsubmodule_index == 16) { WriteAttr2(XY(44, 5), 0x202); WriteAttr2(XY(44, 6), 0x202); WriteAttr2(XY(50, 5), 0x200); WriteAttr2(XY(50, 6), 0x200); for (int i = 0; i != 6; i += 2) { WriteAttr2(XY(45 + i, 0), 0x0); WriteAttr2(XY(45 + i, 1), 0x0); WriteAttr2(XY(45 + i, 2), 0x0); WriteAttr2(XY(45 + i, 3), 0x0); WriteAttr2(XY(45 + i, 4), 0x0); WriteAttr2(XY(45 + i, 5), 0x0); WriteAttr2(XY(45 + i, 6), 0x0); } room_bounds_y.a0 = -64; submodule_index = 0; subsubmodule_index = 0; } nmi_copy_packets_flag = 1; } void Module11_DungeonFallingEntrance() { // 829af9 switch (subsubmodule_index) { case 0: // Module_11_00_SetSongAndInit if (kEntranceData_musicTrack[which_entrance] != 3 || sram_progress_indicator >= 2) music_control = 0xf1; ResetTransitionPropsAndAdvance_ResetInterface(); break; case 1: if (!(frame_counter & 1)) ApplyPaletteFilter_bounce(); break; case 2: Module11_02_LoadEntrance(); break; case 3: DungeonTransition_LoadSpriteGFX(); break; case 4: INIDISP_copy = (INIDISP_copy + 1) & 0xf; if (INIDISP_copy == 15) subsubmodule_index++; case 5: HandleDungeonLandingFromPit(); if (submodule_index) return; main_module_index = 7; flag_skip_call_tag_routines++; Dungeon_PlayBlipAndCacheQuadrantVisits(); ResetThenCacheRoomEntryProperties(); music_control = buffer_for_playing_songs; last_music_control = music_unk1; break; } } void Module11_02_LoadEntrance() { // 829b1c EnableForceBlank(); CGWSEL_copy = 2; Dungeon_LoadEntrance(); uint8 dung = BYTE(cur_palace_index_x2); link_num_keys = (dung != 255) ? link_keys_earned_per_dungeon[((dung == 2) ? 0 : dung) >> 1] : 255; Hud_Rebuild(); link_this_controls_sprite_oam = 4; player_near_pit_state = 3; link_visibility_status = 12; link_speed_modifier = 16; uint8 y = link_y_coord - BG2VOFS_copy2; link_state_bits = 0; link_picking_throw_state = 0; some_animation_timer = 0; dungeon_room_index_prev = dungeon_room_index; tiledetect_which_y_pos[0] = link_y_coord; link_y_coord -= y + 16; uint8 bak = subsubmodule_index; dung_num_lit_torches = 0; hdr_dungeon_dark_with_lantern = 0; Dungeon_LoadAndDrawRoom(); Dungeon_LoadCustomTileAttr(); DecompressAnimatedDungeonTiles(kDungAnimatedTiles[main_tile_theme_index]); Dungeon_LoadAttributeTable(); subsubmodule_index = bak + 1; misc_sprites_graphics_index = 10; zelda_ppu_write(OBSEL, 2); InitializeTilesets(); palette_sp6 = 10; Dungeon_LoadPalettes(); Hud_RestoreTorchBackground(); button_mask_b_y = 0; button_b_frames = 0; Dungeon_ResetTorchBackgroundAndPlayer(); if (link_is_bunny_mirror) LoadGearPalettes_bunny(); HDMAEN_copy = 0x80; Hud_RefillLogic(); Module_PreDungeon_setAmbientSfx(); submodule_index = 7; Dungeon_LoadSongBankIfNeeded(); } void Dungeon_LoadSongBankIfNeeded() { // 829bd7 if (buffer_for_playing_songs == 0xff || buffer_for_playing_songs == 0xf2) return; if (buffer_for_playing_songs == 3 || buffer_for_playing_songs == 7 || buffer_for_playing_songs == 14) { LoadOWMusicIfNeeded(); } else { if (flag_which_music_type) return; zelda_snes_dummy_write(NMITIMEN, 0); zelda_snes_dummy_write(HDMAEN, 0); flag_which_music_type = 1; LoadDungeonSongs(); zelda_snes_dummy_write(NMITIMEN, 0x81); } } void Mirror_SaveRoomData() { // 82a1b1 if (cur_palace_index_x2 == 0xff) { sound_effect_1 = 60; return; } submodule_index = 25; subsubmodule_index = 0; sound_effect_1 = 51; Dungeon_FlagRoomData_Quadrants(); SaveDungeonKeys(); } void SaveDungeonKeys() { // 82a1c7 uint8 idx = cur_palace_index_x2; if (idx == 0xff) return; if (idx == 2) idx = 0; link_keys_earned_per_dungeon[idx >> 1] = link_num_keys; } void Dungeon_AdjustAfterSpiralStairs() { // 82a2f0 int xd = ((dungeon_room_index & 0xf) - (dungeon_room_index_prev & 0xf)) * 0x200; link_x_coord += xd; BG2HOFS_copy2 += xd; room_bounds_x.a1 += xd; room_bounds_x.b1 += xd; room_bounds_x.a0 += xd; room_bounds_x.b0 += xd; int yd = (((dungeon_room_index & 0xf0) >> 4) - ((dungeon_room_index_prev & 0xf0) >> 4)) * 0x200; link_y_coord += yd; BG2VOFS_copy2 += yd; room_bounds_y.a1 += yd; room_bounds_y.b1 += yd; room_bounds_y.a0 += yd; room_bounds_y.b0 += yd; } void Dungeon_AdjustForTeleportDoors(uint8 room, uint8 flag) { // 82a37c dungeon_room_index2 = room; dungeon_room_index_prev = room; uint16 xx = (room & 0xf) * 2 - (link_x_coord >> 8) + flag; link_x_coord += (xx << 8); BG2HOFS_copy2 += (xx << 8); room_bounds_x.a1 += (xx << 8); room_bounds_x.b1 += (xx << 8); room_bounds_x.a0 += (xx << 8); room_bounds_x.b0 += (xx << 8); xx = ((room & 0xf0) >> 3) - (link_y_coord >> 8); link_y_coord += (xx << 8); BG2VOFS_copy2 += (xx << 8); room_bounds_y.a1 += (xx << 8); room_bounds_y.b1 += (xx << 8); room_bounds_y.a0 += (xx << 8); room_bounds_y.b0 += (xx << 8); for (int i = 0; i < 20; i++) tagalong_y_hi[i] = link_y_coord >> 8; } void Dungeon_AdjustForRoomLayout() { // 82b5dc Dungeon_AdjustQuadrant(); quadrant_fullsize_x = (dung_blastwall_flag_x || (kLayoutQuadrantFlags[composite_of_layout_and_quadrant] & (link_quadrant_x ? 2 : 1)) == 0) ? 2 : 0; quadrant_fullsize_y = (dung_blastwall_flag_y || (kLayoutQuadrantFlags[composite_of_layout_and_quadrant] & (link_quadrant_y ? 8 : 4)) == 0) ? 2 : 0; if ((uint8)dung_unk2) quadrant_fullsize_x = (uint8)dung_unk2; if ((uint8)(dung_unk2 >> 8)) quadrant_fullsize_y = (uint8)(dung_unk2 >> 8); } void HandleEdgeTransitionMovementEast_RightBy8() { // 82b62e link_x_coord += 8; Dungeon_StartInterRoomTrans_Right(); } void Dungeon_StartInterRoomTrans_Right() { // 82b63a link_quadrant_x ^= 1; Dungeon_AdjustQuadrant(); RoomBounds_AddA(&room_bounds_x); Dung_SaveDataForCurrentRoom(); DungeonTransition_AdjustCamera_X(link_quadrant_x); HandleEdgeTransition_AdjustCameraBoundaries(2); submodule_index++; if (!link_quadrant_x) { RoomBounds_AddB(&room_bounds_x); BYTE(dungeon_room_index_prev) = dungeon_room_index; if ((link_tile_below & 0xcf) == 0x89) { dungeon_room_index = dung_hdr_travel_destinations[4]; Dungeon_AdjustForTeleportDoors(dungeon_room_index - 1, 1); } else { if ((uint8)dungeon_room_index != (uint8)dungeon_room_index2) { BYTE(dungeon_room_index_prev) = dungeon_room_index2; Dungeon_AdjustAfterSpiralStairs(); } dungeon_room_index += 1; } submodule_index += 1; if (room_transitioning_flags & 1) { link_is_on_lower_level ^= 1; link_is_on_lower_level_mirror = link_is_on_lower_level; } if (room_transitioning_flags & 2) { cur_palace_index_x2 ^= 2; } } room_transitioning_flags = 0; quadrant_fullsize_y = (dung_blastwall_flag_y || (kLayoutQuadrantFlags[composite_of_layout_and_quadrant] & (link_quadrant_y ? 8 : 4)) == 0) ? 2 : 0; } void HandleEdgeTransitionMovementSouth_DownBy16() { // 82b76e link_y_coord += 16; Dungeon_StartInterRoomTrans_Down(); } void Dung_HandleExitToOverworld() { // 82b7ae SaveDungeonKeys(); SaveQuadrantsToSram(); saved_module_for_menu = 8; main_module_index = 15; submodule_index = 0; subsubmodule_index = 0; Dungeon_ResetTorchBackgroundAndPlayerInner(); } void AdjustQuadrantAndCamera_right() { // 82b8bd link_quadrant_x ^= 1; Dungeon_AdjustQuadrant(); RoomBounds_AddA(&room_bounds_x); SetAndSaveVisitedQuadrantFlags(); } void SetAndSaveVisitedQuadrantFlags() { // 82b8cb dung_quadrants_visited |= kQuadrantVisitingFlags[(quadrant_fullsize_y << 2) + (quadrant_fullsize_x << 1) + link_quadrant_y + link_quadrant_x]; save_dung_info[dungeon_room_index] |= dung_quadrants_visited; } void SaveQuadrantsToSram() { // 82b8e5 save_dung_info[dungeon_room_index] |= dung_quadrants_visited; } void AdjustQuadrantAndCamera_left() { // 82b8f9 link_quadrant_x ^= 1; Dungeon_AdjustQuadrant(); RoomBounds_SubA(&room_bounds_x); SetAndSaveVisitedQuadrantFlags(); } void AdjustQuadrantAndCamera_down() { // 82b909 link_quadrant_y ^= 2; Dungeon_AdjustQuadrant(); RoomBounds_AddA(&room_bounds_y); SetAndSaveVisitedQuadrantFlags(); } void AdjustQuadrantAndCamera_up() { // 82b919 link_quadrant_y ^= 2; Dungeon_AdjustQuadrant(); RoomBounds_SubA(&room_bounds_y); SetAndSaveVisitedQuadrantFlags(); } void Dungeon_FlagRoomData_Quadrants() { // 82b929 dung_quadrants_visited |= kQuadrantVisitingFlags[(quadrant_fullsize_y << 2) + (quadrant_fullsize_x << 1) + link_quadrant_y + link_quadrant_x]; Dung_SaveDataForCurrentRoom(); } void Dung_SaveDataForCurrentRoom() { // 82b947 save_dung_info[dungeon_room_index] = (dung_savegame_state_bits >> 4) | (dung_door_opened & 0xf000) | dung_quadrants_visited; } void HandleEdgeTransition_AdjustCameraBoundaries(uint8 arg) { // 82b9dc static const uint16 kCameraBoundsX[] = { 127, 383, 127, 383 }; static const uint16 kCameraBoundsY[] = { 120, 376, 136, 392 }; overworld_screen_transition = arg; if (link_direction & 3) { uint8 t = link_direction & 1 ? 0 : 2; if (link_quadrant_x) t += 1; camera_x_coord_scroll_low = kCameraBoundsX[t]; camera_x_coord_scroll_hi = camera_x_coord_scroll_low + 2; } else { uint8 t = link_direction & 4 ? 0 : 2; if (link_quadrant_y) t += 1; camera_y_coord_scroll_low = kCameraBoundsY[t]; camera_y_coord_scroll_hi = camera_y_coord_scroll_low + 2; } } void Dungeon_AdjustQuadrant() { // 82ba27 composite_of_layout_and_quadrant = dung_layout_and_starting_quadrant | link_quadrant_y | link_quadrant_x; } void Dungeon_HandleCamera() { // 82ba31 if (link_y_vel) { int z = (allow_scroll_z && link_z_coord != 0xffff) ? link_z_coord : 0; int y = ((link_y_coord - z) & 0x1ff) + 12; int scrollamt = 1; int y_vel_abs = sign8(link_y_vel) ? (scrollamt = -1, -(int8)link_y_vel) : link_y_vel; do { int qm = quadrant_fullsize_y >> 1; if (sign8(link_y_vel)) { if (y > camera_y_coord_scroll_low) continue; } else { if (y < camera_y_coord_scroll_hi) continue; qm += 2; } if (BG2VOFS_copy2 == room_bounds_y.v[qm]) continue; BG2VOFS_copy2 += scrollamt; if (dungeon_room_index == 0xffff) continue; BG1VOFS_subpixel += 0x8000; BG1VOFS_copy2 += (scrollamt >> 1) + ((BG1VOFS_subpixel & 0x8000) == 0); camera_y_coord_scroll_low += scrollamt; camera_y_coord_scroll_hi = camera_y_coord_scroll_low + 2; } while (--y_vel_abs); } if (link_x_vel) { int x = (link_x_coord & 0x1ff) + 8; int scrollamt = 1; int x_vel_abs = sign8(link_x_vel) ? (scrollamt = -1, -(int8)link_x_vel) : link_x_vel; do { int qm = quadrant_fullsize_x >> 1; if (sign8(link_x_vel)) { if (x > camera_x_coord_scroll_low) continue; } else { if (x < camera_x_coord_scroll_hi) continue; qm += 2; } if (BG2HOFS_copy2 == room_bounds_x.v[qm]) continue; BG2HOFS_copy2 += scrollamt; if (dungeon_room_index == 0xffff) continue; BG1HOFS_subpixel += 0x8000; BG1HOFS_copy2 += (scrollamt >> 1) + ((BG1HOFS_subpixel & 0x8000) == 0); camera_x_coord_scroll_low += scrollamt; camera_x_coord_scroll_hi = camera_x_coord_scroll_low + 2; } while (--x_vel_abs); } if (dungeon_room_index != 0xffff) { if (dung_hdr_bg2_properties == 0 || dung_hdr_bg2_properties == 2 || dung_hdr_bg2_properties == 3 || dung_hdr_bg2_properties == 4 || dung_hdr_bg2_properties >= 6) { BG1HOFS_copy2 = BG2HOFS_copy2; BG1VOFS_copy2 = BG2VOFS_copy2; } } } void MirrorBg1Bg2Offs() { // 82bb7b BG1HOFS_copy2 = BG2HOFS_copy2; BG1VOFS_copy2 = BG2VOFS_copy2; } void DungeonTransition_AdjustCamera_X(uint8 arg) { // 82bdc8 static const uint16 kUpDownScroll[4] = { 0, 256, 256, 0 }; left_right_scroll_target = kUpDownScroll[arg * 2]; left_right_scroll_target_end = kUpDownScroll[arg * 2 + 1]; } void DungeonTransition_AdjustCamera_Y(uint8 arg) { // 82bde2 static const uint16 kUpDownScroll[4] = { 0, 272, 256, 16 }; up_down_scroll_target = kUpDownScroll[arg]; up_down_scroll_target_end = kUpDownScroll[arg + 1]; } void DungeonTransition_ScrollRoom() { // 82be03 transition_counter++; int i = overworld_screen_transition; bg1_y_offset = bg1_x_offset = 0; uint16 t; if (i >= 2) { t = BG1HOFS_copy2 = BG2HOFS_copy2 = (BG2HOFS_copy2 + kStaircaseTab3[i]) & ~1; if (transition_counter >= kStaircaseTab4[i]) link_x_coord += kStaircaseTab3[i]; } else { t = BG1VOFS_copy2 = BG2VOFS_copy2 = (BG2VOFS_copy2 + kStaircaseTab3[i]) & ~1; if (transition_counter >= kStaircaseTab4[i]) link_y_coord += kStaircaseTab3[i]; } if ((t & 0x1fc) == (&up_down_scroll_target)[i]) { SetAndSaveVisitedQuadrantFlags(); subsubmodule_index++; transition_counter = 0; if (submodule_index == 2) WaterFlood_BuildOneQuadrantForVRAM(); } } void Module07_11_0A_ScrollCamera() { // 82be75 link_visibility_status = tagalong_var5 = 12; int i = overworld_screen_transition; BG1VOFS_copy2 = BG2VOFS_copy2 = (BG2VOFS_copy2 + kStaircaseTab3[i]) & ~3; if ((BG1VOFS_copy2 & 0x1fc) == (&up_down_scroll_target)[i]) { if (submodule_index >= 18) i += 2; link_y_coord += kStaircaseTab5[i]; link_visibility_status = tagalong_var5 = 0; subsubmodule_index++; } } void DungeonTransition_FindSubtileLanding() { // 82c110 Dungeon_ResetTorchBackgroundAndPlayerInner(); SubtileTransitionCalculateLanding(); subsubmodule_index++; save_dung_info[dungeon_room_index] |= dung_quadrants_visited; } void SubtileTransitionCalculateLanding() { // 82c12c int st = overworld_screen_transition; int a = CalculateTransitionLanding(); if (a == 2) a = 1; else if (a == 4) a = 2; a += overworld_screen_transition * 5; int8 v = kStaircaseTab2[a]; v -= (v < 0) ? -8 : 8; if (st & 2) BYTE(link_x_coord) = v; else BYTE(link_y_coord) = v; link_visibility_status = 0; } void Dungeon_InterRoomTrans_State13() { // 82c162 if (dung_want_lights_out | dung_want_lights_out_copy) ApplyPaletteFilter_bounce(); Dungeon_IntraRoomTrans_State5(); } void Dungeon_IntraRoomTrans_State5() { // 82c170 Link_HandleMovingAnimation_FullLongEntry(); if (!DungeonTransition_MoveLinkOutDoor()) return; if (byte_7E004E == 2 || byte_7E004E == 4) is_standing_in_doorway = 0; // todo: write to tiledetect_diag_state BYTE(force_move_any_direction) = 0; byte_7E004E = 0; overworld_screen_transition = 0; subsubmodule_index++; } bool DungeonTransition_MoveLinkOutDoor() { // 82c191 uint8 x = kStaircaseTab2[byte_7E004E + overworld_screen_transition * 5]; int r0 = overworld_screen_transition & 1 ? -2 : 2; if ((overworld_screen_transition & 2) == 0) { link_y_coord += r0; return (BYTE(link_y_coord) & 0xfe) == x; } else { link_x_coord += r0; return (BYTE(link_x_coord) & 0xfe) == x; } } uint8 CalculateTransitionLanding() { // 82c1e5 int pos = ((link_y_coord + 12) & 0x1f8) << 3; pos |= ((link_x_coord + 8) & 0x1f8) >> 3; pos |= (link_is_on_lower_level ? 0x1000 : 0); uint8 a = dung_bg2_attr_table[pos]; uint8 r = (a == 0 || a == 9) ? 0 : ((a &= 0x8e) == 0x80) ? 1 : (a == 0x82) ? 2 : (a == 0x84 || a == 0x88) ? 3 : (a == 0x86) ? 4 : 2; return byte_7E004E = r; } // This gets called when entering a dungeon from ow. void Dungeon_LoadAndDrawRoom() { // 82c57b int bak = HDMAEN_copy; zelda_snes_dummy_write(HDMAEN, 0); HDMAEN_copy = 0; Dungeon_LoadRoom(); overworld_screen_transition = 0; overworld_map_state = 0; for (dung_cur_quadrant_upload = 0; dung_cur_quadrant_upload != 16; ) { TileMapPrep_NotWaterOnTag(); NMI_UploadTilemap(); Dungeon_PrepareNextRoomQuadrantUpload(); NMI_UploadTilemap(); } HDMAEN_copy = bak; nmi_subroutine_index = 0; overworld_map_state = 0; subsubmodule_index = 0; } void Dungeon_LoadEntrance() { // 82d8b3 player_is_indoors = 1; if (death_var5) { death_var5 = 0; } else { overworld_area_index_exit = overworld_area_index; TM_copy_exit = WORD(TM_copy); BG2VOFS_copy2_exit = BG2VOFS_copy2; BG2HOFS_copy2_exit = BG2HOFS_copy2; link_y_coord_exit = link_y_coord; link_x_coord_exit = link_x_coord; camera_y_coord_scroll_low_exit = camera_y_coord_scroll_low; camera_x_coord_scroll_low_exit = camera_x_coord_scroll_low; overworld_screen_index_exit = overworld_screen_index; map16_load_src_off_exit = map16_load_src_off; overworld_screen_index = 0; overlay_index = 0; ow_scroll_vars0_exit = ow_scroll_vars0; up_down_scroll_target_exit = up_down_scroll_target; up_down_scroll_target_end_exit = up_down_scroll_target_end; left_right_scroll_target_exit = left_right_scroll_target; left_right_scroll_target_end_exit = left_right_scroll_target_end; overworld_unk1_exit = overworld_unk1; overworld_unk1_neg_exit = overworld_unk1_neg; overworld_unk3_exit = overworld_unk3; overworld_unk3_neg_exit = overworld_unk3_neg; byte_7EC164 = byte_7E0AA0; main_tile_theme_index_exit = main_tile_theme_index; aux_tile_theme_index_exit = aux_tile_theme_index; sprite_graphics_index_exit = sprite_graphics_index; } bg1_y_offset = bg1_x_offset = 0; WORD(death_var5) = 0; if (WORD(follower_indicator) == 4 || WORD(death_var4)) { int i = which_starting_point; WORD(which_entrance) = kStartingPoint_entrance[i]; dungeon_room_index = dungeon_room_index2 = kStartingPoint_rooms[i]; BG1VOFS_copy = BG2VOFS_copy = BG1VOFS_copy2 = BG2VOFS_copy2 = kStartingPoint_scrollY[i]; BG1HOFS_copy = BG2HOFS_copy = BG1HOFS_copy2 = BG2HOFS_copy2 = kStartingPoint_scrollX[i]; if (WORD(sram_progress_indicator)) { link_y_coord = kStartingPoint_playerY[i]; link_x_coord = kStartingPoint_playerX[i]; } camera_y_coord_scroll_low = kStartingPoint_cameraY[i]; camera_y_coord_scroll_hi = camera_y_coord_scroll_low + 2; camera_x_coord_scroll_low = kStartingPoint_cameraX[i]; camera_x_coord_scroll_hi = camera_x_coord_scroll_low + 2; tilemap_location_calc_mask = 0x1f8; ow_entrance_value = kStartingPoint_doorSettings[i]; up_down_scroll_target = 0; up_down_scroll_target_end = 0x110; left_right_scroll_target = 0; left_right_scroll_target_end = 0x100; room_bounds_y.a0 = kStartingPoint_relativeCoords[i * 8 + 0] << 8; room_bounds_y.b0 = kStartingPoint_relativeCoords[i * 8 + 1] << 8; room_bounds_y.a1 = kStartingPoint_relativeCoords[i * 8 + 2] << 8 | 0x10; room_bounds_y.b1 = kStartingPoint_relativeCoords[i * 8 + 3] << 8 | 0x10; room_bounds_x.a0 = kStartingPoint_relativeCoords[i * 8 + 4] << 8; room_bounds_x.b0 = kStartingPoint_relativeCoords[i * 8 + 5] << 8; room_bounds_x.a1 = kStartingPoint_relativeCoords[i * 8 + 6] << 8; room_bounds_x.b1 = kStartingPoint_relativeCoords[i * 8 + 7] << 8; link_direction_facing = 2; main_tile_theme_index = kStartingPoint_blockset[i]; dung_cur_floor = kStartingPoint_floor[i]; BYTE(cur_palace_index_x2) = kStartingPoint_palace[i]; is_standing_in_doorway = 0; link_is_on_lower_level = kStartingPoint_startingBg[i] >> 4; link_is_on_lower_level_mirror = kStartingPoint_startingBg[i] & 0xf; quadrant_fullsize_x = kStartingPoint_quadrant1[i] >> 4; quadrant_fullsize_y = kStartingPoint_quadrant1[i] & 0xf; link_quadrant_x = kStartingPoint_quadrant2[i] >> 4; link_quadrant_y = kStartingPoint_quadrant2[i] & 0xf; buffer_for_playing_songs = kStartingPoint_musicTrack[i]; if (i == 0 && sram_progress_indicator == 0) buffer_for_playing_songs = 0xff; death_var4 = 0; } else { int i = which_entrance; dungeon_room_index = dungeon_room_index2 = kEntranceData_rooms[i]; BG1VOFS_copy = BG2VOFS_copy = BG1VOFS_copy2 = BG2VOFS_copy2 = kEntranceData_scrollY[i]; BG1HOFS_copy = BG2HOFS_copy = BG1HOFS_copy2 = BG2HOFS_copy2 = kEntranceData_scrollX[i]; if (WORD(sram_progress_indicator)) { link_y_coord = kEntranceData_playerY[i]; link_x_coord = kEntranceData_playerX[i]; } camera_y_coord_scroll_low = kEntranceData_cameraY[i]; camera_y_coord_scroll_hi = camera_y_coord_scroll_low + 2; camera_x_coord_scroll_low = kEntranceData_cameraX[i]; camera_x_coord_scroll_hi = camera_x_coord_scroll_low + 2; tilemap_location_calc_mask = 0x1f8; ow_entrance_value = kEntranceData_doorSettings[i]; big_rock_starting_address = 0; up_down_scroll_target = 0; up_down_scroll_target_end = 0x110; left_right_scroll_target = 0; left_right_scroll_target_end = 0x100; room_bounds_y.a0 = kEntranceData_relativeCoords[i * 8 + 0] << 8; room_bounds_y.b0 = kEntranceData_relativeCoords[i * 8 + 1] << 8; room_bounds_y.a1 = kEntranceData_relativeCoords[i * 8 + 2] << 8 | 0x10; room_bounds_y.b1 = kEntranceData_relativeCoords[i * 8 + 3] << 8 | 0x10; room_bounds_x.a0 = kEntranceData_relativeCoords[i * 8 + 4] << 8; room_bounds_x.b0 = kEntranceData_relativeCoords[i * 8 + 5] << 8; room_bounds_x.a1 = kEntranceData_relativeCoords[i * 8 + 6] << 8; room_bounds_x.b1 = kEntranceData_relativeCoords[i * 8 + 7] << 8; link_direction_facing = (i == 0 || i == 0x43) ? 2 : 0; main_tile_theme_index = kEntranceData_blockset[i]; buffer_for_playing_songs = kEntranceData_musicTrack[i]; if (buffer_for_playing_songs == 3 && sram_progress_indicator >= 2) buffer_for_playing_songs = 18; dung_cur_floor = kEntranceData_floor[i]; BYTE(cur_palace_index_x2) = kEntranceData_palace[i]; is_standing_in_doorway = kEntranceData_doorwayOrientation[i]; link_is_on_lower_level = kEntranceData_startingBg[i] >> 4; link_is_on_lower_level_mirror = kEntranceData_startingBg[i] & 0xf; quadrant_fullsize_x = kEntranceData_quadrant1[i] >> 4; quadrant_fullsize_y = kEntranceData_quadrant1[i] & 0xf; link_quadrant_x = kEntranceData_quadrant2[i] >> 4; link_quadrant_y = kEntranceData_quadrant2[i] & 0xf; if (dungeon_room_index >= 0x100) dung_cur_floor = 0; } player_oam_x_offset = player_oam_y_offset = 0x80; link_direction_mask_a = link_direction_mask_b = 0xf; BYTE(link_z_coord) = link_actual_vel_z = 0xff; memcpy(movable_block_datas, kMovableBlockDataInit, kMovableBlockDataInit_SIZE); memcpy(&movable_block_datas[99], kTorchDataInit, 116); // junk memcpy(dung_torch_data, kTorchDataInit, kTorchDataInit_SIZE); memcpy(&dung_torch_data[144], kTorchDataJunk, kTorchDataJunk_SIZE); memset(memorized_tile_addr, 0, 0x100); memset(pots_revealed_in_room, 0, 0x280); orange_blue_barrier_state = 0; byte_7E04BC = 0; } void PushBlock_Slide(uint8 j) { // 87edb5 if (submodule_index) return; int i = (index_of_changable_dungeon_objs[1] - 1) * 2 == j; pushedblocks_maybe_timeout = 9; pushedblocks_some_index = 0; PushBlock_ApplyVelocity(i); int y = (uint8)pushedblocks_y_lo[i] | (uint8)pushedblocks_y_hi[i] << 8; int x = (uint8)pushedblocks_x_lo[i] | (uint8)pushedblocks_x_hi[i] << 8; PushBlock_HandleCollision(i, x, y); } void PushBlock_HandleFalling(uint8 y) { // 87edf9 y >>= 1; if (!sign8(--pushedblocks_maybe_timeout)) return; pushedblocks_maybe_timeout = 9; if (++pushedblocks_some_index == 4) { BYTE(dung_replacement_tile_state[y]) = 0; pushedblocks_some_index = 0; int i = (index_of_changable_dungeon_objs[1] - 1) == y; index_of_changable_dungeon_objs[i] = 0; } } void PushBlock_ApplyVelocity(uint8 i) { // 87ee35 static const uint8 kPushedBlockDirMask[] = { 0x8, 0x4, 0x2, 0x1 }; uint8 m = kPushedBlockDirMask[(uint8)pushedblock_facing[i] >> 1]; uint32 o; link_actual_vel_x = link_actual_vel_y = 0; if (m & 3) { int8 vel = (m & 2) ? -12 : 12; link_actual_vel_x = vel; o = (pushedblocks_subpixel[i] | pushedblocks_x_lo[i] << 8 | pushedblocks_x_hi[i] << 16) + vel * 16; pushedblocks_subpixel[i] = (uint8)o; pushedblocks_x_lo[i] = (uint8)(o >> 8); pushedblocks_x_hi[i] = (uint8)(o >> 16); } else { int8 vel = (m & 8) ? -12 : 12; link_actual_vel_y = vel; o = (pushedblocks_subpixel[i] | pushedblocks_y_lo[i] << 8 | pushedblocks_y_hi[i] << 16); o += vel * 16; pushedblocks_subpixel[i] = (uint8)o; pushedblocks_y_lo[i] = (uint8)(o >> 8); pushedblocks_y_hi[i] = (uint8)(o >> 16); } if (((o >> 8) & 0xf) == (uint8)pushedblocks_target[i]) { int j = index_of_changable_dungeon_objs[i] - 1; dung_replacement_tile_state[j]++; link_cant_change_direction &= ~0x4; bitmask_of_dragstate &= ~0x4; } uint16 x = pushedblocks_x_lo[i] | pushedblocks_x_hi[i] << 8; uint16 y = pushedblocks_y_lo[i] | pushedblocks_y_hi[i] << 8; for (int j = 15; j >= 0; j--) { if (sprite_state[j] >= 9) { uint16 sx = sprite_x_lo[j] | sprite_x_hi[j] << 8; uint16 sy = sprite_y_lo[j] | sprite_y_hi[j] << 8; if ((uint16)(x - sx + 0x10) < 0x20 && (uint16)(y - sy + 0x10) < 0x20) { sprite_F[j] = 8; static const uint8 kPushBlockTab1[] = { 0x0, 0x0, 0xe0, 0x20 }; static const uint8 kPushBlockTab2[] = { 0xe0, 0x20, 0x0, 0x0 }; int k = (uint8)pushedblock_facing[i] >> 1; sprite_x_recoil[j] = kPushBlockTab1[k]; sprite_y_recoil[j] = kPushBlockTab2[k]; } } } } void PushBlock_HandleCollision(uint8 i, uint16 x, uint16 y) { // 87efb9 static const uint8 kPushBlock_A[] = { 0, 0, 8, 8 }; static const uint8 kPushBlock_B[] = { 15, 15, 23, 23 }; static const uint8 kPushBlock_D[] = { 15, 15, 15, 15 }; static const uint8 kPushBlock_C[] = { 0x0, 0x0, 0x0, 0x0 }; static const uint8 kPushBlock_E[] = { 8, 24, 0, 16 }; static const uint8 kPushBlock_F[] = { 15, 0, 15, 0 }; link_y_coord_safe_return_hi = link_y_coord >> 8; link_x_coord_safe_return_hi = link_x_coord >> 8; int dir = 3; uint8 m = link_direction & 0xf; while (!(m & 1)) { m >>= 1; if (--dir < 0) return; } int l = (dir < 2) ? link_x_coord : link_y_coord; int o = (dir < 2) ? x : y; uint16 r0 = l + kPushBlock_A[dir]; uint16 r2 = l + kPushBlock_B[dir]; uint16 r4 = o + kPushBlock_C[dir]; uint16 r6 = o + kPushBlock_D[dir]; uint16 *coord_p = (dir < 2) ? &link_y_coord : &link_x_coord; uint16 r8 = *coord_p + kPushBlock_E[dir]; uint16 r10 = ((dir < 2) ? y : x) + kPushBlock_F[dir]; bitmask_of_dragstate &= ~4; if (r0 >= r4 && r0 < r6 || r2 >= r4 && r2 < r6) { if (link_direction_facing == pushedblock_facing[i]) bitmask_of_dragstate |= index_of_changable_dungeon_objs[i] ? 4 : 1; if (dir & 1 ? (r8 >= r10 && (uint16)(r8 - r10) < 8) : (uint16)(r8 - r10) >= 0xfff8) { *coord_p -= r8 - r10; *(dir & 2 ? &link_x_vel : &link_y_vel) -= r8 - r10; } } HandleIndoorCameraAndDoors(); } void Sprite_Dungeon_DrawAllPushBlocks() { // 87f0ac for (int i = 1; i >= 0; i--) if (index_of_changable_dungeon_objs[i]) Sprite_HandlePushedBlocks_One(i); } void UsedForStraightInterRoomStaircase() { // 87f25a int i = 9; do { if (ancilla_type[i] == 13) ancilla_type[i] = 0; } while (--i >= 0); if (link_animation_steps >= 5) link_animation_steps = 0; link_subpixel_x = 0; link_subpixel_y = 0; some_animation_timer_steps = 0; link_timer_push_get_tired = 28; countdown_timer_for_staircases = 32; link_disable_sprite_damage = 1; Ancilla_Sfx2_Near(which_staircase_index & 4 ? 0x18 : 0x16); tiledetect_which_y_pos[1] = link_x_coord + (which_staircase_index & 4 ? -15 : 16); tiledetect_which_y_pos[0] = link_y_coord; } void HandleLinkOnSpiralStairs() { // 87f2c1 link_x_coord_prev = link_x_coord; link_y_coord_prev = link_y_coord; if (some_animation_timer_steps) return; link_give_damage = 0; link_incapacitated_timer = 0; link_auxiliary_state = 0; if (which_staircase_index & 4) { link_actual_vel_y = -2; if (sign8(--link_timer_push_get_tired)) { link_timer_push_get_tired = 0; link_actual_vel_y = 0; link_actual_vel_x = -2; } } else { link_actual_vel_y = -2; if (sign8(--link_timer_push_get_tired)) { link_timer_push_get_tired = 0; link_actual_vel_y = -2; link_actual_vel_x = 2; } } LinkHop_FindArbitraryLandingSpot(); Link_HandleMovingAnimation_StartWithDash(); if (!link_timer_push_get_tired && sign8(--countdown_timer_for_staircases)) { countdown_timer_for_staircases = 0; link_direction_facing = (which_staircase_index & 4) ? 4 : 6; } int8 xd = link_x_coord - tiledetect_which_y_pos[1]; if (xd < 0) xd = -xd; if (xd) return; RepositionLinkAfterSpiralStairs(); if (follower_indicator) Follower_Initialize(); tiledetect_which_y_pos[1] = link_x_coord + ((which_staircase_index & 4) ? -8 : 12); some_animation_timer_steps = 1; countdown_timer_for_staircases = 6; Ancilla_Sfx2_Near(which_staircase_index & 4 ? 25 : 23); } void SpiralStairs_FindLandingSpot() { // 87f391 link_give_damage = 0; link_incapacitated_timer = 0; link_auxiliary_state = 0; link_disable_sprite_damage = 0; link_x_coord_prev = link_x_coord; link_y_coord_prev = link_y_coord; if (sign8(--countdown_timer_for_staircases)) { countdown_timer_for_staircases = 0; link_direction_facing = 2; } link_actual_vel_x = 4, link_actual_vel_y = 0; if (which_staircase_index & 4) link_actual_vel_x = -4, link_actual_vel_y = 2; if (some_animation_timer_steps == 2) link_actual_vel_x = 0, link_actual_vel_y = 16; LinkHop_FindArbitraryLandingSpot(); Link_HandleMovingAnimation_StartWithDash(); if ((uint8)link_x_coord == (uint8)tiledetect_which_y_pos[1]) some_animation_timer_steps = 2; } void Dungeon_HandleLayerEffect() { // 8afe80 kDungeon_Effect_Handler[dung_hdr_collision_2](); } void LayerEffect_Nothing() { // 8afe87 } void LayerEffect_Scroll() { // 8afe88 if (dung_savegame_state_bits & 0x8000) { dung_hdr_collision_2 = 0; return; } dung_floor_x_vel = dung_floor_y_vel = 0; if (dung_floor_move_flags & 1) return; int t = dung_some_subpixel[1] + 0x80; dung_some_subpixel[1] = t; t >>= 8; if (dung_floor_move_flags & 2) t = -t; if (dung_floor_move_flags < 4) { dung_floor_x_vel = t; dung_floor_x_offs -= t; BG1HOFS_copy2 = BG2HOFS_copy2 + dung_floor_x_offs; } else { dung_floor_y_vel = t; dung_floor_y_offs -= t; BG1VOFS_copy2 = BG2VOFS_copy2 + dung_floor_y_offs; } } void LayerEffect_Trinexx() { // 8afeee dung_floor_x_offs += dung_floor_x_vel; dung_floor_y_offs += dung_floor_y_vel; dung_floor_x_vel = 0; dung_floor_y_vel = 0; } void LayerEffect_Agahnim2() { // 8aff0d int j = frame_counter & 0x7f; if (j == 3 || j == 36) { main_palette_buffer[0x6d] = 0x1d59; main_palette_buffer[0x6e] = 0x25ff; main_palette_buffer[0x77] = main_palette_buffer[0x6f] = 0x1a; flag_update_cgram_in_nmi++; } else if (j == 5 || j == 38) { main_palette_buffer[0x6d] = aux_palette_buffer[0x6d]; main_palette_buffer[0x6e] = aux_palette_buffer[0x6e]; main_palette_buffer[0x77] = main_palette_buffer[0x6f] = aux_palette_buffer[0x6f]; flag_update_cgram_in_nmi++; } TS_copy = 2; } void LayerEffect_InvisibleFloor() { // 8aff5d int count = 0; for (int i = 0; i < 16; i++) count += (dung_object_tilemap_pos[i] & 0x8000) != 0; uint16 x = 0x2940, y = 0x4e60; if (count == 0) x = y = 0; if (aux_palette_buffer[0x7b] != x) { main_palette_buffer[0x7b] = aux_palette_buffer[0x7b] = x; main_palette_buffer[0x7c] = aux_palette_buffer[0x7c] = y; flag_update_cgram_in_nmi++; } TS_copy = 2; } void LayerEffect_Ganon() { // 8affa4 int count = 0; for (int i = 0; i < 16; i++) count += (dung_object_tilemap_pos[i] & 0x8000) != 0; byte_7E04C5 = count; if (count == 0) { TS_copy = 0; CGADSUB_copy = 0xb3; } else if (count == 1) { TS_copy = 2; CGADSUB_copy = 0x70; } else { TS_copy = 0; CGADSUB_copy = 0x70; } } void LayerEffect_WaterRapids() { // 8affde int t; dung_some_subpixel[1] = t = dung_some_subpixel[1] + 0x80; dung_floor_x_vel = -(t >> 8); } void Dungeon_LoadCustomTileAttr() { // 8e942a memcpy(&attributes_for_tile[0x140], &kDungAttrsForTile[kDungAttrsForTile_Offs[aux_tile_theme_index]], 0x80); } void Link_CheckBunnyStatus() { // 8ffd22 if (link_player_handler_state == kPlayerState_RecoilWall) { link_player_handler_state = !link_is_bunny_mirror ? kPlayerState_Ground : link_item_moon_pearl ? kPlayerState_TempBunny : kPlayerState_PermaBunny; } } void CrystalCutscene_Initialize() { // 9ecce3 static const uint16 kCrystalMaiden_Pal[8] = { 0, 0x3821, 0x4463, 0x54a5, 0x5ce7, 0x6d29, 0x79ad, 0x7e10 }; CGADSUB_copy = 0x33; BYTE(palette_filter_countdown) = 0; BYTE(darkening_or_lightening_screen) = 0; Palette_AssertTranslucencySwap(); PaletteFilter_Crystal(); for (int i = 0; i < 8; i++) main_palette_buffer[112 + i] = kCrystalMaiden_Pal[i]; flag_update_cgram_in_nmi++; CrystalCutscene_SpawnMaiden(); CrystalCutscene_InitializePolyhedral(); } void CrystalCutscene_SpawnMaiden() { // 9ecd48 memset(sprite_state, 0, 16); SpriteSpawnInfo info; int j = Sprite_SpawnDynamically(0, 0xab, &info); sprite_x_hi[j] = link_x_coord >> 8; sprite_y_hi[j] = link_y_coord >> 8; sprite_x_lo[j] = 0x78; sprite_y_lo[j] = 0x7c; sprite_D[j] = 1; sprite_oam_flags[j] = 0xb; sprite_subtype2[j] = 0; sprite_floor[j] = 0; sprite_A[j] = Ancilla_TerminateSelectInteractives(j); item_receipt_method = 0; if (BYTE(cur_palace_index_x2) == 24) { sprite_oam_flags[j] = 9; follower_indicator = 1; } else { follower_indicator = 6; } LoadFollowerGraphics(); follower_indicator = 0; dung_floor_x_offs = BG2HOFS_copy2 - link_x_coord + 0x79; dung_floor_y_offs = 0x30 - (uint8)BG1VOFS_copy2; dung_hdr_collision_2_mirror = 1; }