/**************************************************************************** * Visual Boy Advance GX * * Carl Kenner Febuary 2009 * * inputzelda.cpp * * Wii/Gamecube controls for Legend of Zelda games ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include "vba.h" #include "button_mapping.h" #include "audio.h" #include "video.h" #include "input.h" #include "gameinput.h" #include "vbasupport.h" #include "wiiusbsupport.h" #include "gba/GBA.h" #include "gba/bios.h" #include "gba/GBAinline.h" #define ALLOWCHEAT u8 ZeldaDxLeftPos = 2, ZeldaDxRightPos = 3, ZeldaDxDownPos = 4; u8 ZeldaDxShieldPos = 5, ZeldaDxSwordPos = 5, ZeldaDxBraceletPos = 5; void ZeldaSwap(u8 pos1, u8 pos2, u16 addr) { u8 OldItem = gbReadMemory(addr + pos1); gbWriteMemory(addr + pos1, gbReadMemory(addr + pos2)); gbWriteMemory(addr + pos2, OldItem); } u8 DrawnItemPos = 0xFF; bool ZeldaDrawItem(u8 ItemNumber, u16 addr, int boxes) { if (gbReadMemory(addr + 1) == ItemNumber) return true; DrawnItemPos = 0xFF; for (int i = 0; i < boxes; i++) { if (gbReadMemory(addr + i) == ItemNumber) { DrawnItemPos = i; } } if (DrawnItemPos == 0xFF) return false; if (DrawnItemPos != 1) { gbWriteMemory(addr + DrawnItemPos, gbReadMemory(addr + 1)); // put A item away gbWriteMemory(addr + 1, ItemNumber); // set A item to shield } return true; } bool ZeldaDxDrawBombs() { if (gbReadMemory(0xDB00 + 1) == 2) return true; ZeldaDxShieldPos = 0xFF; for (int i = 0; i <= 11; i++) { if (gbReadMemory(0xDB00 + i) == 2) { ZeldaDxShieldPos = i; } } if (ZeldaDxShieldPos == 0xFF) return false; if (ZeldaDxShieldPos != 2) { gbWriteMemory(0xDB00 + ZeldaDxShieldPos, gbReadMemory(0xDB00 + 1)); // put A item away gbWriteMemory(0xDB00 + 1, 2); // set A item to bombs } return true; } bool ZeldaDxDrawSword() { if (gbReadMemory(0xDB00 + 1) == 1) return true; ZeldaDxSwordPos = 0xFF; for (int i = 0; i <= 11; i++) { if (gbReadMemory(0xDB00 + i) == 1) { ZeldaDxSwordPos = i; } } if (ZeldaDxSwordPos == 0xFF) return false; if (ZeldaDxSwordPos != 1) { gbWriteMemory(0xDB00 + ZeldaDxSwordPos, gbReadMemory(0xDB00 + 1)); // put A item away gbWriteMemory(0xDB00 + 1, 1); // set A item to sword } return true; } void ZeldaDxSheathSword() { if (ZeldaDxSwordPos == 0xFF || gbReadMemory(0xDB00 + 1) != 1) return; gbWriteMemory(0xDB00 + 1, gbReadMemory(0xDB00 + ZeldaDxSwordPos)); gbWriteMemory(0xDB00 + ZeldaDxSwordPos, 1); ZeldaDxSwordPos = 0xFF; } void ZeldaDxCheat() { #ifdef ALLOWCHEAT gbWriteMemory(0xDB00 + 11, 0); for (int i = 0; i <= 10; i++) { gbWriteMemory(0xDB00 + i, i + 1); } gbWriteMemory(0xDB15, 5); // leaves gbWriteMemory(0xDB43, 3); // bracelet level gbWriteMemory(0xDB44, 3); // shield level gbWriteMemory(0xDB45, 0x30); // arrows gbWriteMemory(0xDB49, 7); // songs gbWriteMemory(0xDB4C, 0x30); // powder gbWriteMemory(0xDB4D, 0x30); // bombs gbWriteMemory(0xDB4E, 3); // sword level gbWriteMemory(0xDB5D, 0x9); // rupees gbWriteMemory(0xDB5E, 0x99); // rupees gbWriteMemory(0xDBD0, 1); // keys #endif } void ZeldaAgesCheat() { #ifdef ALLOWCHEAT int j = 1; for (int i = 0; i <= 14; i++, j++) { switch(j) { case 2: case 0xb: case 0x10: case 0x18: j++; break; case 7: case 0x12: j+=3; } gbWriteMemory(0xC688 + i, j); } gbWriteMemory(0xC697, 0); gbWriteMemory(0xC698, 0); gbWriteMemory(0xC699, 0); gbWriteMemory(0xC6AF, 3); // shield gbWriteMemory(0xC6B2, 3); // sword gbWriteMemory(0xC6B6, 2); // long shot? gbWriteMemory(0xC6B7, 3); // harp's chosen song gbWriteMemory(0xC6B8, 2); // power glove for (j=0xC69F; j<=0xC6A2; j++) gbWriteMemory(j, 0xFF); // secondary items gbWriteMemory(0xC6A3, 0x0C); // mermaid suit for (j=0xC6A4; j<=0xC6A5; j++) gbWriteMemory(j, 0xFF); // secondary items, Brother emblem for (j=0xC6B9; j<=0xC6BD; j++) gbWriteMemory(j, 0x05); // seeds gbWriteMemory(0xC6BF, 0xFF); // essences gbWriteMemory(0xCF14, 0xEA); // GBA shop #endif } void ZeldaSeasonsCheat() { #ifdef ALLOWCHEAT gbWriteMemory(0xC68F, 0); gbWriteMemory(0xC690, 0); gbWriteMemory(0xC691, 0); int j = 1; for (int i = 0; i <= 16; i++, j++) { switch(j) { case 2: case 4: case 9: case 0xb: case 0x14: case 0x18: j++; break; case 0xF: case 0x1a: j+=4; } gbWriteMemory(0xC680 + i, j); } for (j=0xC696; j<=0xC69C; j++) gbWriteMemory(j, 0xFF); // secondary items gbWriteMemory(0xC6A9, 3); // shield gbWriteMemory(0xC6AA, 9); // bombs gbWriteMemory(0xC6AC, 3); // sword gbWriteMemory(0xC6B0, 0xF); // rod of seasons gbWriteMemory(0xC6B1, 2); // boomerang gbWriteMemory(0xC6B2, 2); // ? gbWriteMemory(0xC6B3, 2); // sling shot gbWriteMemory(0xC6B4, 2); // feather/cape for (j=0xC6B5; j<=0xC6BA; j++) gbWriteMemory(j, 0x05); // seeds gbWriteMemory(0xC6BF, 0xFF); // essences gbWriteMemory(0xC6C6, 3); // ring box gbWriteMemory(0xCF14, 0xEA); // GBA shop #endif } u32 LinksAwakeningInput(unsigned short pad) // aka Zelda DX { u16 ItemsAddr = 0xDB00; static bool QuestScreen = false; static int StartCount = 0; static int SwordCount = 0; static bool BombArrows = false; static int DelayCount = 0; bool OnItemScreen = gbReadMemory(0xC16C) == 0x20; // 0x20 = items, 0x10 = normal // There are no Zelda games for PC, so let user choose keyboard controls. // There is Zelda 1 & 2 for Wii VC wiimote but it doesn't make sense to use their controls, // so let user choose sideways wiimote controls. u32 J = StandardMovement(pad) | DecodeKeyboard(pad) | DecodeWiimote(pad); u8 CursorPos = gbReadMemory(0xC1B6) + 2; u8 SelItem = 0; if (CursorPos < 12) SelItem = gbReadMemory(ItemsAddr + CursorPos); // Rumble when they lose health! u8 Health = gbReadMemory(0xDB5A); static u8 OldHealth = 0; if (Health < OldHealth) systemGameRumble(20); OldHealth = Health; bool ActionButton=0, SwordButton=0, ShieldButton=0, PullButton=0, ItemsButton=0, QuestButton=0, MapButton=0, SpeedButton=0, CheatButton=0, MidnaButton=0, #ifdef HW_RVL LeftItemButton=0, DownItemButton=0, RightItemButton=0, #endif BItemButton=0, UseLeftItemButton=0, UseRightItemButton=0; #ifdef HW_RVL WPADData * wp = WPAD_Data(pad); // Nunchuk controls are based on Twilight Princess for the Wii if (wp->exp.type == WPAD_EXP_NUNCHUK) { ActionButton = wp->btns_h & WPAD_BUTTON_A; ShieldButton = wp->btns_h & WPAD_NUNCHUK_BUTTON_Z; SpeedButton = wp->btns_h & WPAD_NUNCHUK_BUTTON_C; MidnaButton = wp->btns_h & WPAD_BUTTON_UP; LeftItemButton = wp->btns_d & WPAD_BUTTON_LEFT; DownItemButton = wp->btns_d & WPAD_BUTTON_DOWN; RightItemButton = wp->btns_d & WPAD_BUTTON_RIGHT; BItemButton = wp->btns_h & WPAD_BUTTON_B; ItemsButton = wp->btns_h & WPAD_BUTTON_MINUS; QuestButton = wp->btns_h & WPAD_BUTTON_PLUS; MapButton = wp->btns_h & WPAD_BUTTON_1; UseLeftItemButton = UseRightItemButton = false; CheatButton = wp->btns_h & WPAD_BUTTON_2; // Sword SwordButton = false; if (fabs(wp->gforce.x)> 1.5 && !OnItemScreen) { if (ZeldaDxDrawSword()) { if (SwordCount<3) SwordCount = 3; } QuestScreen = false; } // Spin attack if (fabs(wp->exp.nunchuk.gforce.x)> 0.6 && !OnItemScreen) { if (ZeldaDxDrawSword()) { if (SwordCount<60) SwordCount=60; } QuestScreen = false; } if (SwordCount>0) { if (SwordCount == 50) systemGameRumbleOnlyFor(50); if (!OnItemScreen) SwordButton = true; SwordCount--; } // Classic controller controls are loosely based on Ocarina of Time virtual console // but with R as the B button like in Twilight Princess } else if (wp->exp.type == WPAD_EXP_CLASSIC) { J |= StandardDPad(pad); signed char wm_sx = WPAD_Stick(pad,1,0); // CC right joystick signed char wm_sy = WPAD_Stick(pad,1,1); // CC right joystick static bool StickReady = true; ActionButton = wp->btns_h & WPAD_CLASSIC_BUTTON_A; SwordButton = wp->btns_h & WPAD_CLASSIC_BUTTON_B; ShieldButton = wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L || wp->exp.classic.ls_raw >= 0x10; LeftItemButton = wp->btns_d & WPAD_CLASSIC_BUTTON_ZR || (StickReady && wm_sx < -70); DownItemButton = wp->btns_d & WPAD_CLASSIC_BUTTON_Y || (StickReady && wm_sy < -70); RightItemButton = wp->btns_d & WPAD_CLASSIC_BUTTON_X || (StickReady && wm_sx > 70); MidnaButton = wm_sy > 70; // right stick up if (abs(wm_sx)>70 || abs(wm_sy)>70) StickReady = false; else if (abs(wm_sx)<50 && abs(wm_sy)<50) StickReady = true; BItemButton = wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R || wp->exp.classic.rs_raw >= 0x10; if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS) J |= VBA_BUTTON_START; if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS) J |= VBA_BUTTON_SELECT; SpeedButton = wp->btns_h & WPAD_CLASSIC_BUTTON_ZL; // Must use Wiimote for these buttons CheatButton = wp->btns_d & WPAD_BUTTON_2; } CheatButton = CheatButton || DownUsbKeys[KB_C]; #endif // Gamecube controls are based on Twilight Princess for the Gamecube { u32 gc = PAD_ButtonsHeld(pad); signed char gc_px = PAD_SubStickX(pad); if (gc_px > 70) J |= VBA_SPEED; ActionButton = ActionButton || gc & PAD_BUTTON_A; PullButton = PullButton || gc & PAD_TRIGGER_R; SwordButton = SwordButton || gc & PAD_BUTTON_B; ShieldButton = ShieldButton || gc & PAD_TRIGGER_L; MidnaButton = MidnaButton || gc & PAD_TRIGGER_Z; UseLeftItemButton = UseLeftItemButton || gc & PAD_BUTTON_Y; UseRightItemButton = UseRightItemButton || gc & PAD_BUTTON_X; ItemsButton = ItemsButton || gc & PAD_BUTTON_UP; QuestButton = QuestButton || gc & PAD_BUTTON_START; MapButton = MapButton || gc & PAD_BUTTON_RIGHT; SpeedButton = SpeedButton || gc & PAD_BUTTON_DOWN; CheatButton = CheatButton || gc & PAD_BUTTON_LEFT; } // Action button, and put away sword if (ActionButton) { if (QuestScreen && OnItemScreen) { if (StartCount>=0) StartCount = -80; } else { if (OnItemScreen) systemGameRumble(5); else { // Unless they are trying to use 2 items at once, put away A item if (!BItemButton && !UseLeftItemButton && !UseRightItemButton) { if (!ZeldaDrawItem(0, ItemsAddr, 12)) // draw nothing if possible ZeldaDrawItem(4, ItemsAddr, 12); // or draw shield } } J |= VBA_BUTTON_A; } } // Sword button if (SwordButton) { if (ZeldaDxDrawSword()) J |= VBA_BUTTON_A; } // Pull button (Gamecube R Trigger) automatically switches to bracelet if (PullButton) { if (ZeldaDrawItem(3, ItemsAddr, 12)) J |= VBA_BUTTON_A; } // Shield and Z targetting if (ShieldButton && !OnItemScreen) { if (!SwordCount) { if (ZeldaDrawItem(4, ItemsAddr, 12)) J |= VBA_BUTTON_A; } QuestScreen = false; } // Z Button Selects bomb arrows on or off if (ShieldButton && OnItemScreen) { if (SelItem==2 || SelItem==5) { // toggle bomb arrows BombArrows = !BombArrows; if (BombArrows) systemGameRumbleOnlyFor(16); else systemGameRumbleOnlyFor(4); if (SelItem==2 && BombArrows) J |= VBA_BUTTON_A; } else if (BombArrows) { // switch off bomb arrows BombArrows = false; systemGameRumbleOnlyFor(4); J |= VBA_BUTTON_A; } QuestScreen = false; } static bool BIsLeft = true; if (UseLeftItemButton) { if (!BIsLeft) { // Swap B with first inventory item ZeldaSwap(0, ZeldaDxLeftPos, ItemsAddr); BIsLeft = true; } if (OnItemScreen) { systemGameRumbleOnlyFor(5); J |= VBA_BUTTON_B; } else { u8 BButtonItem = gbReadMemory(ItemsAddr); if (BombArrows && (BButtonItem==5)) { if (ZeldaDrawItem(2, ItemsAddr, 12)) { J |= VBA_BUTTON_A; DelayCount++; } } else DelayCount = 10; if (DelayCount>1) J |= VBA_BUTTON_B; } QuestScreen = false; } if (UseRightItemButton) { if (BIsLeft) { // Swap B with first inventory item ZeldaSwap(0, ZeldaDxLeftPos, ItemsAddr); BIsLeft = false; } if (OnItemScreen) { systemGameRumbleOnlyFor(5); J |= VBA_BUTTON_B; } else { u8 BButtonItem = gbReadMemory(ItemsAddr); if (BombArrows && (BButtonItem==5)) { if (ZeldaDrawItem(2, ItemsAddr, 12)) { J |= VBA_BUTTON_A; DelayCount++; } } else DelayCount = 10; if (DelayCount>1) J |= VBA_BUTTON_B; } QuestScreen = false; } #ifdef HW_RVL // Left Item if (LeftItemButton) { if (OnItemScreen) ZeldaSwap(ZeldaDxLeftPos, CursorPos, ItemsAddr); else ZeldaSwap(0, ZeldaDxLeftPos, ItemsAddr); systemGameRumbleOnlyFor(5); QuestScreen = false; } // Right Item if (RightItemButton) { if (OnItemScreen) ZeldaSwap(ZeldaDxRightPos, CursorPos, ItemsAddr); else ZeldaSwap(0, ZeldaDxRightPos, ItemsAddr); systemGameRumbleOnlyFor(5); QuestScreen = false; } // Down Item if (DownItemButton) { if (OnItemScreen) ZeldaSwap(ZeldaDxDownPos, CursorPos, ItemsAddr); else ZeldaSwap(0, ZeldaDxDownPos, ItemsAddr); systemGameRumbleOnlyFor(5); QuestScreen = false; } // B Item if (BItemButton) { if (QuestScreen && OnItemScreen) { if (StartCount>=0) StartCount = -80; } else { if (OnItemScreen) { /*if (BombArrows) { if (SelItem==5) { // bow } else { BombArrows = false; } }*/ systemGameRumble(5); DelayCount = 10; } else { u8 BButtonItem = gbReadMemory(ItemsAddr); if (BombArrows && (BButtonItem==5)) { if (ZeldaDrawItem(2, ItemsAddr, 12)) { J |= VBA_BUTTON_A; DelayCount++; } } else DelayCount = 10; } if (DelayCount>1) J |= VBA_BUTTON_B; } } #endif if (!BItemButton && !UseLeftItemButton && !UseRightItemButton) DelayCount = 0; // Talk to Midna, er... I mean save the game if (MidnaButton) { J |= VBA_BUTTON_A | VBA_BUTTON_B | VBA_BUTTON_START | VBA_BUTTON_SELECT; systemGameRumbleOnlyFor(5); QuestScreen = false; } // Map if (MapButton) { QuestScreen = false; J |= VBA_BUTTON_SELECT; } // Items if (ItemsButton) { if (QuestScreen) QuestScreen = false; else J |= VBA_BUTTON_START; } // Quest Status if (QuestButton) { StartCount = 80; if (OnItemScreen) StartCount = -StartCount; } if (StartCount>0) { if (StartCount>75) J |= VBA_BUTTON_START; StartCount--; if (StartCount==0) QuestScreen = true; } else if (StartCount<0) { QuestScreen = false; if (StartCount>=-5) J |= VBA_BUTTON_START; StartCount++; } if (QuestScreen && OnItemScreen) J |= VBA_BUTTON_SELECT; // Cheat if (CheatButton) { ZeldaDxCheat(); QuestScreen = false; } // Camera (fast forward) if (SpeedButton) { J |= VBA_SPEED; QuestScreen = false; } return J; } static u32 ZeldaOracleInput(bool Seasons, unsigned short pad) { u16 ItemsAddr; if (Seasons) ItemsAddr = 0xC680; else ItemsAddr = 0xC688; static u32 OldJ = 0; // There are no Zelda games for PC, so let user choose keyboard controls. // There is Zelda 1 & 2 for Wii VC wiimote but it doesn't make sense to use their controls, // so let user choose sideways wiimote controls. u32 J = StandardMovement(pad) | DecodeKeyboard(pad) | DecodeWiimote(pad); // Rumble when they lose health! u8 Health; if (Seasons) Health = gbReadMemory(0xC6A2); // health in quarters... note C6A3 is max health else Health = gbReadMemory(0xC6AA); // health in quarters... note C6AB is max health static u8 OldHealth = 0; if (Health < OldHealth) systemGameRumble(20); OldHealth = Health; static int DesiredSubscreen = -1; int Subscreen = 0; switch (gbReadMemory(0xCBCB)) { case 0: Subscreen = 0; break; case 1: Subscreen = 1+gbReadMemory(0xCBCF); break; case 2: Subscreen = 4; break; case 3: Subscreen = 5; break; } bool ActionButton=0, SwordButton=0, ShieldButton=0, PullButton=0, ItemsButton=0, QuestButton=0, MapButton=0, SpeedButton=0, CheatButton=0, MidnaButton=0, #ifdef HW_RVL LeftItemButton=0, DownItemButton=0, RightItemButton=0, BItemButton=0, #endif UseLeftItemButton=0, UseRightItemButton=0; bool OnItemScreen = (Subscreen == 1); #ifdef HW_RVL static int SwordCount = 0; WPADData * wp = WPAD_Data(pad); // Nunchuk controls are based on Twilight Princess for the Wii if (wp->exp.type == WPAD_EXP_NUNCHUK) { ActionButton = wp->btns_h & WPAD_BUTTON_A; ShieldButton = wp->btns_h & WPAD_NUNCHUK_BUTTON_Z; SpeedButton = wp->btns_h & WPAD_NUNCHUK_BUTTON_C; MidnaButton = wp->btns_d & WPAD_BUTTON_UP; LeftItemButton = wp->btns_d & WPAD_BUTTON_LEFT; DownItemButton = wp->btns_d & WPAD_BUTTON_DOWN; RightItemButton = wp->btns_d & WPAD_BUTTON_RIGHT; BItemButton = wp->btns_h & WPAD_BUTTON_B; ItemsButton = wp->btns_d & WPAD_BUTTON_MINUS; QuestButton = wp->btns_d & WPAD_BUTTON_PLUS; MapButton = wp->btns_d & WPAD_BUTTON_1; CheatButton = wp->btns_d & WPAD_BUTTON_2; // Sword SwordButton = false; if (fabs(wp->gforce.x)> 1.5 && !OnItemScreen) { if (SwordCount<3) SwordCount = 3; } // Spin attack if (fabs(wp->exp.nunchuk.gforce.x)> 0.6 && !OnItemScreen) { if (SwordCount<60) SwordCount=60; } if (SwordCount>0) { if (SwordCount == 50) systemGameRumbleOnlyFor(50); if (!OnItemScreen) SwordButton = true; SwordCount--; } // Classic controller controls are loosely based on Ocarina of Time virtual console // but with R as the B button like in Twilight Princess } else if (wp->exp.type == WPAD_EXP_CLASSIC) { J |= StandardDPad(pad); signed char wm_sx = WPAD_Stick(pad,1,0); // CC right joystick signed char wm_sy = WPAD_Stick(pad,1,1); // CC right joystick static bool StickReady = true; ActionButton = wp->btns_h & WPAD_CLASSIC_BUTTON_A; SwordButton = wp->btns_h & WPAD_CLASSIC_BUTTON_B; ShieldButton = wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L || wp->exp.classic.ls_raw >= 0x10; LeftItemButton = wp->btns_d & WPAD_CLASSIC_BUTTON_ZR || (StickReady && wm_sx < -70); DownItemButton = wp->btns_d & WPAD_CLASSIC_BUTTON_Y || (StickReady && wm_sy < -70); RightItemButton = wp->btns_d & WPAD_CLASSIC_BUTTON_X || (StickReady && wm_sx > 70); if (abs(wm_sx)>70 || abs(wm_sy)>70) StickReady = false; else if (abs(wm_sx)<50 && abs(wm_sy)<50) StickReady = true; BItemButton = wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R || wp->exp.classic.rs_raw >= 0x10; if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS) J |= VBA_BUTTON_START; if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS) J |= VBA_BUTTON_SELECT; SpeedButton = wp->btns_h & WPAD_CLASSIC_BUTTON_ZL; // Must use Wiimote for these buttons CheatButton = wp->btns_d & WPAD_BUTTON_2; } CheatButton = CheatButton || DownUsbKeys[KB_C]; #endif // Gamecube controls are based on Twilight Princess for the Gamecube { u32 gc = PAD_ButtonsHeld(pad); u32 pressed = PAD_ButtonsDown(pad); signed char gc_px = PAD_SubStickX(pad); if (gc_px > 70) J |= VBA_SPEED; ActionButton = ActionButton || gc & PAD_BUTTON_A; PullButton = PullButton || gc & PAD_TRIGGER_R; SwordButton = SwordButton || gc & PAD_BUTTON_B; ShieldButton = ShieldButton || gc & PAD_TRIGGER_L; MidnaButton = MidnaButton || pressed & PAD_TRIGGER_Z; UseLeftItemButton = UseLeftItemButton || gc & PAD_BUTTON_Y; UseRightItemButton = UseRightItemButton || gc & PAD_BUTTON_X; ItemsButton = ItemsButton || pressed & PAD_BUTTON_UP; QuestButton = QuestButton || pressed & PAD_BUTTON_START; MapButton = MapButton || pressed & PAD_BUTTON_RIGHT; SpeedButton = SpeedButton || gc & PAD_BUTTON_DOWN; CheatButton = CheatButton || gc & PAD_BUTTON_LEFT; } static int OldDesiredSubscreen = -1, DelayCount = 0; OldDesiredSubscreen = DesiredSubscreen; // Items if (ItemsButton) { if (Subscreen == 1) DesiredSubscreen = 0; else DesiredSubscreen = 1; DelayCount = 1; } // Talk to Midna, er... I mean go to secondary items screen if (MidnaButton) { if (Subscreen == 2) DesiredSubscreen = 0; else DesiredSubscreen = 2; DelayCount = 1; } // Quest Status if (QuestButton) { if (Subscreen == 3) DesiredSubscreen = 0; else DesiredSubscreen = 3; DelayCount = 1; } // Map if (MapButton) { if (Subscreen == 4) DesiredSubscreen = 0; else DesiredSubscreen = 4; DelayCount = 1; } // after using sword, need to release A button before using shield static int SheathCount = 0; if (OldJ & VBA_BUTTON_A) { if (gbReadMemory(ItemsAddr+1)==5) SheathCount = 15; } #ifdef HW_RVL u8 CursorPos = gbReadMemory(0xCBD0)+2; // Can't swap items if using two handed sword unless on item screen if (OnItemScreen || (gbReadMemory(ItemsAddr+0)!=0x0C && gbReadMemory(ItemsAddr+1)!=0x0C)) { // Left Item if (LeftItemButton) { if (OnItemScreen) ZeldaSwap(2, CursorPos, ItemsAddr); else ZeldaSwap(0, ZeldaDxLeftPos, ItemsAddr); systemGameRumbleOnlyFor(5); } // Right Item if (RightItemButton) { if (OnItemScreen) ZeldaSwap(4, CursorPos, ItemsAddr); else ZeldaSwap(0, ZeldaDxRightPos, ItemsAddr); systemGameRumbleOnlyFor(5); } // Down Item if (DownItemButton) { if (OnItemScreen) ZeldaSwap(3, CursorPos, ItemsAddr); else ZeldaSwap(0, ZeldaDxDownPos, ItemsAddr); systemGameRumbleOnlyFor(5); } } // B Item if (BItemButton) { if (OnItemScreen) systemGameRumbleOnlyFor(5); J |= VBA_BUTTON_B; } #endif static bool BIsLeft = true; if (UseLeftItemButton) { if (!BIsLeft) { // Fix two-handed sword before swap if (gbReadMemory(ItemsAddr+0)==0x0C && gbReadMemory(ItemsAddr+1)==0x0C && !OnItemScreen) { } else { bool DrawingTwoHanded = (gbReadMemory(ItemsAddr+2)==0x0C); if (DrawingTwoHanded) DrawingTwoHanded = ZeldaDrawItem(0, ItemsAddr, 18); // put A item away (by drawing emptiness) // Swap B with first inventory item ZeldaSwap(0, ZeldaDxLeftPos, ItemsAddr); if (DrawingTwoHanded) gbWriteMemory(ItemsAddr+1, 0x0C); BIsLeft = true; } } if (OnItemScreen) systemGameRumbleOnlyFor(5); J |= VBA_BUTTON_B; } if (UseRightItemButton) { if (BIsLeft) { // Fix two-handed sword before swap if (gbReadMemory(ItemsAddr+0)==0x0C && gbReadMemory(ItemsAddr+1)==0x0C && !OnItemScreen) { } else { bool DrawingTwoHanded = (gbReadMemory(ItemsAddr+2)==0x0C); if (DrawingTwoHanded) DrawingTwoHanded = ZeldaDrawItem(0, ItemsAddr, 18); // put A item away (by drawing emptiness) // Swap B with first inventory item ZeldaSwap(0, ZeldaDxLeftPos, ItemsAddr); if (DrawingTwoHanded) gbWriteMemory(ItemsAddr+1, 0x0C); BIsLeft = false; } } if (OnItemScreen) systemGameRumbleOnlyFor(5); J |= VBA_BUTTON_B; } // Action if (ActionButton) { if (!OnItemScreen) { // If not using 2-handed sword then switch to holding nothing or shield if (gbReadMemory(ItemsAddr+1)!=0x0C && !ZeldaDrawItem(0, ItemsAddr, 18))// draw nothing or shield ZeldaDrawItem(1, ItemsAddr, 18); } J |= VBA_BUTTON_A; } // Z-Targetting if (ShieldButton && !SwordButton) { // Fix two-handed sword before swap if (gbReadMemory(ItemsAddr+0)==0x0C && gbReadMemory(ItemsAddr+1)==0x0C) gbWriteMemory(ItemsAddr+0, 0); if (SheathCount>0) {// was using sword before ZeldaDrawItem(1, ItemsAddr, 18); SheathCount--; } else if (ZeldaDrawItem(1, ItemsAddr, 18)) J |= VBA_BUTTON_A; } // Pulling if (PullButton) { // Fix two-handed sword before swap if (gbReadMemory(ItemsAddr+0)==0x0C && gbReadMemory(ItemsAddr+1)==0x0C) gbWriteMemory(ItemsAddr+0, 0); if (ZeldaDrawItem(0x16, ItemsAddr, 18)) J |= VBA_BUTTON_A; } // Sword if (SwordButton) { if (ShieldButton && gbReadMemory(ItemsAddr+1)==1) // was using shield before ZeldaDrawItem(5, ItemsAddr, 18); else if (gbReadMemory(ItemsAddr)==0x0C || gbReadMemory(ItemsAddr+1)==0x0C || ZeldaDrawItem(5, ItemsAddr, 18)) J |= VBA_BUTTON_A; } // Camera (fast forward) if (SpeedButton) J |= VBA_SPEED; // Cheat if (CheatButton) { if (Seasons) ZeldaSeasonsCheat(); else ZeldaAgesCheat(); } if (DesiredSubscreen == Subscreen) DesiredSubscreen = -1; static int OldSubscreen = 0; if (Subscreen != OldSubscreen) { if (Subscreen==1) DelayCount = 80; // wait for items screen to fade in else DelayCount = 20; // wait to swap subscreens } OldSubscreen = Subscreen; if (DelayCount > 0) { // do nothing DelayCount--; } else if (DesiredSubscreen == 0) { // game switch(Subscreen) { case 1: case 2: case 3: case 5: default: J |= VBA_BUTTON_START; break; case 4: // map J |= VBA_BUTTON_SELECT; } } else if (DesiredSubscreen == 1) { // items switch(Subscreen) { case 0: case 5: default: // game or save J |= VBA_BUTTON_START; break; case 2: case 3: case 4: J |= VBA_BUTTON_SELECT; } } else if (DesiredSubscreen == 2) { // secondary items switch(Subscreen) { case 0: case 5: default: // game or save J |= VBA_BUTTON_START; break; case 1: case 3: case 4: J |= VBA_BUTTON_SELECT; } } else if (DesiredSubscreen == 3) { // quest status switch(Subscreen) { case 0: case 5: default: // game or save J |= VBA_BUTTON_START; break; case 1: case 2: case 4: J |= VBA_BUTTON_SELECT; } } else if (DesiredSubscreen == 4) { // map switch(Subscreen) { case 0: // game J |= VBA_BUTTON_SELECT; break; case 1: case 2: case 3: case 5: default: J |= VBA_BUTTON_START; } } else if (DesiredSubscreen == 5) { // save switch(Subscreen) { case 0: default: // game J |= VBA_BUTTON_START; break; case 1: case 2: case 4: // other J |= VBA_BUTTON_SELECT; break; case 3: // quest status J |= VBA_RIGHT; // give up, this is as close as I can be bothered to get DesiredSubscreen = -1; } } OldJ = J; return J; } u32 OracleOfAgesInput(unsigned short pad) { return ZeldaOracleInput(false, pad); } u32 OracleOfSeasonsInput(unsigned short pad) { return ZeldaOracleInput(true, pad); } u32 MinishCapInput(unsigned short pad) { u32 J = StandardMovement(pad) | DecodeKeyboard(pad) | DecodeWiimote(pad); // Rumble when they lose health! u8 Health = CPUReadByte(0x2002aea); static u8 OldHealth = 0; if (Health < OldHealth) systemGameRumble(20); OldHealth = Health; static u8 SubscreenWanted = 0xFF; static bool waiting = false; u8 Subscreen = CPUReadByte(0x200008C); if (Subscreen == 0x64) Subscreen = 0; // Boss battle (balloon) u8 GameStart = CPUReadByte(0x2000086); u8 SelBox = CPUReadByte(0x2000083); u8 LoadMenu = CPUReadByte(0x200AF57); static u8 AButtonItem = 0; static u8 BButtonItem = 0; if (Subscreen == 0x2c) { AButtonItem = CPUReadByte(0x200af3c); BButtonItem = CPUReadByte(0x200af5c); } else if (Subscreen == 0) { AButtonItem = CPUReadByte(0x200af5c); BButtonItem = CPUReadByte(0x200af7c); } static int frame = 0; u32 SwordButtonNumber = 0; u32 ZTargetButton = 0; if (AButtonItem <= 6 && AButtonItem >= 1) SwordButtonNumber = VBA_BUTTON_A; else if (BButtonItem <= 6 && BButtonItem >= 1) SwordButtonNumber = VBA_BUTTON_B; else SwordButtonNumber = VBA_BUTTON_START; // Shield if (BButtonItem >= 0xD && BButtonItem <= 0xE) ZTargetButton = VBA_BUTTON_B; else if (AButtonItem >= 0xD && AButtonItem <= 0xE) ZTargetButton = VBA_BUTTON_A; // Gust Jar also does Z targetting else if (BButtonItem == 0x11) ZTargetButton = VBA_BUTTON_B; else if (AButtonItem == 0x11) ZTargetButton = VBA_BUTTON_A; else ZTargetButton = 0; bool ActionButton=0, SwordButton=0, ShieldButton=0, PullButton=0, ItemsButton=0, QuestButton=0, MapButton=0, SpeedButton=0, CheatButton=0, MidnaButton=0, LeftItemButton=0, DownItemButton=0, RightItemButton=0, BItemButton=0, UseLeftItemButton=0, UseRightItemButton=0; #ifdef HW_RVL bool OnItemScreen = (Subscreen==0x2c); u8 RButtonAction = CPUReadByte(0x200af32); WPADData * wp = WPAD_Data(pad); // Wii Pointer selection on item screen int cx, cy, SelRow, SelCol, CursorRow = 0xFF, CursorCol = 0xFF; static int OldCursorRow = 0xFF; static int OldCursorCol = 0xFF; CursorVisible = ((Subscreen != 0 && Subscreen != 0x64) || LoadMenu == 2); if (CursorVisible) { cx = (CursorX * 240) / 640; cy = (CursorY * 160) / 480; } else { cx = -1; cy = -1; } if (Subscreen == 0x2c) { SelRow = SelBox / 4; SelCol = SelBox % 4; if (SelBox == 16) { SelRow = 3; SelCol = 4; } else if (SelRow < 3 && SelCol >= 2) SelCol++; if (cy >= 35 && cy <= 55) CursorRow = 0; else if (cy >= 59 && cy <= 79) CursorRow = 1; else if (cy >= 83 && cy <= 103) CursorRow = 2; else if (cy >= 107 && cy <= 127) CursorRow = 3; else CursorRow = 0xFF; if (CursorRow < 3) { if (cx >= 52 && cx <= 79) CursorCol = 0; else if (cx >= 88 && cx <= 116) CursorCol = 1; else if (cx >= 124 && cx <= 152) CursorCol = 3; else if (cx >= 160 && cx <= 188) CursorCol = 4; else CursorCol = 0xFF; } else { if (cx >= 157 && cx <= 204) CursorCol = 4; else if (cx >= 52 && cx < 152) CursorCol = (cx - 52) / 25; else CursorCol = 0xFF; } if (CursorCol != 0xFF && CursorRow != 0xFF && (CursorCol != SelCol || CursorRow != SelRow)) { if (CursorCol > SelCol) J |= VBA_RIGHT; else if (CursorCol < SelCol) J |= VBA_LEFT; else if (CursorRow > SelRow) J |= VBA_DOWN; else if (CursorRow < SelRow) J |= VBA_UP; } } else if (Subscreen == 0x38) { switch (SelBox) { case 0: case 1: case 10: case 9: case 11: SelRow = 0; break; case 12: SelRow = 1; break; case 2: case 3: case 13: case 14: case 15: SelRow = 2; break; case 6: case 7: case 8: case 4: case 5: SelRow = 3; break; default: SelRow = 0xFF; break; } switch (SelBox) { case 0: case 2: case 6: SelCol = 0; break; case 7: SelCol = 1; break; case 1: case 3: case 8: SelCol = 2; break; case 10: case 13: case 4: SelCol = 3; break; case 9: case 12: case 14: SelCol = 4; break; case 11: case 15: case 5: SelCol = 5; break; default: SelCol = 0xFF; break; } if (cy >= 109 && cy <= 130) { CursorRow = 3; if (cx >= 36 && cx <= 113) CursorCol = (cx - 36) / 26; else if (cx >= 118 && cx <= 165) CursorCol = 3; else if (cx >= 168 && cx <= 215) CursorCol = 5; else CursorCol = 0xFF; } else { if (cx >= 35 && cx <= 70) { CursorCol = 0; if (cy >= 40 && cy <= 73) CursorRow = 0; else if (cy >= 79 && cy <= 104) CursorRow = 2; else CursorRow = 0xFF; } else if (cx >= 78 && cx <= 113) { CursorCol = 2; if (cy >= 40 && cy <= 73) CursorRow = 0; else if (cy >= 79 && cy <= 104) CursorRow = 2; else CursorRow = 0xFF; } else { if (cx >= 125 && cx <= 148) { CursorCol = 3; if (cy >= 44 && cy <= 65) CursorRow = 0; else if (cy >= 83 && cy <= 104) CursorRow = 2; else CursorRow = 0xFF; } else if (cx >= 151 && cx <= 172) { CursorCol = 4; if (cy >= 31 && cy <= 53) CursorRow = 0; else if (cy >= 57 && cy <= 78) CursorRow = 1; else if (cy >= 83 && cy <= 104) CursorRow = 2; else CursorRow = 0xFF; } else if (cx >= 175 && cx <= 198) { CursorCol = 5; if (cy >= 44 && cy <= 65) CursorRow = 0; else if (cy >= 83 && cy <= 104) CursorRow = 2; else CursorRow = 0xFF; } else { CursorCol = 0xFF; CursorRow = 0xFF; } } } if (CursorCol != 0xFF && CursorRow != 0xFF && (CursorCol != SelCol || CursorRow != SelRow)) { if (CursorCol > SelCol) J |= VBA_RIGHT; else if (CursorCol < SelCol) J |= VBA_LEFT; else if (CursorRow > SelRow) J |= VBA_DOWN; else if (CursorRow < SelRow) J |= VBA_UP; } } if ((CursorRow == 0xFF || CursorCol == 0xFF) && (OldCursorRow == 0xFF || OldCursorCol == 0xFF)) { // no change, still not pointing at anything } else if (CursorVisible && (CursorRow != OldCursorRow || CursorCol != OldCursorCol)) { // Cursor changed buttons, so rumble //systemGameRumble(5); } OldCursorRow = CursorRow; OldCursorCol = CursorCol; static int SwordCount = 0; // Nunchuk controls are based on Twilight Princess for the Wii if (wp->exp.type == WPAD_EXP_NUNCHUK) { ActionButton = wp->btns_h & WPAD_BUTTON_A; ShieldButton = wp->btns_h & WPAD_NUNCHUK_BUTTON_Z; SpeedButton = wp->btns_h & WPAD_NUNCHUK_BUTTON_C; MidnaButton = wp->btns_h & WPAD_BUTTON_UP; LeftItemButton = wp->btns_h & WPAD_BUTTON_LEFT; DownItemButton = wp->btns_h & WPAD_BUTTON_DOWN; RightItemButton = wp->btns_h & WPAD_BUTTON_RIGHT; BItemButton = wp->btns_h & WPAD_BUTTON_B; ItemsButton = wp->btns_d & WPAD_BUTTON_MINUS; QuestButton = wp->btns_d & WPAD_BUTTON_PLUS; MapButton = wp->btns_d & WPAD_BUTTON_1; CheatButton = wp->btns_h & WPAD_BUTTON_2; // Sword SwordButton = false; if (fabs(wp->gforce.x)> 1.5 && !OnItemScreen) { if (SwordCount<3) SwordCount = 3; } // Throw gesture if (RButtonAction==0x03) { if (fabs(wp->exp.nunchuk.gforce.y)> 0.6) { J |= VBA_BUTTON_R; systemGameRumble(5); } // Spin attack } else if (fabs(wp->exp.nunchuk.gforce.x)> 0.6 && !OnItemScreen) { if (SwordCount<60) SwordCount=60; } if (SwordCount>0) { if (SwordCount == 50) systemGameRumbleOnlyFor(50); if (!OnItemScreen) SwordButton = true; SwordCount--; } // Classic controller controls are loosely based on Ocarina of Time virtual console // but with R as the B button like in Twilight Princess } else if (wp->exp.type == WPAD_EXP_CLASSIC) { J |= StandardDPad(pad); signed char wm_sx = WPAD_Stick(pad,1,0); // CC right joystick signed char wm_sy = WPAD_Stick(pad,1,1); // CC right joystick static bool StickReady = true; ActionButton = wp->btns_h & WPAD_CLASSIC_BUTTON_A; SwordButton = wp->btns_h & WPAD_CLASSIC_BUTTON_B; ShieldButton = wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L || wp->exp.classic.ls_raw >= 0x10; if (abs(wm_sx)>80 || abs(wm_sy)>80) StickReady = true; LeftItemButton = wp->btns_h & WPAD_CLASSIC_BUTTON_ZR || (StickReady && wm_sx < -70); DownItemButton = wp->btns_h & WPAD_CLASSIC_BUTTON_Y || (StickReady && wm_sy < -70); RightItemButton = wp->btns_h & WPAD_CLASSIC_BUTTON_X || (StickReady && wm_sx > 70); MidnaButton = wm_sy > 70; if (abs(wm_sx)<70 && abs(wm_sy)<70) StickReady = false; BItemButton = wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R || wp->exp.classic.rs_raw >= 0x10; if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS) J |= VBA_BUTTON_START; if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS) J |= VBA_BUTTON_SELECT; SpeedButton = wp->btns_h & WPAD_CLASSIC_BUTTON_ZL; // Must use Wiimote for these buttons CheatButton = wp->btns_h & WPAD_BUTTON_2; } CheatButton = CheatButton || DownUsbKeys[KB_C]; #endif // Gamecube controls are based on Twilight Princess for the Gamecube { u32 gc = PAD_ButtonsHeld(pad); u32 pressed = PAD_ButtonsDown(pad); signed char gc_px = PAD_SubStickX(pad); if (gc_px > 70) J |= VBA_SPEED; ActionButton = ActionButton || gc & PAD_BUTTON_A; PullButton = PullButton || gc & PAD_TRIGGER_R; SwordButton = SwordButton || gc & PAD_BUTTON_B; ShieldButton = ShieldButton || gc & PAD_TRIGGER_L; MidnaButton = MidnaButton || pressed & PAD_TRIGGER_Z; UseLeftItemButton = UseLeftItemButton || gc & PAD_BUTTON_Y; UseRightItemButton = UseRightItemButton || gc & PAD_BUTTON_X; ItemsButton = ItemsButton || pressed & PAD_BUTTON_UP; QuestButton = QuestButton || pressed & PAD_BUTTON_START; MapButton = MapButton || pressed & PAD_BUTTON_RIGHT; SpeedButton = SpeedButton || gc & PAD_BUTTON_DOWN; LeftItemButton = CheatButton || gc & PAD_BUTTON_LEFT; } if (ItemsButton) { // items if (Subscreen == 0x2c) SubscreenWanted = 0; else SubscreenWanted = 0x2c; waiting = false; } else if (MapButton) { // map if (Subscreen == 0x0c || Subscreen==0x70) SubscreenWanted = 0; else SubscreenWanted = 0x0c; waiting = false; } else if (QuestButton) { // quest if (Subscreen == 0x38) SubscreenWanted = 0; else SubscreenWanted = 0x38; waiting = false; } else if (ActionButton && Subscreen == 0x2c && SelBox!=16) { SubscreenWanted = 0; waiting = false; } else if (BItemButton && Subscreen == 0x38) { SubscreenWanted = 0; waiting = false; } if (GameStart==2 || GameStart==3) { SubscreenWanted = 0; waiting = false; if (QuestButton || (ActionButton && BButtonItem)) J |= VBA_BUTTON_START; return J; } else if (LoadMenu==2) { if (MidnaButton) J |= VBA_UP; if (DownItemButton) J |= VBA_DOWN; if (LeftItemButton) J |= VBA_LEFT; if (RightItemButton) J |= VBA_RIGHT; if (ActionButton) J |= VBA_BUTTON_A; if (BButtonItem) J |= VBA_BUTTON_B; if (QuestButton) J |= VBA_BUTTON_R; if (ItemsButton) J |= VBA_BUTTON_L; if (MapButton) J |= VBA_BUTTON_SELECT; if (CheatButton) J |= VBA_BUTTON_START; if (SpeedButton) J |= VBA_BUTTON_SELECT; if (ShieldButton) J |= VBA_BUTTON_START; return J; } //0c = map //70 = dungeon map //38 = quest //2c = items //89 = KINSTONE PIECES //f0 = SWORD TECHNIQUES //00 = none or changing or save //64 = Boss battle (balloon thing) //FF = don't care! //; if (Subscreen == 0x70 && SubscreenWanted == 0x0c) { SubscreenWanted = 0xFF; waiting = false; } if (Subscreen != SubscreenWanted && SubscreenWanted != 0xFF) { frame++; if (frame % 2 == 0) switch (Subscreen) { case 0: frame = 0; if (!waiting) { waiting = true; //waittime = J |= VBA_BUTTON_START; } break; case 0x0c: // map case 0x70: if (SubscreenWanted == 0x38) J |= VBA_BUTTON_L; // quest else if (SubscreenWanted == 0x2c) J |= VBA_BUTTON_R; // items else J |= VBA_BUTTON_START; waiting = false; break; case 0x2c: // items if (SubscreenWanted == 0x0c || SubscreenWanted == 0x70) J |= VBA_BUTTON_L; // map else if (SubscreenWanted == 0x38) J |= VBA_BUTTON_R; // quest else J |= VBA_BUTTON_START; waiting = false; break; case 0x38: // quest if (SubscreenWanted == 0x2c) J |= VBA_BUTTON_L; // map else if (SubscreenWanted == 0x0c || SubscreenWanted == 0x70) J |= VBA_BUTTON_R; // quest else J |= VBA_BUTTON_START; // CAKTODO: kinstone and sword techniques waiting = false; break; case 0x89: // kinstone case 0xF0: // sword techniques J |= VBA_BUTTON_B; // cancel waiting = false; break; } } else { SubscreenWanted = 0xFF; waiting = false; } /*** Report wp->btns_h buttons (gamepads) ***/ // Talk to Midna, er... I mean Ezlo if (MidnaButton) J |= VBA_BUTTON_SELECT; // Save button if ((Subscreen==0x2c && SelBox==16) || (Subscreen==0x38 && SelBox==5)) { if (ActionButton) { J |= VBA_BUTTON_A; systemGameRumble(12); } } else if (Subscreen==0x2c) { } else if (Subscreen==0x38 && SelBox==4) { // Sleep button returns to menu instead of sleep if (ActionButton) { ConfigRequested = 1; return 0; } } else if (Subscreen==0x38) { // Action button counts as A Button on quest status screen // Action if (ActionButton) { J |= VBA_BUTTON_A; //systemGameRumble(4); } } else { // Action if (ActionButton) J |= VBA_BUTTON_R; } // Right Item if (RightItemButton || UseRightItemButton) { J |= VBA_BUTTON_A; if (Subscreen==0x2c) { systemGameRumble(10); } } // Down Item if (Subscreen==0x38) { } else { if (BItemButton) { J |= VBA_BUTTON_B; if (Subscreen==0x2c) { systemGameRumble(10); } } } if (DownItemButton || UseLeftItemButton) { J |= VBA_BUTTON_B; if (Subscreen==0x2c) { systemGameRumble(10); } } // Kinstone (doesn't work in items screen) if (LeftItemButton && Subscreen != 0x2c) J |= VBA_BUTTON_L; // Menu if (CheatButton) J |= VBA_BUTTON_START; // Sword if (Subscreen == 0 && SwordButton) J |= SwordButtonNumber; // Z-Targetting if (Subscreen==0 && ShieldButton) J |= ZTargetButton; // Camera (use as extra way of pressing A without using DPad) if (SpeedButton) J |= VBA_BUTTON_A; // Pull (I was going to check RButtonAction, but the in-game text always tells you to // use R as the action button, so let's just make Gamecube R = Gameboy R) if (PullButton) J |= VBA_BUTTON_R; return J; } u32 ALinkToThePastInput(unsigned short pad) { u32 J = StandardMovement(pad); u8 Health = 0; static u8 OldHealth = 0; // Rumble when they lose health! if (Health < OldHealth) systemGameRumble(20); OldHealth = Health; #ifdef HW_RVL WPADData * wp = WPAD_Data(pad); // Talk to Midna, er... I mean ... nobody if (wp->btns_h & WPAD_BUTTON_UP) J |= VBA_BUTTON_START; // Action if (wp->btns_h & WPAD_BUTTON_A) J |= VBA_BUTTON_R; if (wp->exp.type == WPAD_EXP_NUNCHUK) { if (fabs(wp->exp.nunchuk.gforce.x)> 0.6) { // Wiiuse bug!!! Not correct values J |= VBA_BUTTON_B; systemGameRumble(20); } // CAKTODO hold down attack button to do spin attack } // Use item if (wp->btns_h & WPAD_BUTTON_B) { J |= VBA_BUTTON_A; } if (wp->btns_h & WPAD_BUTTON_LEFT) { J |= VBA_BUTTON_A; } if (wp->btns_h & WPAD_BUTTON_RIGHT) { J |= VBA_BUTTON_A; } if (wp->btns_h & WPAD_BUTTON_DOWN) { J |= VBA_BUTTON_A; } // Menu (like Quest Status) if (wp->btns_h & WPAD_BUTTON_PLUS) J |= VBA_BUTTON_START; // Items if (wp->btns_h & WPAD_BUTTON_MINUS) J |= VBA_BUTTON_SELECT; // Map if (wp->btns_h & WPAD_BUTTON_1) J |= VBA_BUTTON_L; // Sword if (fabs(wp->gforce.x)> 1.5) J |= VBA_BUTTON_B; if (wp->btns_h & WPAD_BUTTON_2) J |= VBA_BUTTON_B; // Shield has no controls // Camera (speed) if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_C)) J |= VBA_SPEED; #endif return J; } u32 Zelda1Input(unsigned short pad) { u32 J = StandardMovement(pad); u8 Health = 0; static u8 OldHealth = 0; // Rumble when they lose health! if (Health < OldHealth) systemGameRumble(20); OldHealth = Health; #ifdef HW_RVL WPADData * wp = WPAD_Data(pad); // Talk to Midna, er... I mean ... nobody if (wp->btns_h & WPAD_BUTTON_UP) J |= 0; // Action if (wp->btns_h & WPAD_BUTTON_A) J |= VBA_BUTTON_A; if (wp->exp.type == WPAD_EXP_NUNCHUK) { if (fabs(wp->exp.nunchuk.gforce.x)> 0.6) { // Wiiuse bug!!! Not correct values J |= VBA_BUTTON_A; systemGameRumble(20); } } // Use item if (wp->btns_h & WPAD_BUTTON_B) { J |= VBA_BUTTON_B; } if (wp->btns_h & WPAD_BUTTON_LEFT) { J |= VBA_BUTTON_B; } if (wp->btns_h & WPAD_BUTTON_RIGHT) { J |= VBA_BUTTON_A; } if (wp->btns_h & WPAD_BUTTON_DOWN) { J |= VBA_BUTTON_B; } // Menu (like Quest Status) if (wp->btns_h & WPAD_BUTTON_PLUS) J |= VBA_BUTTON_SELECT; // Items if (wp->btns_h & WPAD_BUTTON_MINUS) J |= VBA_BUTTON_START; // Map if (wp->btns_h & WPAD_BUTTON_1) J |= 0; // Sword if (fabs(wp->gforce.x)> 1.5) J |= VBA_BUTTON_A; // Shield has no controls // Camera (speed) if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_C)) J |= VBA_SPEED; #endif return J; } u32 Zelda2Input(unsigned short pad) { u32 J = StandardMovement(pad); u8 Health = 0; static u8 OldHealth = 0; // Rumble when they lose health! if (Health < OldHealth) systemGameRumble(20); OldHealth = Health; #ifdef HW_RVL WPADData * wp = WPAD_Data(pad); // Talk to Midna, er... I mean ... nobody if (wp->btns_h & WPAD_BUTTON_UP) J |= 0; // Jump if (wp->btns_h & WPAD_BUTTON_A) J |= VBA_BUTTON_A; // spin attack if (wp->exp.type == WPAD_EXP_NUNCHUK) { if (fabs(wp->exp.nunchuk.gforce.x)> 0.6) { // Wiiuse bug!!! Not correct values J |= VBA_BUTTON_B; systemGameRumble(20); } } // Use item if (wp->btns_h & WPAD_BUTTON_B) { J |= VBA_BUTTON_SELECT; } if (wp->btns_h & WPAD_BUTTON_LEFT) { J |= VBA_BUTTON_SELECT; } if (wp->btns_h & WPAD_BUTTON_RIGHT) { J |= VBA_BUTTON_SELECT; } if (wp->btns_h & WPAD_BUTTON_DOWN) { J |= VBA_BUTTON_SELECT; } // Menu (like Quest Status) if (wp->btns_h & WPAD_BUTTON_PLUS) J |= VBA_BUTTON_START; // Items if (wp->btns_h & WPAD_BUTTON_MINUS) J |= VBA_BUTTON_START; // Map if (wp->btns_h & WPAD_BUTTON_1) J |= 0; // Sword if (fabs(wp->gforce.x)> 1.5) J |= VBA_BUTTON_B; // No shield control, just duck if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z)) J |= VBA_DOWN; // Camera (speed) if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_C)) J |= VBA_SPEED; #endif return J; }