515 lines
12 KiB
C
515 lines
12 KiB
C
/* **************************************
|
|
* Includes *
|
|
* *************************************/
|
|
|
|
#include "Menu.h"
|
|
|
|
/* **************************************
|
|
* Defines *
|
|
* *************************************/
|
|
|
|
#define MAIN_MENU_FILES 1
|
|
#define BUTTON_SIZE 64
|
|
#define SELECTED_BUTTON_LUMINANCE 0xC0
|
|
|
|
/* **************************************
|
|
* Structs and enums *
|
|
* *************************************/
|
|
|
|
typedef enum
|
|
{
|
|
PLAY_OPTIONS_LEVEL = 0,
|
|
ONE_TWO_PLAYERS_LEVEL,
|
|
OPTIONS_LEVEL
|
|
}MainMenuLevel;
|
|
|
|
enum
|
|
{
|
|
MAIN_MENU_PLAY_OPTIONS_LEVEL_BUTTONS = 2,
|
|
MAIN_MENU_ONE_TWO_PLAYERS_LEVEL_BUTTONS = 2,
|
|
MAIN_MENU_OPTIONS_LEVEL_BUTTONS = 1
|
|
};
|
|
|
|
typedef enum
|
|
{
|
|
PLAY_BUTTON_INDEX = 0,
|
|
OPTIONS_BUTTON_INDEX,
|
|
ONE_PLAYER_BUTTON_INDEX,
|
|
TWO_PLAYER_BUTTON_INDEX,
|
|
|
|
MAIN_MENU_BUTTONS_MAX
|
|
}MMBtn_Index;
|
|
|
|
enum
|
|
{
|
|
MAIN_MENU_PLAY_BUTTON_X = 92,
|
|
MAIN_MENU_PLAY_BUTTON_Y = 92,
|
|
|
|
MAIN_MENU_OPTIONS_BUTTON_X = 225,
|
|
MAIN_MENU_OPTIONS_BUTTON_Y = 92,
|
|
|
|
MAIN_MENU_ONE_PLAYER_BUTTON_X = 92,
|
|
MAIN_MENU_ONE_PLAYER_BUTTON_Y = 92,
|
|
|
|
MAIN_MENU_TWO_PLAYER_BUTTON_X = 225,
|
|
MAIN_MENU_TWO_PLAYER_BUTTON_Y = 92
|
|
};
|
|
|
|
typedef enum
|
|
{
|
|
PLAY_BUTTON_U_OFFSET = 0,
|
|
PLAY_BUTTON_Y_OFFSET = 64,
|
|
|
|
ONE_PLAYER_BUTTON_U_OFFSET = 128,
|
|
ONE_PLAYER_BUTTON_Y_OFFSET = 64,
|
|
|
|
OPTIONS_BUTTON_U_OFFSET = 64,
|
|
OPTIONS_BUTTON_Y_OFFSET = 64,
|
|
|
|
TWO_PLAYER_BUTTON_U_OFFSET = 192,
|
|
TWO_PLAYER_BUTTON_Y_OFFSET = 64,
|
|
|
|
DEFAULT_BUTTON_U_OFFSET = 0,
|
|
DEFAULT_BUTTON_V_OFFSET = 128
|
|
|
|
}MMBtn_Offset;
|
|
|
|
typedef struct
|
|
{
|
|
MMBtn_Offset offset_u;
|
|
MMBtn_Offset offset_v;
|
|
|
|
// Timer for absolute, sine-like animation
|
|
short timer;
|
|
|
|
// Pointer to function executed by pressing the button
|
|
void (*f)();
|
|
|
|
MMBtn_Index i;
|
|
|
|
bool selected;
|
|
bool was_selected;
|
|
|
|
}TYPE_MMBtn;
|
|
|
|
/* **************************************
|
|
* Local prototypes *
|
|
* **************************************/
|
|
|
|
static void MainMenuDrawButton(TYPE_MMBtn * btn);
|
|
static void PlayMenu(void);
|
|
static void OptionsMenu(void);
|
|
static void OnePlayerMenu(void);
|
|
static void TwoPlayerMenu(void);
|
|
static void MainMenuButtonHandler(void);
|
|
static void MainMenuRestoreInitValues(void);
|
|
static void MenuTestCheat(void);
|
|
|
|
/* **************************************
|
|
* Local variables *
|
|
* **************************************/
|
|
|
|
static GsSprite MenuSpr;
|
|
static SsVag BellSnd;
|
|
static SsVag AcceptSnd;
|
|
static TYPE_CHEAT TestCheat;
|
|
static TYPE_CHEAT StackCheckCheat;
|
|
|
|
static char* MainMenuFiles[] = { "cdrom:\\DATA\\SPRITES\\MAINMENU.TIM;1" ,
|
|
"cdrom:\\DATA\\SOUNDS\\BELL.VAG;1" ,
|
|
"cdrom:\\DATA\\SOUNDS\\ACCEPT.VAG;1" ,
|
|
"cdrom:\\DATA\\SPRITES\\PSXDISK.TIM;1" ,
|
|
"cdrom:\\DATA\\SPRITES\\INTROFNT.TIM;1" ,
|
|
"cdrom:\\DATA\\SPRITES\\BUTTONS.TIM;1" ,
|
|
#ifndef NO_INTRO
|
|
"cdrom:\\DATA\\SPRITES\\GPL.TIM;1" ,
|
|
"cdrom:\\DATA\\SPRITES\\OPENSRC.TIM;1" ,
|
|
"cdrom:\\DATA\\SOUNDS\\TRAYCL.VAG;1" ,
|
|
"cdrom:\\DATA\\SOUNDS\\SPINDISK.VAG;1"
|
|
#endif // NO_INTRO
|
|
};
|
|
|
|
static void * MainMenuDest[] = { (GsSprite*)&MenuSpr ,
|
|
(SsVag*)&BellSnd ,
|
|
(SsVag*)&AcceptSnd ,
|
|
(GsSprite*)&PsxDisk ,
|
|
(GsSprite*)&PSXSDKIntroFont ,
|
|
(GsSprite*)&PSXButtons ,
|
|
#ifndef NO_INTRO
|
|
(GsSprite*)&GPL_Logo ,
|
|
(GsSprite*)&OpenSource_Logo ,
|
|
(SsVag*)&TrayClSnd ,
|
|
(SsVag*)&SpinDiskSnd
|
|
#endif // NO_INTRO
|
|
};
|
|
|
|
static TYPE_MMBtn MainMenuBtn[MAIN_MENU_BUTTONS_MAX];
|
|
static MainMenuLevel menuLevel;
|
|
static MMBtn_Index MainMenuMinimumBtn;
|
|
|
|
void PlayMenu(void)
|
|
{
|
|
menuLevel = ONE_TWO_PLAYERS_LEVEL;
|
|
MainMenuMinimumBtn = ONE_PLAYER_BUTTON_INDEX;
|
|
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].selected = false;
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].was_selected = false;
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].timer = 0;
|
|
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].selected = false;
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].was_selected = false;
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].timer = 0;
|
|
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].selected = true;
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].was_selected = false;
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].timer = 0;
|
|
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].selected = false;
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].was_selected = false;
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].timer = 0;
|
|
}
|
|
|
|
void OptionsMenu(void)
|
|
{
|
|
dprintf("OptionsMenu(void)!\n");
|
|
}
|
|
|
|
void OnePlayerMenu(void)
|
|
{
|
|
EndAnimation();
|
|
Game(false /* One Player Only */);
|
|
}
|
|
|
|
void TwoPlayerMenu(void)
|
|
{
|
|
EndAnimation();
|
|
Game(true /* Two players */);
|
|
}
|
|
|
|
|
|
void MainMenuInit(void)
|
|
{
|
|
LoadMenu( MainMenuFiles,MainMenuDest,
|
|
sizeof(MainMenuFiles) / sizeof(char*) ,
|
|
sizeof(MainMenuDest) / sizeof(void*) );
|
|
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].offset_u = PLAY_BUTTON_U_OFFSET;
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].offset_v = PLAY_BUTTON_Y_OFFSET;
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].timer = 0;
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].f = &PlayMenu;
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].i = PLAY_BUTTON_INDEX;
|
|
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].offset_u = OPTIONS_BUTTON_U_OFFSET;
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].offset_v = OPTIONS_BUTTON_Y_OFFSET;
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].timer = 0;
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].f = &OptionsMenu;
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].i = OPTIONS_BUTTON_INDEX;
|
|
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].offset_u = ONE_PLAYER_BUTTON_U_OFFSET;
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].offset_v = ONE_PLAYER_BUTTON_Y_OFFSET;
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].timer = 0;
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].f = &OnePlayerMenu;
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].i = ONE_PLAYER_BUTTON_INDEX;
|
|
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].offset_u = TWO_PLAYER_BUTTON_U_OFFSET;
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].offset_v = TWO_PLAYER_BUTTON_Y_OFFSET;
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].timer = 0;
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].f = &TwoPlayerMenu;
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].i = TWO_PLAYER_BUTTON_INDEX;
|
|
|
|
menuLevel = PLAY_OPTIONS_LEVEL;
|
|
|
|
MainMenuMinimumBtn = PLAY_BUTTON_INDEX;
|
|
|
|
TestCheat.Callback = &MenuTestCheat;
|
|
memset(TestCheat.Combination,0,CHEAT_ARRAY_SIZE);
|
|
//memcpy(myarray, (int [5]){a,b,c,d,e}, 5*sizeof(int));
|
|
|
|
memcpy( TestCheat.Combination,
|
|
(unsigned short[CHEAT_ARRAY_SIZE])
|
|
{ PAD_CIRCLE, PAD_CIRCLE, PAD_CROSS, PAD_TRIANGLE,
|
|
PAD_TRIANGLE, PAD_TRIANGLE, 0 , 0 ,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0 } , sizeof(unsigned short) * CHEAT_ARRAY_SIZE);
|
|
|
|
PadAddCheat(&TestCheat);
|
|
|
|
StackCheckCheat.Callback = &SystemPrintStackPointerAddress;
|
|
memset(StackCheckCheat.Combination, 0, CHEAT_ARRAY_SIZE);
|
|
|
|
memcpy( StackCheckCheat.Combination,
|
|
(unsigned short[CHEAT_ARRAY_SIZE])
|
|
{ PAD_TRIANGLE, PAD_TRIANGLE, PAD_CROSS, PAD_TRIANGLE,
|
|
PAD_L1, PAD_R1, 0 , 0 ,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0 } , sizeof(unsigned short) * CHEAT_ARRAY_SIZE);
|
|
|
|
PadAddCheat(&StackCheckCheat);
|
|
|
|
LoadMenuEnd();
|
|
}
|
|
|
|
void MainMenu(void)
|
|
{
|
|
unsigned short* cheat_array;
|
|
uint8_t i;
|
|
MainMenuInit();
|
|
|
|
#ifndef NO_INTRO
|
|
PSXSDKIntro();
|
|
#endif //PSXSDK_DEBUG
|
|
|
|
GfxSetGlobalLuminance(NORMAL_LUMINANCE);
|
|
|
|
while(1)
|
|
{
|
|
MainMenuButtonHandler();
|
|
|
|
while(GfxIsGPUBusy() == true);
|
|
|
|
switch(menuLevel)
|
|
{
|
|
case PLAY_OPTIONS_LEVEL:
|
|
|
|
GsSortCls(0,0,40);
|
|
MainMenuDrawButton(&MainMenuBtn[PLAY_BUTTON_INDEX]);
|
|
MainMenuDrawButton(&MainMenuBtn[OPTIONS_BUTTON_INDEX]);
|
|
|
|
for(cheat_array = PadGetPlayerOneCheatArray(), i = 0; *cheat_array != 0; cheat_array++, i += 16)
|
|
{
|
|
GfxDrawButton(i, 220, *cheat_array);
|
|
}
|
|
|
|
GfxDrawScene();
|
|
break;
|
|
|
|
case ONE_TWO_PLAYERS_LEVEL:
|
|
|
|
GsSortCls(0,0,40);
|
|
MainMenuDrawButton(&MainMenuBtn[ONE_PLAYER_BUTTON_INDEX]);
|
|
MainMenuDrawButton(&MainMenuBtn[TWO_PLAYER_BUTTON_INDEX]);
|
|
|
|
for(cheat_array = PadGetPlayerOneCheatArray(), i = 0; *cheat_array != 0; cheat_array++, i += 16)
|
|
{
|
|
GfxDrawButton(i, 220, *cheat_array);
|
|
}
|
|
|
|
GfxDrawScene();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void MainMenuRestoreInitValues(void)
|
|
{
|
|
menuLevel = PLAY_OPTIONS_LEVEL;
|
|
MainMenuMinimumBtn = PLAY_BUTTON_INDEX;
|
|
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].selected = true;
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].was_selected = false;
|
|
MainMenuBtn[PLAY_BUTTON_INDEX].timer = 0;
|
|
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].selected = false;
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].was_selected = false;
|
|
MainMenuBtn[OPTIONS_BUTTON_INDEX].timer = 0;
|
|
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].selected = false;
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].was_selected = false;
|
|
MainMenuBtn[ONE_PLAYER_BUTTON_INDEX].timer = 0;
|
|
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].selected = false;
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].was_selected = false;
|
|
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].timer = 0;
|
|
|
|
GfxSetGlobalLuminance(NORMAL_LUMINANCE);
|
|
}
|
|
|
|
void MainMenuButtonHandler(void)
|
|
{
|
|
static uint8_t btn_selected = PLAY_BUTTON_INDEX;
|
|
static uint8_t previous_btn_selected = 0;
|
|
uint8_t max_buttons;
|
|
|
|
if(PadOneAnyKeyPressed() == true)
|
|
{
|
|
if(SystemIsRandSeedSet() == false)
|
|
{
|
|
SystemSetRandSeed();
|
|
}
|
|
}
|
|
|
|
if( (PadOneKeySinglePress(PAD_CROSS) == true)
|
|
||
|
|
(PadOneKeySinglePress(PAD_TRIANGLE) == true) )
|
|
{
|
|
SfxPlaySound(&AcceptSnd);
|
|
}
|
|
|
|
switch(menuLevel)
|
|
{
|
|
case PLAY_OPTIONS_LEVEL:
|
|
max_buttons = MAIN_MENU_PLAY_OPTIONS_LEVEL_BUTTONS;
|
|
break;
|
|
|
|
case ONE_TWO_PLAYERS_LEVEL:
|
|
max_buttons = MAIN_MENU_ONE_TWO_PLAYERS_LEVEL_BUTTONS;
|
|
if(PadOneKeySinglePress(PAD_TRIANGLE) == true)
|
|
{
|
|
menuLevel = PLAY_OPTIONS_LEVEL;
|
|
MainMenuMinimumBtn = PLAY_BUTTON_INDEX;
|
|
btn_selected = PLAY_BUTTON_INDEX;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
max_buttons = 0;
|
|
break;
|
|
}
|
|
|
|
MainMenuBtn[previous_btn_selected].was_selected = MainMenuBtn[previous_btn_selected].selected;
|
|
MainMenuBtn[btn_selected].was_selected = MainMenuBtn[btn_selected].selected;
|
|
|
|
if(PadOneKeySinglePress(PAD_LEFT) && (btn_selected > 0) )
|
|
{
|
|
MainMenuBtn[btn_selected].selected = false;
|
|
previous_btn_selected = btn_selected;
|
|
btn_selected--;
|
|
SfxPlaySound(&BellSnd);
|
|
}
|
|
else if(PadOneKeySinglePress(PAD_RIGHT)
|
|
&&
|
|
(btn_selected < (max_buttons - 1 + MainMenuMinimumBtn) ) )
|
|
{
|
|
MainMenuBtn[btn_selected].selected = false;
|
|
previous_btn_selected = btn_selected;
|
|
btn_selected++;
|
|
SfxPlaySound(&BellSnd);
|
|
}
|
|
|
|
if(btn_selected < MainMenuMinimumBtn)
|
|
{
|
|
btn_selected = MainMenuMinimumBtn;
|
|
}
|
|
|
|
if(btn_selected > (max_buttons - 1 + MainMenuMinimumBtn) )
|
|
{
|
|
// Avoid overflow when going back in menu navigation
|
|
btn_selected = (max_buttons - 1 + MainMenuMinimumBtn);
|
|
}
|
|
|
|
if(PadOneKeySinglePress(PAD_CROSS) )
|
|
{
|
|
if(menuLevel == ONE_TWO_PLAYERS_LEVEL)
|
|
{
|
|
MainMenuBtn[btn_selected].f();
|
|
// Once gameplay has finished, turn back to first level
|
|
MainMenuRestoreInitValues();
|
|
btn_selected = PLAY_BUTTON_INDEX;
|
|
}
|
|
else
|
|
{
|
|
MainMenuBtn[btn_selected].f();
|
|
}
|
|
|
|
|
|
|
|
if(menuLevel == ONE_TWO_PLAYERS_LEVEL)
|
|
{
|
|
btn_selected = PLAY_BUTTON_INDEX;
|
|
}
|
|
|
|
}
|
|
|
|
MainMenuBtn[btn_selected].selected = true;
|
|
|
|
|
|
}
|
|
|
|
void MainMenuDrawButton(TYPE_MMBtn * btn)
|
|
{
|
|
MenuSpr.w = BUTTON_SIZE;
|
|
MenuSpr.h = BUTTON_SIZE;
|
|
|
|
if(btn->timer < MainMenuBtnAni_sz)
|
|
{
|
|
btn->timer++;
|
|
}
|
|
|
|
if(btn->selected == true)
|
|
{
|
|
if(btn->was_selected == false)
|
|
{
|
|
btn->timer = 0;
|
|
}
|
|
|
|
MenuSpr.r = SELECTED_BUTTON_LUMINANCE;
|
|
MenuSpr.g = SELECTED_BUTTON_LUMINANCE;
|
|
MenuSpr.b = SELECTED_BUTTON_LUMINANCE;
|
|
}
|
|
else
|
|
{
|
|
MenuSpr.r = NORMAL_LUMINANCE;
|
|
MenuSpr.g = NORMAL_LUMINANCE;
|
|
MenuSpr.b = NORMAL_LUMINANCE;
|
|
}
|
|
|
|
MenuSpr.u = DEFAULT_BUTTON_U_OFFSET;
|
|
MenuSpr.v = DEFAULT_BUTTON_V_OFFSET;
|
|
|
|
switch(btn->i)
|
|
{
|
|
case PLAY_BUTTON_INDEX:
|
|
MenuSpr.x = MAIN_MENU_PLAY_BUTTON_X;
|
|
MenuSpr.y = MAIN_MENU_PLAY_BUTTON_Y - MainMenuBtnAni[btn->timer];
|
|
MenuSpr.u += btn->offset_u;
|
|
MenuSpr.v += btn->offset_v;
|
|
|
|
GsSortSprite(&MenuSpr);
|
|
break;
|
|
|
|
case OPTIONS_BUTTON_INDEX:
|
|
MenuSpr.x = MAIN_MENU_OPTIONS_BUTTON_X;
|
|
MenuSpr.y = MAIN_MENU_OPTIONS_BUTTON_Y - MainMenuBtnAni[btn->timer];
|
|
MenuSpr.u += btn->offset_u;
|
|
MenuSpr.v += btn->offset_v;
|
|
|
|
GsSortSprite(&MenuSpr);
|
|
break;
|
|
|
|
case ONE_PLAYER_BUTTON_INDEX:
|
|
MenuSpr.x = MAIN_MENU_ONE_PLAYER_BUTTON_X;
|
|
MenuSpr.y = MAIN_MENU_ONE_PLAYER_BUTTON_Y - MainMenuBtnAni[btn->timer];
|
|
MenuSpr.u += btn->offset_u;
|
|
MenuSpr.v += btn->offset_v;
|
|
|
|
GsSortSprite(&MenuSpr);
|
|
break;
|
|
|
|
case TWO_PLAYER_BUTTON_INDEX:
|
|
MenuSpr.x = MAIN_MENU_TWO_PLAYER_BUTTON_X;
|
|
MenuSpr.y = MAIN_MENU_TWO_PLAYER_BUTTON_Y - MainMenuBtnAni[btn->timer];
|
|
MenuSpr.u += btn->offset_u;
|
|
MenuSpr.v += btn->offset_v;
|
|
|
|
GsSortSprite(&MenuSpr);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void MenuTestCheat(void)
|
|
{
|
|
if(MemCardShowMap() == false)
|
|
{
|
|
dprintf("MemCardShowMap() failed!\n");
|
|
return;
|
|
}
|
|
}
|