Much improved Wii controls, especially Zelda, now falls through to configured controls.

Added controls for One Piece.
Fixed in-game cursor.
Removed annoying rumble from Minish Cap items screen.
Added change list and instructions to readme.txt.
Moved some of the functions from gameinput.cpp.
I think it is ready for release.
This commit is contained in:
Carl.Kenner 2009-04-02 23:41:09 +00:00
parent f4715d3c26
commit 5727662110
9 changed files with 4491 additions and 3355 deletions

View File

@ -12,7 +12,8 @@ With it you can play GBA/Game Boy Color/Game Boy games on your Wii/GameCube.
-=[ Features ]=-
* Wiimote, Nunchuk, Classic, Gamecube controller, Keyboard, and Mouse support
* Wiimote, Nunchuk, Classic, Gamecube controller, and Keyboard support
* Rotation sensors, Solar sensors, and Rumble support
* Optional special Wii controls built-in for some games
* SRAM and State saving
* IPS/UPS/PPF patch support
@ -27,6 +28,23 @@ With it you can play GBA/Game Boy Color/Game Boy games on your Wii/GameCube.
|0O×øo· UPDATE HISTORY ·oø×O0|
`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨'
[What's New 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
[What's New 1.0.7 - January 27, 2009]
* Updated to VBA-M r847
* Corrected sound interpolation
@ -155,6 +173,558 @@ it to your Gamecube, or by booting a bootable DVD with VBAGX on it.
This document doesn't cover how to do any of that. A good source for information
on these topics is the tehskeen forums: http://www.tehskeen.com/forums/
×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬
|0O×øo· INSTRUCTIONS ·oø×O0|
`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨'
Note! You will need to unplug and replug the USB keyboard (perhaps more than
once) while in the emulator to get it to work. A keyboard is not required.
If you have upgraded from a previous version, the emulator will start with a
message that your preferences have been reset. Press A and you will be taken
to the preferences menu. You will need to set your preferences how you want
them.
Otherwise the emulator will start at the main menu.
Navigate the menu with the D-Pad, and select options with the A button.
Press B to cancel out of a menu. Cancelling out of the main menu with B will
return you to the game, if you have chosen one.
When choosing a file, the B button takes you up a folder. Once you get to
the root directory pressing B will cancel and take you back to the menu.
There may be more than one page of files, even if it doesn't look like it.
Keep pressing down or up to go to the next page, or use left and right.
If you don't want to load ROMs from the SD card, you can go to the
preferences menu and choose where to load from. You can load from SD cards,
USB memory sticks/hard drives, DVD (if you installed DVDX), gamecube memory
cards, or from shared folders over the network (this is called SMB).
ROMs can be in ZIP files, but the ROM must be the first file in the ZIP. If
not, you will get an error. ROMs can also be in .7z files, or ordinary rom
files.
Patches can be used to colourise a monochrome gameboy game, or to translate
a game into your language, or to stop the game from needing special hardware.
Search the internet for patches. Many games have been translated by fans.
They can be in IPS or UPS format. You don't need to patch anything yourself.
Just put the IPS or UPS file in the vbagx/roms folder along with the rom
itself. The patch must have the same name as the rom. Patches can not be put
inside the ZIP file. If a rom is zipped, you might need to check inside the
zip for the actual rom filename.
Colourised games still have some distortion in this version, but it is
improved from the previous version, and better than VBA-M.
You must not use patched versions of Boktai roms! (Except for the translation
patch for Boktai 3, which is highly recommended). The patches are for old
emulators that don't support the solar sensor. VBA GX and NO$GBA support the
solar sensor natively, and the patch will stop them from working.
You must also not use patched versions of WarioWare Twisted, Kirby's Tilt n
Tumble, or Yoshi's Universal Gravitation (Topsy Turvy). The original roms
are fully supported, and the patch will stop them from working.
-=[ Controls ]=-
The default controls are...
+ = Gameboy Start Button
- = Gameboy Select Button
Home = Show emulator's game menu
Wii Remote by itself:
Hold the Wii Remote sideways.
2 = Gameboy A Button
1 = Gameboy B Button
A = Gameboy R Button
B = Gameboy L Button
Wii Remote + Nunchuk:
Hold the Nunchuk and ignore the Wii Remote.
Z = Gameboy A Button
C = Gameboy B Button
Classic Controller:
Use the buttons as labelled.
A = Gameboy A Button
B = Gameboy B Button
R = Gameboy R Button
L = Gameboy L Button
Keyboard:
X = Gameboy A Button
Z = Gameboy B Button
S = Gameboy R Button
A = Gameboy L Button
Enter = Gameboy Start Button
Backspace = Gameboy Select Button
Space = Fast forward
You can configure the controls how you want from the controls menu. Different
controls will be used depending on what you have plugged into the Wii Remote.
Nunchuk means Nunchuk + Wii Remote. Gamecube controllers and Keyboards can
be used at the same time as Wii Remotes and all control the same player.
When configuring controls, press HOME to cancel.
But the controls you choose will be overridden for certain games if you
choose "Match Wii Game" (or "Match Gamecube Game" on a Gamecube) and you have
the appropriate expansion plugged in. If the game does not have special Wii
controls, then the controls you chose will be used.
Gameboy and Gameboy colour games don't have L and R buttons. Those buttons
only work in Gameboy Advance games.
In addition to the controls you can configure, these other controls apply:
HOME, Escape: returns you to the emulator's game menu. Then press B to go
to the main menu and B again to return to the game.
A+B, Spacebar, or right analog stick: fast forward
Right analog stick: zoom (if enabled)
-=[ Match Wii Controls ]=-
Special Wii controls exist for the following games:
These Zelda games can be played with Twilight Princess controls:
The Legend Of Zelda, Zelda 2, A Link To The Past, Link's Awakening (DX), Oracle of Ages,
Oracle of Seasons, Minish Cap
These Mario games can be played with Mario Galaxy controls:
Super Mario Bros., Super Mario Bros. DX, Super Mario 2, Super Mario (2)
Advance, Super Mario 3, Super Mario World, Yoshi's Island,
Yoshi's Universal Gravitation (Topsy Turvy)
Mario Kart can be played with Mario Kart wii controls
These Metroid games can be played with Metroid Prime 3 controls:
Metroid Zero Mission, Metroid 1, Metroid 2, Metroid Fusion
These Mortal Kombat games can be played with Mortal Kombat Armageddon controls:
Mortal Kombat, Mortal Kombat II, Mortal Kombat 3, Mortal Kombat 4, Mortal
Kombat Advance, Mortal Kombat Deadly Alliance, Mortal Kombat Tournament
Edition
These Lego games can be played with Lego Star Wars the Complete Saga
controls:
Lego Star Wars The Video Game, Lego Star Wars The Original Trilogy
TMNT can be played with TMNT Wii controls.
These Harry Potter games can be played with Harry Potter and the Order of
the Phoenix Wii controls:
Harry Potter 1, Harry Potter 1 GBC, Harry Potter 2, Harry Potter 2 GBC, Harry Potter 3, Harry Potter 4, Harry Potter 5
These Medal Of Honour games can be played with Medal Of Honour Wii controls:
Medal Of Honour Underground, Medal Of Honour Infiltrator
One Piece can be played with One Piece Unlimited Adventure controls.
Boktai 1, Boktai 2, Boktai 3, Kirby's Tilt n Tumble, and WarioWare Twisted can be played with
controls I designed for them.
-=[ Zelda, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
All Zelda games use the same controls as Twilight Princess on the Wii or
Gamecube. You can also connect a Classic Controller to use similar controls
to the Ocarina Of Time for the Virtual Console, but with the R trigger
acting as the B button and an inventory like Twilight Princess. With nothing
plugged in to the Wii Remote, your configured controls are used instead.
The Wii Zelda controls are:
===========================
Swing your Wii Remote to draw or swing your sword. Press A to put your sword
away again. The 2 handed sword can't be drawn this way, and must be drawn
manually from the items menu, but you can swing it like normal.
Shake your Nunchuk to do a spin attack.
Use the Z Button to Z-Target and to draw and use your shield. While
Z-Targetting you will sidestep in some games. If you have a Gust Jar
equipped instead of a shield, it will be used for Z-Targetting.
Use the A Button to perform an action, such as rolling, talking to people,
reading signs, picking things up, throwing things, shrinking or growing,
pulling things, etc. It will also put away your sword or shield. In Zelda 2,
it will jump.
Use the C Button to fast forward. It was originally the camera button in
Twilight Princess.
Press the B Button to use the currently selected item. 3 other items will be
mapped to Left, Down, and Right D-Pad buttons. Swap the currently selected
item with one of those items by pressing that D-Pad button. The three slots
correspond to the first 3 slots in your inventory. In Minish Cap, the D-Pad
buttons use the item directly instead of swapping it with the B Button, and
the B Button is the same as the down button. In Minish Cap the left item is
always the Kinstones and the down and right items correspond to the B and A
slots.
Up on the D-Pad talks to Midna, or to your hat. It will take you to the save
screen in Link's Awakening, or to the secondary items screen in the Oracle
games.
The 1 Button goes to the Map screen.
The - Button goes to the Items screen.
The + Button goes to the Quest Status screen
On the Items screen, choose an item and then press either the B Button or the
D-Pad button to move it to that slot. The change may not be visible until you
go to another screen and back. In Link's Awakening you can toggle Bomb
Arrows by choosing the bombs and pressing Z. It will rumble for a short time
when bomb arrows are deactivated, and for a long time when bomb arrows are
activated. You still need to equip the bow to use bomb arrows. In Minish Cap
you should be able to use the IR pointer function to select items.
The Gamecube controller Zelda controls are:
===========================================
B is the sword button. Use it to draw or swing your sword. Hold B for a spin
attack. Press A to put the sword away again. The 2 handed sword can't be
drawn this way, and must be selected manually from the items screen, but can
be swung with this (or any other) button.
Use the L Trigger to L-Target and to draw and use your shield. While
L-Targetting you will sidestep in some games. If you have a Gust Jar
equipped instead of a shield, it will be used for L-Targetting.
Use the A Button to perform an action, such as rolling, talking to people,
reading signs, picking things up, throwing things, shrinking or growing,
etc. It will also put away your sword or shield. In Zelda 2, it will jump.
Use the R Trigger to pull on blocks or walls, or to lift things. You must
have a bracelet or gloves to lift some objects. The bracelet or gloves will
be equipped automatically. This feature is unique to the Gamecube controller.
Use the right analog stick to fast forward. It was originally the camera
control in Twilight Princess.
Press the X or Y buttons to use the two equipped items. These two items both
share the B slot, except in Minish Cap where one is in the A slot. The item
that was not used last will be in the first slot in your inventory.
Right on the D-Pad takes you to the map.
Up on the D-Pad takes you to the items screen.
Start takes you to the quest status screen.
The Z trigger talks to Midna, or to your hat. It will take you to the save
screen in Link's Awakening, or to the secondary items screen in the Oracle
games.
The Classic controller Zelda controls are:
==========================================
B is the sword button. Use it to draw or swing your sword. Hold B for a spin
attack. Press A to put the sword away again. The 2 handed sword can't be
drawn this way, and must be selected manually from the items screen, but can
be swung with this (or any other) button.
Use the L Trigger to L-Target and to draw and use your shield. While
L-Targetting you will sidestep in some games. If you have a Gust Jar
equipped instead of a shield, it will be used for L-Targetting.
Use the A Button to perform an action, such as rolling, talking to people,
reading signs, picking things up, throwing things, shrinking or growing,
pulling, etc. It will also put away your sword or shield. In Zelda 2, it
will jump.
Use the ZL Button to fast forward.
Press the R Button to use the currently selected item. 3 other items will be
mapped to Left, Down, and Right on the right analog stick. They are also
mapped to ZR, Y, and X. Swap the currently selected item with one of those
items by pressing that button or direction. The three slots correspond to
the first 3 slots in your inventory. In Minish Cap, the D-Pad buttons use the
item directly instead of swapping it with the B Button, and the B Button is
the same as the down button. In Minish Cap the left item is always the
Kinstones and the down and right items correspond to the B and A slots.
+ (Start) takes you to the subscreens.
- (Select) takes you to the map or changes subscreens.
Up on the analog stick talks to Midna, or to your hat.
-=[ Mario, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
All Mario or Yoshi games use the same controls as Super Mario Galaxy on the
Wii. You can also connect a Classic Controller to use similar controls to
Super Mario World on the SNES.
The Wii Mario controls are:
===========================
Shake the Wii Remote to do a spin attack, or to shoot fireballs when you are
fire Mario. In some games that have a spin attack, you will need to use the
B Button instead to shoot fireballs. You can also dismount Yoshi by shaking.
Walk by moving the joystick a little, run by moving the joystick a lot.
A = jump
B = shoot, run, hold on to things, yoshi's tongue, etc.
Z = crouch or lay egg. Press Z while in the air to butt stomp.
C = camera. Hold C to look around with the joystick.
D-Pad = look around, or walk in some games
+ = pause
1 = throw egg if you are Yoshi
The Classic Controller Mario controls are:
==========================================
Walk by moving the joystick a little, run by moving the joystick a lot.
B = jump
A = spin attack
X/Y = shoot, run, hold on to things, yoshi's tongue, etc.
ZL or sometimes L = crouch or lay egg. Press in the air to butt stomp.
+ = pause
L/R sometimes look around
-=[ Yoshi's Universal Gravitation (Topsy Turvy), Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
The controls are the same as all other Mario or Yoshi games, except that
tilting the Wii Remote tilts the world and the screen. This affects
everything in the world and also how you move.
-=[ Metroid, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
All Metroid games use the same controls as Metroid Prime 3: Corruption on
the Wii. You aim up and down by pointing the Wii Remote up and down.
The Wii Metroid controls are:
=============================
Aim up and down by pointing the Wii Remote up and down.
Flick the Wii remote up while in Morph Ball to spring jump.
A = shoot
B = jump
Down on D-Pad = fire missile
C = toggle Morph Ball
- = start
+ = toggle super missiles
1 = map
2 = hint
-=[ TMNT, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
The TMNT game based on the CGI movie uses the same controls as TMNT on Wii.
They are not fully implemented yet.
The Wii TMNT controls are:
==========================
Shake the Wii Remote or Nunchuk to attack or to throw away a weapon if
in the air. Also shake to pick up a weapon.
A = jump
B = swap turtle
-=[ Boktai, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
The 3 Boktai games use special controls that I created. They are not based on
anything, since the real game uses a solar sensor.
The controls are the same with or without a Nunchuk.
The Wii Boktai controls are:
============================
Point your Wii Remote at the sky to quickly charge your Gun Del Sol. Point
your Wii Remote at the ground to block the sunlight and prevent it from
charging or overheating. Or hold it like normal to use it like normal.
Press Home to set the real life weather in the emulator's game menu. Note
that if it is night time in real life, there will not be any sun, regardless
of what you set the weather to. Please set the weather honestly or it spoils
the fun. Note that maximum sun is not actually the best, since it rots fruit,
and overheats your gun. The weather must be set each time you play, it is not
saved.
Swing your Wii Remote to swing your sword or other weapon, if you have one.
D-Pad or Nunchuk joystick walks.
Press B to fire your Gun Del Sol.
A = read signs, open chests, talk to people
C or 2 = look around, or change subscreen (R)
+ = start
- = select
Z or 1 = change element, or change subscreen (L)
1 (if Nunchuk plugged in) = fast forward
-=[ WarioWare Twisted, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
WarioWare Twisted uses similar controls to the Gameboy game.
The Wii WarioWare Twisted controls are:
=======================================
Rotate the Wii Remote to rotate.
Hold Z to lock the current menu item.
A = Select
B = Cancel
+ = Start
-=[ Kirby's Tilt n Tumble, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
Kirby's Tilt n Tumble uses similar controls to the Gameboy game.
The Kirby Tilt n Tumble controls are:
=====================================
Tilt the Wii Remote to tilt the world. Shake the Wii Remote to flick Kirby
and the monsters up into the air.
A = shoot yourself out of holes in the ground, or jump from clouds.
-=[ Mortal Kombat, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
All Mortal Kombat games use the same controls as Mortal Kombat Armaggedon
for the Wii, except that special moves gestures are not implemented yet.
Note that the Gameboy games all only have 1 punch and 1 kick, rather than
the 4 attacks on other consoles.
The Mortal Kombat Wii controls are:
===================================
Use the Nunchuk joystick to move and jump.
D-Pad up/left = punch
D-Pad down/right = kick
Z = block
A = throw
C = change style, run
- = pause
-=[ Lego Star Wars, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
Both Lego Star Wars games use the same controls as Lego Star Wars: The
Complete Saga for the Wii.
The Lego Star Wars Wii controls are:
====================================
Swing the Wii Remote to swing your lightsaber.
Flick the Wii Remote up to grapple.
A = Jump
B = Shoot
Z = Use the force, build lego
C = Change characters, talk to people
- = force power, special ability
+ = start
1/2 = fast forward
-=[ Harry Potter, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
All the Harry Potter games use the same controls as Harry Potter & The Order
Of The Phoenix on the Wii. They also use the keyboard controls from the PC
version of each game. Spell gestures are not supported yet.
The Harry Potter Wii controls are:
==================================
Wave the Wii Remote to cast a spell.
Nunchuk joystick walks.
D-Pad changes subscreen in the map and navigates menu.
In Harry Potter and the Order of the Phoenix you must use the IR Pointer
to select where to cast a spell.
A = Talk, open door, push button, interract, etc. / Jinx
B = Use your wand / charm / cancel
Z = run (fast forward) / sneak
C = show location name / flute / jump
- = Maurauders map / Tasks
+ = pause / menu
1/2 = change spells
-=[ Medal of Honour, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
All the Medal of Honour games use the same controls as various
Medal of Honour games and modes on the Wii.
The Medal of Honour Wii controls are:
=====================================
In Medal of Honour Underground you turn by aiming with the Wii Remote IR
pointer on the screen like any FPS game. In Medal of Honour Infiltrator,
you don't.
Swing the Wiimote up to reload.
Move with the Nunchuk joystick.
B = shoot
- = use
+ = pause, objectives, menu
2 / D-Pad Up = reload
D-Pad Left/Right = change weapons
D-Pad Down = toggle crouch
C = strafe
1 = run
-=[ One Piece, Match Wii Controls ]=-
Turn "Match Wii Controls" ON to use these controls.
One Piece uses the same controls as One Piece Unlimited Adventure on the Wii
or One Piece Grand Adventure (and others) on the Gamecube.
The One Piece Wii controls are:
===============================
A = attack
B = jump
- = change character
+ = pause
C = dash (double click and hold)
Z = grab
2 = fast forward
1 = select (maybe does nothing)
The One Piece Gamecube controls are:
===============================
A = attack
X = attack up
Y = jump
B = grab
R Trigger = change character
start = pause
L Trigger = dash (double click and hold)
Z = grab
right analog stick = fast forward
1 = select (maybe does nothing)
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
-=[ Credits ]=-

File diff suppressed because it is too large Load Diff

View File

@ -82,6 +82,8 @@
#define CORVETTE gid('A','V','C')
#define ONEPIECE gid('B','O','N')
u8 gbReadMemory(register u16 address);
void gbWriteMemory(register u16 address, register u8 value);
@ -91,6 +93,18 @@ u32 StandardSideways(unsigned short pad);
u32 StandardClassic(unsigned short pad);
u32 StandardGamecube(unsigned short pad);
u32 StandardKeyboard(unsigned short pad);
u32 DPadWASD(unsigned short pad);
u32 DPadArrowKeys(unsigned short pad);
u32 DecodeKeyboard(unsigned short pad);
u32 DecodeWiimote(unsigned short pad);
u32 DecodeClassic(unsigned short pad);
u32 DecodeGamecube(unsigned short pad);
u32 DecodeNunchuk(unsigned short pad);
// For developers who don't have gamecube pads but need to test gamecube input
u32 PAD_ButtonsDownFake(unsigned short pad);
u32 PAD_ButtonsHeldFake(unsigned short pad);
u32 PAD_ButtonsUpFake(unsigned short pad);
u32 MarioLand1Input(unsigned short pad);
u32 MarioLand2Input(unsigned short pad);
@ -106,6 +120,7 @@ u32 Zelda2Input(unsigned short pad);
u32 ALinkToThePastInput(unsigned short pad);
u32 LinksAwakeningInput(unsigned short pad);
u32 OracleOfAgesInput(unsigned short pad);
u32 OracleOfSeasonsInput(unsigned short pad);
u32 MinishCapInput(unsigned short pad);
u32 MetroidZeroInput(unsigned short pad);
u32 Metroid1Input(unsigned short pad);
@ -132,6 +147,7 @@ u32 TwistedInput(unsigned short pad);
u32 KirbyTntInput(unsigned short pad);
u32 BoktaiInput(unsigned short pad);
u32 Boktai2Input(unsigned short pad);
u32 OnePieceInput(unsigned short pad);
#endif

View File

@ -537,6 +537,160 @@ u32 StandardKeyboard(unsigned short pad)
return J;
}
u32 DPadWASD(unsigned short pad)
{
u32 J = 0;
#ifdef HW_RVL
if (DownUsbKeys[KB_W])
J |= VBA_UP;
if (DownUsbKeys[KB_S])
J |= VBA_DOWN;
if (DownUsbKeys[KB_A])
J |= VBA_LEFT;
if (DownUsbKeys[KB_D])
J |= VBA_RIGHT;
#endif
return J;
}
u32 DPadArrowKeys(unsigned short pad)
{
u32 J = 0;
#ifdef HW_RVL
if (DownUsbKeys[KB_UP])
J |= VBA_UP;
if (DownUsbKeys[KB_DOWN])
J |= VBA_DOWN;
if (DownUsbKeys[KB_LEFT])
J |= VBA_LEFT;
if (DownUsbKeys[KB_RIGHT])
J |= VBA_RIGHT;
#endif
return J;
}
u32 DecodeKeyboard(unsigned short pad)
{
u32 J = 0;
#ifdef HW_RVL
for (int i = 0; i < MAXJP; i++)
{
if (DownUsbKeys[kbpadmap[i]]) // keyboard
J |= vbapadmap[i];
}
#endif
return J;
}
u32 DecodeGamecube(unsigned short pad)
{
u32 J = 0;
u32 jp = PAD_ButtonsHeld(pad);
for (int i = 0; i < MAXJP; i++)
{
if (jp & gcpadmap[i])
J |= vbapadmap[i];
}
return J;
}
u32 DecodeWiimote(unsigned short pad)
{
u32 J = 0;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
for (int i = 0; i < MAXJP; i++)
{
if ( (wp->exp.type == WPAD_EXP_NONE) && (wp->btns_h & wmpadmap[i]) )
J |= vbapadmap[i];
}
#endif
return J;
}
u32 DecodeClassic(unsigned short pad)
{
u32 J = 0;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
for (int i = 0; i < MAXJP; i++)
{
if ( (wp->exp.type == WPAD_EXP_CLASSIC) && (wp->btns_h & ccpadmap[i]) )
J |= vbapadmap[i];
}
#endif
return J;
}
u32 DecodeNunchuk(unsigned short pad)
{
u32 J = 0;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
for (int i = 0; i < MAXJP; i++)
{
if ( (wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & ncpadmap[i]) )
J |= vbapadmap[i];
}
#endif
return J;
}
#ifdef HW_RVL
static u32 CCToGC(u32 w) {
u32 gc = 0;
if (w & WPAD_CLASSIC_BUTTON_A) gc |= PAD_BUTTON_A;
if (w & WPAD_CLASSIC_BUTTON_B) gc |= PAD_BUTTON_B;
if (w & WPAD_CLASSIC_BUTTON_X) gc |= PAD_BUTTON_X;
if (w & WPAD_CLASSIC_BUTTON_Y) gc |= PAD_BUTTON_Y;
if (w & WPAD_CLASSIC_BUTTON_PLUS) gc |= PAD_BUTTON_START;
if (w & WPAD_CLASSIC_BUTTON_MINUS) gc |= 0;
if (w & (WPAD_CLASSIC_BUTTON_ZL | WPAD_CLASSIC_BUTTON_ZR)) gc |= PAD_TRIGGER_Z;
if (w & WPAD_CLASSIC_BUTTON_FULL_L) gc |= PAD_TRIGGER_L;
if (w & WPAD_CLASSIC_BUTTON_FULL_R) gc |= PAD_TRIGGER_R;
if (w & WPAD_CLASSIC_BUTTON_UP) gc |= PAD_BUTTON_UP;
if (w & WPAD_CLASSIC_BUTTON_DOWN) gc |= PAD_BUTTON_DOWN;
if (w & WPAD_CLASSIC_BUTTON_LEFT) gc |= PAD_BUTTON_LEFT;
if (w & WPAD_CLASSIC_BUTTON_RIGHT) gc |= PAD_BUTTON_RIGHT;
return gc;
}
#endif
// For developers who don't have gamecube pads but need to test gamecube input
u32 PAD_ButtonsHeldFake(unsigned short pad)
{
u32 gc = 0;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
if (wp->exp.type == WPAD_EXP_CLASSIC) {
gc = CCToGC(wp->btns_h);
}
#endif
return gc;
}
u32 PAD_ButtonsDownFake(unsigned short pad)
{
u32 gc = 0;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
if (wp->exp.type == WPAD_EXP_CLASSIC) {
gc = CCToGC(wp->btns_d);
}
#endif
return gc;
}
u32 PAD_ButtonsUpFake(unsigned short pad)
{
u32 gc = 0;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
if (wp->exp.type == WPAD_EXP_CLASSIC) {
gc = CCToGC(wp->btns_u);
}
#endif
return gc;
}
/****************************************************************************
* DecodeJoy
*
@ -547,16 +701,19 @@ u32 StandardKeyboard(unsigned short pad)
static u32 DecodeJoy(unsigned short pad)
{
TiltScreen = false;
CursorVisible = false;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
CursorX = wp->ir.x;
CursorY = wp->ir.y;
CursorValid = wp->ir.valid;
#else
CursorX = CursorY = CursorValid = 0;
#endif
// check for games that should have special Wii controls (uses wiimote + nunchuk)
if (GCSettings.WiiControls && wp->exp.type == WPAD_EXP_NUNCHUK)
{
// check for games that should have special Wii controls
if (GCSettings.WiiControls)
switch (RomIdCode & 0xFFFFFF)
{
// Zelda
@ -569,8 +726,9 @@ static u32 DecodeJoy(unsigned short pad)
case LINKSAWAKENING:
return LinksAwakeningInput(pad);
case ORACLEOFAGES:
case ORACLEOFSEASONS:
return OracleOfAgesInput(pad);
case ORACLEOFSEASONS:
return OracleOfSeasonsInput(pad);
case MINISHCAP:
return MinishCapInput(pad);
@ -655,7 +813,7 @@ static u32 DecodeJoy(unsigned short pad)
return MKTEInput(pad);
// WarioWare
case TWISTED: //CAKTODO move this somewhere not depended on WiiControls setting
case TWISTED:
return TwistedInput(pad);
// Kirby
@ -669,9 +827,11 @@ static u32 DecodeJoy(unsigned short pad)
case BOKTAI2:
case BOKTAI3:
return Boktai2Input(pad);
// One Piece
case ONEPIECE:
return OnePieceInput(pad);
}
}
#endif
// the function result, J, is a combination of flags for all the VBA buttons that are down
u32 J = StandardMovement(pad);

891
source/ngc/inputmario.cpp Normal file
View File

@ -0,0 +1,891 @@
/****************************************************************************
* Visual Boy Advance GX
*
* Carl Kenner Febuary 2009
*
* gameinput.cpp
*
* Wii/Gamecube controls for individual 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"
u32 MarioKartInput(unsigned short pad) {
u32 J = StandardMovement(pad);
static u32 frame = 0;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
u8 Health = 0;
static u8 OldHealth = 0;
float fraction;
// Rumble when they lose health!
if (Health < OldHealth)
systemGameRumble(20);
OldHealth = Health;
// Start/Select
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
if (wp->exp.type == WPAD_EXP_NONE)
{
// Use item
if (wp->btns_h & WPAD_BUTTON_RIGHT)
{
J |= VBA_BUTTON_L | VBA_UP;
J &= ~VBA_DOWN;
}
else if (wp->btns_h & WPAD_BUTTON_LEFT)
{
J |= VBA_BUTTON_L | VBA_DOWN;
J &= ~VBA_UP;
}
else if (wp->btns_h & WPAD_BUTTON_UP || wp->btns_h & WPAD_BUTTON_DOWN)
J |= VBA_BUTTON_L;
// Accelerate
if (wp->btns_h & WPAD_BUTTON_2)
J |= VBA_BUTTON_A;
// Brake
if (wp->btns_h & WPAD_BUTTON_1)
J |= VBA_BUTTON_B;
// Jump/Power slide
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_R;
if (wp->btns_h & WPAD_BUTTON_B)
J |= VBA_BUTTON_R;
if (wp->orient.pitch> 12) {
fraction = (wp->orient.pitch - 12)/60.0f;
if ((frame % 60)/60.0f < fraction)
J |= VBA_LEFT;
} else if (wp->orient.pitch <- 12) {
fraction = -(wp->orient.pitch + 10)/60.0f;
if ((frame % 60)/60.0f < fraction)
J |= VBA_RIGHT;
}
} else if (wp->exp.type == WPAD_EXP_NUNCHUK) {
// Use item
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z)
J |= VBA_BUTTON_L;
// Accelerate
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_A;
// Brake
if (wp->btns_h & WPAD_BUTTON_B)
J |= VBA_BUTTON_B;
// Jump
if (fabs(wp->gforce.y)> 1.5 )
J |= VBA_BUTTON_R;
if (wp->btns_h & WPAD_BUTTON_UP || wp->btns_h & WPAD_BUTTON_LEFT || wp->btns_h & WPAD_BUTTON_RIGHT || wp->btns_h & WPAD_BUTTON_DOWN)
J |= VBA_BUTTON_R;
} else if (wp->exp.type == WPAD_EXP_CLASSIC) {
// Use item
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L)
J |= VBA_BUTTON_L;
// Accelerate
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A)
J |= VBA_BUTTON_A;
// Brake
if (wp->btns_h & WPAD_BUTTON_B)
J |= VBA_BUTTON_B;
// Jump
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
J |= VBA_BUTTON_R;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_UP || wp->btns_h & WPAD_CLASSIC_BUTTON_LEFT || wp->btns_h & WPAD_CLASSIC_BUTTON_RIGHT || wp->btns_h & WPAD_CLASSIC_BUTTON_DOWN)
J |= VBA_BUTTON_R;
// Start/Select
if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS)
J |= VBA_BUTTON_START;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
}
#endif
u32 gc = PAD_ButtonsHeld(pad);
if (gc & PAD_BUTTON_START)
J |= VBA_BUTTON_START;
if (gc & PAD_BUTTON_X || gc & PAD_BUTTON_Y)
J |= VBA_BUTTON_SELECT;
if (gc & PAD_BUTTON_A)
J |= VBA_BUTTON_A;
if (gc & PAD_BUTTON_B)
J |= VBA_BUTTON_B;
if (gc & PAD_TRIGGER_L)
J |= VBA_BUTTON_L;
if (gc & PAD_TRIGGER_R)
J |= VBA_BUTTON_R;
if (gc & PAD_BUTTON_UP || gc & PAD_BUTTON_DOWN || gc & PAD_BUTTON_LEFT
|| gc & PAD_BUTTON_RIGHT)
J |= VBA_BUTTON_R;
frame++;
return J;
}
u32 Mario1DXInput(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeKeyboard(pad);
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
bool run = false;
run = (wp->exp.type==WPAD_EXP_NUNCHUK && wp->exp.nunchuk.js.mag> 0.83) || (wp->exp.type==WPAD_EXP_CLASSIC && wp->exp.classic.ljs.mag> 0.83);
run = run && ((J & VBA_LEFT) || (J & VBA_RIGHT));
if (wp->exp.type==WPAD_EXP_NUNCHUK) {
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_A;
// Run, pick up
if (wp->btns_h & WPAD_BUTTON_B || run)
J |= VBA_BUTTON_B;
// Starspin shoots when using fireflower
if (fabs(wp->gforce.x)> 1.5)
J |= VBA_BUTTON_B;
// Camera (must come before Crouch)
if (!(wp->btns_h & WPAD_NUNCHUK_BUTTON_C))
J &= ~(VBA_DOWN | VBA_UP);
if (wp->btns_h & WPAD_BUTTON_UP)
J |= VBA_UP;
if (wp->btns_h & WPAD_BUTTON_DOWN)
J |= VBA_DOWN;
// Crouch (must come after Camera)
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z)
J |= VBA_DOWN;
// Speed
if (wp->btns_h & WPAD_BUTTON_1 || wp->btns_h & WPAD_BUTTON_2)
J |= VBA_SPEED;
} else if (wp->exp.type == WPAD_EXP_CLASSIC) {
// Pause
if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_CLASSIC_BUTTON_B)
J |= VBA_BUTTON_A;
// Run, pick up, throw, fire
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y || run)
J |= VBA_BUTTON_B;
// Spin attack
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A)
J |= VBA_BUTTON_B;
// Camera
J &= ~(VBA_DOWN | VBA_UP);
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L)
J |= VBA_DOWN;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
J |= VBA_UP;
// Crouch
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL) {
J |= VBA_DOWN;
J &= ~VBA_UP;
}
// DPad movement/camera
if (wp->btns_h & WPAD_CLASSIC_BUTTON_UP)
J |= VBA_UP;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_DOWN)
J |= VBA_DOWN;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_LEFT)
J |= VBA_LEFT;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_RIGHT)
J |= VBA_RIGHT;
// Speed
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZR)
J |= VBA_SPEED;
} else
J |= StandardSideways(pad);
#endif
return J;
}
u32 Mario1ClassicInput(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeKeyboard(pad);
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
bool run = false;
run = (wp->exp.type==WPAD_EXP_NUNCHUK && wp->exp.nunchuk.js.mag> 0.83) || (wp->exp.type==WPAD_EXP_CLASSIC && wp->exp.classic.ljs.mag> 0.83);
run = run && ((J & VBA_LEFT) || (J & VBA_RIGHT));
if (wp->exp.type==WPAD_EXP_NUNCHUK) {
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_A;
// Run, pick up
if (wp->btns_h & WPAD_BUTTON_B || run)
J |= VBA_BUTTON_B;
// Starspin shoots when using fireflower
if (fabs(wp->gforce.x)> 1.5)
J |= VBA_BUTTON_B;
// Crouch
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z) {
J |= VBA_DOWN;
J &= ~VBA_UP;
}
// Speed
if (wp->btns_h & WPAD_BUTTON_1 || wp->btns_h & WPAD_BUTTON_2)
J |= VBA_SPEED;
} else if (wp->exp.type == WPAD_EXP_CLASSIC) {
// DPad movement
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_CLASSIC_BUTTON_B)
J |= VBA_BUTTON_A;
// Run, pick up, throw, fire
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y || run)
J |= VBA_BUTTON_B;
// Spin attack
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A)
J |= VBA_BUTTON_B;
// Crouch
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL || wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L)
{
J |= VBA_DOWN;
J &= ~VBA_UP;
}
// Speed
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZR)
J |= VBA_SPEED;
} else
J |= StandardSideways(pad);
#endif
return J;
}
u32 MarioLand1Input(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeKeyboard(pad) | DecodeGamecube(pad);
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
bool run = false;
run = (wp->exp.type==WPAD_EXP_NUNCHUK && wp->exp.nunchuk.js.mag> 0.83) || (wp->exp.type==WPAD_EXP_CLASSIC && wp->exp.classic.ljs.mag> 0.83);
run = run && ((J & VBA_LEFT) || (J & VBA_RIGHT));
if (wp->exp.type == WPAD_EXP_NONE)
J |= StandardSideways(pad);
else if (wp->exp.type == WPAD_EXP_CLASSIC) {
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_CLASSIC_BUTTON_B)
J |= VBA_BUTTON_A;
// Run, pick up, throw, fire
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y || run)
J |= VBA_BUTTON_B;
// Spin attack
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A)
J |= VBA_BUTTON_B;
// Crouch
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL || wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L)
{
J |= VBA_DOWN;
J &= ~VBA_UP;
}
// Speed
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZR || wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
J |= VBA_SPEED;
} else if (wp->exp.type == WPAD_EXP_NUNCHUK) {
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_A;
// Run, pick up, throw, fire
if (wp->btns_h & WPAD_BUTTON_B || run)
J |= VBA_BUTTON_B;
if (fabs(wp->gforce.x)> 1.5)
J |= VBA_BUTTON_B;
// Crouch
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z)
J |= VBA_DOWN;
// Speed
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_C || wp->btns_h & WPAD_BUTTON_1 || wp->btns_h & WPAD_BUTTON_2)
J |= VBA_SPEED;
}
else
J |= DecodeWiimote(pad);
#endif
return J;
}
u32 MarioLand2Input(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeKeyboard(pad) | DecodeGamecube(pad);
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
bool run = false;
run = (wp->exp.type==WPAD_EXP_NUNCHUK && wp->exp.nunchuk.js.mag> 0.83) || (wp->exp.type==WPAD_EXP_CLASSIC && wp->exp.classic.ljs.mag> 0.83);
run = run && ((J & VBA_LEFT) || (J & VBA_RIGHT));
if (wp->exp.type == WPAD_EXP_NONE)
J |= StandardSideways(pad);
else if (wp->exp.type == WPAD_EXP_CLASSIC) {
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_CLASSIC_BUTTON_B)
J |= VBA_BUTTON_A;
// Run, pick up, throw, fire
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y || run)
J |= VBA_BUTTON_B;
// Spin attack
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A)
J |= VBA_DOWN | VBA_BUTTON_A;
// Camera
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L)
J |= VBA_DOWN | VBA_BUTTON_B;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
J |= VBA_UP | VBA_BUTTON_B;
// Crouch
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL && (!(wp->btns_h & WPAD_CLASSIC_BUTTON_A))) {
J |= VBA_DOWN;
// if the run button is held down, crouching also looks down
// which we don't want when using the Z button
J &= ~VBA_BUTTON_B;
J &= ~VBA_UP;
}
// Speed
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZR)
J |= VBA_SPEED;
} else if (wp->exp.type == WPAD_EXP_NUNCHUK) {
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_A;
// Run, pick up, throw, fire
if (wp->btns_h & WPAD_BUTTON_B || run)
J |= VBA_BUTTON_B;
// Spin attack
if (fabs(wp->gforce.x)> 1.4)
J |= VBA_DOWN | VBA_BUTTON_A;
// Camera
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_C)
J |= VBA_BUTTON_B;
if (wp->btns_h & WPAD_BUTTON_UP)
J |= VBA_BUTTON_B | VBA_UP;
if (wp->btns_h & WPAD_BUTTON_DOWN)
J |= VBA_BUTTON_B | VBA_DOWN;
if (wp->btns_h & WPAD_BUTTON_LEFT)
J |= VBA_BUTTON_B | VBA_LEFT;
if (wp->btns_h & WPAD_BUTTON_RIGHT)
J |= VBA_BUTTON_B | VBA_RIGHT;
// Crouch
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z && (!(wp->btns_h & WPAD_BUTTON_A))) {
J |= VBA_DOWN;
// if the run button is held down, crouching also looks down
// which we don't want when using the Z button
J &= ~VBA_BUTTON_B;
J &= ~VBA_UP;
}
// Speed
if (wp->btns_h & WPAD_BUTTON_1 || wp->btns_h & WPAD_BUTTON_2)
J |= VBA_SPEED;
} else
J |= DecodeWiimote(pad);
#endif
return J;
}
u32 Mario2Input(unsigned short pad)
{
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeKeyboard(pad) | DecodeWiimote(pad);
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
bool run = false;
run = (wp->exp.type==WPAD_EXP_NUNCHUK && wp->exp.nunchuk.js.mag> 0.83) || (wp->exp.type==WPAD_EXP_CLASSIC && wp->exp.classic.ljs.mag> 0.83);
run = run && ((J & VBA_LEFT) || (J & VBA_RIGHT));
if (wp->exp.type == WPAD_EXP_NUNCHUK) {
// DPad looks around
if (wp->btns_h & WPAD_BUTTON_RIGHT)
J |= VBA_BUTTON_R;
if (wp->btns_h & WPAD_BUTTON_LEFT)
J |= VBA_BUTTON_L;
if (wp->btns_h & WPAD_BUTTON_UP)
J |= VBA_BUTTON_L;
if (wp->btns_h & WPAD_BUTTON_DOWN)
J |= VBA_BUTTON_L;
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_A;
// Run, pick up
if (wp->btns_h & WPAD_BUTTON_B)
J |= VBA_BUTTON_B;
if (fabs(wp->gforce.x)> 1.5)
J |= VBA_BUTTON_B;
// Crouch
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z)
J |= VBA_DOWN;
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_C)
J |= VBA_BUTTON_L;
if (wp->btns_h & WPAD_BUTTON_1)
J |= VBA_BUTTON_R;
if (wp->btns_h & WPAD_BUTTON_2)
J |= VBA_BUTTON_R;
} else if (wp->exp.type == WPAD_EXP_CLASSIC) {
// DPad movement
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_CLASSIC_BUTTON_B)
J |= VBA_BUTTON_A;
// Run, pick up, throw, fire
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y || run)
J |= VBA_BUTTON_B;
// Spin attack
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A)
J |= VBA_BUTTON_A;
// R
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
J |= VBA_BUTTON_R;
// Crouch
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L || wp->btns_h & WPAD_CLASSIC_BUTTON_ZL) {
J |= VBA_DOWN;
J &= ~VBA_UP;
}
// Speed
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZR)
J |= VBA_SPEED;
}
#endif
return J;
}
u32 MarioWorldInput(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeKeyboard(pad);
u8 CarryState = CPUReadByte(0x3003F06); // 01 = carrying, 00 = not carrying
u8 InYoshisMouth = CPUReadByte(0x3003F53); // FF = nothing, 00 = no level, else thing
u8 FallState = CPUReadByte(0x3003FA1); // 0B = jump, 24 = fall
u8 RidingYoshi = CPUReadByte(0x3004302); // 00 = not riding, 01 = riding
static bool NeedStomp = false;
bool dontrun = false;
bool run = false;
static bool dontletgo = false;
dontrun = (InYoshisMouth != 0 && InYoshisMouth != 0xFF && RidingYoshi);
bool BButton = false;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
run = (wp->exp.type==WPAD_EXP_NUNCHUK && wp->exp.nunchuk.js.mag> 0.83) || (wp->exp.type==WPAD_EXP_CLASSIC && wp->exp.classic.ljs.mag> 0.83);
BButton = (wp->exp.type == WPAD_EXP_CLASSIC && (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y)) || wp->btns_h & WPAD_BUTTON_B;
#endif
u32 gc = PAD_ButtonsHeld(pad);
BButton = BButton || gc & PAD_BUTTON_B;
if (run && CarryState && !BButton)
dontletgo = true;
if (!CarryState)
dontletgo = false;
#ifdef HW_RVL
if (wp->exp.type == WPAD_EXP_NUNCHUK) {
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_A;
// Run, pick up
if ((run && !dontrun) || wp->btns_h & WPAD_BUTTON_B || dontletgo)
J |= VBA_BUTTON_B;
if (wp->btns_h & WPAD_BUTTON_B && dontletgo) {
J = J & ~VBA_BUTTON_B;
dontletgo = false;
}
// Spin attack
if (fabs(wp->gforce.x)> 1.5)
J |= VBA_BUTTON_R;
// Butt stomp
if (FallState!=0 && (wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z) && (!RidingYoshi))
NeedStomp = true;
if (FallState!=0 && (wp->exp.type == WPAD_EXP_CLASSIC) && (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL || wp->btns_h & WPAD_CLASSIC_BUTTON_ZR) && (!RidingYoshi))
NeedStomp = true;
// Crouch
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z) {
J |= VBA_DOWN; // Crouch
J &= ~VBA_UP;
}
// Camera
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_C) {
if (J & VBA_DOWN || J & VBA_UP)
J |= VBA_BUTTON_L;
else if (J & VBA_RIGHT || J & VBA_LEFT) {
J |= VBA_BUTTON_L;
J &= ~VBA_RIGHT;
J &= ~VBA_LEFT;
}
}
} else if (wp->exp.type == WPAD_EXP_CLASSIC) {
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS)
J |= VBA_BUTTON_START;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y)
J |= VBA_BUTTON_B;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_B)
J |= VBA_BUTTON_A;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A || wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
J |= VBA_BUTTON_R;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L)
J |= VBA_BUTTON_L;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL || wp->btns_h & WPAD_CLASSIC_BUTTON_ZR)
{
J |= VBA_DOWN; // Crouch
J &= ~VBA_UP;
}
}
BButton = (wp->exp.type == WPAD_EXP_CLASSIC && (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y)) || wp->btns_h & WPAD_BUTTON_B;
#endif
// Gamecube controller
if (gc & PAD_BUTTON_A)
J |= VBA_BUTTON_A;
if (gc & PAD_BUTTON_B)
J |= VBA_BUTTON_B;
if (gc & PAD_BUTTON_X)
J |= VBA_BUTTON_R;
if (gc & PAD_BUTTON_Y)
J |= VBA_BUTTON_SELECT;
if (gc & PAD_TRIGGER_R)
J |= VBA_BUTTON_R;
if (gc & PAD_TRIGGER_L)
J |= VBA_BUTTON_L;
if (gc & PAD_BUTTON_START)
J |= VBA_BUTTON_START;
if (gc & PAD_TRIGGER_Z) {
J |= VBA_DOWN;
J &= ~VBA_UP;
}
// if we try to use Yoshi's tongue while running, release run for one frame
if (run && BButton && !dontrun && !dontletgo)
J &= ~VBA_BUTTON_B;
if (NeedStomp && FallState == 0 && !RidingYoshi) {
J |= VBA_BUTTON_R; // spin attack only works when on ground
NeedStomp = false;
}
return J;
}
u32 Mario3Input(unsigned short pad)
{
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeKeyboard(pad);
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
bool run = false;
run = (wp->exp.type==WPAD_EXP_NUNCHUK && wp->exp.nunchuk.js.mag> 0.83) || (wp->exp.type==WPAD_EXP_CLASSIC && wp->exp.classic.ljs.mag> 0.83);
run = run && ((J & VBA_LEFT) || (J & VBA_RIGHT));
if (wp->exp.type == WPAD_EXP_NONE)
J |= DecodeWiimote(pad);
else if (wp->exp.type == WPAD_EXP_CLASSIC) {
// DPad movement
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS)
J |= VBA_BUTTON_L;
// Replay menu
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_CLASSIC_BUTTON_B)
J |= VBA_BUTTON_A;
// Run, pick up, throw, fire
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y || run)
J |= VBA_BUTTON_B;
// Spin attack (racoon costume, fire flower)
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A)
J |= VBA_BUTTON_B;
// Crouch
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL || wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L) {
J |= VBA_DOWN;
J &= ~VBA_UP;
}
// Speed
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZR)
J |= VBA_SPEED;
} else if (wp->exp.type == WPAD_EXP_NUNCHUK) {
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_L;
// Replay Menu
if (wp->btns_h & WPAD_BUTTON_1)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_A;
// Run, pick up, throw, fire
if (wp->btns_h & WPAD_BUTTON_B || run)
J |= VBA_BUTTON_B;
// Spin attack (racoon, fire flower)
if (fabs(wp->gforce.x)> 1.4)
J |= VBA_BUTTON_B;
// Crouch
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z)
{
J |= VBA_DOWN;
J &= ~VBA_UP;
}
// Speed
if (wp->btns_h & WPAD_BUTTON_2)
J |= VBA_SPEED;
}
#endif
return J;
}
u32 YoshiIslandInput(unsigned short pad)
{
u32 J = StandardMovement(pad) | DecodeWiimote(pad) | DecodeGamecube(pad) | DecodeKeyboard(pad);
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
if (wp->exp.type == WPAD_EXP_NUNCHUK) {
J |= StandardDPad(pad);
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Jump
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_A;
// Run, pick up
if (wp->btns_h & WPAD_BUTTON_B)
J |= VBA_BUTTON_B;
// throw
if (wp->btns_h & WPAD_BUTTON_1 || wp->btns_h & WPAD_BUTTON_2)
J |= VBA_BUTTON_R;
// Crouch, lay egg
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z) {
J |= VBA_DOWN; // Crouch
J &= ~VBA_UP;
}
// Camera
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_C)
J |= VBA_BUTTON_L;
} else if (wp->exp.type == WPAD_EXP_CLASSIC) {
J |= StandardDPad(pad);
if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS)
J |= VBA_BUTTON_START;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X)
J |= VBA_BUTTON_B;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_Y)
J |= VBA_BUTTON_R;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_B)
J |= VBA_BUTTON_A;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A || wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
J |= VBA_BUTTON_R;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L)
J |= VBA_BUTTON_L;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL || wp->btns_h & WPAD_CLASSIC_BUTTON_ZR)
{
J |= VBA_DOWN; // Crouch
J &= ~VBA_UP;
}
}
#endif
// Gamecube controller
{
u32 gc = PAD_ButtonsHeld(pad);
if (gc & PAD_BUTTON_A)
J |= VBA_BUTTON_A;
if (gc & PAD_BUTTON_B)
J |= VBA_BUTTON_B;
if (gc & PAD_BUTTON_X)
J |= VBA_BUTTON_R;
if (gc & PAD_BUTTON_Y)
J |= VBA_BUTTON_SELECT;
if (gc & PAD_TRIGGER_R)
J |= VBA_BUTTON_R;
if (gc & PAD_TRIGGER_L)
J |= VBA_BUTTON_L;
if (gc & PAD_BUTTON_START)
J |= VBA_BUTTON_START;
if (gc & PAD_TRIGGER_Z) {
J |= VBA_DOWN;
J &= ~VBA_UP;
}
}
return J;
}
u32 UniversalGravitationInput(unsigned short pad) {
TiltScreen = true;
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeKeyboard(pad);
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
if (wp->exp.type == WPAD_EXP_NUNCHUK) {
J |= StandardDPad(pad);
TiltSideways = false;
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Select, L & R do nothing!
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
if (wp->btns_h & WPAD_BUTTON_1)
J |= VBA_BUTTON_L | VBA_SPEED;
if (wp->btns_h & WPAD_BUTTON_2)
J |= VBA_BUTTON_R | VBA_SPEED;
// Jump
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_A;
// tongue
if (wp->btns_h & WPAD_BUTTON_B)
J |= VBA_BUTTON_B;
// Crouch, butt stomp
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z) {
J |= VBA_DOWN; // Crouch
J &= ~VBA_UP;
}
// Camera
if (wp->btns_h & WPAD_NUNCHUK_BUTTON_C) {
J |= VBA_UP;
}
}
else if (wp->exp.type == WPAD_EXP_CLASSIC) {
TiltSideways = false;
J |= StandardDPad(pad);
// A bit stupid playing with the classic controller, but nevermind.
if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS)
J |= VBA_BUTTON_START;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X)
J |= VBA_BUTTON_B;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_Y)
J |= VBA_BUTTON_R;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_B || wp->btns_h & WPAD_CLASSIC_BUTTON_A)
J |= VBA_BUTTON_A;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L || wp->btns_h & WPAD_CLASSIC_BUTTON_ZL)
J |= VBA_DOWN;
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
J |= VBA_UP;
if (WPAD_CLASSIC_BUTTON_ZR)
J |= VBA_SPEED;
} else {
J |= StandardSideways(pad);
TiltSideways = true;
}
#endif
return J;
}

655
source/ngc/inputmetroid.cpp Normal file
View File

@ -0,0 +1,655 @@
/****************************************************************************
* Visual Boy Advance GX
*
* Carl Kenner Febuary 2009
*
* gameinput.cpp
*
* Wii/Gamecube controls for individual 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"
u32 MetroidZeroInput(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeClassic(pad) | DecodeKeyboard(pad);
u8 BallState = CPUReadByte(0x30015df); // 0 = stand, 1 = crouch, 2 = ball
u16 Health = CPUReadByte(0x3001536); // 0 = stand, 1 = crouch, 2 = ball
static u16 OldHealth = 0;
// Rumble when they lose health!
if (Health < OldHealth)
systemGameRumble(20);
OldHealth = Health;
static int Morph = 0;
static int AimCount = 0;
static int MissileCount = 0;
if (BallState == 2) // Can't exit morph ball without pressing C!
J &= ~VBA_UP;
if (BallState == 1) // Can't enter morph ball without pressing C!
J &= ~VBA_DOWN;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
if (wp->btns_h & WPAD_BUTTON_UP)
J |= VBA_SPEED;
if (wp->btns_h & WPAD_BUTTON_LEFT)
J |= VBA_BUTTON_L;
if (wp->btns_h & WPAD_BUTTON_RIGHT)
J |= VBA_BUTTON_R;
// Visor doesn't exist, use as start button
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_START;
// Hyper (toggle super missiles)
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_SELECT;
// Map
if (wp->btns_h & WPAD_BUTTON_1)
J |= VBA_BUTTON_START;
// Hint
if (wp->btns_h & WPAD_BUTTON_2)
J |= VBA_BUTTON_R;
// Z-Target
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z))
;
// Jump
if (wp->btns_h & WPAD_BUTTON_B && BallState!=2)
J |= VBA_BUTTON_A;
else if (BallState==2 && fabs(wp->gforce.y)> 1.5)
J |= VBA_BUTTON_A;
// Fire
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_B;
// Aim
/*if (CursorValid && CursorY < 96 && BallState!=2)
J |= VBA_UP;
else if (CursorValid && CursorY < 192 && BallState!=2)
J |= VBA_BUTTON_L;
else if (CursorValid && CursorY < 288 && BallState!=2)
J |= 0;
else if (CursorValid && CursorY < 384 && BallState!=2)
J |= VBA_BUTTON_L & VBA_DOWN;
else if (CursorValid && BallState==0)
J |= VBA_DOWN;*/
if (wp->orient.pitch < -45 && BallState !=2) {
J |= VBA_UP;
AimCount = 0;
} else if (wp->orient.pitch < -22 && BallState !=2) {
if (AimCount>=0) AimCount = -1;
} else if (wp->orient.pitch> 45 && BallState ==0) {
if (AimCount<10) AimCount=10;
} else if (wp->orient.pitch> 22 && BallState !=2) {
if (AimCount<=0 || AimCount>=10) AimCount = 1;
} else {
AimCount=0;
}
// Morph Ball
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_d & WPAD_NUNCHUK_BUTTON_C)) {
if (BallState == 2) { // ball
Morph = -1;
} else if (BallState == 1) {
Morph = 2;
} else {
Morph = 1;
}
}
// Missile
if (wp->btns_h & WPAD_BUTTON_DOWN) {
MissileCount = 1;
}
switch (AimCount) {
case 1:
J &= ~(VBA_UP | VBA_DOWN | VBA_BUTTON_L);
J |= VBA_BUTTON_L;
AimCount++;
break;
case 2:
J &= ~(VBA_UP | VBA_DOWN | VBA_BUTTON_L);
J |= VBA_BUTTON_L | VBA_DOWN;
AimCount++;
break;
case 3:
J |= VBA_BUTTON_L;
break;
case -1:
J &= ~(VBA_UP | VBA_DOWN | VBA_BUTTON_L);
J |= 0;
AimCount--;
break;
case -2:
J &= ~(VBA_UP | VBA_DOWN | VBA_BUTTON_L);
J |= VBA_BUTTON_L;
AimCount--;
break;
case -3:
J |= VBA_BUTTON_L;
break;
case 10:
J |= VBA_BUTTON_A;
AimCount++;
break;
case 11:
J |= VBA_DOWN;
AimCount++;
break;
case 12:
J |= VBA_DOWN;
break;
}
switch (MissileCount) {
case 1:
case 2:
J |= VBA_BUTTON_R;
MissileCount++;
break;
case 3:
case 4:
J |= VBA_BUTTON_R | VBA_BUTTON_B;
MissileCount++;
break;
case 5:
MissileCount = 0;
break;
}
switch (Morph) {
case 1:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_DOWN;
Morph = 2;
break;
case 2:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
Morph = 3;
break;
case 3:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_DOWN;
Morph = 0;
break;
case -1:
case -2:
case -3:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_UP;
Morph--;
break;
case -4:
case -5:
case -6:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
Morph--;
break;
case -7:
case -8:
case -9:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_UP;
Morph--;
break;
case -10:
Morph = 0;
break;
}
#endif
return J;
}
u32 MetroidFusionInput(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeClassic(pad) | DecodeKeyboard(pad);
u8 BallState = CPUReadByte(0x3001329); // 0 = stand, 2 = crouch, 5 = ball
u16 Health = CPUReadHalfWord(0x3001310);
static u16 OldHealth = 0;
// Rumble when they lose health!
if (Health < OldHealth)
systemGameRumble(20);
OldHealth = Health;
static int Morph = 0;
static int AimCount = 0;
static int MissileCount = 0;
if (BallState == 5) // Can't exit morph ball without pressing C!
J &= ~VBA_UP;
if (BallState == 2) // Can't enter morph ball without pressing C!
J &= ~VBA_DOWN;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
if (wp->btns_h & WPAD_BUTTON_LEFT)
J |= VBA_BUTTON_L;
if (wp->btns_h & WPAD_BUTTON_RIGHT)
J |= VBA_BUTTON_R;
// Visor doesn't exist, just use as select button
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Hyper isn't available, just use start button as start
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Map
if (wp->btns_h & WPAD_BUTTON_1)
J |= VBA_BUTTON_START;
// Hint
if (wp->btns_h & WPAD_BUTTON_2)
J |= VBA_BUTTON_R;
// Z-Target
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z))
J |= VBA_SPEED;
// Jump
if (wp->btns_h & WPAD_BUTTON_B && BallState!=5)
J |= VBA_BUTTON_A;
else if (BallState==5 && fabs(wp->gforce.y)> 1.5)
J |= VBA_BUTTON_A;
// Fire
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_B;
// Aim
if (wp->orient.pitch < -45 && BallState !=5) {
J |= VBA_UP;
AimCount = 0;
} else if (wp->orient.pitch < -22 && BallState !=5) {
if (AimCount>=0) AimCount = -1;
} else if (wp->orient.pitch> 45 && BallState !=5) {
if (AimCount<10) AimCount=10;
} else if (wp->orient.pitch> 22 && BallState !=5) {
if (AimCount<=0 || AimCount>=10) AimCount = 1;
} else {
AimCount=0;
}
// Morph Bdall
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_d & WPAD_NUNCHUK_BUTTON_C)) {
if (BallState == 5) { // ball
Morph = -1;
} else if (BallState == 2) {
Morph = 2;
} else {
Morph = 1;
}
}
// Missile
if (wp->btns_h & WPAD_BUTTON_DOWN) {
MissileCount = 1;
}
#endif
switch (AimCount) {
case 1:
J &= ~(VBA_UP | VBA_DOWN | VBA_BUTTON_L);
J |= VBA_BUTTON_L;
AimCount++;
break;
case 2:
J &= ~(VBA_UP | VBA_DOWN | VBA_BUTTON_L);
J |= VBA_BUTTON_L | VBA_DOWN;
AimCount++;
break;
case 3:
J |= VBA_BUTTON_L;
break;
case -1:
J &= ~(VBA_UP | VBA_DOWN | VBA_BUTTON_L);
J |= 0;
AimCount--;
break;
case -2:
J &= ~(VBA_UP | VBA_DOWN | VBA_BUTTON_L);
J |= VBA_BUTTON_L;
AimCount--;
break;
case -3:
J |= VBA_BUTTON_L;
break;
case 10:
case 11:
J |= VBA_BUTTON_A;
AimCount++;
break;
case 12:
case 13:
J |= VBA_DOWN;
AimCount++;
break;
case 14:
J |= VBA_DOWN;
break;
}
switch (MissileCount) {
case 1:
case 2:
J |= VBA_BUTTON_R;
MissileCount++;
break;
case 3:
case 4:
J |= VBA_BUTTON_R | VBA_BUTTON_B;
MissileCount++;
break;
case 5:
MissileCount = 0;
break;
}
switch (Morph) {
case 1:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_DOWN;
Morph = 2;
break;
case 2:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
Morph = 3;
break;
case 3:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_DOWN;
Morph = 0;
break;
case -1:
case -2:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_UP;
Morph--;
break;
case -3:
case -4:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
Morph--;
break;
case -5:
case -6:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_UP;
Morph--;
break;
case -7:
Morph = 0;
break;
}
return J;
}
u32 Metroid1Input(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeClassic(pad) | DecodeKeyboard(pad);
u8 BallState = CPUReadByte(0x3007500); // 3 = ball, other = stand
u8 MissileState = CPUReadByte(0x300730E); // 1 = missile, 0 = beam
u16 Health = CPUReadHalfWord(0x3007306); // Binary Coded Decimal
static u16 OldHealth = 0;
// Rumble when they lose health!
if (Health < OldHealth)
systemGameRumble(20);
OldHealth = Health;
static int Morph = 0;
if (BallState == 3) // Can't exit morph ball without pressing C!
J &= ~VBA_UP;
if (BallState != 3) // Can't enter morph ball without pressing C!
J &= ~VBA_DOWN;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
// No visors
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Start button just pauses
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Map (doesn't exist)
if (wp->btns_h & WPAD_BUTTON_1)
J |= VBA_BUTTON_START;
// Hint (doesn't exist)
if (wp->btns_h & WPAD_BUTTON_2)
J |= VBA_SPEED;
// Z-Target
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z))
;
// Jump
if (wp->btns_h & WPAD_BUTTON_B && BallState!=5)
J |= VBA_BUTTON_A;
else if (BallState==5 && fabs(wp->gforce.y)> 1.5)
J |= VBA_BUTTON_A;
// Fire
if (wp->btns_h & WPAD_BUTTON_A) {
if (MissileState)
J |= VBA_BUTTON_SELECT;
else
J |= VBA_BUTTON_B;
}
// Aim
if (wp->orient.pitch < -45 && BallState !=3)
J |= VBA_UP;
// Morph Ball
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_d & WPAD_NUNCHUK_BUTTON_C)) {
if (BallState == 3) { // ball
Morph = -1;
} else {
Morph = 2;
}
}
// Missile
if (wp->btns_h & WPAD_BUTTON_DOWN) {
if (!(MissileState))
J |= VBA_BUTTON_SELECT;
else
J |= VBA_BUTTON_B;
} if (wp->btns_u & WPAD_BUTTON_DOWN) {
if (MissileState)
J |= VBA_BUTTON_SELECT;
}
#endif
switch (Morph) {
case 1:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_DOWN;
Morph = 2;
break;
case 2:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
Morph = 3;
break;
case 3:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_DOWN;
Morph = 0;
break;
case -1:
case -2:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_UP;
Morph--;
break;
case -3:
case -4:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
Morph--;
break;
case -5:
case -6:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_UP;
Morph--;
break;
case -7:
Morph = 0;
break;
}
return J;
}
u32 Metroid2Input(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeClassic(pad) | DecodeKeyboard(pad);
u8 BallState = gbReadMemory(0xD020); // 4 = crouch, 5 = ball, other = stand
u8 MissileState = gbReadMemory(0xD04D); // 8 = missile hatch open, 0 = missile closed
u8 Health = gbReadMemory(0xD051); // Binary Coded Decimal
static u8 OldHealth = 0;
// Rumble when they lose (or gain) health! (since I'm not checking energy tanks)
if (Health != OldHealth)
systemGameRumble(20);
OldHealth = Health;
static int Morph = 0;
static int AimCount = 0;
if (BallState == 5) // Can't exit morph ball without pressing C!
J &= ~VBA_UP;
if (BallState == 4) // Can't enter morph ball without pressing C!
J &= ~VBA_DOWN;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
// No visors
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Start button just pauses
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Map (doesn't exist)
if (wp->btns_h & WPAD_BUTTON_1)
J |= VBA_BUTTON_START;
// Hint (doesn't exist)
if (wp->btns_h & WPAD_BUTTON_2)
J |= VBA_SPEED;
// Z-Target
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z))
;
// Jump
if (wp->btns_h & WPAD_BUTTON_B && BallState!=5)
J |= VBA_BUTTON_A;
else if (BallState==5 && fabs(wp->gforce.y)> 1.5)
J |= VBA_BUTTON_A;
// Fire
if (wp->btns_h & WPAD_BUTTON_A) {
if (MissileState & 8)
J |= VBA_BUTTON_SELECT;
else
J |= VBA_BUTTON_B;
}
// Aim
/*if (CursorValid && CursorY < 96 && BallState!=2)
J |= VBA_UP;
else if (CursorValid && CursorY < 192 && BallState!=2)
J |= VBA_BUTTON_L;
else if (CursorValid && CursorY < 288 && BallState!=2)
J |= 0;
else if (CursorValid && CursorY < 384 && BallState!=2)
J |= VBA_BUTTON_L & VBA_DOWN;
else if (CursorValid && BallState==0)
J |= VBA_DOWN;*/
if (wp->orient.pitch < -45 && BallState !=5) {
J |= VBA_UP;
AimCount = 0;
} else if (wp->orient.pitch> 45 && BallState !=5 && BallState !=4) {
//if (AimCount<10) AimCount=10;
} else {
AimCount=0;
}
// Morph Ball
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_d & WPAD_NUNCHUK_BUTTON_C)) {
if (BallState == 5) { // ball
Morph = -1;
} else if (BallState == 4) {
Morph = 2;
} else {
Morph = 1;
}
}
// Missile
if (wp->btns_h & WPAD_BUTTON_DOWN) {
if (!(MissileState & 8))
J |= VBA_BUTTON_SELECT;
else
J |= VBA_BUTTON_B;
}
if (wp->btns_u & WPAD_BUTTON_DOWN) {
if (MissileState & 8)
J |= VBA_BUTTON_SELECT;
}
#endif
switch (Morph) {
case 1:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_DOWN;
Morph = 2;
break;
case 2:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
Morph = 3;
break;
case 3:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_DOWN;
Morph = 0;
break;
case -1:
case -2:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_UP;
Morph--;
break;
case -3:
case -4:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
Morph--;
break;
case -5:
case -6:
J &= ~(VBA_UP | VBA_DOWN | VBA_LEFT | VBA_RIGHT | VBA_BUTTON_L);
J |= VBA_UP;
Morph--;
break;
case -7:
Morph = 0;
break;
}
return J;
}

