From b02f07b457e1bc73d8394650fa6a2e0e3971b589 Mon Sep 17 00:00:00 2001 From: "Carl.Kenner" Date: Sat, 25 Apr 2009 12:09:13 +0000 Subject: [PATCH] Teenage Mutant Ninja Turtles (more games) and Mortal Kombat (lots of added characters, distinguishes between low and high attacks, standard moves now have normal controls). --- source/ngc/gameinput.cpp | 346 ++++++- source/ngc/gameinput.h | 13 + source/ngc/input.cpp | 12 + source/ngc/inputmortalkombat.cpp | 1515 ++++++++++++++++++++++++++---- source/ngc/menu.cpp | 3 + source/ngc/vbasupport.cpp | 8 + 6 files changed, 1730 insertions(+), 167 deletions(-) diff --git a/source/ngc/gameinput.cpp b/source/ngc/gameinput.cpp index 5ec12df..411bcaa 100644 --- a/source/ngc/gameinput.cpp +++ b/source/ngc/gameinput.cpp @@ -30,14 +30,14 @@ #include "gba/bios.h" #include "gba/GBAinline.h" -/*char DebugStr[50] = ""; +char DebugStr[50] = ""; void DebugPrintf(const char *format, ...) { va_list args; va_start( args, format ); vsprintf( DebugStr, format, args ); va_end( args ); -}*/ +} u32 LegoStarWars1Input(unsigned short pad) { u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DPadWASD(pad); @@ -153,7 +153,7 @@ u32 LegoStarWars2Input(unsigned short pad) { } u32 TMNTInput(unsigned short pad) { - u32 J = StandardMovement(pad) | StandardDPad(pad) | DecodeClassic(pad) | DecodeKeyboard(pad) | DecodeGamecube(pad); + u32 J = StandardMovement(pad) | StandardDPad(pad) | DecodeKeyboard(pad); static u32 LastDir = VBA_RIGHT; static bool wait = false; static int holdcount = 0; @@ -261,6 +261,346 @@ u32 TMNTInput(unsigned short pad) { return J; } +u32 TMNT1Input(unsigned short pad) { + u32 J = StandardMovement(pad) | StandardDPad(pad) | DecodeKeyboard(pad); + static u32 LastDir = VBA_RIGHT; + static bool wait = false; + static int holdcount = 0; + bool Jump=0, Attack=0, SpinKick=0, Roll=0, Pause=0, Select=0; + +#ifdef HW_RVL + WPADData * wp = WPAD_Data(pad); + if (wp->exp.type == WPAD_EXP_NUNCHUK) { + Jump = (wp->btns_h & WPAD_BUTTON_A); + Attack = (fabs(wp->gforce.x)> 1.5); + SpinKick = (fabs(wp->exp.nunchuk.gforce.x)> 0.5); + Roll = (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z || wp->btns_h & WPAD_NUNCHUK_BUTTON_C); + Pause = (wp->btns_h & WPAD_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_BUTTON_MINUS); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_BUTTON_B) { + // N/A + } + } else if (wp->exp.type == WPAD_EXP_CLASSIC) { + J |= StandardDPad(pad); + Jump = (wp->btns_h & WPAD_CLASSIC_BUTTON_B); + Attack = (wp->btns_h & WPAD_CLASSIC_BUTTON_A); + SpinKick = (wp->btns_h & WPAD_CLASSIC_BUTTON_X); + Pause = (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS); + Roll = (wp->btns_h & (WPAD_CLASSIC_BUTTON_FULL_L | WPAD_CLASSIC_BUTTON_FULL_R | WPAD_CLASSIC_BUTTON_ZL | WPAD_CLASSIC_BUTTON_ZR)); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_CLASSIC_BUTTON_Y) { + // N/A + } + } else { + Jump = (wp->btns_h & WPAD_BUTTON_A); + Attack = (fabs(wp->gforce.x)> 1.5); + Pause = (wp->btns_h & WPAD_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_BUTTON_MINUS); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_BUTTON_B) { + //N/A + } + SpinKick = (wp->btns_h & WPAD_BUTTON_1); + Roll = (wp->btns_h & WPAD_BUTTON_2); + } + +#endif + u32 gc = PAD_ButtonsHeld(pad); + u32 released = PAD_ButtonsUp(pad); + // DPad moves + if (gc & PAD_BUTTON_UP) + J |= VBA_UP; + if (gc & PAD_BUTTON_DOWN) + J |= VBA_DOWN; + if (gc & PAD_BUTTON_LEFT) + J |= VBA_LEFT; + if (gc & PAD_BUTTON_RIGHT) + J |= VBA_RIGHT; + // Jump + if (gc & PAD_BUTTON_A) J |= VBA_BUTTON_A; + // Swap turtles, hold for super family move + if (gc & PAD_BUTTON_B) { + // N/A + } + // Attack + if (gc & PAD_BUTTON_X) Attack = true; + // Spin kick + if (gc & PAD_BUTTON_Y) SpinKick = true; + // Pause + if (gc & PAD_BUTTON_START) Pause = true; + // Select + if (gc & PAD_TRIGGER_Z) Select = true; + // Roll + if (gc & PAD_TRIGGER_L || gc & PAD_TRIGGER_R) Roll = true; + + if (Jump) J |= VBA_BUTTON_A; + if (Attack || SpinKick) J |= VBA_BUTTON_B; + if (Pause) J |= VBA_BUTTON_START; + if (Select) J |= VBA_BUTTON_SELECT; + + if (J & VBA_RIGHT) LastDir = VBA_RIGHT; + else if (J & VBA_LEFT) LastDir = VBA_LEFT; + return J; +} + +u32 TMNT2Input(unsigned short pad) { + u32 J = StandardMovement(pad) | StandardDPad(pad) | DecodeKeyboard(pad); + static u32 LastDir = VBA_RIGHT; + static bool wait = false; + static int holdcount = 0; + bool Jump=0, Attack=0, SpinKick=0, Roll=0, Pause=0, Select=0; + +#ifdef HW_RVL + WPADData * wp = WPAD_Data(pad); + if (wp->exp.type == WPAD_EXP_NUNCHUK) { + Jump = (wp->btns_h & WPAD_BUTTON_A); + Attack = (fabs(wp->gforce.x)> 1.5); + SpinKick = (fabs(wp->exp.nunchuk.gforce.x)> 0.5); + Roll = (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z || wp->btns_h & WPAD_NUNCHUK_BUTTON_C); + Pause = (wp->btns_h & WPAD_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_BUTTON_MINUS); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_BUTTON_B) { + // N/A + } + } else if (wp->exp.type == WPAD_EXP_CLASSIC) { + J |= StandardDPad(pad); + Jump = (wp->btns_h & WPAD_CLASSIC_BUTTON_B); + Attack = (wp->btns_h & WPAD_CLASSIC_BUTTON_A); + SpinKick = (wp->btns_h & WPAD_CLASSIC_BUTTON_X); + Pause = (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS); + Roll = (wp->btns_h & (WPAD_CLASSIC_BUTTON_FULL_L | WPAD_CLASSIC_BUTTON_FULL_R | WPAD_CLASSIC_BUTTON_ZL | WPAD_CLASSIC_BUTTON_ZR)); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_CLASSIC_BUTTON_Y) { + // N/A + } + } else { + Jump = (wp->btns_h & WPAD_BUTTON_A); + Attack = (fabs(wp->gforce.x)> 1.5); + Pause = (wp->btns_h & WPAD_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_BUTTON_MINUS); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_BUTTON_B) { + //N/A + } + SpinKick = (wp->btns_h & WPAD_BUTTON_1); + Roll = (wp->btns_h & WPAD_BUTTON_2); + } + +#endif + u32 gc = PAD_ButtonsHeld(pad); + u32 released = PAD_ButtonsUp(pad); + // DPad moves + if (gc & PAD_BUTTON_UP) + J |= VBA_UP; + if (gc & PAD_BUTTON_DOWN) + J |= VBA_DOWN; + if (gc & PAD_BUTTON_LEFT) + J |= VBA_LEFT; + if (gc & PAD_BUTTON_RIGHT) + J |= VBA_RIGHT; + // Jump + if (gc & PAD_BUTTON_A) J |= VBA_BUTTON_A; + // Swap turtles, hold for super family move + if (gc & PAD_BUTTON_B) { + // N/A + } + // Attack + if (gc & PAD_BUTTON_X) Attack = true; + // Spin kick + if (gc & PAD_BUTTON_Y) SpinKick = true; + // Pause + if (gc & PAD_BUTTON_START) Pause = true; + // Select + if (gc & PAD_TRIGGER_Z) Select = true; + // Roll + if (gc & PAD_TRIGGER_L || gc & PAD_TRIGGER_R) Roll = true; + + if (Jump) J |= VBA_BUTTON_A; + if (Attack) J |= VBA_BUTTON_B; + if (SpinKick || Roll) J |= VBA_BUTTON_B | VBA_BUTTON_A; + if (Pause) J |= VBA_BUTTON_START; + if (Select) J |= VBA_BUTTON_SELECT; + + if (J & VBA_RIGHT) LastDir = VBA_RIGHT; + else if (J & VBA_LEFT) LastDir = VBA_LEFT; + return J; +} + +u32 TMNT3Input(unsigned short pad) { + u32 J = StandardMovement(pad) | StandardDPad(pad) | DecodeKeyboard(pad); + static u32 LastDir = VBA_RIGHT; + static bool wait = false; + static int holdcount = 0; + bool Jump=0, Attack=0, SpinKick=0, Roll=0, Pause=0, Select=0; + +#ifdef HW_RVL + WPADData * wp = WPAD_Data(pad); + if (wp->exp.type == WPAD_EXP_NUNCHUK) { + Jump = (wp->btns_h & WPAD_BUTTON_A); + Attack = (fabs(wp->gforce.x)> 1.5); + SpinKick = (fabs(wp->exp.nunchuk.gforce.x)> 0.5); + Roll = (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z || wp->btns_h & WPAD_NUNCHUK_BUTTON_C); + Pause = (wp->btns_h & WPAD_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_BUTTON_MINUS); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_BUTTON_B) { + J |= VBA_BUTTON_START; + } + } else if (wp->exp.type == WPAD_EXP_CLASSIC) { + J |= StandardDPad(pad); + Jump = (wp->btns_h & WPAD_CLASSIC_BUTTON_B); + Attack = (wp->btns_h & WPAD_CLASSIC_BUTTON_A); + SpinKick = (wp->btns_h & WPAD_CLASSIC_BUTTON_X); + Pause = (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS); + Roll = (wp->btns_h & (WPAD_CLASSIC_BUTTON_FULL_L | WPAD_CLASSIC_BUTTON_FULL_R | WPAD_CLASSIC_BUTTON_ZL | WPAD_CLASSIC_BUTTON_ZR)); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_CLASSIC_BUTTON_Y) { + J |= VBA_BUTTON_START; + } + } else { + Jump = (wp->btns_h & WPAD_BUTTON_A); + Attack = (fabs(wp->gforce.x)> 1.5); + Pause = (wp->btns_h & WPAD_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_BUTTON_MINUS); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_BUTTON_B) { + J |= VBA_BUTTON_START; + } + SpinKick = (wp->btns_h & WPAD_BUTTON_1); + Roll = (wp->btns_h & WPAD_BUTTON_2); + } + +#endif + u32 gc = PAD_ButtonsHeld(pad); + u32 released = PAD_ButtonsUp(pad); + // DPad moves + if (gc & PAD_BUTTON_UP) + J |= VBA_UP; + if (gc & PAD_BUTTON_DOWN) + J |= VBA_DOWN; + if (gc & PAD_BUTTON_LEFT) + J |= VBA_LEFT; + if (gc & PAD_BUTTON_RIGHT) + J |= VBA_RIGHT; + // Jump + if (gc & PAD_BUTTON_A) J |= VBA_BUTTON_A; + // Swap turtles + if (gc & PAD_BUTTON_B) { + J |= VBA_BUTTON_START; + } + // Attack + if (gc & PAD_BUTTON_X) Attack = true; + // Spin kick + if (gc & PAD_BUTTON_Y) SpinKick = true; + // Pause + if (gc & PAD_BUTTON_START) Pause = true; + // Select + if (gc & PAD_TRIGGER_Z) Select = true; + // Roll + if (gc & PAD_TRIGGER_L || gc & PAD_TRIGGER_R) Roll = true; + + if (Jump || Roll) J |= VBA_BUTTON_A; + if (Attack || SpinKick) J |= VBA_BUTTON_B; + if (Pause) J |= VBA_BUTTON_SELECT; + if (Select) J |= VBA_BUTTON_START; + + if (J & VBA_RIGHT) LastDir = VBA_RIGHT; + else if (J & VBA_LEFT) LastDir = VBA_LEFT; + return J; +} + +u32 TMNTGBAInput(unsigned short pad) { + u32 J = StandardMovement(pad) | StandardDPad(pad) | DecodeKeyboard(pad); + static u32 LastDir = VBA_RIGHT; + static bool wait = false; + static int holdcount = 0; + bool Jump=0, Attack=0, SpinKick=0, SpecialMove=0, Pause=0, Select=0; + +#ifdef HW_RVL + WPADData * wp = WPAD_Data(pad); + if (wp->exp.type == WPAD_EXP_NUNCHUK) { + Jump = (wp->btns_h & WPAD_BUTTON_A); + Attack = (fabs(wp->gforce.x)> 1.5) || (wp->btns_h & WPAD_BUTTON_B); + SpinKick = (fabs(wp->exp.nunchuk.gforce.x)> 0.5); + SpecialMove = (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z); + Pause = (wp->btns_h & WPAD_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_BUTTON_MINUS); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_BUTTON_B) { + //J |= VBA_BUTTON_START; + } + } else if (wp->exp.type == WPAD_EXP_CLASSIC) { + Jump = (wp->btns_h & WPAD_CLASSIC_BUTTON_B); + Attack = (wp->btns_h & WPAD_CLASSIC_BUTTON_A); + SpinKick = (wp->btns_h & WPAD_CLASSIC_BUTTON_X); + Pause = (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS); + SpecialMove = (wp->btns_h & (WPAD_CLASSIC_BUTTON_FULL_L | WPAD_CLASSIC_BUTTON_FULL_R | WPAD_CLASSIC_BUTTON_ZL | WPAD_CLASSIC_BUTTON_ZR)); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_CLASSIC_BUTTON_Y) { + //J |= VBA_BUTTON_START; + } + } else { + Jump = (wp->btns_h & WPAD_BUTTON_A); + Attack = (fabs(wp->gforce.x)> 1.5) || (wp->btns_h & WPAD_BUTTON_B); + Pause = (wp->btns_h & WPAD_BUTTON_PLUS); + Select = (wp->btns_h & WPAD_BUTTON_MINUS); + // Swap Turtles or super turtle summon + if (wp->btns_h & WPAD_BUTTON_B) { + //J |= VBA_BUTTON_START; + } + SpinKick = (wp->btns_h & WPAD_BUTTON_1); + SpecialMove = (wp->btns_h & WPAD_BUTTON_2); + } + +#endif + u32 gc = PAD_ButtonsHeld(pad); + u32 released = PAD_ButtonsUp(pad); + // DPad moves + if (gc & PAD_BUTTON_UP) + J |= VBA_UP; + if (gc & PAD_BUTTON_DOWN) + J |= VBA_DOWN; + if (gc & PAD_BUTTON_LEFT) + J |= VBA_LEFT; + if (gc & PAD_BUTTON_RIGHT) + J |= VBA_RIGHT; + // Jump + if (gc & PAD_BUTTON_A) J |= VBA_BUTTON_A; + // Swap turtles + if (gc & PAD_BUTTON_B) { + //J |= VBA_BUTTON_B; + } + // Attack + if (gc & PAD_BUTTON_X) Attack = true; + // Spin kick + if (gc & PAD_BUTTON_Y) SpinKick = true; + // Pause + if (gc & PAD_BUTTON_START) Pause = true; + // Select + if (gc & PAD_TRIGGER_Z) Select = true; + // SpecialMove + if (gc & PAD_TRIGGER_L || gc & PAD_TRIGGER_R) SpecialMove = true; + + if (Jump) J |= VBA_BUTTON_A; + if (Attack) J |= VBA_BUTTON_B; + if (SpinKick) J |= VBA_BUTTON_R; + if (Pause) J |= VBA_BUTTON_START; + if (Select) J |= VBA_BUTTON_SELECT; + if (SpecialMove) { + J |= VBA_BUTTON_R | VBA_BUTTON_A; // CAKTODO + } + + if (J & VBA_RIGHT) LastDir = VBA_RIGHT; + else if (J & VBA_LEFT) LastDir = VBA_LEFT; + return J; +} + u32 HarryPotter1GBCInput(unsigned short pad) { u32 J = StandardMovement(pad) | StandardDPad(pad) | DPadWASD(pad) | DPadArrowKeys(pad) | DecodeGamecube(pad); diff --git a/source/ngc/gameinput.h b/source/ngc/gameinput.h index 767c725..483ec0f 100644 --- a/source/ngc/gameinput.h +++ b/source/ngc/gameinput.h @@ -49,6 +49,10 @@ #define HARRYPOTTER5 gid('B','J','X') #define QUIDDITCH gid('B','H','P') +#define TMNT1 0xFF000B +#define TMNT2 0xFF000C +#define TMNT3 0xFF000D +#define TMNTGBA gid('B','N','T') #define TMNT gid('B','E','X') #define RESIDENTEVIL gid('B','I','O') @@ -84,6 +88,8 @@ #define ONEPIECE gid('B','O','N') +#define MARBLEMADNESS 0xFF000A + u8 gbReadMemory(register u16 address); void gbWriteMemory(register u16 address, register u8 value); @@ -112,6 +118,9 @@ u32 LegoStarWars1Input(unsigned short pad); u32 LegoStarWars2Input(unsigned short pad); u32 MarioKartInput(unsigned short pad); u32 MK1Input(unsigned short pad); +u32 MK12Input(unsigned short pad); +u32 MK2Input(unsigned short pad); +u32 MK3Input(unsigned short pad); u32 MK4Input(unsigned short pad); u32 MKAInput(unsigned short pad); u32 MKTEInput(unsigned short pad); @@ -127,6 +136,10 @@ u32 Metroid1Input(unsigned short pad); u32 Metroid2Input(unsigned short pad); u32 MetroidFusionInput(unsigned short pad); u32 TMNTInput(unsigned short pad); +u32 TMNT1Input(unsigned short pad); +u32 TMNT2Input(unsigned short pad); +u32 TMNT3Input(unsigned short pad); +u32 TMNTGBAInput(unsigned short pad); u32 HarryPotter1Input(unsigned short pad); u32 HarryPotter1GBCInput(unsigned short pad); u32 HarryPotter2Input(unsigned short pad); diff --git a/source/ngc/input.cpp b/source/ngc/input.cpp index c8e4e37..e254f4e 100644 --- a/source/ngc/input.cpp +++ b/source/ngc/input.cpp @@ -751,6 +751,14 @@ static u32 DecodeJoy(unsigned short pad) return MetroidFusionInput(pad); // TMNT + case TMNT1: + return TMNT1Input(pad); + case TMNT2: + return TMNT2Input(pad); + case TMNT3: + return TMNT3Input(pad); + case TMNTGBA: + return TMNTGBAInput(pad); case TMNT: return TMNTInput(pad); @@ -810,8 +818,12 @@ static u32 DecodeJoy(unsigned short pad) // Mortal Kombat case MK1: return MK1Input(pad); + case MK12: + return MK12Input(pad); case MK2: + return MK2Input(pad); case MK3: + return MK3Input(pad); case MK4: return MK4Input(pad); case MKA: diff --git a/source/ngc/inputmortalkombat.cpp b/source/ngc/inputmortalkombat.cpp index 84cf857..12de3ef 100644 --- a/source/ngc/inputmortalkombat.cpp +++ b/source/ngc/inputmortalkombat.cpp @@ -30,56 +30,142 @@ #include "gba/bios.h" #include "gba/GBAinline.h" -u32 MK1Input(unsigned short pad) { - u32 J = StandardMovement(pad) | DecodeKeyboard(pad); - u8 Health = gbReadMemory(0xc695); - static u8 OldHealth = 0; +void DebugPrintf(const char *format, ...); + +#define MK1_CAGE 0 +#define MK1_KANO 1 +#define MK1_RAIDEN 2 +#define MK1_LIUKANG 3 +#define MK1_SCORPION 4 +#define MK1_SUBZERO 5 +#define MK1_SONYA 6 +#define MK1_GORO 7 +#define MK1_SHANGTSUNG 8 + +#define MK2_LIUKANG 0 +#define MK2_SUBZERO 1 +#define MK2_KITANA 2 +#define MK2_REPTILE 3 +#define MK2_SHANGTSUNG 4 +#define MK2_MILEENA 5 +#define MK2_SCORPION 6 +#define MK2_JAX 7 +// boss and secret characters +#define MK2_KINTARO 8 +#define MK2_KHAN 9 +#define MK2_SMOKE 10 +#define MK2_JADE 11 + +#define MK3_SINDEL 0 +#define MK3_SEKTOR 1 +#define MK3_KABAL 2 +#define MK3_SHEEVA 3 +#define MK3_SMOKE 4 +#define MK3_SUBZERO 5 +#define MK3_KANO 6 +#define MK3_SONYA 7 +#define MK3_CYRAX 8 +// boss +#define MK3_SHAOKHAN 9 + +#define MK4_RAIDEN 0 +#define MK4_QUANCHI 1 +#define MK4_FUJIN 2 +#define MK4_LIUKANG 3 +#define MK4_REPTILE 4 +#define MK4_SUBZERO 5 +#define MK4_REIKO 6 +#define MK4_TANYA 7 +#define MK4_SCORPION 8 +// boss +#define MK4_SHINNOK 9 + +#define MKA_Rain 0 +#define MKA_Reptile 1 +#define MKA_Stryker 2 +#define MKA_Jax 3 +#define MKA_Nightwolf 4 +#define MKA_Jade 5 +#define MKA_NoobSaibot 6 +#define MKA_Sonya 7 +#define MKA_Kano 8 +#define MKA_Mileena 9 +#define MKA_Ermac 10 +#define MKA_SubZero 11 +#define MKA_SubZero2 12 +#define MKA_KungLao 13 +#define MKA_Sektor 14 +#define MKA_Kitana 15 +#define MKA_Mystery 16 +#define MKA_Scorpion 17 +#define MKA_Cyrax 18 +#define MKA_Kabal 19 +#define MKA_Sindel 20 +#define MKA_Smoke 21 +#define MKA_LiuKang 22 +#define MKA_ShangTsung 23 +#define MKA_Motaro 24 +#define MKA_ShaoKhan 25 + +static bool HP=0,LP=0,HK=0,LK=0,BL=0,Throw=0,CS=0,F=0,B=0,Select=0,Start=0,SpecialMove=0; +static u16 OurHealth=0,OpponentHealth=0,OurOldHealth=0; +static s16 OurX=0,OpponentX=1; +static u32 VBA_FORWARD=VBA_RIGHT, VBA_BACK=VBA_LEFT; + +u32 GetMKInput(unsigned short pad, int rumbleTime=4) { + u32 J = StandardMovement(pad) | DecodeKeyboard(pad) | DecodeWiimote(pad); + HP=0;LP=0;HK=0;LK=0;BL=0;Throw=0;CS=0;F=0;B=0;Select=0;Start=0;SpecialMove=0; // Rumble when they lose health! - if (Health < OldHealth) - systemGameRumble(5); - OldHealth = Health; - + if (OurHealth < OurOldHealth) + systemGameRumble(rumbleTime); + OurOldHealth = OurHealth; + #ifdef HW_RVL WPADData * wp = WPAD_Data(pad); - // Punch - if (wp->btns_h & WPAD_BUTTON_UP || wp->btns_h & WPAD_BUTTON_LEFT) - J |= VBA_BUTTON_B; - // Kick - if (wp->btns_h & WPAD_BUTTON_DOWN || wp->btns_h & WPAD_BUTTON_RIGHT) - J |= VBA_BUTTON_A; - // Block - if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z)) - J |= VBA_BUTTON_A | VBA_BUTTON_B; // different from MK2 - // Throw - if (wp->btns_h & WPAD_BUTTON_A) - J |= VBA_BUTTON_B | VBA_RIGHT; // CAKTODO check which way we are facing - // Pause - if (wp->btns_h & WPAD_BUTTON_MINUS) - J |= VBA_BUTTON_SELECT; - // Start - if (wp->btns_h & WPAD_BUTTON_PLUS) - J |= VBA_BUTTON_START; - // Special move - if (wp->btns_h & WPAD_BUTTON_B) - { - // CAKTODO - } - - if (wp->exp.type == WPAD_EXP_CLASSIC) { + if (wp->exp.type == WPAD_EXP_NUNCHUK) { + // Punch + if (wp->btns_h & WPAD_BUTTON_LEFT) LP = true; + if (wp->btns_h & WPAD_BUTTON_UP) HP = true; + // Kick + if (wp->btns_h & WPAD_BUTTON_DOWN) LK = true; + if (wp->btns_h & WPAD_BUTTON_RIGHT) HK = true; + // Block + if (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z) BL = true; + // Throw + if (wp->btns_h & WPAD_BUTTON_A) Throw = true; + // Run / Change Styles + if (wp->btns_h & WPAD_NUNCHUK_BUTTON_C) CS = true; + // Start and Select + if (wp->btns_h & WPAD_BUTTON_MINUS) Select=true; + if (wp->btns_h & WPAD_BUTTON_PLUS) Start=true; + // Special move + if (wp->btns_h & WPAD_BUTTON_B) SpecialMove=true; + } else if (wp->exp.type == WPAD_EXP_CLASSIC) { + // D-Pad 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; - if (wp->btns_h & (WPAD_CLASSIC_BUTTON_X | WPAD_CLASSIC_BUTTON_Y)) J |= VBA_BUTTON_B; - if (wp->btns_h & (WPAD_CLASSIC_BUTTON_A | WPAD_CLASSIC_BUTTON_B)) J |= VBA_BUTTON_A; - if (wp->btns_h & WPAD_CLASSIC_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_ZR) J |= VBA_BUTTON_B | VBA_RIGHT; // CAKTODO - if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R) J |= VBA_BUTTON_B | VBA_BUTTON_A; // block + // Punch + if (wp->btns_h & WPAD_CLASSIC_BUTTON_Y) LP = true; + if (wp->btns_h & WPAD_CLASSIC_BUTTON_X) HP = true; + // Kick + if (wp->btns_h & WPAD_CLASSIC_BUTTON_B) LK = true; + if (wp->btns_h & WPAD_CLASSIC_BUTTON_A) HK = true; + // Throw + if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZR) Throw = true; + // Block + if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R) BL = true; // block + // Run / Change Styles + if (wp->btns_h & (WPAD_CLASSIC_BUTTON_FULL_L | WPAD_CLASSIC_BUTTON_ZL)) CS = true; + // Start and Select + if (wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS) Select = true; + if (wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS) Start = true; + // Special move + if (wp->btns_h & WPAD_BUTTON_B) SpecialMove=true; } - #endif { u32 gc = PAD_ButtonsHeld(pad); @@ -88,148 +174,1249 @@ u32 MK1Input(unsigned short pad) { if (gc & PAD_BUTTON_DOWN) J |= VBA_DOWN; if (gc & PAD_BUTTON_LEFT) J |= VBA_LEFT; if (gc & PAD_BUTTON_RIGHT) J |= VBA_RIGHT; - if (gc & PAD_BUTTON_START) J |= VBA_BUTTON_START; - if (gc & (PAD_BUTTON_B | PAD_BUTTON_Y)) J |= VBA_BUTTON_B; - if (gc & (PAD_BUTTON_A | PAD_BUTTON_X)) J |= VBA_BUTTON_A; - if (gc & PAD_TRIGGER_Z) J |= VBA_BUTTON_B | VBA_RIGHT; // CAKTODO - if (gc & PAD_TRIGGER_R) J |= VBA_BUTTON_B | VBA_BUTTON_A; // block + // Start and Select + if (gc & PAD_BUTTON_START) Start = true; + // Punch + if (gc & PAD_BUTTON_B) LP = true; + if (gc & PAD_BUTTON_X) HP = true; + // Kick + if (gc & PAD_BUTTON_B) LK = true; + if (gc & PAD_BUTTON_X) HK = true; + // Block + if (gc & PAD_TRIGGER_R) BL = true; + // Run / Change Style + if (gc & PAD_TRIGGER_L) CS = true; + // Throw + if (gc & PAD_TRIGGER_Z) Throw = true; + } + // Check which side they are on + if (OurX < OpponentX) { + VBA_FORWARD = VBA_RIGHT; + VBA_BACK = VBA_LEFT; + } else { + VBA_FORWARD = VBA_LEFT; + VBA_BACK = VBA_RIGHT; + } + if (J & VBA_FORWARD) F = true; + if (J & VBA_BACK) B = true; + return J; +} + +// Allows writes to the ROM memory for hacking +void gbaWriteMemory(u32 addr, u32 value) { + if (addr<0x8000000 || addr>=0xD000000) CPUWriteMemory(addr, value); +#ifndef USE_VM + else WRITE32LE(((u16 *)&rom[addr&0x1FFFFFC]), value); +#endif +} +void gbaWriteHalfWord(u32 addr, u16 value) { + if (addr<0x8000000 || addr>=0xD000000) CPUWriteHalfWord(addr, value); +#ifndef USE_VM + else WRITE16LE(((u16 *)&rom[addr&0x1FFFFFC]), value); +#endif +} +void gbaWriteByte(u32 addr, u8 value) { + if (addr<0x8000000 || addr>=0xD000000) CPUWriteByte(addr, value); +#ifndef USE_VM + else rom[addr & 0x1FFFFFF] = value; +#endif +} + + +u32 MK1Input(unsigned short pad) { + OurHealth = gbReadMemory(0xD695); + OpponentHealth = gbReadMemory(0xD696); + OurX = gbReadMemory(0xCF00); + OpponentX = gbReadMemory(0xCF26); + u8 OurChar = gbReadMemory(0xD685); + u8 OpponentChar = gbReadMemory(0xD686); + u8 MenuChar = gbReadMemory(0xD61D)+1; + static u8 OldMenuChar = 0; + // Rumble when they change character + if (MenuChar != OldMenuChar) { + systemGameRumble(4); + OldMenuChar = MenuChar; + } + u32 J = GetMKInput(pad, 8); + if (LK || HK || BL) J |= VBA_BUTTON_A; + if (LP || HP || BL) J |= VBA_BUTTON_B; + if (Start) J |= VBA_BUTTON_START; + if (Select) J |= VBA_BUTTON_SELECT; + // Fix kick controls to what they should be! + if (!(J & (VBA_UP | VBA_DOWN))) { + if (B && HK) { // Make B+HK do roundhouse, while B+LK does sweep! + J &= ~VBA_BACK; + J |= VBA_FORWARD; + } else if (F && HK) { // Make F+HK do normal high kick + J &= ~VBA_FORWARD; + } else if (F && LK) { // Make F+LK also do normal high kick, since no low kicks + J &= ~VBA_FORWARD; + } + } + if (Throw) J |= VBA_FORWARD | VBA_BUTTON_B; + if (CS) J |= VBA_SPEED; + return J; +} + +u32 MK2Input(unsigned short pad) { + u8 OurChar = gbReadMemory(0xDD01); + u8 OpponentChar = gbReadMemory(0xDD01+0x40); + OurX = gbReadMemory(0xDD12) | (gbReadMemory(0xDD13) << 8); + OpponentX = gbReadMemory(0xDD12+0x40) | (gbReadMemory(0xDD13+0x40) << 8); + OurHealth = gbReadMemory(0xDD20); + OpponentHealth = gbReadMemory(0xDD20+0x40); + + u32 J = GetMKInput(pad, 5); + if (LK || HK) J |= VBA_BUTTON_A; + if (LP || HP) J |= VBA_BUTTON_B; + if (BL) J |= VBA_BUTTON_START; + if (Start || Select) J |= VBA_BUTTON_SELECT; + // Can't fix kick controls to what they should be! Sorry + if (Throw) J |= VBA_FORWARD | VBA_BUTTON_B; + if (CS) J |= VBA_SPEED; + return J; +} + +u32 MK12Input(unsigned short pad) { + OurHealth = 0; + OpponentHealth = 0; + OurX = 0; + OpponentX = 1; + + u32 J = GetMKInput(pad, 5); + if (LK || HK) J |= VBA_BUTTON_A; + if (LP || HP) J |= VBA_BUTTON_B; + if (BL) J |= VBA_BUTTON_START; + // Fix kick controls to what they should be! + if (!(J & (VBA_UP | VBA_DOWN))) { + if (B && HK) { // Make B+HK do roundhouse, while B+LK does sweep! + J &= ~VBA_BACK; + J |= VBA_FORWARD; + } else if (F && HK) { // Make F+HK do normal high kick + J &= ~VBA_FORWARD; + } else if (F && LK) { // Make F+LK also do normal high kick, since no low kicks + J &= ~VBA_FORWARD; + } + } + if (Throw) J |= VBA_FORWARD | VBA_BUTTON_B; + if (Start || Select) J |= VBA_BUTTON_SELECT; + if (CS) J |= VBA_SPEED; + return J; +} + +void MK3Rename(int n, const char *name, const char *nick) { + // CAKTODO +} + +u8 MK3SetSubchar(int Char, int Subchar, u16 OriginalColour) { + switch (Char) { + case MK3_SUBZERO: + if (Subchar>=5) Subchar = 0; + switch (Subchar) { + // Subzero Unmasked + case 0: + MK3Rename(MK3_SUBZERO, "SUBZERO", "SUB-ZERO"); + break; + // Cyborg + case 1: + MK3Rename(MK3_SUBZERO, "SUBZERO", "SUB-ZERO"); + break; + // Noob Saibot + case 2: + MK3Rename(MK3_SUBZERO, "NOOB", "NOOB"); + break; + // Frost + case 3: + MK3Rename(MK3_SUBZERO, "FROST", "FROST"); + break; + // Chameleon + case 4: + MK3Rename(MK3_SUBZERO, "CAMELEON", "CHAM"); + break; + } + break; + default: + Subchar = 0; + break; + } + return Subchar; +} + + +u32 MK3Input(unsigned short pad) { + OurHealth = gbReadMemory(0xC0D6); + OpponentHealth = gbReadMemory(0xC0D7); + u8 OurChar = gbReadMemory(0xC0F0); // also CD00? + u8 OpponentChar = gbReadMemory(0xC0F1); // also CD40, D526 + OurX = gbReadMemory(0xCD02) | (gbReadMemory(0xCD03) << 8); + OpponentX = gbReadMemory(0xCD42) | (gbReadMemory(0xCD43) << 8); + bool InMenu = false; + if (gbReadMemory(0xC028)==0x48 && gbReadMemory(0xC029)==0x4C) + InMenu = true; + static bool WasInMenu = false; + static u8 MenuChar = 0; + static u8 MenuSubChar = 0; + if (InMenu) MenuChar = gbReadMemory(0xD4CE); + + static u8 OldMenuChar = 0; + // Rumble when they change character + if (MenuChar != OldMenuChar) { + if (InMenu) + systemGameRumble(4); + OldMenuChar = MenuChar; + } + + u32 J = GetMKInput(pad); + if (LK || HK) J |= VBA_BUTTON_A; + if (LP || HP) J |= VBA_BUTTON_B; + if (BL) J |= VBA_BUTTON_START; + if (Throw) J |= VBA_BUTTON_B; + if (InMenu && (Start || Throw || HP || LP || HK || LK || BL)) { + J |= VBA_BUTTON_START; + } else if (Start || Select) J |= VBA_BUTTON_SELECT; + // Fix kick controls to what they should be! + if (!InMenu && !(J & (VBA_UP | VBA_DOWN))) { + if (B && HK && !LK) { // Make B+HK do roundhouse, while B+LK does sweep! + J &= ~VBA_BACK; + J |= VBA_FORWARD; + } else if (F && HK) { // Make F+HK do normal high kick + J &= ~VBA_FORWARD; + } else if (F && LK) { // Make F+LK also do normal high kick, since no low kicks + J &= ~VBA_FORWARD; + } + } + // Fix punch controls to what they should be! + if ((!InMenu) && (J & VBA_DOWN)) { + // Make D+LP do crouch punch instead of uppercut + if (LP && !F && !B && !LK && !HK && !HP) { + J &= ~VBA_BACK; + J |= VBA_FORWARD; + } + } + // Run, sometimes does roundhouse kick (Midway's fault, not mine) + if (CS) J |= VBA_FORWARD | VBA_BUTTON_A | VBA_BUTTON_B; + // Allow to choose secret characters from menu + static bool CancelMovement = false; + if (InMenu) { + if ((MenuChar==1 && (J & VBA_DOWN)) + || (MenuChar==3 && (J & VBA_RIGHT)) + || (MenuChar==5 && (J & VBA_LEFT)) + || (MenuChar==7 && (J & VBA_UP))) { + CancelMovement = true; + gbWriteMemory(0xD4CE,4); + } else if (MenuChar==8 && (J & VBA_RIGHT)) { + gbWriteMemory(0xD4CE,MK3_SHAOKHAN); + } + if (CancelMovement) { + if (J & (VBA_RIGHT | VBA_LEFT | VBA_UP | VBA_DOWN)) + J &= ~(VBA_RIGHT | VBA_LEFT | VBA_UP | VBA_DOWN); + else CancelMovement = false; + } + WasInMenu = true; + } else { + CancelMovement = false; + if (WasInMenu) { + // We just chose a character, so apply anything special here + if (MenuChar==MK3_SUBZERO && MenuSubChar==1) + gbWriteMemory(0xD4CE,MK3_SEKTOR); + else if (MenuChar==MK3_KANO && MenuSubChar==1) + gbWriteMemory(0xD4CE,MK3_SEKTOR); + else if (MenuChar==MK3_KABAL && MenuSubChar==1) + gbWriteMemory(0xD4CE,MK3_SEKTOR); + else if (MenuChar==MK3_CYRAX && MenuSubChar==1) + gbWriteMemory(0xD4CE,MK3_SUBZERO); + else if (MenuChar==MK3_SEKTOR && MenuSubChar==1) + gbWriteMemory(0xD4CE,MK3_SUBZERO); + else if (MenuChar==MK3_SMOKE && MenuSubChar==1) + gbWriteMemory(0xD4CE,MK3_SUBZERO); + WasInMenu = false; + } } return J; } u32 MK4Input(unsigned short pad) { - u32 J = StandardMovement(pad) | DecodeKeyboard(pad); - u8 Health = 0; - static u8 OldHealth = 0; + OurHealth = gbReadMemory(0xC0D6); + OpponentHealth = gbReadMemory(0xC0D7); + u8 OurChar = gbReadMemory(0xC0F0); // also CD00? + u8 OpponentChar = gbReadMemory(0xC0F1); // also CD40, D526 + OurX = gbReadMemory(0xCD02) | (gbReadMemory(0xCD03) << 8); + OpponentX = gbReadMemory(0xCD42) | (gbReadMemory(0xCD43) << 8); + bool InMenu = false; // CAKTODO - // Rumble when they lose health! - if (Health < OldHealth) - systemGameRumble(20); - OldHealth = Health; - -#ifdef HW_RVL - WPADData * wp = WPAD_Data(pad); - - // Punch - if (wp->btns_h & WPAD_BUTTON_UP || wp->btns_h & WPAD_BUTTON_LEFT) - J |= VBA_BUTTON_B; - // Kick - if (wp->btns_h & WPAD_BUTTON_DOWN || wp->btns_h & WPAD_BUTTON_RIGHT) - J |= VBA_BUTTON_A; - // Block - if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z)) - J |= VBA_BUTTON_START; - // Throw - if (wp->btns_h & WPAD_BUTTON_A) - J |= VBA_BUTTON_B | VBA_RIGHT; // CAKTODO check which way we are facing - // Pause - if (wp->btns_h & WPAD_BUTTON_MINUS) - J |= VBA_BUTTON_SELECT; - // Start - if (wp->btns_h & WPAD_BUTTON_PLUS) - J |= VBA_BUTTON_START; - // Special move - if (wp->btns_h & WPAD_BUTTON_B) - { - // CAKTODO + u32 J = GetMKInput(pad); + if (LK || HK) J |= VBA_BUTTON_A; + if (LP || HP) J |= VBA_BUTTON_B; + if (BL) J |= VBA_BUTTON_START; + if (Start || Select) J |= VBA_BUTTON_SELECT; + // Fix kick controls to what they should be! + if (!InMenu && !(J & (VBA_UP | VBA_DOWN))) { + if (B && HK && !LK) { // Make B+HK do roundhouse, while B+LK does sweep! + J &= ~VBA_BACK; + J |= VBA_FORWARD; + } else if (F && HK) { // Make F+HK do normal high kick + J &= ~VBA_FORWARD; + } else if (F && LK) { // Make F+LK also do normal high kick, since no low kicks + J &= ~VBA_FORWARD; + } } - if (wp->exp.type == WPAD_EXP_CLASSIC) { - 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; - if (wp->btns_h & (WPAD_CLASSIC_BUTTON_X | WPAD_CLASSIC_BUTTON_Y)) J |= VBA_BUTTON_B; - if (wp->btns_h & (WPAD_CLASSIC_BUTTON_A | WPAD_CLASSIC_BUTTON_B)) J |= VBA_BUTTON_A; - if (wp->btns_h & WPAD_CLASSIC_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_ZR) J |= VBA_BUTTON_B | VBA_RIGHT; // CAKTODO - if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R) J |= VBA_BUTTON_START; // block + // Fix punch controls to what they should be! + if ((!InMenu) && (J & VBA_DOWN)) { + // Make D+LP do crouch punch instead of uppercut + if (LP && !F && !B && !LK && !HK && !HP) { + J &= ~VBA_BACK; + J |= VBA_FORWARD; + } } -#endif - { - u32 gc = PAD_ButtonsHeld(pad); - // DPad moves - if (gc & PAD_BUTTON_UP) J |= VBA_UP; - if (gc & PAD_BUTTON_DOWN) J |= VBA_DOWN; - if (gc & PAD_BUTTON_LEFT) J |= VBA_LEFT; - if (gc & PAD_BUTTON_RIGHT) J |= VBA_RIGHT; - if (gc & PAD_BUTTON_START) J |= VBA_BUTTON_START; - if (gc & (PAD_BUTTON_B | PAD_BUTTON_Y)) J |= VBA_BUTTON_B; - if (gc & (PAD_BUTTON_A | PAD_BUTTON_X)) J |= VBA_BUTTON_A; - if (gc & PAD_TRIGGER_Z) J |= VBA_BUTTON_B | VBA_RIGHT; // CAKTODO - if (gc & PAD_TRIGGER_R) J |= VBA_BUTTON_START; // block - } - + // Run? + if (CS) J |= VBA_FORWARD | VBA_BUTTON_A | VBA_BUTTON_B; + if (Throw) J |= VBA_BUTTON_B; return J; } +void MKASetYPos(s16 y) { + s16 def = 0; + switch (CPUReadHalfWord(0x200005c)) { + case 0x5F3C: def = 0x3B; break; // Jax (actually tall not short) + case 0x89E4: def = 0x39; break; // shang tsung (shortest) + case 0x704C: def = 0x37; break; + case 0x3494: case 0x45A4: def = 0x36; break; + case 0x9AF4: case 0xA37C: def = 0x35; break; + case 0x67C4: case 0x78D4: case 0x56B4: def = 0x34; break; + case 0x815C: def = 0x33; break; // sonya + case 0xB48C: case 0x926C: def = 0x32; break; + case 0x3D1C: case 0x4E2C: def = 0x31; break; + case 0xAC04: def = 0x1E; break; // Motaro (tallest) + default: def = 0x33; break; + } + y-=def; + gbaWriteHalfWord(0x200000A, (u16)((s16)CPUReadHalfWord(0x200000A)+y)); +} + +bool MKAIsStanding() { + switch (CPUReadHalfWord(0x2000040)) { + case 0x039b: + case 0x03F8: + case 0x02DF: + case 0x04BC: + case 0x04F3: + case 0x0362: // shao khan + case 0x01D3: // motaro + case 0x0427: + case 0x02A2: + case 0x052D: + case 0x0561: + case 0x034C: + case 0x0488: + case 0x0591: + case 0x0456: + case 0x0316: + return true; + default: + return false; + } +} +void MKARename(u8 n, const char *name) { +#ifndef USE_VM + if (n>=MKA_SubZero2) n--; // second sub zero is not in names list! + u32 addr = 0x80285CC+n*16; + char *s = (char *)&rom[addr & 0x1FFFFFF]; + int L = strlen(s)-1-strlen(name); + int i; + strcpy(s, " "); + strncpy(s, name, 12); + strcat(s, " "); + for (i=0; i=5) Subchar = 0; + switch (Subchar) { + // Reptile + case 0: + MKARename(MKA_Reptile, "REPTILE"); + MKAMakeNinja(); + MKAChangeColour(OriginalColour); + break; + case 1: + MKARename(MKA_Reptile, "REPTILE"); + MKAMakeCyborg(); + MKAChangeColour(NINJA_GREEN); + break; + case 2: + MKARename(MKA_Reptile, "REPTILE"); + MKAMakeUnmasked(); + MKAChangeColour(UNMASKED_DARKGREEN); // different from green subzero + break; + // Chameleon + case 3: + MKARename(MKA_Reptile, "CHAMELEON"); + MKAMakeNinja(); + MKAChangeColour(NINJA_GREY); + break; + case 4: + MKARename(MKA_Reptile, "CHAMELEON"); + MKAMakeCyborg(); + MKAChangeColour(CYBORG_GREY); + break; + } + break; + case MKA_NoobSaibot: + if (Subchar>=4) Subchar = 0; + switch (Subchar) { + // Noob-Saibot + case 0: + MKAMakeNinja(); + MKAChangeColour(OriginalColour); + gbaWriteByte(0x202F6A8, MKA_NoobSaibot); + gbaWriteByte(0x2000025, MKA_NoobSaibot); + MKARename(MKA_Kano, "KANO"); + break; + // As a Cyborg + case 1: + MKAMakeCyborg(); + MKAChangeColour(SHADOW_GREY); + gbaWriteByte(0x202F6A8, MKA_NoobSaibot); + gbaWriteByte(0x2000025, MKA_NoobSaibot); + MKARename(MKA_Kano, "KANO"); + break; + // Looks like Kano + case 2: + MKAMakeKano(); + MKAChangeColour(SHADOW_BLACK); + gbaWriteByte(0x202F6A8, MKA_Kano); + gbaWriteByte(0x2000025, MKA_Kano); + MKARename(MKA_Kano, "NOOB SAIBOT"); + break; + // Looks like Classic Sub Zero (because he is) + case 3: + MKAMakeNinja(); + MKAChangeColour(NINJA_BLUE); + gbaWriteByte(0x202F6A8, MKA_NoobSaibot); + gbaWriteByte(0x2000025, MKA_NoobSaibot); + MKARename(MKA_Kano, "KANO"); + break; + } + break; + case MKA_Ermac: + if (Subchar>=3) Subchar = 0; + switch (Subchar) { + // Ermac + case 0: + MKARename(MKA_Ermac, "ERMAC"); + MKAMakeNinja(); + MKAChangeColour(OriginalColour); + break; + case 1: + MKARename(MKA_Ermac, "ERMAC"); + MKAMakeCyborg(); + MKAChangeColour(CYBORG_RED); + break; + case 2: + MKARename(MKA_Ermac, "RUBY"); + MKAMakeFemale(); + MKAChangeColour(NINJA_RED); + break; + } + break; + case MKA_SubZero: + if (Subchar>=5) Subchar = 0; + switch (Subchar) { + // Classic Subzero + case 0: + MKARename(MKA_SubZero, "SUB ZERO"); + MKAMakeNinja(); + MKAChangeColour(OriginalColour); + break; + case 1: + MKARename(MKA_SubZero, "SUB ZERO"); + MKAMakeCyborg(); + MKAChangeColour(NINJA_BLUE); + break; + case 2: + MKARename(MKA_SubZero, "SUB ZERO"); + MKAMakeUnmasked(); + MKAChangeColour(UNMASKED_BLUE); + break; + // Looking like Noob Saibot (which he is) + case 3: + MKARename(MKA_SubZero, "SUB ZERO"); + MKAMakeNinja(); + MKAChangeColour(SHADOW_BLACK); + break; + // Frost + case 4: + MKARename(MKA_SubZero, "FROST"); + MKAMakeFemale(); + MKAChangeColour(NINJA_ICE); + break; + } + break; + case MKA_SubZero2: + if (Subchar>=4) Subchar = 0; + switch (Subchar) { + // Subzero Unmasked + case 0: + MKARename(MKA_SubZero2, "SUB ZERO"); + MKAMakeUnmasked(); + MKAChangeColour(OriginalColour); + break; + // As a cyborg + case 1: + MKARename(MKA_SubZero2, "SUB ZERO"); + MKAMakeCyborg(); + MKAChangeColour(NINJA_BLUE); + break; + // Masked in his MK2 coloured costume + case 2: + MKARename(MKA_SubZero2, "SUB ZERO"); + MKAMakeNinja(); + MKAChangeColour(FEMALE_CYAN); + break; + // Frost + case 3: + MKARename(MKA_SubZero2, "FROST"); + MKAMakeFemale(); + MKAChangeColour(NINJA_ICE); + break; + } + break; + case MKA_Scorpion: + if (Subchar>=3) Subchar = 0; + switch (Subchar) { + // Human Scorpion + case 0: + MKARename(MKA_Scorpion, "SCORPION"); + MKAMakeNinja(); + MKAChangeColour(OriginalColour); + break; + // As a cyborg + case 1: + MKARename(MKA_Scorpion, "SCORPION"); + MKAMakeCyborg(); + MKAChangeColour(CYBORG_YELLOW2); + break; + // Monster + case 2: + MKARename(MKA_Scorpion, "MONSTER"); + MKAMakeShaoKhan(); + MKAChangeColour(SHADOW_GREY); + break; + } + break; + case MKA_Mystery: + if (Subchar>=2) Subchar = 0; + switch (Subchar) { + // Human Smoke + case 0: + MKARename(MKA_Mystery, "SMOKE"); + gbaWriteByte(0x20001A8, 1); // unlock + MKAMakeNinja(); + MKAChangeColour(OriginalColour); + gbaWriteByte(0x202F6A8, MKA_Mystery); + gbaWriteByte(0x2000025, MKA_Mystery); + break; + // Looking like a Cyborg + case 1: + MKARename(MKA_Mystery, "SMOKE"); + MKAMakeCyborg(); + MKAChangeColour(CYBORG_GREY); + gbaWriteByte(0x202F6A8, MKA_Smoke); + gbaWriteByte(0x2000025, MKA_Smoke); + break; + } + break; + case MKA_Rain: + if (Subchar>=3) Subchar = 0; + switch (Subchar) { + // Human Rain + case 0: + MKARename(MKA_Rain, "RAIN"); + MKARename(MKA_Jax, "JAX"); + MKAMakeRainHuman(); + MKAMakeNinja(); + MKAChangeColour(OriginalColour); + gbaWriteByte(0x202F6A8, MKA_Rain); + gbaWriteByte(0x2000025, MKA_Rain); + break; + // Cyborg Rain + case 1: + MKARename(MKA_Rain, "RAIN"); + MKARename(MKA_Jax, "JAX"); + MKAMakeRainCyborg(); + MKAMakeCyborg(); + MKAChangeColour(NINJA_PINKPURPLE); + gbaWriteByte(0x202F6A8, MKA_Rain); + gbaWriteByte(0x2000025, MKA_Rain); + break; + // Unmasked Rain + case 2: + MKARename(MKA_Rain, "RAIN"); + MKARename(MKA_Jax, "JAX"); + MKAMakeRainUnmasked(); + MKAMakeUnmasked(); + MKAChangeColour(UNMASKED_PURPLE); + gbaWriteByte(0x202F6A8, MKA_Rain); + gbaWriteByte(0x2000025, MKA_Rain); + break; + // Tremor + case 3: + MKARename(MKA_Rain, "TREMOR"); + MKARename(MKA_Jax, "TREMOR"); + MKAMakeNinja(); + MKAChangeColour(NINJA_BROWN); + gbaWriteByte(0x202F6A8, MKA_Jax); + gbaWriteByte(0x2000025, MKA_Jax); + break; + case 4: + MKARename(MKA_Rain, "TREMOR"); + MKARename(MKA_Jax, "TREMOR"); + MKAMakeCyborg(); + MKAChangeColour(NINJA_BROWN); + gbaWriteByte(0x202F6A8, MKA_Jax); + gbaWriteByte(0x2000025, MKA_Jax); + break; + } + break; + case MKA_Sektor: + if (Subchar>=2) Subchar = 0; + switch (Subchar) { + // Cyborg Sektor + case 0: + MKAMakeCyborg(); + MKAChangeColour(OriginalColour); + break; + // Human Sektor + case 1: + MKAMakeNinja(); + MKAChangeColour(NINJA_RED); + break; + } + break; + case MKA_Cyrax: + if (Subchar>=2) Subchar = 0; + switch (Subchar) { + // Cyborg Cyrax + case 0: + MKAMakeCyborg(); + MKAChangeColour(OriginalColour); + break; + // Human Cyrax + case 1: + MKAMakeNinja(); + MKAChangeColour(OriginalColour); + break; + } + break; + case MKA_Kano: + if (Subchar>=2) Subchar = 0; + switch (Subchar) { + // Human Kano + case 0: + MKAMakeKano(); + MKAChangeColour(OriginalColour); + break; + // Cyborg Kano + case 1: + MKAMakeCyborg(); + MKAChangeColour(CYBORG_DARKRED); + break; + } + break; + case MKA_Kabal: + if (Subchar>=2) Subchar = 0; + switch (Subchar) { + // Human Kabal + case 0: + MKAMakeKabal(); + MKAChangeColour(OriginalColour); + break; + // Cyborg Kabal + case 1: + MKAMakeCyborg(); + MKAChangeColour(OriginalColour); // Brown cyborg, like Tremor + break; + } + break; + case MKA_Jax: + if (Subchar>=3) Subchar = 0; + switch (Subchar) { + // Half Cyborg Jax + case 0: + MKAMakeJax(); + MKAChangeColour(OriginalColour); + break; + // Human Jax (a bit glitchy, but OK) + case 1: + MKAMakeJax(); + MKAChangeColour(NINJA_YELLOW2); + break; + // Cyborg Jax + case 2: + MKAMakeCyborg(); + MKAChangeColour(NINJA_WHITE); + break; + } + break; + case MKA_Smoke: + if (Subchar>=2) Subchar = 0; + switch (Subchar) { + // Cyborg Smoke + case 0: + MKAMakeCyborg(); + MKAChangeColour(OriginalColour); + gbaWriteByte(0x202F6A8, MKA_Smoke); + gbaWriteByte(0x2000025, MKA_Smoke); + break; + // Human Smoke + case 1: + gbaWriteByte(0x20001A8, 1); + MKAMakeNinja(); + MKAChangeColour(NINJA_WHITE); + gbaWriteByte(0x202F6A8, MKA_Mystery); + gbaWriteByte(0x2000025, MKA_Mystery); + break; + } + break; + case MKA_Jade: + if (Subchar>=2) Subchar = 0; + switch (Subchar) { + // Jade + case 0: + MKARename(MKA_Jade, "JADE"); + //MKAMakeFemale(); + MKAChangeColour(OriginalColour); + break; + // Khameleon + case 1: + MKARename(MKA_Jade, "KHAMELEON"); + //MKAMakeFemale(); + MKAChangeColour(NINJA_GREY); + break; + } + break; + case MKA_Kitana: + if (Subchar>=2) Subchar = 0; + switch (Subchar) { + // Kitana + case 0: + MKARename(MKA_Kitana, "KITANA"); + //MKAMakeFemale(); + MKAChangeColour(OriginalColour); + break; + // Skarlet (a red version of kitana, supposed to be faster but isn't here) + case 1: + MKARename(MKA_Kitana, "SKARLET"); + //MKAMakeFemale(); + MKAChangeColour(NINJA_BRIGHTRED); + break; + } + break; + case MKA_Mileena: + if (Subchar>=2) Subchar = 0; + switch (Subchar) { + // Mileena + case 0: + MKARename(MKA_Mileena, "MILEENA"); + MKARename(MKA_LiuKang, "LIU KANG"); + MKAMakeFemale(); + MKAChangeColour(OriginalColour); + gbaWriteByte(0x202F6A8, MKA_Mileena); + gbaWriteByte(0x2000025, MKA_Mileena); + break; + // Tanya + case 1: + MKARename(MKA_Mileena, "TANYA"); + MKARename(MKA_LiuKang, "TANYA"); + MKAMakeFemale(); + MKAChangeColour(NINJA_YELLOW); + gbaWriteByte(0x202F6A8, MKA_LiuKang); + gbaWriteByte(0x2000025, MKA_LiuKang); + break; + } + break; + case MKA_ShangTsung: + if (Subchar>=3) Subchar = 0; + switch (Subchar) { + // Shang Tsung + case 0: + MKARename(MKA_ShangTsung, "SHANG TSUNG"); + MKAMakeShangTsung(); + MKAChangeColour(OriginalColour); + gbaWriteByte(0x202F6A8, MKA_ShangTsung); + gbaWriteByte(0x2000025, MKA_ShangTsung); + break; + // Motaro + case 1: + gbaWriteByte(0x20001A8, 2); // unlock + MKARename(MKA_ShangTsung, "MOTARO"); + MKAMakeMotaro(); + MKAChangeColour(NINJA_BROWN); + gbaWriteByte(0x202F6A8, MKA_Motaro); + gbaWriteByte(0x2000025, MKA_Motaro); + //MKAMakeShaoKhan(); + //gbaWriteByte(0x202F6A8, MKA_ShaoKhan); + break; + // Shao Khan + case 2: + gbaWriteByte(0x20001A8, 3); // unlock + MKARename(MKA_ShangTsung, "SHAO KHAN"); + MKARename(MKA_ShaoKhan, "SHAO KHAN"); + MKAChangeColour(BOSS_RED); + gbaWriteByte(0x202F6A8, MKA_ShaoKhan); + gbaWriteByte(0x2000025, MKA_ShaoKhan); + MKAMakeShaoKhan(); + //gbaWriteByte(0x202F6A8, MKA_ShaoKhan); + break; + // Reiko + case 3: + gbaWriteByte(0x20001A8, 3); // unlock Shao Khan + MKARename(MKA_ShangTsung, "REIKO"); + MKARename(MKA_ShaoKhan, "REIKO"); + gbaWriteByte(0x202F6A8, MKA_ShaoKhan); + gbaWriteByte(0x2000025, MKA_ShaoKhan); + MKAMakeNinja(); + MKAChangeColour(FEMALE_PURPLE); + //gbaWriteByte(0x202F6A8, MKA_ShaoKhan); + break; + } + break; + case MKA_LiuKang: + if (Subchar>=4) Subchar = 0; + switch (Subchar) { + // Liu Kang + case 0: + MKARename(MKA_LiuKang, "LIU KANG"); + MKAMakeLiuKang(); + MKAChangeColour(OriginalColour); + gbaWriteByte(0x202F6A8, MKA_LiuKang); + gbaWriteByte(0x2000025, MKA_LiuKang); + break; + // Johnny Cage + case 1: + MKARename(MKA_LiuKang, "JOHNNY CAGE"); + MKAMakeLiuKang(); + MKAChangeColour(0x92); // Stryker's Blue + gbaWriteByte(0x202F6A8, MKA_Jade); + gbaWriteByte(0x2000025, MKA_Jade); + break; + // Blaze + case 2: + MKARename(MKA_LiuKang, "BLAZE"); + MKAMakeLiuKang(); + MKAChangeColour(0x63); // Yellowy orange + gbaWriteByte(0x202F6A8, MKA_LiuKang); + gbaWriteByte(0x2000025, MKA_LiuKang); + break; + // Hornbuckle + case 3: + MKARename(MKA_LiuKang, "HORNBUCKLE"); + MKAMakeLiuKang(); + MKAChangeColour(UNMASKED_DARKGREEN); + gbaWriteByte(0x202F6A8, MKA_LiuKang); + gbaWriteByte(0x2000025, MKA_LiuKang); + break; + } + break; + default: + Subchar = 0; + break; + } + return Subchar; +} + u32 MKAInput(unsigned short pad) { - u32 J = StandardMovement(pad) | DecodeKeyboard(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); - - // Punch - if (wp->btns_h & WPAD_BUTTON_UP || wp->btns_h & WPAD_BUTTON_LEFT) - J |= VBA_BUTTON_B; - // Kick - if (wp->btns_h & WPAD_BUTTON_DOWN || wp->btns_h & WPAD_BUTTON_RIGHT) - J |= VBA_BUTTON_A; - // Block - if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z)) - J |= VBA_BUTTON_R; - // Run (supposed to be change styles) - if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_C)) - J |= VBA_BUTTON_L; - // Throw - if (wp->btns_h & WPAD_BUTTON_A) - J |= VBA_RIGHT; // CAKTODO check which way we are facing - // Pause - if (wp->btns_h & WPAD_BUTTON_PLUS || wp->btns_h & WPAD_BUTTON_MINUS) - J |= VBA_BUTTON_SELECT; - // Special move - if (wp->btns_h & WPAD_BUTTON_B) - { - // CAKTODO + bool InMenu= false; + if (CPUReadHalfWord(0x2000008)==0xFFFC) InMenu=true; + else InMenu = false; + + OurHealth = CPUReadByte(0x2000020); + OpponentHealth = CPUReadByte(0x2000020+0x68); + OurX = (s16)CPUReadHalfWord(0x2000008); + OpponentX = (s16)CPUReadHalfWord(0x2000008+0x68); + u8 OurChar = CPUReadByte(0x2000025); // also 202f6a8 + u8 OpponentChar = CPUReadByte(0x2000025+0x68); + + // Special characters + static int MenuChar = 0; + static int MenuSubchar = 0; + static bool WasInMenu = false; + static u8 OurOldChar = 255; + static u8 OriginalColour = 0; + static bool OldCostumeButton = false; + bool CostumeButton = false; + if (OriginalColour == 0) OriginalColour = CPUReadByte(0x2000004); + // Manually changed characters, so reset MenuChar and SubChar + if (InMenu && OurChar!=OurOldChar && OurChar!=0) { + //DebugPrintf("%d %d %d", OurChar, OurOldChar, MenuChar); + MenuChar = OurChar; + MenuSubchar = 0; + OriginalColour = CPUReadByte(0x2000004); + systemGameRumble(4); + MKARenameEveryoneProperlyExcept(255); + } else if (InMenu && OurChar!=OurOldChar) { + // Either changing character to Rain, or more likely starting combat + // if changing to rain, they might actually end up changing to Cyborg Rain or Tremor + MenuChar = OurChar; + OriginalColour = CPUReadByte(0x2000004); } - if (wp->exp.type == WPAD_EXP_CLASSIC) { - 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; - if (wp->btns_h & (WPAD_CLASSIC_BUTTON_X | WPAD_CLASSIC_BUTTON_Y)) J |= VBA_BUTTON_B; - if (wp->btns_h & (WPAD_CLASSIC_BUTTON_A | WPAD_CLASSIC_BUTTON_B)) J |= VBA_BUTTON_A; - if (wp->btns_h & WPAD_CLASSIC_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_ZR) J |= VBA_RIGHT; // CAKTODO - if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R) J |= VBA_BUTTON_R; // block - if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L) J |= VBA_BUTTON_L; // run + + // Special Characters in-game + if (!InMenu) { + // in the game we just changed from 0 back to our real character + // unless OurChar is Jax and Subchar is 3 or 4 in which case MenuChar should be 0 + // So check for Tremor, also check for Shao Khan + if (OurOldChar==0 && OurChar!=0) { + if (OurChar==MKA_Jax && (MenuSubchar==3 || MenuSubchar==4)) + MenuChar=0; + else if (OurChar==MKA_ShaoKhan && (MenuSubchar==2 || MenuSubchar==3)) + MenuChar=MKA_ShangTsung; + else + MenuChar=OurChar; + } + if (MenuSubchar!=0) { + //u8 OldMaxFrame = CPUReadByte(0x2000048); + MKANextSubchar(MenuChar, MenuSubchar-1, OriginalColour); + if (OurOldChar==0 && OurChar!=0) MKARenameEveryoneProperlyExcept(OurChar); + if (CPUReadByte(0x200001D)>=CPUReadByte(0x2000048)) + gbaWriteByte(0x200001D,CPUReadByte(0x2000048)-1); + //if (CPUReadByte(0x200001D)>=OldMaxFrame && OldMaxFrame>0) + // gbaWriteByte(0x200001D,OldMaxFrame-1); + if (MenuChar==MKA_Reptile && MenuSubchar==3) + MKARandomNinja(); + else if (MenuChar==MKA_Reptile && MenuSubchar==4) + MKARandomCyborg(); + else if (MenuChar==MKA_Jade && MenuSubchar==1) + MKARandomFemale(); + } else { + if (OurOldChar==0 && OurChar!=0) + MKARenameEveryoneProperlyExcept(OurChar); + } + OurOldChar=CPUReadByte(0x2000025); } -#endif - { - u32 gc = PAD_ButtonsHeld(pad); - // DPad moves - if (gc & PAD_BUTTON_UP) J |= VBA_UP; - if (gc & PAD_BUTTON_DOWN) J |= VBA_DOWN; - if (gc & PAD_BUTTON_LEFT) J |= VBA_LEFT; - if (gc & PAD_BUTTON_RIGHT) J |= VBA_RIGHT; - if (gc & PAD_BUTTON_START) J |= VBA_BUTTON_START; - if (gc & (PAD_BUTTON_B | PAD_BUTTON_Y)) J |= VBA_BUTTON_B; - if (gc & (PAD_BUTTON_A | PAD_BUTTON_X)) J |= VBA_BUTTON_A; - if (gc & PAD_TRIGGER_Z) J |= VBA_RIGHT; // CAKTODO - if (gc & PAD_TRIGGER_R) J |= VBA_BUTTON_R; // block - if (gc & PAD_TRIGGER_L) J |= VBA_BUTTON_L; // block + WasInMenu = InMenu; + + DebugPrintf("M=%d O=%d MC=%d,%d Old=%d",InMenu,OurChar,MenuChar,MenuSubchar,OurOldChar); + + // CONTROLS + u32 J = GetMKInput(pad); + if (LK || HK) J |= VBA_BUTTON_A; + if (LP || HP) J |= VBA_BUTTON_B; + if (BL) J |= VBA_BUTTON_R; + if (CS) J |= VBA_BUTTON_L; + if (Throw) { + if (InMenu) J |= VBA_BUTTON_A; + else J |= VBA_FORWARD | VBA_BUTTON_B; + } + if (Start) J |= VBA_BUTTON_START; + if (Select) J |= VBA_BUTTON_SELECT; + // Fix kick controls to what they should be! + if (!InMenu && !(J & (VBA_UP | VBA_DOWN))) { + if (B && LK && !HK) { // Make B+HK do roundhouse, while B+LK does sweep! + J |= VBA_DOWN; + } + } else if (!InMenu && (J & VBA_DOWN)) { // Make D+HK do crouch HK, while D+LK does crouch LK + if (HK && !LK && !B && !F && !LP && !HP) { + J &= ~VBA_BACK; + J |= VBA_FORWARD; + } + } + // Fix punch controls to what they should be! + if ((!InMenu) && (J & VBA_DOWN)) { + // Make D+LP do crouch punch instead of uppercut + if (LP && !F && !B && !LK && !HK && !HP) { + J &= ~VBA_BACK; + J |= VBA_FORWARD; + } } + CostumeButton = InMenu && (CS || (J & VBA_BUTTON_SELECT)); // Change Style/Select changes costume + + if (CostumeButton && !OldCostumeButton) { + int OldSubChar = MenuSubchar; + u8 OldMaxFrame = CPUReadByte(0x2000048); + MenuSubchar = MKANextSubchar(MenuChar, MenuSubchar, OriginalColour); + if (MenuSubchar!=OldSubChar) systemGameRumble(8); + OurOldChar = CPUReadByte(0x2000025); + // apply change instantly and safely by skipping to last frame of new animation + gbaWriteByte(0x200001D,CPUReadByte(0x2000048)-1); + if (CPUReadByte(0x200001D)>=OldMaxFrame && OldMaxFrame>0) + gbaWriteByte(0x200001D,OldMaxFrame-1); + } + OurOldChar = CPUReadByte(0x2000025); + OldCostumeButton = CostumeButton; + return J; } diff --git a/source/ngc/menu.cpp b/source/ngc/menu.cpp index 42d856c..7b52398 100644 --- a/source/ngc/menu.cpp +++ b/source/ngc/menu.cpp @@ -972,6 +972,8 @@ static int MenuGameSelection() return menu; } +extern char DebugStr[50]; + /**************************************************************************** * MenuGame * @@ -982,6 +984,7 @@ static int MenuGame() int menu = MENU_NONE; GuiText titleTxt(ROMFilename, 24, (GXColor){255, 255, 255, 255}); + if (DebugStr[0]) titleTxt.SetText(DebugStr); titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); titleTxt.SetPosition(50,50); diff --git a/source/ngc/vbasupport.cpp b/source/ngc/vbasupport.cpp index 59f0891..35cf974 100644 --- a/source/ngc/vbasupport.cpp +++ b/source/ngc/vbasupport.cpp @@ -768,6 +768,14 @@ static void gbApplyPerImagePreferences() RomIdCode = MARIOLAND2; else if (strcmp(title, "METROID2") == 0) RomIdCode = METROID2; + else if (strcmp(title, "MARBLE MADNESS") == 0) + RomIdCode = MARBLEMADNESS; + else if (strcmp(title, "TMNT FOOT CLAN") == 0) + RomIdCode = TMNT1; + else if (strcmp(title, "TMNT BACK FROM") == 0 || strcmp(title, "TMNT 2") == 0) + RomIdCode = TMNT2; + else if (strcmp(title, "TMNT3") == 0) + RomIdCode = TMNT3; } }