vbagx/source/ngc/inputzelda.cpp
dborth c42a5d40a7 [1.0.9 - April 7, 2009]
* Gamecube controller should no longer rumble constantly
2009-04-10 03:19:29 +00:00

1655 lines
45 KiB
C++

/****************************************************************************
* Visual Boy Advance GX
*
* Carl Kenner Febuary 2009
*
* inputzelda.cpp
*
* Wii/Gamecube controls for Legend of Zelda games
***************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ogcsys.h>
#include <unistd.h>
#include <wiiuse/wpad.h>
#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"
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()
{
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
}
void ZeldaAgesCheat()
{
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
}
void ZeldaSeasonsCheat()
{
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
}
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;
}