1654
source/ngc/inputzelda.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@ extern "C"
extern int menu;
extern bool ROMLoaded;
extern char DebugStr[50];
/****************************************************************************
* Load Manager
@ -281,7 +282,7 @@ PreferencesMenu ()
static int
GameMenu ()
{
int gamemenuCount = 9;
int gamemenuCount = 10;
char gamemenu[][50] = {
"Return to Game",
"Reset Game",
@ -289,7 +290,8 @@ GameMenu ()
"Load Game Snapshot", "Save Game Snapshot",
"Reset Zoom",
"Weather: 100% sun",
"Back to Main Menu"
"Back to Main Menu",
""
};
int ret, retval = 0;
@ -325,6 +327,8 @@ GameMenu ()
else
gamemenu[7][0] = '\0';
sprintf(gamemenu[9], "%s", DebugStr);
ret = RunMenu (gamemenu, gamemenuCount, "Game Menu");
switch (ret)
@ -639,8 +643,13 @@ ConfigureControllers ()
while (quit == 0)
{
#ifdef HW_RVL
sprintf (ctlrmenu[0], "Match Wii Game: %s",
GCSettings.WiiControls == true ? " ON" : "OFF");
#else
sprintf (ctlrmenu[0], "Match Gamecube Game: %s",
GCSettings.WiiControls == true ? " ON" : "OFF");
#endif
/*** Controller Config Menu ***/
ret = RunMenu (ctlrmenu, ctlrmenucount, "Configure Controllers");

