mirror of
https://github.com/dborth/vbagx.git
synced 2025-07-09 15:05:49 +02:00

* "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
1655 lines
45 KiB
C++
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;
|
|
}
|
|
|