Files
vbagx/source/ngc/inputzelda.cpp
dborth 2d9b7ef1f9 [1.0.8 - April 4, 2009]
* "Match Wii Game" controls option! Games that have a Wii equivalent can be
  played using the controls for that Wii game. For example all Zelda games
  can be played with Twilight Princess controls. See the Instructions section
  below for important details.
* Rotation/Tilt sensor games all work
* Solar sensors (Boktai 1/2/3)
* Rumble (except for games that rely on Gameboy Player)
* Keyboard
* PAL support, finally!
* New scaling options, choose how much stretching you want
* Colourised games now partially work but still have distortion
* "Corvette" no longer has a screwed up palette (but still crashes)
* Triggers net reconnection on SMB failure
* Source code refactored, and project file added
* Instructions section added to this readme file
2009-04-10 03:16:28 +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;
}