View File

@ -245,34 +245,56 @@ static void draw_square(Mtx v)
GX_End();
}
void Menu_DrawImg(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], f32 degrees, f32 scaleX, f32 scaleY, u8 alpha);
static void draw_cursor(Mtx v)
{
if (!CursorVisible)
if (!CursorVisible || !CursorValid)
return;
/*
#ifdef HW_RVL
WPADData *wp = WPAD_Data(0);
if(wp->ir.valid)
Menu_DrawImg(wp->ir.x-48, wp->ir.y-48, 96, 96, pointer1->GetImage(), wp->ir.angle, 1, 1, 255);
#endif
*/
GX_InitTexObj(&texobj, pointer1->GetImage(), 96, 96, GX_TF_RGBA8,GX_CLAMP, GX_CLAMP,GX_FALSE);
GX_LoadTexObj(&texobj, GX_TEXMAP0);
GX_SetBlendMode(GX_BM_BLEND,GX_BL_DSTALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR);
GX_SetTevOp (GX_TEVSTAGE0, GX_REPLACE);
GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT);
Mtx m; // model matrix.
guMtxIdentity(m);
guMtxScaleApply(m, m, 0.05f, 0.05f, 0.06f);
guMtxTransApply(m, m, CursorX-320, 240-CursorY, -100);
guMtxScaleApply(m, m, 0.070f, 0.10f, 0.06f);
// I needed to hack this position
guMtxTransApply(m, m, CursorX-315, 220-CursorY, -100);
GX_LoadPosMtxImm(m, GX_PNMTX0);
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
draw_vert(0, 0, 0.0, 0.0);
draw_vert(1, 0, 1.0, 0.0);
draw_vert(2, 0, 1.0, 1.0);
draw_vert(3, 0, 0.0, 1.0);
// I needed to hack the texture coords to cut out the opaque bit around the outside
draw_vert(0, 0, 0.4, 0.45);
draw_vert(1, 0, 0.76, 0.45);
draw_vert(2, 0, 0.76, 0.97);
draw_vert(3, 0, 0.4, 0.97);
GX_End();
GX_ClearVtxDesc ();
GX_SetVtxDesc (GX_VA_POS, GX_INDEX8);
GX_SetVtxDesc (GX_VA_CLR0, GX_INDEX8);
GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT);
GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GX_SetArray (GX_VA_POS, square, 3 * sizeof (s16));
GX_SetNumTexGens (1);
GX_SetTexCoordGen (GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
GX_InvVtxCache (); // update vertex cache
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565,
GX_CLAMP, GX_CLAMP, GX_FALSE);
if (!(GCSettings.render&1))
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF
}
/****************************************************************************
@ -695,51 +717,3 @@ zoom_reset ()
updateScaling = 1; // update video
}
void Menu_DrawImg(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], f32 degrees, f32 scaleX, f32 scaleY, u8 alpha)
{
if(data == NULL)
return;
GXTexObj texObj;
GX_InitTexObj(&texObj, data, width,height, GX_TF_RGBA8,GX_CLAMP, GX_CLAMP,GX_FALSE);
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT);
Mtx m,m1,m2, mv;
width *=.5;
height*=.5;
guMtxIdentity (m1);
guMtxScaleApply(m1,m1,scaleX,scaleY,1.0);
Vector axis = (Vector) {0 , 0, 1 };
guMtxRotAxisDeg (m2, &axis, degrees);
guMtxConcat(m2,m1,m);
guMtxTransApply(m,m, xpos+width,ypos+height,0);
guMtxConcat (view, m, mv);
GX_LoadPosMtxImm (mv, GX_PNMTX0);
GX_Begin(GX_QUADS, GX_VTXFMT0,4);
GX_Position3f32(-width, -height, 0);
GX_Color4u8(0xFF,0xFF,0xFF,alpha);
GX_TexCoord2f32(0, 0);
GX_Position3f32(width, -height, 0);
GX_Color4u8(0xFF,0xFF,0xFF,alpha);
GX_TexCoord2f32(1, 0);
GX_Position3f32(width, height, 0);
GX_Color4u8(0xFF,0xFF,0xFF,alpha);
GX_TexCoord2f32(1, 1);
GX_Position3f32(-width, height, 0);
GX_Color4u8(0xFF,0xFF,0xFF,alpha);
GX_TexCoord2f32(0, 1);
GX_End();
GX_LoadPosMtxImm (view, GX_PNMTX0);
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
GX_SetVtxDesc (GX_VA_TEX0, GX_NONE);
}