aboutsummaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorXaviDCR92 <xavi.dcr@gmail.com>2017-05-01 23:05:51 +0200
committerXaviDCR92 <xavi.dcr@gmail.com>2017-05-01 23:05:51 +0200
commit83b4684d7cb9934371909b522d6daa0f16cc0396 (patch)
tree39fa1ca99061b12203dae50898a2b3dec3b5f276 /Source
parent8629c228db1fe1f206d409356ad75995060a0ca8 (diff)
downloadairport-83b4684d7cb9934371909b522d6daa0f16cc0396.tar.gz
* 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.
Diffstat (limited to 'Source')
-rw-r--r--Source/Aircraft.c51
-rw-r--r--Source/Aircraft.h5
-rw-r--r--Source/Game.c208
-rw-r--r--Source/Game.h1
-rw-r--r--Source/GameGui.c27
-rw-r--r--Source/GameStructures.h1
-rw-r--r--Source/Gfx.c71
-rw-r--r--Source/Gfx.h30
-rw-r--r--Source/Makefile2
-rw-r--r--Source/Menu.c26
-rw-r--r--Source/Pad.c10
-rw-r--r--Source/Pad.h3
-rw-r--r--Source/System.c145
-rw-r--r--Source/System.h40
14 files changed, 485 insertions, 135 deletions
diff --git a/Source/Aircraft.c b/Source/Aircraft.c
index aed8793..5ddc4b8 100644
--- a/Source/Aircraft.c
+++ b/Source/Aircraft.c
@@ -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)
+{
+ TYPE_ISOMETRIC_POS isoPos = AircraftGetIsoPos(index);
+ return GameGetTileFromIsoPosition(&isoPos);
+}
+
+TYPE_AIRCRAFT_DATA* AircraftFromFlightDataIndex(uint8_t index)
{
- return &AircraftData[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)
diff --git a/Source/Aircraft.h b/Source/Aircraft.h
index 2c64422..d941a13 100644
--- a/Source/Aircraft.h
+++ b/Source/Aircraft.h
@@ -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 );
diff --git a/Source/Game.c b/Source/Game.c
index 88d2b75..bb7e6c3 100644
--- a/Source/Game.c
+++ b/Source/Game.c
@@ -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);
+
+ GameGuiAircraftNotificationRequest(&FlightData);
- for(i = 0; i < MAX_PLAYERS ; i++)
- {
- GameGuiAircraftList(&PlayerData[i], &FlightData);
+ GameGuiBubble(&FlightData);
+
+ GameGuiClock(GameHour,GameMinutes);
+
+ /*for(i = 0; i < MAX_PLAYERS ; i++)
+ {*/
+ GameGuiAircraftList(&PlayerData[i], &FlightData);
+ //}
+
+ GfxDrawScene_Fast();
+ while(GfxIsGPUBusy() == true);
+ }
}
- 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);
-
- 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;
+ 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;
- 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?
+ }
}
}
diff --git a/Source/Game.h b/Source/Game.h
index 8bccf63..712c404 100644
--- a/Source/Game.h
+++ b/Source/Game.h
@@ -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__
diff --git a/Source/GameGui.c b/Source/GameGui.c
index 47d6c37..dc13e6c 100644
--- a/Source/GameGui.c
+++ b/Source/GameGui.c
@@ -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;
}
diff --git a/Source/GameStructures.h b/Source/GameStructures.h
index 4baa03a..3efe573 100644
--- a/Source/GameStructures.h
+++ b/Source/GameStructures.h
@@ -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;
diff --git a/Source/Gfx.c b/Source/Gfx.c
index a976b00..329ba19 100644
--- a/Source/Gfx.c
+++ b/Source/Gfx.c
@@ -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);
+}
diff --git a/Source/Gfx.h b/Source/Gfx.h
index b9984ee..68c0f5b 100644
--- a/Source/Gfx.h
+++ b/Source/Gfx.h
@@ -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);
diff --git a/Source/Makefile b/Source/Makefile
index 3e96e0b..96c3f7d 100644
--- a/Source/Makefile
+++ b/Source/Makefile
@@ -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)
diff --git a/Source/Menu.c b/Source/Menu.c
index 411c276..32d0e45 100644
--- a/Source/Menu.c
+++ b/Source/Menu.c
@@ -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)
{
diff --git a/Source/Pad.c b/Source/Pad.c
index 7fc08a2..2a84304 100644
--- a/Source/Pad.c
+++ b/Source/Pad.c
@@ -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);
diff --git a/Source/Pad.h b/Source/Pad.h
index 3e0ff69..5e5588b 100644
--- a/Source/Pad.h
+++ b/Source/Pad.h
@@ -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);
diff --git a/Source/System.c b/Source/System.c
index b158004..833c80f 100644
--- a/Source/System.c
+++ b/Source/System.c
@@ -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);
+}
diff --git a/Source/System.h b/Source/System.h
index cbb22ea..b6ed48b 100644
--- a/Source/System.h
+++ b/Source/System.h
@@ -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 *
* **************************************/