525 lines
13 KiB
C
525 lines
13 KiB
C
/* **************************************
|
|
* Includes *
|
|
* *************************************/
|
|
|
|
#include "LoadMenu.h"
|
|
|
|
/* **************************************
|
|
* Defines *
|
|
* *************************************/
|
|
|
|
/* **************************************
|
|
* Structs and enums *
|
|
* *************************************/
|
|
|
|
enum
|
|
{
|
|
SMALL_FONT_SIZE = 8
|
|
};
|
|
|
|
enum
|
|
{
|
|
BG_BLUE_TARGET_VALUE = 0xC0,
|
|
BG_WHITE_TARGET_VALUE = /*0x40*/ 0,
|
|
BG_INCREASE_STEP = 0x10
|
|
};
|
|
|
|
enum
|
|
{
|
|
LOADING_BAR_X = 64,
|
|
LOADING_BAR_Y = 200,
|
|
LOADING_BAR_N_LINES = 4,
|
|
|
|
LOADING_BAR_WIDTH = 256,
|
|
LOADING_BAR_HEIGHT = 16,
|
|
|
|
LOADING_BAR_LUMINANCE_TARGET = NORMAL_LUMINANCE,
|
|
LOADING_BAR_LUMINANCE_STEP = 10
|
|
};
|
|
|
|
enum
|
|
{
|
|
LOADING_TITLE_CLUT_X = 384,
|
|
LOADING_TITLE_CLUT_Y = 496,
|
|
LOADING_TITLE_X = 128,
|
|
LOADING_TITLE_Y = 32,
|
|
|
|
LOADING_TITLE_U = 0,
|
|
LOADING_TITLE_V = 0,
|
|
|
|
LOADING_TITLE_LUMINANCE_STEP = 10,
|
|
LOADING_TITLE_LUMINANCE_TARGET = NORMAL_LUMINANCE
|
|
};
|
|
|
|
enum
|
|
{
|
|
PLANE_START_X = 56,
|
|
PLANE_START_Y = 200,
|
|
|
|
PLANE_U = 0,
|
|
PLANE_V = 32,
|
|
PLANE_SIZE = 16,
|
|
|
|
PLANE_LUMINANCE_STEP = 0x10,
|
|
PLANE_LUMINANCE_TARGET_VALUE = NORMAL_LUMINANCE
|
|
};
|
|
|
|
/* *************************************
|
|
* Local Prototypes
|
|
* *************************************/
|
|
|
|
static void LoadMenuInit(void);
|
|
static void ISR_LoadMenuVBlank(void);
|
|
static bool LoadMenuISRHasEnded(void);
|
|
static bool LoadMenuISRHasStarted(void);
|
|
static void LoadMenuLoadFileList( char* fileList[], void * dest[],
|
|
uint8_t szFileList, uint8_t szDestList);
|
|
|
|
/* *************************************
|
|
* Local Variables
|
|
* *************************************/
|
|
|
|
static GsGPoly4 loadMenuBg;
|
|
static GsSprite LoadMenuPlaneSpr;
|
|
static GsSprite LoadMenuTitleSpr;
|
|
static GsLine LoadMenuBarLines[LOADING_BAR_N_LINES];
|
|
static GsRectangle LoadMenuBarRect;
|
|
|
|
static char* LoadMenuFiles[] = { "cdrom:\\DATA\\SPRITES\\PLANE.TIM;1",
|
|
"cdrom:\\DATA\\SPRITES\\LOADING.TIM;1",
|
|
"cdrom:\\DATA\\FONTS\\FONT_2.FNT;1" };
|
|
|
|
static void * LoadMenuDest[] = {(GsSprite*)&LoadMenuPlaneSpr,
|
|
(GsSprite*)&LoadMenuTitleSpr,
|
|
(TYPE_FONT*)&SmallFont };
|
|
|
|
static char* strCurrentFile;
|
|
|
|
// Flags to communicate with ISR state
|
|
// * startup_flag: background fades in from black to blue.
|
|
// * end_flag: tells the background to fade out to black.
|
|
// * isr_ended: background has totally faded out to black.
|
|
// * isr_started: tells the ISR has finished starting up.
|
|
static volatile bool startup_flag;
|
|
static volatile bool isr_started;
|
|
static volatile bool end_flag;
|
|
static volatile bool isr_ended;
|
|
// Set to true when LoadMenuInit() has been called, and set to false
|
|
// once LoadMenuEnd() is called.
|
|
// It's used when multiple modules call LoadMenu() at the same time,
|
|
// so load menu does not have to be initialised each time;
|
|
static bool load_menu_running;
|
|
|
|
void LoadMenuInit(void)
|
|
{
|
|
int i;
|
|
static bool first_load = false;
|
|
|
|
if(first_load == false)
|
|
{
|
|
first_load = true;
|
|
LoadMenuLoadFileList( LoadMenuFiles,
|
|
LoadMenuDest,
|
|
sizeof(LoadMenuFiles) / sizeof(char*),
|
|
sizeof(LoadMenuDest) / sizeof(void*));
|
|
}
|
|
|
|
FontSetSize(&SmallFont, SMALL_FONT_SIZE);
|
|
|
|
LoadMenuPlaneSpr.r = 0;
|
|
LoadMenuPlaneSpr.g = 0;
|
|
LoadMenuPlaneSpr.b = 0;
|
|
|
|
LoadMenuPlaneSpr.x = PLANE_START_X;
|
|
LoadMenuPlaneSpr.y = PLANE_START_Y;
|
|
|
|
// "Loading..." title init
|
|
|
|
LoadMenuTitleSpr.r = 0;
|
|
LoadMenuTitleSpr.g = 0;
|
|
LoadMenuTitleSpr.b = 0;
|
|
|
|
LoadMenuTitleSpr.x = LOADING_TITLE_X;
|
|
LoadMenuTitleSpr.y = LOADING_TITLE_Y;
|
|
|
|
LoadMenuTitleSpr.cx = LOADING_TITLE_CLUT_X;
|
|
LoadMenuTitleSpr.cy = LOADING_TITLE_CLUT_Y;
|
|
LoadMenuTitleSpr.u = LOADING_TITLE_U;
|
|
LoadMenuTitleSpr.v = LOADING_TITLE_V;
|
|
|
|
startup_flag = true;
|
|
isr_started = false;
|
|
end_flag = false;
|
|
isr_ended = false;
|
|
|
|
// Background init
|
|
|
|
loadMenuBg.x[0] = 0;
|
|
loadMenuBg.x[1] = X_SCREEN_RESOLUTION;
|
|
loadMenuBg.x[2] = 0;
|
|
loadMenuBg.x[3] = X_SCREEN_RESOLUTION;
|
|
|
|
loadMenuBg.y[0] = 0;
|
|
loadMenuBg.y[1] = 0;
|
|
loadMenuBg.y[2] = Y_SCREEN_RESOLUTION;
|
|
loadMenuBg.y[3] = Y_SCREEN_RESOLUTION;
|
|
|
|
// Colour components adjustment (default to zero)
|
|
for(i = 0; i < 4 ; i++)
|
|
{
|
|
loadMenuBg.r[i] = 0;
|
|
loadMenuBg.g[i] = 0;
|
|
loadMenuBg.b[i] = 0;
|
|
}
|
|
|
|
// "Loading" bar line 0 (up left - up right)
|
|
|
|
LoadMenuBarLines[0].x[0] = LOADING_BAR_X;
|
|
LoadMenuBarLines[0].x[1] = LOADING_BAR_X + LOADING_BAR_WIDTH;
|
|
|
|
LoadMenuBarLines[0].y[0] = LOADING_BAR_Y;
|
|
LoadMenuBarLines[0].y[1] = LOADING_BAR_Y;
|
|
|
|
// "Loading" bar line 1 (up left - down left)
|
|
|
|
LoadMenuBarLines[1].x[0] = LOADING_BAR_X;
|
|
LoadMenuBarLines[1].x[1] = LOADING_BAR_X;
|
|
|
|
LoadMenuBarLines[1].y[0] = LOADING_BAR_Y;
|
|
LoadMenuBarLines[1].y[1] = LOADING_BAR_Y + LOADING_BAR_HEIGHT;
|
|
|
|
// "Loading" bar line 2 (down left - down right)
|
|
|
|
LoadMenuBarLines[2].x[0] = LOADING_BAR_X;
|
|
LoadMenuBarLines[2].x[1] = LOADING_BAR_X + LOADING_BAR_WIDTH;
|
|
|
|
LoadMenuBarLines[2].y[0] = LOADING_BAR_Y + LOADING_BAR_HEIGHT;
|
|
LoadMenuBarLines[2].y[1] = LOADING_BAR_Y + LOADING_BAR_HEIGHT;
|
|
|
|
// "Loading" bar line 3 (up right - down right)
|
|
|
|
LoadMenuBarLines[3].x[0] = LOADING_BAR_X + LOADING_BAR_WIDTH;
|
|
LoadMenuBarLines[3].x[1] = LOADING_BAR_X + LOADING_BAR_WIDTH;
|
|
|
|
LoadMenuBarLines[3].y[0] = LOADING_BAR_Y;
|
|
LoadMenuBarLines[3].y[1] = LOADING_BAR_Y + LOADING_BAR_HEIGHT;
|
|
|
|
for(i = 0; i < LOADING_BAR_N_LINES ; i++)
|
|
{
|
|
LoadMenuBarLines[i].r = 0;
|
|
LoadMenuBarLines[i].g = 0;
|
|
LoadMenuBarLines[i].b = 0;
|
|
}
|
|
|
|
LoadMenuBarRect.r = 0;
|
|
LoadMenuBarRect.g = 0;
|
|
LoadMenuBarRect.b = 0;
|
|
|
|
// LoadMenuBarRect.attribute |= ENABLE_TRANS | TRANS_MODE(0);
|
|
|
|
LoadMenuBarRect.x = LOADING_BAR_X;
|
|
LoadMenuBarRect.y = LOADING_BAR_Y;
|
|
LoadMenuBarRect.w = 0;
|
|
LoadMenuBarRect.h = LOADING_BAR_HEIGHT;
|
|
|
|
LoadMenuBarRect.attribute |= ENABLE_TRANS | TRANS_MODE(0);
|
|
|
|
load_menu_running = true;
|
|
|
|
SmallFont.spr.r = 0;
|
|
SmallFont.spr.g = 0;
|
|
SmallFont.spr.b = 0;
|
|
|
|
GfxSetGlobalLuminance(0);
|
|
|
|
SetVBlankHandler(&ISR_LoadMenuVBlank);
|
|
}
|
|
|
|
void LoadMenuEnd(void)
|
|
{
|
|
end_flag = true;
|
|
load_menu_running = false;
|
|
|
|
while(LoadMenuISRHasEnded() == false);
|
|
dprintf("Set default VBlank handler.\n");
|
|
SetVBlankHandler(&ISR_SystemDefaultVBlank);
|
|
|
|
GfxSetGlobalLuminance(NORMAL_LUMINANCE);
|
|
}
|
|
|
|
void ISR_LoadMenuVBlank(void)
|
|
{
|
|
uint8_t i;
|
|
|
|
if( (SystemIsBusy() == true) || (GfxIsGPUBusy() == true) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(startup_flag == true)
|
|
{
|
|
// "Loading..." text
|
|
if(LoadMenuTitleSpr.r < LOADING_TITLE_LUMINANCE_TARGET)
|
|
{
|
|
LoadMenuTitleSpr.r += LOADING_TITLE_LUMINANCE_STEP;
|
|
LoadMenuTitleSpr.g += LOADING_TITLE_LUMINANCE_STEP;
|
|
LoadMenuTitleSpr.b += LOADING_TITLE_LUMINANCE_STEP;
|
|
}
|
|
|
|
if(loadMenuBg.g[0] < BG_WHITE_TARGET_VALUE)
|
|
{
|
|
loadMenuBg.r[0] += BG_INCREASE_STEP;
|
|
loadMenuBg.r[1] += BG_INCREASE_STEP;
|
|
|
|
loadMenuBg.g[0] += BG_INCREASE_STEP;
|
|
loadMenuBg.g[1] += BG_INCREASE_STEP;
|
|
|
|
loadMenuBg.b[0] += BG_INCREASE_STEP;
|
|
loadMenuBg.b[1] += BG_INCREASE_STEP;
|
|
}
|
|
// Blue background
|
|
if(loadMenuBg.b[2] < BG_BLUE_TARGET_VALUE)
|
|
{
|
|
loadMenuBg.b[2] += BG_INCREASE_STEP;
|
|
loadMenuBg.b[3] += BG_INCREASE_STEP;
|
|
}
|
|
|
|
if(LoadMenuBarRect.r < LOADING_BAR_LUMINANCE_TARGET)
|
|
{
|
|
LoadMenuBarRect.r += LOADING_BAR_LUMINANCE_STEP;
|
|
LoadMenuBarRect.g += LOADING_BAR_LUMINANCE_STEP;
|
|
LoadMenuBarRect.b += LOADING_BAR_LUMINANCE_STEP;
|
|
}
|
|
else
|
|
{
|
|
startup_flag = false;
|
|
isr_started = true;
|
|
}
|
|
|
|
for(i = 0;i < LOADING_BAR_N_LINES ; i++)
|
|
{
|
|
if(LoadMenuBarLines[i].r < LOADING_BAR_LUMINANCE_TARGET)
|
|
{
|
|
LoadMenuBarLines[i].r += LOADING_BAR_LUMINANCE_STEP;
|
|
LoadMenuBarLines[i].g += LOADING_BAR_LUMINANCE_STEP;
|
|
LoadMenuBarLines[i].b += LOADING_BAR_LUMINANCE_STEP;
|
|
}
|
|
}
|
|
|
|
if(LoadMenuPlaneSpr.r < PLANE_LUMINANCE_TARGET_VALUE)
|
|
{
|
|
LoadMenuPlaneSpr.r += PLANE_LUMINANCE_STEP;
|
|
LoadMenuPlaneSpr.g += PLANE_LUMINANCE_STEP;
|
|
LoadMenuPlaneSpr.b += PLANE_LUMINANCE_STEP;
|
|
}
|
|
|
|
}
|
|
else if(end_flag == true)
|
|
{
|
|
LoadMenuTitleSpr.r -= LOADING_TITLE_LUMINANCE_STEP;
|
|
LoadMenuTitleSpr.g -= LOADING_TITLE_LUMINANCE_STEP;
|
|
LoadMenuTitleSpr.b -= LOADING_TITLE_LUMINANCE_STEP;
|
|
|
|
if(loadMenuBg.g[0] > 0)
|
|
{
|
|
loadMenuBg.r[0] -= BG_INCREASE_STEP;
|
|
loadMenuBg.r[1] -= BG_INCREASE_STEP;
|
|
|
|
loadMenuBg.g[0] -= BG_INCREASE_STEP;
|
|
loadMenuBg.g[1] -= BG_INCREASE_STEP;
|
|
|
|
loadMenuBg.b[0] -= BG_INCREASE_STEP;
|
|
loadMenuBg.b[1] -= BG_INCREASE_STEP;
|
|
}
|
|
|
|
if(loadMenuBg.b[2] > 0)
|
|
{
|
|
loadMenuBg.b[2] -= BG_INCREASE_STEP;
|
|
loadMenuBg.b[3] -= BG_INCREASE_STEP;
|
|
}
|
|
|
|
if(loadMenuBg.b[2] == 0)
|
|
{
|
|
end_flag = false;
|
|
isr_ended = true;
|
|
}
|
|
|
|
if(LoadMenuPlaneSpr.r > 0)
|
|
{
|
|
LoadMenuPlaneSpr.r -= PLANE_LUMINANCE_STEP;
|
|
LoadMenuPlaneSpr.g -= PLANE_LUMINANCE_STEP;
|
|
LoadMenuPlaneSpr.b -= PLANE_LUMINANCE_STEP;
|
|
}
|
|
|
|
LoadMenuPlaneSpr.x = (PLANE_START_X + LOADING_BAR_WIDTH);
|
|
LoadMenuPlaneSpr.y = PLANE_START_Y;
|
|
|
|
LoadMenuBarRect.w = LOADING_BAR_WIDTH;
|
|
|
|
if(LoadMenuBarRect.r > 0)
|
|
{
|
|
LoadMenuBarRect.r -= LOADING_BAR_LUMINANCE_STEP;
|
|
LoadMenuBarRect.g -= LOADING_BAR_LUMINANCE_STEP;
|
|
LoadMenuBarRect.b -= LOADING_BAR_LUMINANCE_STEP;
|
|
}
|
|
|
|
for(i = 0;i < LOADING_BAR_N_LINES ; i++)
|
|
{
|
|
if(LoadMenuBarLines[i].r > 0)
|
|
{
|
|
LoadMenuBarLines[i].r -= LOADING_BAR_LUMINANCE_STEP;
|
|
LoadMenuBarLines[i].g -= LOADING_BAR_LUMINANCE_STEP;
|
|
LoadMenuBarLines[i].b -= LOADING_BAR_LUMINANCE_STEP;
|
|
}
|
|
}
|
|
}
|
|
|
|
GsSortGPoly4(&loadMenuBg);
|
|
|
|
GsSortRectangle(&LoadMenuBarRect);
|
|
|
|
for(i = 0 ; i < LOADING_BAR_N_LINES ; i++)
|
|
{
|
|
GsSortLine(&LoadMenuBarLines[i]);
|
|
}
|
|
|
|
GsSortSprite(&LoadMenuTitleSpr);
|
|
|
|
LoadMenuPlaneSpr.w = PLANE_SIZE;
|
|
LoadMenuPlaneSpr.h = PLANE_SIZE;
|
|
|
|
//LoadMenuPlaneSpr.u = PLANE_U;
|
|
//LoadMenuPlaneSpr.v = PLANE_V;
|
|
|
|
GsSortSprite(&LoadMenuPlaneSpr);
|
|
|
|
FontSetFlags(&SmallFont, FONT_BLEND_EFFECT);
|
|
|
|
FontPrintText( &SmallFont,
|
|
LOADING_BAR_X - 8,
|
|
LOADING_BAR_Y + LOADING_BAR_HEIGHT + 8,
|
|
strCurrentFile );
|
|
|
|
FontSetFlags(&SmallFont, FONT_NOFLAGS);
|
|
|
|
GfxDrawScene_Fast();
|
|
}
|
|
|
|
bool LoadMenuISRHasEnded(void)
|
|
{
|
|
return isr_ended;
|
|
}
|
|
|
|
bool LoadMenuISRHasStarted(void)
|
|
{
|
|
return isr_started;
|
|
}
|
|
|
|
void LoadMenu( char* fileList[],
|
|
void * dest[],
|
|
uint8_t szFileList , uint8_t szDestList)
|
|
{
|
|
|
|
if(load_menu_running == false)
|
|
{
|
|
LoadMenuInit();
|
|
|
|
while(LoadMenuISRHasStarted() == false);
|
|
}
|
|
|
|
LoadMenuLoadFileList(fileList,dest,szFileList,szDestList);
|
|
|
|
}
|
|
|
|
void LoadMenuLoadFileList( char* fileList[], void * dest[],
|
|
uint8_t szFileList, uint8_t szDestList)
|
|
{
|
|
char aux_file_name[100];
|
|
char* extension;
|
|
short x_increment;
|
|
uint8_t fileLoadedCount;
|
|
|
|
if(szFileList != szDestList)
|
|
{
|
|
dprintf("File list size different from dest list size! %d vs %d\n",
|
|
szFileList, szDestList);
|
|
return;
|
|
}
|
|
|
|
for(fileLoadedCount = 0; fileLoadedCount < szFileList ; fileLoadedCount++)
|
|
{
|
|
if(fileList[fileLoadedCount] == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
strCurrentFile = fileList[fileLoadedCount];
|
|
|
|
x_increment = (short)(LOADING_BAR_WIDTH / szFileList);
|
|
|
|
// Calculate new X position for loading menu plane sprite.
|
|
// This is not calculated on ISR as to avoid longer ISR time.
|
|
LoadMenuPlaneSpr.x = (PLANE_START_X + (fileLoadedCount* x_increment) );
|
|
|
|
LoadMenuBarRect.w = fileLoadedCount* x_increment;
|
|
|
|
//dprintf("Files %d / %d loaded. New plane X = %d.\n",fileLoadedCount,szFileList,LoadMenuPlaneSpr.x);
|
|
|
|
// Backup original file path
|
|
strncpy(aux_file_name,fileList[fileLoadedCount],100);
|
|
|
|
//We want to get file extension, so split into tokens
|
|
strtok(fileList[fileLoadedCount],".;");
|
|
extension = strtok(NULL,".;");
|
|
|
|
dprintf("File extension: .%s\n",extension);
|
|
//Restore original file path in order to load file
|
|
strncpy(fileList[fileLoadedCount],aux_file_name,100);
|
|
|
|
if(strncmp(extension,"TIM",3) == 0)
|
|
{
|
|
if(GfxSpriteFromFile(fileList[fileLoadedCount], dest[fileLoadedCount]) == false)
|
|
{
|
|
dprintf("Could not load image file \"%s\"!\n",fileList[fileLoadedCount]);
|
|
}
|
|
}
|
|
else if(strncmp(extension,"CLT",3) == 0)
|
|
{
|
|
if(dest[fileLoadedCount] != NULL)
|
|
{
|
|
dprintf("WARNING: File %s linked to non-NULL destination pointer!\n", dest[fileLoadedCount]);
|
|
}
|
|
|
|
if(GfxCLUTFromFile(fileList[fileLoadedCount]) == false)
|
|
{
|
|
dprintf("Could not load CLUT file \"%s\"!\n",fileList[fileLoadedCount]);
|
|
}
|
|
}
|
|
else if(strncmp(extension,"VAG",3) == 0)
|
|
{
|
|
if(SfxUploadSound(fileList[fileLoadedCount], dest[fileLoadedCount]) == false)
|
|
{
|
|
dprintf("Could not load sound file \"%s\"!\n",fileList[fileLoadedCount]);
|
|
}
|
|
}
|
|
else if(strncmp(extension,"FNT",3) == 0)
|
|
{
|
|
if(FontLoadImage(fileList[fileLoadedCount], dest[fileLoadedCount]) == false)
|
|
{
|
|
dprintf("Could not load font file \"%s\"!\n",fileList[fileLoadedCount]);
|
|
}
|
|
}
|
|
else if(strncmp(extension,"PLT",3) == 0)
|
|
{
|
|
if(PltParserLoadFile(fileList[fileLoadedCount], dest[fileLoadedCount]) == false)
|
|
{
|
|
dprintf("Could not load pilots file \"%s\"!\n",fileList[fileLoadedCount]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("LoadMenu does not recognize following extension: %s\n",extension);
|
|
}
|
|
}
|
|
}
|