* Added some comments on System.

* New routine PadOneKeySinglePress() and PadTwoKeySinglePress().
* Temp waypoints now turn red when colliding with an aircraft or with a previously existing waypoint.
* When loading files, GPU operation is finishedbefore calling fopen. Also, I_MASK is disabled just in case.
* For PLT files, actual tile needs to be set instead of parking number.
This commit is contained in:
XaviDCR92 2017-05-01 23:05:51 +02:00
parent 8629c228db
commit 83b4684d7c
16 changed files with 487 additions and 137 deletions

View File

@ -7,4 +7,4 @@
10:30
#Aircraft arrival (or departure) must be set relative to initial time, in HH:MM format.
ARRIVAL;PHX1002;40;00:05;0
DEPARTURE;PHX1000;100;00:05;2
DEPARTURE;PHX1000;100;00:05;19

View File

@ -58,10 +58,10 @@ static const fix16_t AircraftSpeedsTable[] = { 0 /* IDLE */ ,
* Local prototypes
* *************************************/
static void AircraftDirection(TYPE_AIRCRAFT_DATA * ptrAircraft);
static void AircraftDirection(TYPE_AIRCRAFT_DATA* ptrAircraft);
static AIRCRAFT_LIVERY AircraftLiveryFromFlightNumber(char * strFlightNumber);
static void AircraftAttitude(TYPE_AIRCRAFT_DATA * ptrAircraft);
static void AircraftUpdateSpriteFromData(TYPE_AIRCRAFT_DATA * ptrAircraft);
static void AircraftAttitude(TYPE_AIRCRAFT_DATA* ptrAircraft);
static void AircraftUpdateSpriteFromData(TYPE_AIRCRAFT_DATA* ptrAircraft);
void AircraftInit(void)
{
@ -96,7 +96,7 @@ bool AircraftAddNew( TYPE_FLIGHT_DATA * ptrFlightData,
uint8_t FlightDataIndex,
uint16_t * targets )
{
TYPE_AIRCRAFT_DATA * ptrAircraft = &AircraftData[AircraftIndex];
TYPE_AIRCRAFT_DATA* ptrAircraft = &AircraftData[AircraftIndex];
uint8_t level_columns = GameGetLevelColumns();
uint8_t i;
@ -128,6 +128,12 @@ bool AircraftAddNew( TYPE_FLIGHT_DATA * ptrFlightData,
ptrAircraft->Speed = AircraftSpeedsTable[AIRCRAFT_SPEED_APPROACH];
}
else if(ptrFlightData->FlightDirection[FlightDataIndex] == DEPARTURE)
{
ptrAircraft->IsoPos.x = GameGetXFromTile(ptrFlightData->Parking[FlightDataIndex]);
ptrAircraft->IsoPos.y = GameGetYFromTile(ptrFlightData->Parking[FlightDataIndex]);
ptrAircraft->IsoPos.z = 0;
}
ptrAircraft->State = ptrFlightData->State[FlightDataIndex];
@ -177,7 +183,7 @@ AIRCRAFT_LIVERY AircraftLiveryFromFlightNumber(char * strFlightNumber)
void AircraftHandler(void)
{
TYPE_AIRCRAFT_DATA * ptrAircraft;
TYPE_AIRCRAFT_DATA* ptrAircraft;
uint8_t i;
for(i = 0; i < GAME_MAX_AIRCRAFT; i++)
@ -196,7 +202,7 @@ void AircraftHandler(void)
void AircraftRender(TYPE_PLAYER * ptrPlayer)
{
TYPE_AIRCRAFT_DATA * ptrAircraft;
TYPE_AIRCRAFT_DATA* ptrAircraft;
TYPE_CARTESIAN_POS cartPos;
uint8_t i;
@ -228,7 +234,7 @@ void AircraftRender(TYPE_PLAYER * ptrPlayer)
}
}
void AircraftDirection(TYPE_AIRCRAFT_DATA * ptrAircraft)
void AircraftDirection(TYPE_AIRCRAFT_DATA* ptrAircraft)
{
TYPE_ISOMETRIC_FIX16_POS targetPos;
@ -291,7 +297,7 @@ void AircraftDirection(TYPE_AIRCRAFT_DATA * ptrAircraft)
}
}
void AircraftUpdateSpriteFromData(TYPE_AIRCRAFT_DATA * ptrAircraft)
void AircraftUpdateSpriteFromData(TYPE_AIRCRAFT_DATA* ptrAircraft)
{
switch(ptrAircraft->Livery)
{
@ -331,7 +337,7 @@ void AircraftUpdateSpriteFromData(TYPE_AIRCRAFT_DATA * ptrAircraft)
}
}
void AircraftAttitude(TYPE_AIRCRAFT_DATA * ptrAircraft)
void AircraftAttitude(TYPE_AIRCRAFT_DATA* ptrAircraft)
{
if(ptrAircraft->State == STATE_FINAL)
{
@ -347,7 +353,7 @@ TYPE_ISOMETRIC_POS AircraftGetIsoPos(uint8_t FlightDataIdx)
// Aircraft position data is stored in fix16_t data type instead of "short" data type.
// So we must perform a conversion first for convenience.
TYPE_ISOMETRIC_POS retIsoPos;
TYPE_ISOMETRIC_FIX16_POS fix16IsoPos = AircraftData[FlightDataIdx].IsoPos;
TYPE_ISOMETRIC_FIX16_POS fix16IsoPos = AircraftFromFlightDataIndex(FlightDataIdx)->IsoPos;
retIsoPos.x = (short)fix16_to_int(fix16IsoPos.x);
retIsoPos.y = (short)fix16_to_int(fix16IsoPos.y);
@ -356,14 +362,33 @@ TYPE_ISOMETRIC_POS AircraftGetIsoPos(uint8_t FlightDataIdx)
return retIsoPos;
}
void AircraftAddTargets(TYPE_AIRCRAFT_DATA * ptrAircraft, uint16_t * targets)
void AircraftAddTargets(TYPE_AIRCRAFT_DATA* ptrAircraft, uint16_t * targets)
{
memcpy(ptrAircraft->Target, targets, sizeof(uint16_t) * AIRCRAFT_MAX_TARGETS);
}
TYPE_AIRCRAFT_DATA * AircraftFromFlightDataIndex(uint8_t index)
uint16_t AircraftGetTileFromFlightDataIndex(uint8_t index)
{
return &AircraftData[index];
TYPE_ISOMETRIC_POS isoPos = AircraftGetIsoPos(index);
return GameGetTileFromIsoPosition(&isoPos);
}
TYPE_AIRCRAFT_DATA* AircraftFromFlightDataIndex(uint8_t index)
{
uint8_t i;
TYPE_AIRCRAFT_DATA* ptrAircraft;
for(i = 0; i < GAME_MAX_AIRCRAFT; i++)
{
ptrAircraft = &AircraftData[i];
if(ptrAircraft->FlightDataIdx == index)
{
return ptrAircraft;
}
}
return NULL;
}
void AircraftFromFlightDataIndexAddTargets(uint8_t index, uint16_t * targets)

View File

@ -17,10 +17,11 @@
void AircraftInit(void);
void AircraftHandler(void);
void AircraftRender(TYPE_PLAYER * ptrPlayer);
TYPE_AIRCRAFT_DATA * AircraftFromFlightDataIndex(uint8_t index);
TYPE_AIRCRAFT_DATA* AircraftFromFlightDataIndex(uint8_t index);
void AircraftFromFlightDataIndexAddTargets(uint8_t index, uint16_t * targets);
void AircraftAddTargets(TYPE_AIRCRAFT_DATA * ptrAircraft, uint16_t * targets);
void AircraftAddTargets(TYPE_AIRCRAFT_DATA* ptrAircraft, uint16_t * targets);
TYPE_ISOMETRIC_POS AircraftGetIsoPos(uint8_t FlightDataIdx);
uint16_t AircraftGetTileFromFlightDataIndex(uint8_t index);
bool AircraftAddNew( TYPE_FLIGHT_DATA * ptrFlightData,
uint8_t FlightDataIndex,
uint16_t * targets );

View File

@ -111,7 +111,6 @@ static void GameGetRunwayArray(void);
static void GameGetSelectedRunwayArray(uint16_t rwyHeader);
static void GameAssignRunwaytoAircraft(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFlightData);
static bool GameGuiShowAircraftDataSpecialConditions(TYPE_PLAYER * ptrPlayer);
static uint16_t GameGetTileFromIsoPosition(TYPE_ISOMETRIC_POS * IsoPos);
static bool GamePathToTile(TYPE_PLAYER * ptrPlayer);
/* *************************************
@ -195,6 +194,8 @@ void Game(bool two_players)
}
}
GfxDisableSplitScreen();
EndAnimation();
SfxPlayTrack(INTRO_TRACK);
@ -217,8 +218,8 @@ bool GamePause(void)
// Run player-specific functions for each player
if(ptrPlayer->Active == true)
{
//dprintf("Released callback = 0x%08X\n", ptrPlayer->PadKeyReleased_Callback);
if(ptrPlayer->PadKeyReleased_Callback(PAD_START) == true)
//dprintf("Released callback = 0x%08X\n", ptrPlayer->PadKeySinglePress_Callback);
if(ptrPlayer->PadKeySinglePress_Callback(PAD_START) == true)
{
dprintf("Player %d set pause_flag to true!\n",i);
pause_flag = true;
@ -261,6 +262,7 @@ void GameInit(void)
PlayerData[PLAYER_ONE].Active = true;
PlayerData[PLAYER_ONE].PadKeyPressed_Callback = &PadOneKeyPressed;
PlayerData[PLAYER_ONE].PadKeyReleased_Callback = &PadOneKeyReleased;
PlayerData[PLAYER_ONE].PadKeySinglePress_Callback = &PadOneKeySinglePress;
PlayerData[PLAYER_ONE].PadDirectionKeyPressed_Callback = &PadOneDirectionKeyPressed;
PlayerData[PLAYER_ONE].FlightDataPage = 0;
@ -272,6 +274,7 @@ void GameInit(void)
PlayerData[PLAYER_TWO].PadKeyReleased_Callback = &PadTwoKeyReleased;
PlayerData[PLAYER_TWO].PadDirectionKeyPressed_Callback = &PadTwoDirectionKeyPressed;
PlayerData[PLAYER_TWO].FlightDataPage = 0;
PlayerData[PLAYER_TWO].PadKeySinglePress_Callback = &PadTwoKeySinglePress;
// On 2-player mode, one player controls departure flights and
// other player controls arrival flights.
@ -549,12 +552,18 @@ void GameClockFlights(void)
void GameGraphics(void)
{
int i;
bool split_screen = false;
while( (GfxIsGPUBusy() == true)
||
(SystemRefreshNeeded() == false) );
GsSortCls(0,0,NORMAL_LUMINANCE >> 1);
if( (PlayerData[PLAYER_ONE].Active == true)
&&
(PlayerData[PLAYER_TWO].Active == true) )
{
split_screen = true;
}
if(GfxGetGlobalLuminance() < NORMAL_LUMINANCE)
{
@ -564,24 +573,34 @@ void GameGraphics(void)
for(i = 0; i < MAX_PLAYERS ; i++)
{
if(PlayerData[i].Active == true)
{
{
if(split_screen == true)
{
GfxSetSplitScreen(i);
}
GsSortCls(0,0,GfxGetGlobalLuminance() >> 1);
GameRenderLevel(&PlayerData[i]);
AircraftRender(&PlayerData[i]);
GameGuiAircraftNotificationRequest(&FlightData);
GameGuiBubble(&FlightData);
GameGuiClock(GameHour,GameMinutes);
/*for(i = 0; i < MAX_PLAYERS ; i++)
{*/
GameGuiAircraftList(&PlayerData[i], &FlightData);
//}
GfxDrawScene_Fast();
while(GfxIsGPUBusy() == true);
}
}
GameGuiAircraftNotificationRequest(&FlightData);
GameGuiBubble(&FlightData);
GameGuiClock(GameHour,GameMinutes);
for(i = 0; i < MAX_PLAYERS ; i++)
{
GameGuiAircraftList(&PlayerData[i], &FlightData);
}
GfxDrawScene();
SystemCyclicHandler();
}
void GameLoadLevel(void)
@ -658,6 +677,11 @@ char* GetGameLevelTitle(void)
void GameAircraftState(void)
{
uint8_t i;
uint16_t target[2] = {0};
// Arrays are copied to AircraftAddNew, so we create a first and only
// target which is the parking tile itself, and the second element
// is just the NULL character.
// Not an ideal solution, but the best one currently available.
for(i = 0; i < FlightData.nAircraft ; i++)
{
@ -670,6 +694,16 @@ void GameAircraftState(void)
if(FlightData.FlightDirection[i] == DEPARTURE)
{
FlightData.State[i] = STATE_PARKED;
target[0] = FlightData.Parking[i];
dprintf("Target assigned = %d", target[0]);
if(AircraftAddNew(&FlightData, i, target) == false)
{
dprintf("Exceeded maximum aircraft number!\n");
return;
}
}
else if(FlightData.FlightDirection[i] == ARRIVAL)
{
@ -947,11 +981,11 @@ void GameStateShowAircraft(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFlight
{
if(ptrPlayer->ShowAircraftData == true)
{
if(ptrPlayer->PadKeyReleased_Callback(PAD_TRIANGLE) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_TRIANGLE) == true)
{
ptrPlayer->ShowAircraftData = false;
}
else if(ptrPlayer->PadKeyReleased_Callback(PAD_SQUARE) == true)
else if(ptrPlayer->PadKeySinglePress_Callback(PAD_SQUARE) == true)
{
dprintf("Aircraft state = %d. STATE_IDLE = %d\n",
ptrFlightData->State[ptrPlayer->SelectedAircraft],
@ -965,7 +999,7 @@ void GameStateShowAircraft(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFlight
}
}
if(ptrPlayer->PadKeyReleased_Callback(PAD_CIRCLE) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_CIRCLE) == true)
{
if(GameGuiShowAircraftDataSpecialConditions(ptrPlayer) == false)
{
@ -981,7 +1015,7 @@ void GameStateLockTarget(TYPE_PLAYER * ptrPlayer)
{
CameraMoveToIsoPos(ptrPlayer, AircraftGetIsoPos(ptrPlayer->LockedAircraft) );
if(ptrPlayer->PadKeyReleased_Callback(PAD_SQUARE) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_SQUARE) == true)
{
ptrPlayer->LockTarget = false;
ptrPlayer->LockedAircraft = 0;
@ -1010,7 +1044,7 @@ void GameStateSelectTaxiwayRunway(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * pt
ptrPlayer->InvalidPath = true;
}
if(ptrPlayer->PadKeyReleased_Callback(PAD_TRIANGLE) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_TRIANGLE) == true)
{
// State exit.
ptrPlayer->SelectTaxiwayRunway = false;
@ -1019,7 +1053,7 @@ void GameStateSelectTaxiwayRunway(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * pt
ptrPlayer->WaypointIdx = 0;
ptrPlayer->LastWaypointIdx = 0;
}
else if(ptrPlayer->PadKeyReleased_Callback(PAD_CROSS) == true)
else if(ptrPlayer->PadKeySinglePress_Callback(PAD_CROSS) == true)
{
if(ptrPlayer->InvalidPath == false)
{
@ -1035,32 +1069,36 @@ void GameStateSelectTaxiwayRunway(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * pt
target_tile = GameLevelBuffer[ptrPlayer->Waypoints[ptrPlayer->LastWaypointIdx]];
if( (target_tile == TILE_RWY_START_1)
||
(target_tile == (TILE_RWY_START_1 | TILE_MIRROR_FLAG) )
||
(target_tile == TILE_RWY_START_2)
||
(target_tile == (TILE_RWY_START_2 | TILE_MIRROR_FLAG) ) )
switch(target_tile)
{
// TODO: Assign path to aircraft
AircraftFromFlightDataIndexAddTargets(ptrPlayer->LockedAircraft, ptrPlayer->Waypoints);
dprintf("Added these targets to aircraft %d:\n", ptrPlayer->LockedAircraft);
case TILE_RWY_START_1:
// Fall through
case TILE_RWY_START_1 | TILE_MIRROR_FLAG:
// Fall through
case TILE_RWY_START_2:
// Fall through
case TILE_RWY_START_2 | TILE_MIRROR_FLAG:
AircraftFromFlightDataIndexAddTargets(ptrPlayer->LockedAircraft, ptrPlayer->Waypoints);
dprintf("Added these targets to aircraft %d:\n", ptrPlayer->LockedAircraft);
for(i = 0; i < PLAYER_MAX_WAYPOINTS; i++)
{
dprintf("%d ",ptrPlayer->Waypoints[i]);
}
dprintf("\n");
ptrPlayer->SelectTaxiwayParking = false;
// Clear waypoints array.
memset(ptrPlayer->Waypoints, 0, sizeof(uint16_t) * PLAYER_MAX_WAYPOINTS);
ptrPlayer->WaypointIdx = 0;
ptrPlayer->LastWaypointIdx = 0;
ptrFlightData->State[ptrPlayer->LockedAircraft] = STATE_TAXIING;
break;
for(i = 0; i < PLAYER_MAX_WAYPOINTS; i++)
{
dprintf("%d ",ptrPlayer->Waypoints[i]);
}
dprintf("\n");
ptrPlayer->SelectTaxiwayParking = false;
// Clear waypoints array.
memset(ptrPlayer->Waypoints, 0, sizeof(uint16_t) * PLAYER_MAX_WAYPOINTS);
ptrPlayer->WaypointIdx = 0;
ptrPlayer->LastWaypointIdx = 0;
ptrFlightData->State[ptrPlayer->LockedAircraft] = STATE_TAXIING;
default:
break;
}
}
}
@ -1086,7 +1124,7 @@ void GameStateSelectTaxiwayParking(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * p
ptrPlayer->InvalidPath = true;
}
if(ptrPlayer->PadKeyReleased_Callback(PAD_TRIANGLE) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_TRIANGLE) == true)
{
// State exit.
ptrPlayer->SelectTaxiwayParking = false;
@ -1095,7 +1133,7 @@ void GameStateSelectTaxiwayParking(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * p
ptrPlayer->WaypointIdx = 0;
ptrPlayer->LastWaypointIdx = 0;
}
else if(ptrPlayer->PadKeyReleased_Callback(PAD_CROSS) == true)
else if(ptrPlayer->PadKeySinglePress_Callback(PAD_CROSS) == true)
{
if(ptrPlayer->InvalidPath == false)
{
@ -1158,11 +1196,11 @@ void GameStateSelectRunway(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFlight
ptrPlayer->LockTarget = false;
ptrPlayer->LockedAircraft = 0;
if(ptrPlayer->PadKeyReleased_Callback(PAD_TRIANGLE) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_TRIANGLE) == true)
{
ptrPlayer->SelectRunway = false;
}
else if(ptrPlayer->PadKeyReleased_Callback(PAD_CROSS) == true)
else if(ptrPlayer->PadKeySinglePress_Callback(PAD_CROSS) == true)
{
ptrPlayer->SelectRunway = false;
@ -1191,14 +1229,14 @@ void GameStateSelectRunway(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFlight
}
}
}
else if(ptrPlayer->PadKeyReleased_Callback(PAD_LEFT) == true)
else if(ptrPlayer->PadKeySinglePress_Callback(PAD_LEFT) == true)
{
if(ptrPlayer->SelectedRunway != 0)
{
ptrPlayer->SelectedRunway--;
}
}
else if(ptrPlayer->PadKeyReleased_Callback(PAD_RIGHT) == true)
else if(ptrPlayer->PadKeySinglePress_Callback(PAD_RIGHT) == true)
{
if(ptrPlayer->SelectedRunway < GAME_MAX_RUNWAYS)
{
@ -1248,7 +1286,7 @@ void GameSelectAircraftFromList(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrF
if(ptrPlayer->ShowAircraftData == true)
{
if(ptrPlayer->PadKeyReleased_Callback(PAD_CROSS) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_CROSS) == true)
{
if(ptrPlayer->ActiveAircraft != 0)
{
@ -1467,6 +1505,10 @@ void GameTargetsReached(uint8_t index)
FlightData.State[index] = STATE_LANDED;
break;
case STATE_TAXIING:
FlightData.State[index] = STATE_PARKED;
break;
default:
break;
}
@ -1492,6 +1534,11 @@ uint16_t GameGetTileFromIsoPosition(TYPE_ISOMETRIC_POS * IsoPos)
{
uint16_t tile;
if(IsoPos == NULL)
{
return 0;
}
if( (IsoPos->x < 0) || (IsoPos->y < 0) )
{
return GAME_INVALID_TILE_SELECTION; // Invalid XYZ position
@ -1613,8 +1660,20 @@ bool GamePathToTile(TYPE_PLAYER * ptrPlayer)
if(SystemContains_u16(temp_tile, ptrPlayer->Waypoints, PLAYER_MAX_WAYPOINTS) == false)
{
for(i = 0; i < GAME_MAX_AIRCRAFT; i++)
{
if(temp_tile == AircraftGetTileFromFlightDataIndex(i))
{
return false; // Check pending!
}
}
GamePlayerAddWaypoint_Ex(ptrPlayer, temp_tile);
}
else
{
return false; // Tile is already included in the list of temporary tiles?
}
}
while( (y_diff--) > 0)
@ -1631,8 +1690,21 @@ bool GamePathToTile(TYPE_PLAYER * ptrPlayer)
if(SystemContains_u16(temp_tile, ptrPlayer->Waypoints, PLAYER_MAX_WAYPOINTS) == false)
{
for(i = 0; i < GAME_MAX_AIRCRAFT; i++)
{
if(temp_tile == AircraftGetTileFromFlightDataIndex(i))
{
return false; // Check pending!
}
}
GamePlayerAddWaypoint_Ex(ptrPlayer, temp_tile);
}
else
{
// TEST - Check pending!
return false; // Tile is already included in the list of temporary tiles?
}
}
}
else
@ -1651,8 +1723,21 @@ bool GamePathToTile(TYPE_PLAYER * ptrPlayer)
if(SystemContains_u16(temp_tile, ptrPlayer->Waypoints, PLAYER_MAX_WAYPOINTS) == false)
{
for(i = 0; i < GAME_MAX_AIRCRAFT; i++)
{
if(temp_tile == AircraftGetTileFromFlightDataIndex(i))
{
return false; // Check pending!
}
}
GamePlayerAddWaypoint_Ex(ptrPlayer, temp_tile);
}
else
{
// TEST - Check pending!
return false; // Tile is already included in the list of temporary tiles?
}
}
while( (x_diff--) > 0)
@ -1669,8 +1754,21 @@ bool GamePathToTile(TYPE_PLAYER * ptrPlayer)
if(SystemContains_u16(temp_tile, ptrPlayer->Waypoints, PLAYER_MAX_WAYPOINTS) == false)
{
for(i = 0; i < GAME_MAX_AIRCRAFT; i++)
{
if(temp_tile == AircraftGetTileFromFlightDataIndex(i))
{
return false; // Check pending!
}
}
GamePlayerAddWaypoint_Ex(ptrPlayer, temp_tile);
}
else
{
// TEST - Check pending!
return false; // Tile is already included in the list of temporary tiles?
}
}
}

View File

@ -44,5 +44,6 @@ uint8_t GameGetLevelColumns(void);
fix16_t GameGetXFromTile(uint16_t tile);
fix16_t GameGetYFromTile(uint16_t tile);
void GameTargetsReached(uint8_t index);
uint16_t GameGetTileFromIsoPosition(TYPE_ISOMETRIC_POS * IsoPos);
#endif //__GAME_HEADER__

View File

@ -336,7 +336,7 @@ bool GameGuiPauseDialog(TYPE_PLAYER * ptrPlayer)
do
{
if(ptrPlayer->PadKeyReleased_Callback(PAD_CROSS) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_CROSS) == true)
{
return true;
}
@ -347,7 +347,7 @@ bool GameGuiPauseDialog(TYPE_PLAYER * ptrPlayer)
GfxDrawScene_Slow();
}while(ptrPlayer->PadKeyReleased_Callback(PAD_START) == false);
}while(ptrPlayer->PadKeySinglePress_Callback(PAD_START) == false);
return false;
}
@ -388,7 +388,7 @@ void GameGuiActiveAircraftPage(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFl
if(ptrPlayer->ShowAircraftData == true)
{
if(ptrPlayer->PadKeyReleased_Callback(PAD_DOWN) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_DOWN) == true)
{
if( ( (ptrPlayer->SelectedAircraft + 1) < ptrPlayer->ActiveAircraft)
&&
@ -398,7 +398,7 @@ void GameGuiActiveAircraftPage(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFl
}
}
if(ptrPlayer->PadKeyReleased_Callback(PAD_UP) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_UP) == true)
{
if(ptrPlayer->SelectedAircraft > ( (ptrPlayer->FlightDataPage) * GAME_GUI_AIRCRAFT_DATA_MAX_PAGE) )
{
@ -406,7 +406,7 @@ void GameGuiActiveAircraftPage(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFl
}
}
if(ptrPlayer->PadKeyReleased_Callback(PAD_RIGHT) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_RIGHT) == true)
{
if(ptrPlayer->ActiveAircraft > (GAME_GUI_AIRCRAFT_DATA_MAX_PAGE * (ptrPlayer->FlightDataPage + 1) ) )
{
@ -416,7 +416,7 @@ void GameGuiActiveAircraftPage(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFl
}
}
if(ptrPlayer->PadKeyReleased_Callback(PAD_LEFT) == true)
if(ptrPlayer->PadKeySinglePress_Callback(PAD_LEFT) == true)
{
if(ptrPlayer->FlightDataPage != 0)
{
@ -544,7 +544,7 @@ void GameGuiAircraftList(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFlightDa
{
FontPrintText( &SmallFont,
AIRCRAFT_DATA_GSGPOLY4_X0 +
( (AIRCRAFT_DATA_GSGPOLY4_X1 - AIRCRAFT_DATA_GSGPOLY4_X0) >> 1),
( (AIRCRAFT_DATA_GSGPOLY4_X1 - AIRCRAFT_DATA_GSGPOLY4_X0) >> 2),
AIRCRAFT_DATA_GSGPOLY4_Y0 +
( (AIRCRAFT_DATA_GSGPOLY4_Y2 - AIRCRAFT_DATA_GSGPOLY4_Y0) >> 1),
"No flights!" );
@ -696,25 +696,32 @@ void GameGuiShowAircraftData(TYPE_PLAYER * ptrPlayer, TYPE_FLIGHT_DATA * ptrFlig
{
case STATE_FINAL:
FontPrintText( &SmallFont,
AIRCRAFT_DATA_DIRECTION_X + 64,
AIRCRAFT_DATA_DIRECTION_X + 88,
AIRCRAFT_DATA_DIRECTION_Y + (AIRCRAFT_DATA_FLIGHT_GSGPOLY4_H * j),
"Landing" );
break;
case STATE_TAXIING:
FontPrintText( &SmallFont,
AIRCRAFT_DATA_DIRECTION_X + 64,
AIRCRAFT_DATA_DIRECTION_X + 88,
AIRCRAFT_DATA_DIRECTION_Y + (AIRCRAFT_DATA_FLIGHT_GSGPOLY4_H * j),
"Taxiing" );
break;
case STATE_LANDED:
FontPrintText( &SmallFont,
AIRCRAFT_DATA_DIRECTION_X + 64,
AIRCRAFT_DATA_DIRECTION_X + 88,
AIRCRAFT_DATA_DIRECTION_Y + (AIRCRAFT_DATA_FLIGHT_GSGPOLY4_H * j),
"Arrived" );
break;
case STATE_PARKED:
FontPrintText( &SmallFont,
AIRCRAFT_DATA_DIRECTION_X + 88,
AIRCRAFT_DATA_DIRECTION_Y + (AIRCRAFT_DATA_FLIGHT_GSGPOLY4_H * j),
"Parked" );
break;
default:
break;
}

View File

@ -159,6 +159,7 @@ typedef struct
bool (*PadKeyPressed_Callback)(unsigned short);
bool (*PadKeyReleased_Callback)(unsigned short);
bool (*PadKeySinglePress_Callback)(unsigned short);
bool (*PadDirectionKeyPressed_Callback)(void);
TYPE_CAMERA Camera;
}TYPE_PLAYER;

View File

@ -13,6 +13,7 @@
#define UPLOAD_IMAGE_FLAG 1
#define MAX_LUMINANCE 0xFF
#define ROTATE_BIT_SHIFT 12
#define GPUSTAT (*(unsigned int*)0x1F801814)
/* *************************************
* Structs and enums
@ -87,7 +88,6 @@ void GfxSwapBuffers(void)
GsSetDispEnv(&DispEnv);
GsSetDrawEnv(&DrawEnv);
}
}
@ -122,34 +122,20 @@ void GfxDrawScene_Fast(void)
GsDrawList();
}
bool GfxReadyForDMATransfer(void)
{
return (GPUSTAT & 1<<28);
}
void GfxDrawScene(void)
{
while( (SystemRefreshNeeded() == false)
||
(GsIsDrawing() == true)
||
(SystemDMAReady() == false) );
(GfxIsGPUBusy() == true) );
GfxDrawScene_Fast();
if(UpdatePads() == false)
{
SystemSetEmergencyMode(true);
}
else
{
SystemSetEmergencyMode(false);
}
SystemRunTimers();
SystemUserTimersHandler();
SystemDisableScreenRefresh();
MemCardHandler();
SystemCheckStack();
SystemCyclicHandler();
}
void GfxDrawScene_Slow(void)
@ -283,7 +269,7 @@ int GfxRotateFromDegrees(int deg)
bool GfxIsGPUBusy(void)
{
return (GsIsDrawing() || gfx_busy || SystemDMABusy() );
return (GsIsDrawing() || gfx_busy || (GfxReadyForDMATransfer() == false) );
}
bool GfxSpriteFromFile(char * fname, GsSprite * spr)
@ -416,6 +402,8 @@ void GfxDrawButton(short x, short y, unsigned short btn)
void GfxSaveDisplayData(GsSprite *spr)
{
while(GfxIsGPUBusy() == true);
MoveImage( DispEnv.x,
DispEnv.y,
GFX_SECOND_DISPLAY_X,
@ -524,3 +512,40 @@ TYPE_ISOMETRIC_POS GfxCartesianToIsometric(TYPE_CARTESIAN_POS * ptrCartPos)
return IsoPos;
}
void GfxSetSplitScreen(uint8_t playerIndex)
{
switch(playerIndex)
{
case 0:
// PLAYER_ONE
DrawEnv.x = 0;
DrawEnv.w = X_SCREEN_RESOLUTION >> 1;
break;
case 1:
// PLAYER_TWO
DrawEnv.x = X_SCREEN_RESOLUTION >> 1;
DrawEnv.w = X_SCREEN_RESOLUTION >> 1;
break;
default:
break;
}
dprintf("Player idx = %d, x = %d, w = %d\n",
playerIndex,
DrawEnv.x,
DrawEnv.w);
GsSetDrawEnv(&DrawEnv);
}
void GfxDisableSplitScreen(void)
{
DrawEnv.x = 0;
DrawEnv.w = X_SCREEN_RESOLUTION;
GsSetDrawEnv(&DrawEnv);
}

View File

@ -32,43 +32,73 @@
void GfxInitDrawEnv(void);
void GfxInitDispEnv(void);
void GfxSetPrimitiveList(void);
// Renders new scene. Use this function unless you know what you are doing!
void GfxDrawScene(void);
// Blocking version. Calls GfxDrawScene() and then adds a while(GfxIsBusy() )
// after it.
void GfxDrawScene_Slow(void);
// Only renders screen and does not update any pad data or timer data.
// To be used in ISR!
void GfxDrawScene_Fast(void);
// Repotedly, tells is GPU is ready for a DMA transfer.
bool GfxReadyForDMATransfer(void);
// Fills a GsSprite structure with information from a TIM file.
bool GfxSpriteFromFile(char * fname, GsSprite * spr);
// Reportedly, loads CLUT data from a TIM image (image data is discarded)
bool GfxCLUTFromFile(char * fname);
// Returns true if current object is within screen limits, false otherwise.
bool GfxIsInsideScreenArea(short x, short y, short w, short h);
// Function overload for GsSprite structures.
bool GfxIsSpriteInsideScreenArea(GsSprite * spr);
// Used to know whether GPU operation can be done.
bool GfxIsGPUBusy(void);
// Draws a sprite on screen. First, it checks whether sprite is inside
// screen limits.
void GfxSortSprite(GsSprite * spr);
uint8_t GfxGetGlobalLuminance(void);
void GfxSetGlobalLuminance(uint8_t value);
void GfxIncreaseGlobalLuminance(int8_t step);
int GfxRotateFromDegrees(int deg);
void GfxDrawButton(short x, short y, unsigned short btn);
// Sends current display data on a specific VRAM section and fills
// sprite structure pointed to by "spr".
void GfxSaveDisplayData(GsSprite *spr);
TYPE_CARTESIAN_POS GfxIsometricToCartesian(TYPE_ISOMETRIC_POS * ptrIsoPos);
// Function overload for fixed-point 16.16 data type.
TYPE_CARTESIAN_POS GfxIsometricFix16ToCartesian(TYPE_ISOMETRIC_FIX16_POS * ptrIso16Pos);
// Transforms cartesian position to isometric position. Z axis is assumed to be zero!
TYPE_ISOMETRIC_POS GfxCartesianToIsometric(TYPE_CARTESIAN_POS * ptrCartPos);
// Fills GsSprite structure pointed to by "spr" with texture page and U/V
// offset data given a position in VRAM.
bool GfxTPageOffsetFromVRAMPosition(GsSprite * spr, short x, short y);
void GfxSetSplitScreen(uint8_t playerIndex);
void GfxDisableSplitScreen(void);
// Switches between true and false every 1 exact second (used for flashing effects)
bool Gfx1HzFlash(void);
// Switches between true and false every 500 milliseconds (used for flashing effects)
bool Gfx2HzFlash(void);

View File

@ -47,7 +47,7 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $< -o $@ $(DEFINE) $(CC_FLAGS)
$(PROJECT).elf:
$(LINKER) Obj/*.o -o Exe/$(PROJECT).elf $(LIBS)
$(LINKER) Obj/*.o -o Exe/$(PROJECT).elf $(LIBS) -Wl,--gc-sections
$(PROJECT).exe:
$(ELF2EXE) Exe/$(PROJECT).elf Exe/$(PROJECT).exe $(ELF2EXE_FLAGS)

View File

@ -121,10 +121,13 @@ static char * MainMenuFiles[] = { "cdrom:\\DATA\\SPRITES\\MAINMENU.TIM;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" };
"cdrom:\\DATA\\SOUNDS\\SPINDISK.VAG;1"
#endif // NO_INTRO
};
static void * MainMenuDest[] = { (GsSprite*)&MenuSpr ,
(SsVag*)&BellSnd ,
@ -132,10 +135,13 @@ static void * MainMenuDest[] = { (GsSprite*)&MenuSpr ,
(GsSprite*)&PsxDisk ,
(GsSprite*)&PSXSDKIntroFont ,
(GsSprite*)&PSXButtons ,
#ifndef NO_INTRO
(GsSprite*)&GPL_Logo ,
(GsSprite*)&OpenSource_Logo ,
(SsVag*)&TrayClSnd ,
(SsVag*)&SpinDiskSnd };
(SsVag*)&SpinDiskSnd
#endif // NO_INTRO
};
static TYPE_MMBtn MainMenuBtn[MAIN_MENU_BUTTONS_MAX];
static MainMenuLevel menuLevel;
@ -254,12 +260,13 @@ void MainMenu(void)
while(1)
{
while(GfxIsGPUBusy() == true);
MainMenuButtonHandler();
switch(menuLevel)
{
case PLAY_OPTIONS_LEVEL:
while(SystemDMAReady() == false);
GsSortCls(0,0,40);
MainMenuDrawButton(&MainMenuBtn[PLAY_BUTTON_INDEX]);
@ -269,7 +276,6 @@ void MainMenu(void)
break;
case ONE_TWO_PLAYERS_LEVEL:
while(SystemDMAReady() == false);
GsSortCls(0,0,40);
MainMenuDrawButton(&MainMenuBtn[ONE_PLAYER_BUTTON_INDEX]);
@ -320,9 +326,9 @@ void MainMenuButtonHandler(void)
}
}
if( (PadOneKeyReleased(PAD_CROSS) == true)
if( (PadOneKeySinglePress(PAD_CROSS) == true)
||
(PadOneKeyReleased(PAD_TRIANGLE) == true) )
(PadOneKeySinglePress(PAD_TRIANGLE) == true) )
{
SfxPlaySound(&AcceptSnd);
}
@ -335,7 +341,7 @@ void MainMenuButtonHandler(void)
case ONE_TWO_PLAYERS_LEVEL:
max_buttons = MAIN_MENU_ONE_TWO_PLAYERS_LEVEL_BUTTONS;
if(PadOneKeyReleased(PAD_TRIANGLE) == true)
if(PadOneKeySinglePress(PAD_TRIANGLE) == true)
{
menuLevel = PLAY_OPTIONS_LEVEL;
MainMenuMinimumBtn = PLAY_BUTTON_INDEX;
@ -351,14 +357,14 @@ void MainMenuButtonHandler(void)
MainMenuBtn[previous_btn_selected].was_selected = MainMenuBtn[previous_btn_selected].selected;
MainMenuBtn[btn_selected].was_selected = MainMenuBtn[btn_selected].selected;
if(PadOneKeyReleased(PAD_LEFT) && (btn_selected > 0) )
if(PadOneKeySinglePress(PAD_LEFT) && (btn_selected > 0) )
{
MainMenuBtn[btn_selected].selected = false;
previous_btn_selected = btn_selected;
btn_selected--;
SfxPlaySound(&BellSnd);
}
else if(PadOneKeyReleased(PAD_RIGHT)
else if(PadOneKeySinglePress(PAD_RIGHT)
&&
(btn_selected < (max_buttons - 1 + MainMenuMinimumBtn) ) )
{
@ -379,7 +385,7 @@ void MainMenuButtonHandler(void)
btn_selected = (max_buttons - 1 + MainMenuMinimumBtn);
}
if(PadOneKeyReleased(PAD_CROSS) )
if(PadOneKeySinglePress(PAD_CROSS) )
{
if(menuLevel == ONE_TWO_PLAYERS_LEVEL)
{

View File

@ -177,6 +177,16 @@ bool PadTwoKeyPressed(unsigned short key)
return (bool)( pad2 & key );
}
bool PadOneKeySinglePress(unsigned short key)
{
return (bool)( !(previous_pad1 & key) && (pad1 & key) );
}
bool PadTwoKeySinglePress(unsigned short key)
{
return (bool)( !(previous_pad2 & key) && (pad2 & key) );
}
bool PadOneKeyRepeat(unsigned short key, uint8_t time)
{
uint8_t key_index = PadGetKeyIndex(key);

View File

@ -36,6 +36,9 @@ bool PadTwoKeyRepeat(unsigned short key, uint8_t time);
bool PadOneKeyReleased(unsigned short key);
bool PadTwoKeyReleased(unsigned short key);
bool PadOneKeySinglePress(unsigned short key);
bool PadTwoKeySinglePress(unsigned short key);
bool PadOneDirectionKeyPressed(void);
bool PadTwoDirectionKeyPressed(void);

View File

@ -14,6 +14,7 @@
#define END_STACK_PATTERN (uint32_t) 0x18022015
#define BEGIN_STACK_ADDRESS (uint32_t*) 0x801FFF00
#define STACK_SIZE 0x1000
#define I_MASK (*(unsigned int*)0x1F801074)
/* *************************************
* Local Prototypes
@ -21,6 +22,8 @@
static void SystemCheckTimer(bool * timer, uint64_t * last_timer, uint8_t step);
static void SystemSetStackPattern(void);
static void SystemEnableVBlankInterrupt(void);
static void SystemDisableVBlankInterrupt(void);
/* *************************************
* Local Variables
@ -41,16 +44,21 @@ static bool five_hundred_ms_timer;
//Emergency mode flag. Toggled on pad connected/disconnected
static bool emergency_mode;
//Critical section is entered (i.e.: when accessing fopen() or other BIOS functions
static bool system_busy;
static volatile bool system_busy;
//Timer array.
static TYPE_TIMER timer_array[SYSTEM_MAX_TIMERS];
/* *************************************
/* *******************************************************************
*
* @name: void SystemInit(void)
* @date: 19/05/2016
*
* @author: Xavier Del Campo
* @brief:
* *************************************/
*
* @brief: Calls main intialization routines.
*
* @remarks: To be called before main loop.
*
* *******************************************************************/
void SystemInit(void)
{
@ -97,6 +105,22 @@ void SystemInit(void)
StartRCnt(RCntCNT2);
}
/* *******************************************************************
*
* @name: void SystemInit(void)
*
* @author: Xavier Del Campo
*
* @brief:
* Calls srand() while avoiding multiple calls by setting internal
* variable rand_seed to true. Internal variable "global_timer" is
* used to generate the new seed.
*
* @remarks:
* It is recommended to call it once user has pressed any key.
*
* *******************************************************************/
void SystemSetRandSeed(void)
{
if(rand_seed == false)
@ -109,32 +133,81 @@ void SystemSetRandSeed(void)
}
}
/* *******************************************************************
*
* @name: bool SystemIsRandSeedSet(void)
*
* @author: Xavier Del Campo
*
* @brief:
* Reportedly, returns whether rand seed has already been set.
*
* @remarks:
*
* @return:
* Reportedly, returns whether rand seed has already been set.
*
* *******************************************************************/
bool SystemIsRandSeedSet(void)
{
return rand_seed;
}
bool SystemDMAReady(void)
{
return (*((unsigned int*)0x1F801814) & 1<<28);
}
bool SystemDMABusy(void)
{
return !SystemDMAReady();
}
/* *******************************************************************
*
* @name: bool SystemRefreshNeeded(void)
*
* @author: Xavier Del Campo
*
* @brief:
*
* @remarks:
*
* @return:
* Returns whether VSync flag has been enabled.
*
* *******************************************************************/
bool SystemRefreshNeeded(void)
{
return refresh_needed;
}
/* *******************************************************************
*
* @name: void ISR_SystemDefaultVBlank(void)
*
* @author: Xavier Del Campo
*
* @brief:
*
* @remarks:
* Called from VSync interrupt. Called 50 times a second in PAL mode,
* 60 times a second in NTSC mode.
*
* *******************************************************************/
void ISR_SystemDefaultVBlank(void)
{
refresh_needed = true;
SystemIncreaseGlobalTimer();
}
/* *******************************************************************
*
* @name: void SystemIncreaseGlobalTimer(void)
*
* @author: Xavier Del Campo
*
* @brief:
* Increases internal variable responsible for time handling.
*
* @remarks:
* Usually called from ISR_SystemDefaultVBlank().
*
* *******************************************************************/
void SystemIncreaseGlobalTimer(void)
{
global_timer++;
@ -201,6 +274,9 @@ bool SystemLoadFileToBuffer(char * fname, uint8_t * buffer, uint32_t szBuffer)
FILE *f;
int32_t size;
// Wait for possible previous operation from the GPU before entering this section.
while( (SystemIsBusy() == true) || (GfxIsGPUBusy() == true) );
if(fname == NULL)
{
dprintf("SystemLoadFile: NULL fname!\n");
@ -210,6 +286,9 @@ bool SystemLoadFileToBuffer(char * fname, uint8_t * buffer, uint32_t szBuffer)
memset(buffer,0,szBuffer);
system_busy = true;
SystemDisableVBlankInterrupt();
f = fopen(fname, "r");
if(f == NULL)
@ -219,7 +298,7 @@ bool SystemLoadFileToBuffer(char * fname, uint8_t * buffer, uint32_t szBuffer)
return false;
}
fseek(f, 0, SEEK_END);
fseek(f, 0, SEEK_END);
size = ftell(f);
@ -236,6 +315,8 @@ bool SystemLoadFileToBuffer(char * fname, uint8_t * buffer, uint32_t szBuffer)
fclose(f);
SystemEnableVBlankInterrupt();
system_busy = false;
dprintf("File \"%s\" loaded successfully!\n",fname);
@ -275,7 +356,7 @@ bool SystemGetEmergencyMode(void)
return emergency_mode;
}
bool SystemIsBusy(void)
volatile bool SystemIsBusy(void)
{
return system_busy;
}
@ -515,3 +596,35 @@ int32_t SystemIndexOf_U8(uint8_t value, uint8_t * array, uint32_t from, uint32_t
return -1;
}
void SystemCyclicHandler(void)
{
if(UpdatePads() == false)
{
SystemSetEmergencyMode(true);
}
else
{
SystemSetEmergencyMode(false);
}
SystemRunTimers();
SystemUserTimersHandler();
SystemDisableScreenRefresh();
MemCardHandler();
SystemCheckStack();
}
void SystemDisableVBlankInterrupt(void)
{
I_MASK &= ~(0x0001);
}
void SystemEnableVBlankInterrupt(void)
{
I_MASK |= (0x0001);
}

View File

@ -23,78 +23,108 @@
// Calls PSXSDK init routines
void SystemInit(void);
// Sets default VSync (only sets flag to true and increases global_timer)
void ISR_SystemDefaultVBlank(void);
// Calls srand() using current global_timer value as seed
void SystemSetRandSeed(void);
// Returns VSync flag value
bool SystemRefreshNeeded(void);
// Tells whether CPU->GPU DMA transfer is ready
bool SystemDMAReady(void);
// Tells whether CPU->GPU DMA transfer is busy
bool SystemDMABusy(void);
// Loads a file into system's internal buffer
bool SystemLoadFile(char *fname);
// Loads a file into desired buffer
bool SystemLoadFileToBuffer(char * fname, uint8_t * buffer, uint32_t szBuffer);
// Clears VSync flag after each frame
void SystemDisableScreenRefresh(void);
// Returns file buffer address
uint8_t * SystemGetBufferAddress(void);
// Tells whether srand() has been called using a pseudo-random value
bool SystemIsRandSeedSet(void);
// Stops program flow during X cycles
void SystemWaitCycles(uint32_t cycles);
// To be called from GfxDrawScene after each cycle
void SystemRunTimers(void);
// 1 cycle-length flag with a frequency of 1 Hz
bool System1SecondTick(void);
// 1 cycle-length flag with a frequency of 2 Hz
bool System500msTick(void);
// 1 cycle-length flag with a frequency of 10 Hz
bool System100msTick(void);
// Returns random value between given minimum and maximum values
uint32_t SystemRand(uint32_t min, uint32_t max);
// Increases global timer by 1 step
void SystemIncreaseGlobalTimer(void);
// Sets value to emergency mode flag
void SystemSetEmergencyMode(bool value);
// Returns emergency mode flag state
bool SystemGetEmergencyMode(void);
// (Experimental)
uint64_t SystemGetGlobalTimer(void);
// Returns whether critical section of code is being entered
bool SystemIsBusy(void);
volatile bool SystemIsBusy(void);
// Returns whether indicated value is contained inside buffer
bool SystemContains_u8(uint8_t value, uint8_t * buffer, size_t sz);
// Overload for uint16_t
bool SystemContains_u16(uint16_t value, uint16_t * buffer, size_t sz);
// Creates a timer instance wiht a determined value and associates it to a callback
// Once time expires, callback is automatically called right after GfxDrawScene().
TYPE_TIMER * SystemCreateTimer(uint32_t seconds, bool rf, void (*timer_callback)(void) );
// Reportedly, sets all timer data to zero.
void SystemResetTimers(void);
// To be called every cycle (i.e.: inside GfxDrawScene() ).
void SystemUserTimersHandler(void);
// Sets timer remaining time to initial value.
void SystemTimerRestart(TYPE_TIMER * timer);
// Flushes a timer pointed to by timer.
void SystemTimerRemove(TYPE_TIMER * timer);
// Compares two arrays of unsigned short type.
bool SystemArrayCompare(unsigned short * arr1, unsigned short * arr2, size_t sz);
// Prints stack pointer address using dprintf()
void SystemPrintStackPointerAddress(void);
// Checks if a 32-bit pattern set at the end of the stack has been
// accidentally modified by program flow.
void SystemCheckStack(void);
// Looks for string "str" inside a string array pointed to by "array".
// Returns index inside string array on success, -1 if not found.
int32_t SystemIndexOfStringArray(char * str, char ** array);
// Function overload for uint16_t data type.
int32_t SystemIndexOf_U16(uint16_t value, uint16_t * array, uint32_t sz);
// Function overload for uint8_t data type.
int32_t SystemIndexOf_U8(uint8_t value, uint8_t * array, uint32_t from, uint32_t sz);
void SystemCyclicHandler(void);
/* **************************************
* Global Variables *
* **************************************/

View File

@ -7,4 +7,4 @@
10:30
#Aircraft arrival (or departure) must be set relative to initial time, in HH:MM format.
ARRIVAL;PHX1002;40;00:05;0
DEPARTURE;PHX1000;100;00:05;2
DEPARTURE;PHX1000;100;00:05;19