aboutsummaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorXaviDCR92 <xavi.dcr@gmail.com>2018-01-02 06:43:54 +0100
committerXaviDCR92 <xavi.dcr@gmail.com>2018-01-02 06:43:54 +0100
commitb094335404446183954eb1ccaba33f5f4888eacf (patch)
tree14e87f4a12f174dc66cad0ab4010efb2858fdd12 /Source
parente53faffaead15f0aa6c323d0b0dbed05eaf5b4d4 (diff)
downloadairport-b094335404446183954eb1ccaba33f5f4888eacf.tar.gz
* Aircraft.c: taxiing speed has been doubled.
* Game.c: GameRenderLevel() renamed to GameRenderTerrain(). * Game.c: GameRenderTerrainPrecalculations() has been created to perform some calculations which are stored in tables to be then looked up by GameRenderTerrain(). This should save us some calculation time during rendering process. * Camera.c: added new CameraApplyCoordinatesToCartesianPos() prototype. * GameGui.c: AircraftDataGPoly4 RGB data is now only calculated on startup.
Diffstat (limited to 'Source')
-rw-r--r--Source/Aircraft.c2
-rw-r--r--Source/Camera.c10
-rw-r--r--Source/Camera.h5
-rw-r--r--Source/Exe/AIRPORT.elfbin327820 -> 330072 bytes
-rw-r--r--Source/Exe/AIRPORT.isobin1474560 -> 1478656 bytes
-rw-r--r--Source/Game.c422
-rw-r--r--Source/Game.h11
-rw-r--r--Source/GameGui.c34
-rw-r--r--Source/GameStructures.h20
-rw-r--r--Source/Gfx.c16
-rw-r--r--Source/Gfx.h8
-rw-r--r--Source/Makefile2
-rw-r--r--Source/MapEditor/MapEditor.pro.user2
-rw-r--r--Source/MapEditor/settings.ini2
-rw-r--r--Source/Menu.c189
15 files changed, 488 insertions, 235 deletions
diff --git a/Source/Aircraft.c b/Source/Aircraft.c
index 7ecd8af..87685ba 100644
--- a/Source/Aircraft.c
+++ b/Source/Aircraft.c
@@ -65,7 +65,7 @@ static void* GameFileDest[] = { (GsSprite*)&ArrowSpr };
static uint8_t AircraftFlightDataIdx_HashTable[GAME_MAX_AIRCRAFT];
static const fix16_t AircraftSpeedsTable[] = { [AIRCRAFT_SPEED_IDLE] = 0,
- [AIRCRAFT_SPEED_GROUND] = 0x6666,
+ [AIRCRAFT_SPEED_GROUND] = 0x9999,
[AIRCRAFT_SPEED_TAKEOFF] = 0x20000,
[AIRCRAFT_SPEED_FINAL] = 0x10000,
[AIRCRAFT_SPEED_FINAL_Z] = 0x4000 };
diff --git a/Source/Camera.c b/Source/Camera.c
index f55ee4f..d9cd26e 100644
--- a/Source/Camera.c
+++ b/Source/Camera.c
@@ -40,18 +40,24 @@ void CameraInit(TYPE_PLAYER* ptrPlayer)
Camera_Max_Y_Offset = GameGetLevelColumns() * TILE_SIZE_H;
}
-void CameraApplyCoordinatesToSprite(TYPE_PLAYER* ptrPlayer, GsSprite * spr)
+void CameraApplyCoordinatesToSprite(TYPE_PLAYER* ptrPlayer, GsSprite* spr)
{
spr->x += (short)ptrPlayer->Camera.X_Offset;
spr->y += (short)ptrPlayer->Camera.Y_Offset;
}
-void CameraApplyCoordinatesToRectangle(TYPE_PLAYER* ptrPlayer, GsRectangle * rect)
+void CameraApplyCoordinatesToRectangle(TYPE_PLAYER* ptrPlayer, GsRectangle* rect)
{
rect->x += (short)ptrPlayer->Camera.X_Offset;
rect->y += (short)ptrPlayer->Camera.Y_Offset;
}
+void CameraApplyCoordinatesToCartesianPos(TYPE_PLAYER* ptrPlayer, TYPE_CARTESIAN_POS* pos)
+{
+ pos->x += (short)ptrPlayer->Camera.X_Offset;
+ pos->y += (short)ptrPlayer->Camera.Y_Offset;
+}
+
void CameraUpdateSpeed(TYPE_PLAYER* ptrPlayer)
{
if (ptrPlayer->PadDirectionKeyPressed_Callback() != false)
diff --git a/Source/Camera.h b/Source/Camera.h
index 9d958ed..d1b4d29 100644
--- a/Source/Camera.h
+++ b/Source/Camera.h
@@ -15,8 +15,9 @@
* *************************************/
void CameraInit(TYPE_PLAYER* ptrPlayer);
void CameraHandler(TYPE_PLAYER* ptrPlayer);
-void CameraApplyCoordinatesToSprite(TYPE_PLAYER* ptrPlayer, GsSprite * spr);
-void CameraApplyCoordinatesToRectangle(TYPE_PLAYER* ptrPlayer, GsRectangle * rect);
+void CameraApplyCoordinatesToSprite(TYPE_PLAYER* ptrPlayer, GsSprite* spr);
+void CameraApplyCoordinatesToRectangle(TYPE_PLAYER* ptrPlayer, GsRectangle* rect);
+void CameraApplyCoordinatesToCartesianPos(TYPE_PLAYER* ptrPlayer, TYPE_CARTESIAN_POS* pos);
TYPE_ISOMETRIC_POS CameraGetIsoPos(TYPE_PLAYER* ptrPlayer);
void CameraMoveToIsoPos(TYPE_PLAYER* ptrPlayer, TYPE_ISOMETRIC_POS IsoPos);
diff --git a/Source/Exe/AIRPORT.elf b/Source/Exe/AIRPORT.elf
index e6ed20b..bae28c4 100644
--- a/Source/Exe/AIRPORT.elf
+++ b/Source/Exe/AIRPORT.elf
Binary files differ
diff --git a/Source/Exe/AIRPORT.iso b/Source/Exe/AIRPORT.iso
index 763da1a..7e7b4cf 100644
--- a/Source/Exe/AIRPORT.iso
+++ b/Source/Exe/AIRPORT.iso
Binary files differ
diff --git a/Source/Game.c b/Source/Game.c
index 4389e5f..866c6ed 100644
--- a/Source/Game.c
+++ b/Source/Game.c
@@ -17,7 +17,6 @@
* Defines
* *************************************/
-#define GAME_MAX_MAP_SIZE 0x400
#define GAME_MAX_RUNWAYS 16
#define GAME_MAX_AIRCRAFT_PER_TILE 4
#define FLIGHT_DATA_INVALID_IDX 0xFF
@@ -60,6 +59,12 @@ typedef struct t_buildingdata
short v; // Building Y offset inside texture page
}TYPE_BUILDING_DATA;
+typedef struct t_GameLevelBuffer_UVData
+{
+ short u;
+ short v;
+}TYPE_TILE_UV_DATA;
+
enum
{
MOUSE_W = 8,
@@ -150,9 +155,10 @@ enum
* Local Prototypes
* *************************************/
-static void GameInit(void);
+static void GameInit(TYPE_GAME_CONFIGURATION* pGameCfg);
+static void GameInitTileUVTable(void);
static bool GameExit(void);
-static void GameLoadLevel(void);
+static void GameLoadLevel(const char* path);
static bool GamePause(void);
static void GameFinished(uint8_t i);
static void GameEmergencyMode(void);
@@ -161,7 +167,8 @@ static void GamePlayerHandler(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFligh
static void GamePlayerAddWaypoint(TYPE_PLAYER* ptrPlayer);
static void GamePlayerAddWaypoint_Ex(TYPE_PLAYER* ptrPlayer, uint16_t tile);
static void GameGraphics(void);
-static void GameRenderLevel(TYPE_PLAYER* ptrPlayer);
+static void GameRenderTerrainPrecalculations(TYPE_PLAYER* ptrPlayer);
+static void GameRenderTerrain(TYPE_PLAYER* ptrPlayer);
static void GameClock(void);
static void GameClockFlights(uint8_t i);
static void GameAircraftState(uint8_t i);
@@ -226,6 +233,8 @@ static uint8_t GameAircraftCollisionIdx;
static TYPE_BUILDING_DATA GameBuildingData[MAX_BUILDING_ID];
static uint8_t GameAircraftTilemap[GAME_MAX_MAP_SIZE][GAME_MAX_AIRCRAFT_PER_TILE];
+static TYPE_TILE_UV_DATA GameLevelBuffer_UVData[GAME_MAX_MAP_SIZE];
+
// Radio chatter
static SsVag ApproachSnds[MAX_RADIO_CHATTER_SOUNDS];
static SsVag TowerFinalSnds[MAX_RADIO_CHATTER_SOUNDS];
@@ -263,10 +272,8 @@ static void* GameFileDest[] = { (GsSprite*)&GameTilesetSpr ,
(GsSprite*)&CityBg1Spr ,
(SsVag*)&BeepSnd };
-static const char* GamePlt[] = { "cdrom:\\DATA\\LEVELS\\LEVEL2.PLT;1" };
static void* GamePltDest[] = {(TYPE_FLIGHT_DATA*)&FlightData };
-static char* GameLevelList[] = {"cdrom:\\DATA\\LEVELS\\LEVEL2.LVL;1"};
static uint16_t GameLevelBuffer[GAME_MAX_MAP_SIZE];
static uint8_t GameLevelColumns;
@@ -286,7 +293,7 @@ bool GameFinishedFlag;
/* ***************************************************************************************
*
- * @name: void Game(bool two_players)
+ * @name: void Game(TYPE_GAME_CONFIGURATION* pGameCfg)
*
* @author: Xavier Del Campo
*
@@ -297,10 +304,10 @@ bool GameFinishedFlag;
*
* ***************************************************************************************/
-void Game(bool two_players)
+void Game(TYPE_GAME_CONFIGURATION* pGameCfg)
{
- TwoPlayersActive = two_players;
- GameInit();
+ TwoPlayersActive = pGameCfg->TwoPlayers;
+ GameInit(pGameCfg);
while (1)
{
@@ -434,7 +441,7 @@ bool GamePause(void)
*
* ***************************************************************************************/
-void GameInit(void)
+void GameInit(TYPE_GAME_CONFIGURATION* pGameCfg)
{
uint8_t i;
uint32_t track;
@@ -452,20 +459,20 @@ void GameInit(void)
sizeof(GameFileDest) /sizeof(void*) );
}
- LoadMenu( GamePlt,
+ LoadMenu( &pGameCfg->PLTPath,
GamePltDest,
- sizeof(GamePlt) / sizeof(GamePlt[0]),
+ sizeof(char),
sizeof(GamePltDest) / sizeof(GamePltDest[0]) );
- GameLoadLevel();
+ GameLoadLevel(pGameCfg->LVLPath);
GameGuiInit();
GameBuildingsInit();
- memset(GameRwy,0,GAME_MAX_RUNWAYS * sizeof(uint16_t) );
+ memset(GameRwy, 0, GAME_MAX_RUNWAYS * sizeof(uint16_t) );
- memset(GameUsedRwy,0,GAME_MAX_RUNWAYS * sizeof(uint16_t) );
+ memset(GameUsedRwy, 0, GAME_MAX_RUNWAYS * sizeof(uint16_t) );
PlayerData[PLAYER_ONE].Active = true;
PlayerData[PLAYER_ONE].PadKeyPressed_Callback = &PadOneKeyPressed;
@@ -485,6 +492,7 @@ void GameInit(void)
PlayerData[PLAYER_ONE].Unboarding = false;
memset(PlayerData[PLAYER_ONE].UnboardingSequence, 0, GAME_MAX_SEQUENCE_KEYS * sizeof(unsigned short) );
+ memset(PlayerData[PLAYER_ONE].TileData, 0, GAME_MAX_MAP_SIZE * sizeof(TYPE_TILE_DATA));
PlayerData[PLAYER_TWO].Active = TwoPlayersActive? true : false;
@@ -507,6 +515,7 @@ void GameInit(void)
PlayerData[PLAYER_TWO].Unboarding = false;
memset(PlayerData[PLAYER_TWO].UnboardingSequence, 0, GAME_MAX_SEQUENCE_KEYS * sizeof(unsigned short) );
+ memset(PlayerData[PLAYER_TWO].TileData, 0, GAME_MAX_MAP_SIZE * sizeof(TYPE_TILE_DATA));
// On 2-player mode, one player controls departure flights and
// other player controls arrival flights.
@@ -566,6 +575,8 @@ void GameInit(void)
GameFinishedFlag = false;
+ GameInitTileUVTable();
+
AircraftInit();
LoadMenuEnd();
@@ -858,8 +869,6 @@ void GameGetAircraftTilemap(uint8_t i)
}
GameAircraftTilemap[tileNr][j] = i;
-
- //Serial_printf("GameAircraftTileMap[%d][%d] = %d\n", tileNr, j, GameAircraftTilemap[tileNr][j]);
}
/* ***************************************************************************************
@@ -953,6 +962,7 @@ void GamePlayerHandler(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFlightData)
GameStateSelectTaxiwayParking(ptrPlayer, ptrFlightData);
GameStateShowAircraft(ptrPlayer, ptrFlightData);
CameraHandler(ptrPlayer);
+ GameRenderTerrainPrecalculations(ptrPlayer);
GameGuiActiveAircraftPage(ptrPlayer, ptrFlightData);
GameSelectAircraftFromList(ptrPlayer, ptrFlightData);
}
@@ -1095,7 +1105,7 @@ void GameGraphics(void)
// Then ground tiles must be rendered.
- GameRenderLevel(ptrPlayer);
+ GameRenderTerrain(ptrPlayer);
// Ground tiles are now rendered. Now, depending on building/aircraft
// positions, determine in what order they should be rendered.
@@ -1426,7 +1436,7 @@ void GameRenderBuildingAircraft(TYPE_PLAYER* ptrPlayer)
*
* *******************************************************************/
-void GameLoadLevel(void)
+void GameLoadLevel(const char* path)
{
uint8_t i = 0;
uint8_t* ptrBuffer;
@@ -1437,7 +1447,7 @@ void GameLoadLevel(void)
// Header treatment (magic number, map size, map title...) should be done
// using System's file buffer.
- if (SystemLoadFile(GameLevelList[0]) == false)
+ if (SystemLoadFile((char*)path) == false)
{
return;
}
@@ -1601,9 +1611,25 @@ void GameAircraftState(uint8_t i)
}
}
+void GameInitTileUVTable(void)
+{
+ uint16_t i;
+
+ memset(GameLevelBuffer_UVData, 0, sizeof(GameLevelBuffer_UVData));
+
+ for (i = 0 ; i < GameLevelSize; i++)
+ {
+ uint8_t CurrentTile = (uint8_t)(GameLevelBuffer[i] & 0x007F); // Remove building data
+ // and mirror flag.
+
+ GameLevelBuffer_UVData[i].u = (short)(CurrentTile % COLUMNS_PER_TILESET) << TILE_SIZE_BIT_SHIFT;
+ GameLevelBuffer_UVData[i].v = (short)(CurrentTile / COLUMNS_PER_TILESET) * TILE_SIZE_H;
+ }
+}
+
/* ******************************************************************************************
*
- * @name: void GameRenderLevel(TYPE_PLAYER* ptrPlayer)
+ * @name: void GameRenderTerrainPrecalculations(TYPE_PLAYER* ptrPlayer)
*
* @author: Xavier Del Campo
*
@@ -1611,43 +1637,41 @@ void GameAircraftState(uint8_t i)
* TYPE_PLAYER* ptrPlayer:
* Pointer to a player structure
*
- *
* @brief:
- * Draws all tiles depending on GameLevelBuffer configuration.
+ * Reads current player states, precalculates RGB/XY/visibilty data and saves it into
+ * lookup tables which will be then used on GameRenderTerrain().
*
* @remarks:
* Tiles are usually rendered with normal RGB values unless parking/runway is busy
* or ptrPlayer->InvalidPath != false.
*
* ******************************************************************************************/
-void GameRenderLevel(TYPE_PLAYER* ptrPlayer)
+void GameRenderTerrainPrecalculations(TYPE_PLAYER* ptrPlayer)
{
- uint16_t i;
- uint8_t columns = 0;
- uint8_t rows = 0;
- bool flip_id;
- bool used_rwy = SystemContains_u16(ptrPlayer->RwyArray[0], GameUsedRwy, GAME_MAX_RUNWAYS);
- uint8_t aux_id;
- GsSprite * ptrTileset;
- unsigned char rwy_sine = SystemGetSineValue();
- TYPE_ISOMETRIC_POS tileIsoPos;
- TYPE_CARTESIAN_POS tileCartPos;
+ uint16_t i;
+ uint8_t rows = 0;
+ uint8_t columns = 0;
+ unsigned char rwy_sine = SystemGetSineValue();
+ bool used_rwy = SystemContains_u16(ptrPlayer->RwyArray[0], GameUsedRwy, GAME_MAX_RUNWAYS);
- for (i = 0 ; i < GameLevelSize; i++)
+ for (i = 0 ; i < GameLevelSize; i++)
{
- // GameLevelBuffer bits explanation:
- // X X X X X X X X X X X X X X X X
- // | | | | | | | | | | | | | | | |
- // | | | | | | | | | | | | | | | V
- // | | | | | | | | | | | | | | V Tile, bit 0
- // | | | | | | | | | | | | | V Tile, bit 1
- // | | | | | | | | | | | | V Tile, bit 2
- // | | | | | | | | | | | V Tile, bit 3
- // | | | | | | | | | | V Tile, bit 4
- // | | | | | | | | | V Tile, bit 5
- // | | | | | | | | V Tile, bit 6
- // | | | | | | | V Tile mirror flag
- // | | | | | | V Building, bit 0
+ TYPE_ISOMETRIC_POS tileIsoPos;
+
+ // GameLevelBuffer bits explanation:
+ // X X X X X X X X X X X X X X X X
+ // | | | | | | | | | | | | | | | |
+ // | | | | | | | | | | | | | | | V
+ // | | | | | | | | | | | | | | V Tile, bit 0
+ // | | | | | | | | | | | | | V Tile, bit 1
+ // | | | | | | | | | | | | V Tile, bit 2
+ // | | | | | | | | | | | V Tile, bit 3
+ // | | | | | | | | | | V Tile, bit 4
+ // | | | | | | | | | V Tile, bit 5
+ // | | | | | | | | V Tile, bit 6
+ // | | | | | | | | Tile mirror flag
+ // | | | | | | | V
+ // | | | | | | V Building, bit 0
// | | | | | V Building, bit 1
// | | | | V Building, bit 2
// | | | V Building, bit 3
@@ -1655,65 +1679,17 @@ void GameRenderLevel(TYPE_PLAYER* ptrPlayer)
// | V Building, bit 5
// V Building, bit 6
// Building, bit 7
-
- uint8_t CurrentTile = (uint8_t)(GameLevelBuffer[i] & 0x00FF);
+ uint8_t CurrentTile = (uint8_t)(GameLevelBuffer[i] & 0x007F); // Remove building data
+ // and mirror flag.
// Isometric -> Cartesian conversion
tileIsoPos.x = columns << (TILE_SIZE_BIT_SHIFT);
tileIsoPos.y = rows << (TILE_SIZE_BIT_SHIFT);
tileIsoPos.z = 0;
- tileCartPos = GfxIsometricToCartesian(&tileIsoPos);
+ ptrPlayer->TileData[i].CartPos = GfxIsometricToCartesian(&tileIsoPos);
- // Flipped tiles have bit 7 set.
- if (CurrentTile & TILE_MIRROR_FLAG)
- {
- flip_id = true;
- aux_id = CurrentTile;
- CurrentTile &= ~(TILE_MIRROR_FLAG);
- }
- else
- {
- flip_id = false;
- }
-
- if (CurrentTile <= LAST_TILE_TILESET1)
- {
- // Draw using GameTilesetSpr
- ptrTileset = &GameTilesetSpr;
- }
- else if ( (CurrentTile > LAST_TILE_TILESET1)
- &&
- (CurrentTile <= LAST_TILE_TILESET2) )
- {
- // Draw using GameTileset2Spr
- ptrTileset = &GameTileset2Spr;
- }
- else
- {
- ptrTileset = NULL;
-
- continue;
-
-// if (flip_id == false)
-// {
-// continue;
-// }
- }
-
- ptrTileset->w = TILE_SIZE;
- ptrTileset->h = TILE_SIZE_H;
-
- ptrTileset->x = tileCartPos.x;
- ptrTileset->y = tileCartPos.y;
-
- // Set coordinate origin to left upper corner
- ptrTileset->x -= TILE_SIZE >> 1;
- //ptrTileset->y -= TILE_SIZE_H >> 2;
-
- CameraApplyCoordinatesToSprite(ptrPlayer, ptrTileset);
-
- if (columns < (GameLevelColumns - 1) )
+ if (columns < (GameLevelColumns - 1) )
{
columns++;
}
@@ -1723,14 +1699,25 @@ void GameRenderLevel(TYPE_PLAYER* ptrPlayer)
columns = 0;
}
- if (GfxIsSpriteInsideScreenArea(ptrTileset) == false)
- {
- continue;
- }
+ // Set coordinate origin to left upper corner.
+ ptrPlayer->TileData[i].CartPos.x -= TILE_SIZE >> 1;
+
+ CameraApplyCoordinatesToCartesianPos(ptrPlayer, &ptrPlayer->TileData[i].CartPos);
+
+ if (GfxIsInsideScreenArea( ptrPlayer->TileData[i].CartPos.x,
+ ptrPlayer->TileData[i].CartPos.y,
+ TILE_SIZE,
+ TILE_SIZE_H ) == false)
+ {
+ ptrPlayer->TileData[i].ShowTile = false;
+ continue;
+ }
+
+ ptrPlayer->TileData[i].ShowTile = true;
- ptrTileset->r = NORMAL_LUMINANCE;
- ptrTileset->g = NORMAL_LUMINANCE;
- ptrTileset->b = NORMAL_LUMINANCE;
+ ptrPlayer->TileData[i].r = NORMAL_LUMINANCE;
+ ptrPlayer->TileData[i].g = NORMAL_LUMINANCE;
+ ptrPlayer->TileData[i].b = NORMAL_LUMINANCE;
if (i != 0)
{
@@ -1740,15 +1727,15 @@ void GameRenderLevel(TYPE_PLAYER* ptrPlayer)
{
if (used_rwy != false)
{
- ptrTileset->r = rwy_sine;
- ptrTileset->b = NORMAL_LUMINANCE >> 2;
- ptrTileset->g = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].r = rwy_sine;
+ ptrPlayer->TileData[i].b = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].g = NORMAL_LUMINANCE >> 2;
}
else
{
- ptrTileset->r = NORMAL_LUMINANCE >> 2;
- ptrTileset->g = NORMAL_LUMINANCE >> 2;
- ptrTileset->b = rwy_sine;
+ ptrPlayer->TileData[i].r = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].g = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].b = rwy_sine;
}
}
}
@@ -1756,7 +1743,7 @@ void GameRenderLevel(TYPE_PLAYER* ptrPlayer)
||
(ptrPlayer->SelectTaxiwayRunway != false) )
{
- if (( (SystemContains_u16(i, ptrPlayer->Waypoints, PLAYER_MAX_WAYPOINTS) != false)
+ if (( (SystemContains_u16(i, ptrPlayer->Waypoints, ptrPlayer->WaypointIdx) != false)
||
(i == ptrPlayer->SelectedTile) )
&&
@@ -1764,15 +1751,15 @@ void GameRenderLevel(TYPE_PLAYER* ptrPlayer)
{
if (ptrPlayer->InvalidPath != false)
{
- ptrTileset->r = rwy_sine;
- ptrTileset->b = NORMAL_LUMINANCE >> 2;
- ptrTileset->g = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].r = rwy_sine;
+ ptrPlayer->TileData[i].b = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].g = NORMAL_LUMINANCE >> 2;
}
else
{
- ptrTileset->r = NORMAL_LUMINANCE >> 2;
- ptrTileset->g = NORMAL_LUMINANCE >> 2;
- ptrTileset->b = rwy_sine;
+ ptrPlayer->TileData[i].r = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].g = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].b = rwy_sine;
}
}
else if ( (ptrPlayer->SelectTaxiwayRunway != false)
@@ -1781,9 +1768,9 @@ void GameRenderLevel(TYPE_PLAYER* ptrPlayer)
||
(CurrentTile == TILE_RWY_HOLDING_POINT_2) ) )
{
- ptrTileset->r = NORMAL_LUMINANCE >> 2;
- ptrTileset->g = rwy_sine;
- ptrTileset->b = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].r = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].g = rwy_sine;
+ ptrPlayer->TileData[i].b = NORMAL_LUMINANCE >> 2;
}
else if ( (ptrPlayer->SelectTaxiwayParking != false)
&&
@@ -1791,39 +1778,114 @@ void GameRenderLevel(TYPE_PLAYER* ptrPlayer)
||
(CurrentTile == TILE_PARKING_2) ) )
{
- ptrTileset->r = NORMAL_LUMINANCE >> 2;
- ptrTileset->g = rwy_sine;
- ptrTileset->b = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].r = NORMAL_LUMINANCE >> 2;
+ ptrPlayer->TileData[i].g = rwy_sine;
+ ptrPlayer->TileData[i].b = NORMAL_LUMINANCE >> 2;
}
}
}
+ }
+}
- if (ptrTileset != NULL)
- {
- if (flip_id != false)
- {
- ptrTileset->attribute |= H_FLIP;
- }
- }
+/* ******************************************************************************************
+ *
+ * @name: void GameRenderTerrain(TYPE_PLAYER* ptrPlayer)
+ *
+ * @author: Xavier Del Campo
+ *
+ * @param:
+ * TYPE_PLAYER* ptrPlayer:
+ * Pointer to a player structure
+ *
+ *
+ * @brief:
+ * Draws all tiles depending on GameLevelBuffer configuration.
+ *
+ * @remarks:
+ * Tiles are usually rendered with normal RGB values unless parking/runway is busy
+ * or ptrPlayer->InvalidPath != false.
+ *
+ * ******************************************************************************************/
+void GameRenderTerrain(TYPE_PLAYER* ptrPlayer)
+{
+ uint16_t i;
+ uint8_t aux_id;
- ptrTileset->u = (short)(CurrentTile % COLUMNS_PER_TILESET) << TILE_SIZE_BIT_SHIFT;
- ptrTileset->v = (short)(CurrentTile / COLUMNS_PER_TILESET) * TILE_SIZE_H;
+ for (i = 0 ; i < GameLevelSize; i++)
+ {
+ if (ptrPlayer->TileData[i].ShowTile != false)
+ {
+ bool flip_id;
+ GsSprite* ptrTileset;
- ptrTileset->mx = ptrTileset->u + (TILE_SIZE >> 1);
- ptrTileset->my = ptrTileset->v + (TILE_SIZE_H >> 1);
+ uint8_t CurrentTile = (uint8_t)(GameLevelBuffer[i] & 0x00FF);
- if (flip_id != false)
- {
- flip_id = false;
- CurrentTile = aux_id;
- }
+ // Flipped tiles have bit 7 set.
+ if (CurrentTile & TILE_MIRROR_FLAG)
+ {
+ flip_id = true;
+ aux_id = CurrentTile;
+ CurrentTile &= ~(TILE_MIRROR_FLAG);
+ }
+ else
+ {
+ flip_id = false;
+ }
- GfxSortSprite(ptrTileset);
+ if (CurrentTile <= LAST_TILE_TILESET1)
+ {
+ // Draw using GameTilesetSpr
+ ptrTileset = &GameTilesetSpr;
+ }
+ else if ( (CurrentTile > LAST_TILE_TILESET1)
+ &&
+ (CurrentTile <= LAST_TILE_TILESET2) )
+ {
+ // Draw using GameTileset2Spr
+ ptrTileset = &GameTileset2Spr;
+ }
+ else
+ {
+ ptrTileset = NULL;
+ continue;
+ }
- if (ptrTileset->attribute & H_FLIP)
- {
- ptrTileset->attribute &= ~(H_FLIP);
- }
+ // Apply {X, Y} data from precalculated lookup tables.
+ ptrTileset->x = ptrPlayer->TileData[i].CartPos.x;
+ ptrTileset->y = ptrPlayer->TileData[i].CartPos.y;
+
+ // Apply RGB data from precalculated lookup tables.
+ ptrTileset->r = ptrPlayer->TileData[i].r;
+ ptrTileset->g = ptrPlayer->TileData[i].g;
+ ptrTileset->b = ptrPlayer->TileData[i].b;
+
+ if (flip_id != false)
+ {
+ ptrTileset->attribute |= H_FLIP;
+ }
+
+ ptrTileset->w = TILE_SIZE;
+ ptrTileset->h = TILE_SIZE_H;
+
+ ptrTileset->u = GameLevelBuffer_UVData[i].u;
+ ptrTileset->v = GameLevelBuffer_UVData[i].v;
+
+ ptrTileset->mx = ptrTileset->u + (TILE_SIZE >> 1);
+ ptrTileset->my = ptrTileset->v + (TILE_SIZE_H >> 1);
+
+ if (flip_id != false)
+ {
+ flip_id = false;
+ CurrentTile = aux_id;
+ }
+
+ GfxSortSprite(ptrTileset);
+
+ if (ptrTileset->attribute & H_FLIP)
+ {
+ ptrTileset->attribute &= ~(H_FLIP);
+ }
+ }
}
}
@@ -2124,7 +2186,6 @@ void GameStateSelectTaxiwayRunway(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrF
* @remarks:
*
* **************************************************************************************************/
-
void GameStateSelectTaxiwayParking(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFlightData)
{
TYPE_ISOMETRIC_POS IsoPos = CameraGetIsoPos(ptrPlayer);
@@ -2232,7 +2293,6 @@ void GameStateSelectTaxiwayParking(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptr
* @remarks:
*
* **************************************************************************************************/
-
void GameStateSelectRunway(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFlightData)
{
uint8_t i;
@@ -2323,7 +2383,6 @@ void GameStateSelectRunway(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFlightDa
* Do not confuse GameRwy with GameRwyArray, which are used for completely different purposes.
*
* **************************************************************************************************/
-
void GameGetRunwayArray(void)
{
uint16_t i;
@@ -2484,11 +2543,6 @@ void GameSelectAircraftFromList(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFli
* **************************************************************************************************/
DIRECTION GameGetParkingDirection(uint16_t parkingTile)
{
- DEBUG_PRINT_VAR(parkingTile);
- DEBUG_PRINT_VAR(TILE_PARKING);
- DEBUG_PRINT_VAR(TILE_PARKING | TILE_MIRROR_FLAG);
- DEBUG_PRINT_VAR(TILE_PARKING_2);
- DEBUG_PRINT_VAR(TILE_PARKING_2 | TILE_MIRROR_FLAG);
switch (parkingTile)
{
case TILE_PARKING:
@@ -2602,6 +2656,7 @@ void GameGetSelectedRunwayArray(uint16_t rwyHeader, uint16_t* rwyArray, size_t s
if (dir == NO_DIRECTION)
{
+ Serial_printf("rwyHeader = %d returned NO_DIRECTION\n", rwyHeader);
return;
}
}
@@ -2651,6 +2706,7 @@ void GameGetSelectedRunwayArray(uint16_t rwyHeader, uint16_t* rwyArray, size_t s
// Fall through
default:
Serial_printf("Invalid runway direction.\n");
+ DEBUG_PRINT_VAR(rwyHeader);
return;
}
@@ -2761,7 +2817,7 @@ void GameAssignRunwaytoAircraft(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFli
}
else if (ptrFlightData->State[aircraftIndex] == STATE_HOLDING_RWY)
{
- TYPE_RWY_ENTRY_DATA rwyEntryData;
+ TYPE_RWY_ENTRY_DATA rwyEntryData = {0};
GameGetRunwayEntryTile(aircraftIndex, &rwyEntryData);
@@ -3624,22 +3680,18 @@ void GameCreateTakeoffWaypoints(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFli
switch(aircraftDir)
{
case DIR_EAST:
- //Serial_printf("EAST\n");
rwyStep = 1;
break;
case DIR_WEST:
- //Serial_printf("WEST\n");
rwyStep = -1;
break;
case DIR_NORTH:
- //Serial_printf("NORTH\n");
rwyStep = -GameLevelColumns;
break;
case DIR_SOUTH:
- //Serial_printf("SOUTH\n");
rwyStep = GameLevelColumns;
break;
@@ -3648,9 +3700,9 @@ void GameCreateTakeoffWaypoints(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFli
}
for (currentTile = (AircraftGetTileFromFlightDataIndex(aircraftIdx) + rwyStep);
- (GameLevelBuffer[currentTile] != TILE_RWY_START_1)
+ ((GameLevelBuffer[currentTile] & ~(TILE_MIRROR_FLAG)) != TILE_RWY_START_1)
&&
- (GameLevelBuffer[currentTile] != TILE_RWY_START_2);
+ ((GameLevelBuffer[currentTile] & ~(TILE_MIRROR_FLAG)) != TILE_RWY_START_2);
currentTile -= rwyStep )
{
// Calculate new currentTile value until conditions are invalid.
@@ -3665,9 +3717,9 @@ void GameCreateTakeoffWaypoints(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFli
}
}
- for (currentTile = (AircraftGetTileFromFlightDataIndex(aircraftIdx) + rwyStep);
- GameLevelBuffer[currentTile] != TILE_RWY_EXIT;
- currentTile += rwyStep )
+ for ( currentTile = (AircraftGetTileFromFlightDataIndex(aircraftIdx) + rwyStep);
+ (GameLevelBuffer[currentTile] & ~(TILE_MIRROR_FLAG)) != TILE_RWY_EXIT;
+ currentTile += rwyStep )
{
}
@@ -3699,7 +3751,7 @@ void GameCreateTakeoffWaypoints(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFli
void GameGetRunwayEntryTile(uint8_t aircraftIdx, TYPE_RWY_ENTRY_DATA* ptrRwyEntry)
{
// Look for aircraft direction by searching TILE_RWY_EXIT
- uint16_t currentTile = AircraftGetTileFromFlightDataIndex(aircraftIdx);
+ uint16_t currentTile = AircraftGetTileFromFlightDataIndex(aircraftIdx) & (uint16_t)~(TILE_MIRROR_FLAG);
int16_t step = 0;
uint16_t i;
@@ -3707,28 +3759,36 @@ void GameGetRunwayEntryTile(uint8_t aircraftIdx, TYPE_RWY_ENTRY_DATA* ptrRwyEntr
&&
( (currentTile + GameLevelColumns) < GameLevelSize) )
{
- if (GameLevelBuffer[currentTile + 1] == TILE_RWY_EXIT)
+ if ( ((GameLevelBuffer[currentTile + 1] & ~(TILE_MIRROR_FLAG)) == TILE_RWY_EXIT)
+ ||
+ ((GameLevelBuffer[currentTile + 1] & ~(TILE_MIRROR_FLAG)) == TILE_RWY_EXIT_2) )
{
ptrRwyEntry->Direction = DIR_EAST;
ptrRwyEntry->rwyStep = GameLevelColumns;
- step = -1;
+ step = 1;
}
- else if (GameLevelBuffer[currentTile - 1] == TILE_RWY_EXIT)
+ else if ( ((GameLevelBuffer[currentTile - 1] & ~(TILE_MIRROR_FLAG) ) == TILE_RWY_EXIT)
+ ||
+ ((GameLevelBuffer[currentTile - 1] & ~(TILE_MIRROR_FLAG)) == TILE_RWY_EXIT_2) )
{
ptrRwyEntry->Direction = DIR_WEST;
- ptrRwyEntry->rwyStep = -GameLevelColumns;
- step = 1;
+ ptrRwyEntry->rwyStep = GameLevelColumns;
+ step = -1;
}
- else if (GameLevelBuffer[currentTile + GameLevelColumns] == TILE_RWY_EXIT)
+ else if ( ((GameLevelBuffer[currentTile + GameLevelColumns] & ~(TILE_MIRROR_FLAG)) == TILE_RWY_EXIT)
+ ||
+ ((GameLevelBuffer[currentTile + GameLevelColumns] & ~(TILE_MIRROR_FLAG)) == TILE_RWY_EXIT_2) )
{
ptrRwyEntry->Direction = DIR_SOUTH;
ptrRwyEntry->rwyStep = 1;
step = GameLevelColumns;
}
- else if (GameLevelBuffer[currentTile - GameLevelColumns] == TILE_RWY_EXIT)
+ else if ( ((GameLevelBuffer[currentTile - GameLevelColumns] & ~(TILE_MIRROR_FLAG)) == TILE_RWY_EXIT)
+ ||
+ ((GameLevelBuffer[currentTile - GameLevelColumns] & ~(TILE_MIRROR_FLAG)) == TILE_RWY_EXIT_2) )
{
ptrRwyEntry->Direction = DIR_NORTH;
- ptrRwyEntry->rwyStep = -1;
+ ptrRwyEntry->rwyStep = 1;
step = -GameLevelColumns;
}
else
@@ -3736,7 +3796,7 @@ void GameGetRunwayEntryTile(uint8_t aircraftIdx, TYPE_RWY_ENTRY_DATA* ptrRwyEntr
ptrRwyEntry->rwyEntryTile = 0;
ptrRwyEntry->Direction = NO_DIRECTION;
ptrRwyEntry->rwyStep = 0;
- Serial_printf("GameCreateTakeoffWaypoints(): could not determine aircraft direction.\n");
+ Serial_printf("GameGetRunwayEntryTile(): could not determine aircraft direction.\n");
return;
}
@@ -3744,24 +3804,26 @@ void GameGetRunwayEntryTile(uint8_t aircraftIdx, TYPE_RWY_ENTRY_DATA* ptrRwyEntr
i = ptrRwyEntry->rwyEntryTile;
- while ( (GameLevelBuffer[i] != TILE_RWY_START_1)
+ while ( ((GameLevelBuffer[i] & ~TILE_MIRROR_FLAG) != TILE_RWY_START_1)
&&
- (GameLevelBuffer[i] != TILE_RWY_START_2)
+ ((GameLevelBuffer[i] & ~TILE_MIRROR_FLAG) != TILE_RWY_START_2)
&&
(i > ptrRwyEntry->rwyStep)
&&
((i - ptrRwyEntry->rwyStep) < GameLevelSize ) )
{
+ DEBUG_PRINT_VAR(i);
i -= ptrRwyEntry->rwyStep;
}
ptrRwyEntry->rwyHeader = i;
- DEBUG_PRINT_VAR(ptrRwyEntry->rwyHeader);
+ DEBUG_PRINT_VAR(ptrRwyEntry->rwyHeader);
+ DEBUG_PRINT_VAR(ptrRwyEntry->rwyEntryTile);
}
else
{
- Serial_printf("GameCreateTakeoffWaypoints(): Invalid index for tile.\n");
+ Serial_printf("GameGetRunwayEntryTile(): Invalid index for tile.\n");
}
}
diff --git a/Source/Game.h b/Source/Game.h
index b5a191e..fce2fb1 100644
--- a/Source/Game.h
+++ b/Source/Game.h
@@ -21,6 +21,14 @@
/* *************************************
* Structs and enums
* *************************************/
+
+typedef struct t_gameConfiguration
+{
+ bool TwoPlayers;
+ const char* LVLPath;
+ const char* PLTPath;
+}TYPE_GAME_CONFIGURATION;
+
/* *************************************
* Global variables
* *************************************/
@@ -29,7 +37,8 @@ extern bool GameStartupFlag;
/* *************************************
* Global prototypes
* *************************************/
-void Game(bool two_players);
+
+void Game(TYPE_GAME_CONFIGURATION* pGameCfg);
void GameSetTime(uint8_t hour, uint8_t minutes);
bool GameTwoPlayersActive(void);
uint8_t GameGetLevelColumns(void);
diff --git a/Source/GameGui.c b/Source/GameGui.c
index ec40b1a..bda17c2 100644
--- a/Source/GameGui.c
+++ b/Source/GameGui.c
@@ -301,6 +301,23 @@ void GameGuiInit(void)
ShowAircraftPassengersTimer = TimerCreate(20, true, GameGuiClearPassengersLeft);
+ // Prepare RGB data and (X,Y) coordinates for aircraft
+ // data list request rectangle.
+ AircraftDataGPoly4.r[0] = AIRCRAFT_DATA_GSGPOLY4_R0;
+ AircraftDataGPoly4.r[1] = AIRCRAFT_DATA_GSGPOLY4_R1;
+ AircraftDataGPoly4.r[2] = AIRCRAFT_DATA_GSGPOLY4_R2;
+ AircraftDataGPoly4.r[3] = AIRCRAFT_DATA_GSGPOLY4_R3;
+
+ AircraftDataGPoly4.g[0] = AIRCRAFT_DATA_GSGPOLY4_G0;
+ AircraftDataGPoly4.g[1] = AIRCRAFT_DATA_GSGPOLY4_G1;
+ AircraftDataGPoly4.g[2] = AIRCRAFT_DATA_GSGPOLY4_G2;
+ AircraftDataGPoly4.g[3] = AIRCRAFT_DATA_GSGPOLY4_G3;
+
+ AircraftDataGPoly4.b[0] = AIRCRAFT_DATA_GSGPOLY4_B0;
+ AircraftDataGPoly4.b[1] = AIRCRAFT_DATA_GSGPOLY4_B1;
+ AircraftDataGPoly4.b[2] = AIRCRAFT_DATA_GSGPOLY4_B2;
+ AircraftDataGPoly4.b[3] = AIRCRAFT_DATA_GSGPOLY4_B3;
+
slowScore = 0;
GameGuiBubbleShowFlag = false;
@@ -461,23 +478,6 @@ void GameGuiAircraftList(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFlightData
if (ptrPlayer->ShowAircraftData != false)
{
- // Prepare RGB data and (X,Y) coordinates for aircraft
- // data list request rectangle.
- AircraftDataGPoly4.r[0] = AIRCRAFT_DATA_GSGPOLY4_R0;
- AircraftDataGPoly4.r[1] = AIRCRAFT_DATA_GSGPOLY4_R1;
- AircraftDataGPoly4.r[2] = AIRCRAFT_DATA_GSGPOLY4_R2;
- AircraftDataGPoly4.r[3] = AIRCRAFT_DATA_GSGPOLY4_R3;
-
- AircraftDataGPoly4.g[0] = AIRCRAFT_DATA_GSGPOLY4_G0;
- AircraftDataGPoly4.g[1] = AIRCRAFT_DATA_GSGPOLY4_G1;
- AircraftDataGPoly4.g[2] = AIRCRAFT_DATA_GSGPOLY4_G2;
- AircraftDataGPoly4.g[3] = AIRCRAFT_DATA_GSGPOLY4_G3;
-
- AircraftDataGPoly4.b[0] = AIRCRAFT_DATA_GSGPOLY4_B0;
- AircraftDataGPoly4.b[1] = AIRCRAFT_DATA_GSGPOLY4_B1;
- AircraftDataGPoly4.b[2] = AIRCRAFT_DATA_GSGPOLY4_B2;
- AircraftDataGPoly4.b[3] = AIRCRAFT_DATA_GSGPOLY4_B3;
-
AircraftDataGPoly4.attribute |= ENABLE_TRANS | TRANS_MODE(0);
if (GameTwoPlayersActive() != false)
diff --git a/Source/GameStructures.h b/Source/GameStructures.h
index 115255f..17fee7a 100644
--- a/Source/GameStructures.h
+++ b/Source/GameStructures.h
@@ -9,6 +9,7 @@
#define GAME_MAX_CHARACTERS 8
#define GAME_MAX_PARKING 32
#define GAME_MAX_RWY_LENGTH 16
+#define GAME_MAX_MAP_SIZE 0x400
#define CHEAT_ARRAY_SIZE 16
#define AIRCRAFT_MAX_TARGETS 48
#define PLAYER_MAX_WAYPOINTS AIRCRAFT_MAX_TARGETS
@@ -78,6 +79,15 @@ typedef struct t_cartpos
short y;
}TYPE_CARTESIAN_POS;
+typedef struct t_tileData
+{
+ bool ShowTile;
+ TYPE_CARTESIAN_POS CartPos;
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+}TYPE_TILE_DATA;
+
typedef struct t_flightData
{
FL_DIR FlightDirection[GAME_MAX_AIRCRAFT];
@@ -192,14 +202,20 @@ typedef struct
uint8_t UnboardingSequenceIdx;
// Show passengers left
uint8_t PassengersLeftSelectedAircraft;
+ // Lookup tables defined on GameRenderTerrainPrecalculations() to be later used on
+ // GameRenderTerrain().
+ TYPE_TILE_DATA TileData[GAME_MAX_MAP_SIZE];
+ // Player camera instance.
+ TYPE_CAMERA Camera;
+ // Array of tiles which will change their RGB values when displayed under certain player states.
+ uint16_t RwyArray[GAME_MAX_RWY_LENGTH];
+ // Pad callbacks.
bool (*PadKeyPressed_Callback)(unsigned short);
bool (*PadKeyReleased_Callback)(unsigned short);
bool (*PadKeySinglePress_Callback)(unsigned short);
bool (*PadDirectionKeyPressed_Callback)(void);
unsigned short (*PadLastKeySinglePressed_Callback)(void);
- TYPE_CAMERA Camera;
- uint16_t RwyArray[GAME_MAX_RWY_LENGTH];
}TYPE_PLAYER;
typedef enum t_fontflags
diff --git a/Source/Gfx.c b/Source/Gfx.c
index 42ea352..879ec37 100644
--- a/Source/Gfx.c
+++ b/Source/Gfx.c
@@ -309,7 +309,7 @@ void GfxDrawScene_Slow(void)
/* **********************************************************************
*
- * @name: void GfxSortSprite(GsSprite * spr)
+ * @name: void GfxSortSprite(GsSprite* spr)
*
* @author: Xavier Del Campo
*
@@ -323,7 +323,7 @@ void GfxDrawScene_Slow(void)
* if you need to skip this check.
*
* **********************************************************************/
-void GfxSortSprite(GsSprite * spr)
+void GfxSortSprite(GsSprite* spr)
{
uint8_t aux_r = spr->r;
uint8_t aux_g = spr->g;
@@ -423,7 +423,7 @@ void GfxSortSprite(GsSprite * spr)
/* **********************************************************************
*
- * @name: void GfxSortSprite(GsSprite * spr)
+ * @name: void GfxSortSprite(GsSprite* spr)
*
* @author: Xavier Del Campo
*
@@ -512,7 +512,7 @@ bool GfxIsGPUBusy(void)
/* **********************************************************************
*
- * @name: bool GfxSpriteFromFile(char* fname, GsSprite * spr)
+ * @name: bool GfxSpriteFromFile(char* fname, GsSprite* spr)
*
* @author: Xavier Del Campo
*
@@ -524,7 +524,7 @@ bool GfxIsGPUBusy(void)
* false if an error happened, true otherwise.
*
* **********************************************************************/
-bool GfxSpriteFromFile(char* fname, GsSprite * spr)
+bool GfxSpriteFromFile(char* fname, GsSprite* spr)
{
GsImage gsi;
@@ -611,7 +611,7 @@ bool GfxIsInsideScreenArea(short x, short y, short w, short h)
/* **********************************************************************
*
- * @name: bool GfxIsSpriteInsideScreenArea(GsSprite * spr)
+ * @name: bool GfxIsSpriteInsideScreenArea(GsSprite* spr)
*
* @author: Xavier Del Campo
*
@@ -619,7 +619,7 @@ bool GfxIsInsideScreenArea(short x, short y, short w, short h)
* true if sprite is inside screen area, false otherwise.
*
* **********************************************************************/
-bool GfxIsSpriteInsideScreenArea(GsSprite * spr)
+bool GfxIsSpriteInsideScreenArea(GsSprite* spr)
{
return GfxIsInsideScreenArea(spr->x, spr->y, spr->w, spr->h);
}
@@ -809,7 +809,7 @@ bool Gfx2HzFlash(void)
return five_hundred_ms_show;
}
-bool GfxTPageOffsetFromVRAMPosition(GsSprite * spr, short x, short y)
+bool GfxTPageOffsetFromVRAMPosition(GsSprite* spr, short x, short y)
{
if ( (x >= VRAM_W) || (x < 0) || (y >= VRAM_H) || (y < 0) )
{
diff --git a/Source/Gfx.h b/Source/Gfx.h
index 48cc2db..1f8111e 100644
--- a/Source/Gfx.h
+++ b/Source/Gfx.h
@@ -51,7 +51,7 @@ void GfxDrawScene_Fast(void);
bool GfxReadyForDMATransfer(void);
// Fills a GsSprite structure with information from a TIM file.
-bool GfxSpriteFromFile(char* fname, GsSprite * spr);
+bool GfxSpriteFromFile(char* fname, GsSprite* spr);
// Reportedly, loads CLUT data from a TIM image (image data is discarded)
bool GfxCLUTFromFile(char* fname);
@@ -60,14 +60,14 @@ bool GfxCLUTFromFile(char* fname);
bool GfxIsInsideScreenArea(short x, short y, short w, short h);
// Function overload for GsSprite structures.
-bool GfxIsSpriteInsideScreenArea(GsSprite * spr);
+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);
+void GfxSortSprite(GsSprite* spr);
uint8_t GfxGetGlobalLuminance(void);
@@ -97,7 +97,7 @@ 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);
+bool GfxTPageOffsetFromVRAMPosition(GsSprite* spr, short x, short y);
void GfxSetSplitScreen(uint8_t playerIndex);
diff --git a/Source/Makefile b/Source/Makefile
index 667d415..6d906ad 100644
--- a/Source/Makefile
+++ b/Source/Makefile
@@ -76,7 +76,7 @@ SOUND_OBJECTS = $(addprefix $(OBJ_SOUNDS_DIR)/, BELL.VAG \
# Level objects:
SRC_LEVELS_DIR = $(PROJECT_DIR)/Levels
OBJ_LEVELS_DIR = $(CDROM_ROOT)/DATA/LEVELS
-LEVEL_OBJECTS = $(addprefix $(OBJ_LEVELS_DIR)/, LEVEL1.LVL LEVEL2.LVL LEVEL2.PLT LEVEL1.PLT)
+LEVEL_OBJECTS = $(addprefix $(OBJ_LEVELS_DIR)/, LEVEL1.LVL LEVEL2.LVL LEVEL2.PLT LEVEL1.PLT EASY.PLT)
# Sprite objects:
BMP2TIM = bmp2tim
diff --git a/Source/MapEditor/MapEditor.pro.user b/Source/MapEditor/MapEditor.pro.user
index 91bb581..aaf3a0c 100644
--- a/Source/MapEditor/MapEditor.pro.user
+++ b/Source/MapEditor/MapEditor.pro.user
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 4.0.3, 2017-12-29T17:58:10. -->
+<!-- Written by QtCreator 4.0.3, 2018-01-01T07:36:40. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
diff --git a/Source/MapEditor/settings.ini b/Source/MapEditor/settings.ini
index dc943fa..af1583e 100644
--- a/Source/MapEditor/settings.ini
+++ b/Source/MapEditor/settings.ini
@@ -1,2 +1,2 @@
[app_settings]
-last_dir=C:/cygwin/home/Xavier/Airport/Levels/LEVEL2_.LVL
+last_dir=C:/cygwin/home/Xavier/Airport/Levels/LEVEL2.LVL
diff --git a/Source/Menu.c b/Source/Menu.c
index e51515d..325c0c4 100644
--- a/Source/Menu.c
+++ b/Source/Menu.c
@@ -27,6 +27,19 @@
* Structs and enums *
* *************************************/
+typedef enum t_levelId
+{
+ LEVEL1 = 0,
+ LEVEL2,
+ MAX_LEVELS = LEVEL2
+}LEVEL_ID;
+
+typedef struct t_lvlpltdata
+{
+ LEVEL_ID levelID;
+ const char** fileNames[];
+}TYPE_LVL_PLT_DATA;
+
typedef enum
{
PLAY_OPTIONS_LEVEL,
@@ -133,6 +146,9 @@ static TYPE_CHEAT StackCheckCheat;
static TYPE_CHEAT DevMenuCheat;
static TYPE_CHEAT SerialCheat;
static volatile bool BcnGWSpr_set;
+static LEVEL_ID SelectedLevel;
+static uint8_t SelectedPlt;
+static bool isLevelSelected;
static const char* MainMenuFiles[] = { "cdrom:\\DATA\\SPRITES\\MAINMENU.TIM;1" ,
"cdrom:\\DATA\\SOUNDS\\BELL.VAG;1" ,
@@ -149,18 +165,15 @@ static const char* MainMenuFiles[] = { "cdrom:\\DATA\\SPRITES\\MAINMENU.TIM;1" ,
#endif // NO_INTRO
};
-enum
-{
- LEVEL1,
- LEVEL2
-};
-
static const char* MainMenuLevelList[] = { [LEVEL1] = "cdrom:\\DATA\\LEVELS\\LEVEL1.LVL;1" ,
[LEVEL2] = "cdrom:\\DATA\\LEVELS\\LEVEL2.LVL;1" };
-static const char* MainMenuLevelPltList[][] = { [LEVEL1] = {"cdrom:\\DATA\\LEVELS\\LEVEL1.PLT;1"},
- [LEVEL2] = {"cdrom:\\DATA\\LEVELS\\LEVEL2.PLT;1"} };
+static const char* MainMenuLevel1Plt[] = {"cdrom:\\DATA\\LEVELS\\LEVEL1.PLT;1", "cdrom:\\DATA\\LEVELS\\EASY.PLT;1", NULL};
+static const char* MainMenuLevel2Plt[] = {"cdrom:\\DATA\\LEVELS\\LEVEL2.PLT;1", NULL};
+
+static const char** MainMenuPltList[] = {[LEVEL1] = MainMenuLevel1Plt, [LEVEL2] = MainMenuLevel2Plt};
+static TYPE_GAME_CONFIGURATION GameCfg;
static void* MainMenuDest[] = { (GsSprite*)&MenuSpr ,
(SsVag*)&BellSnd ,
@@ -211,6 +224,7 @@ void OptionsMenu(void)
void OnePlayerMenu(void)
{
menuLevel = LEVEL_LIST_LEVEL;
+ GameCfg.TwoPlayers = false;
//EndAnimation();
//Game(false /* One Player Only */);
}
@@ -218,6 +232,7 @@ void OnePlayerMenu(void)
void TwoPlayerMenu(void)
{
menuLevel = LEVEL_LIST_LEVEL;
+ GameCfg.TwoPlayers = true;
//EndAnimation();
//Game(true /* Two players */);
}
@@ -270,6 +285,8 @@ void MainMenuInit(void)
MenuStarSpr.my = MenuStarSpr.h >> 1;
MenuStarSpr.rotate = 0;
+ SelectedLevel = LEVEL1;
+
MenuCheatInit();
LoadMenuEnd();
@@ -407,9 +424,21 @@ void MainMenuRenderLevelList(void)
{
LEVEL_LIST_TEXT_X = LEVEL_LIST_RECT_X + 8,
LEVEL_LIST_TEXT_Y = LEVEL_LIST_RECT_Y + 8,
+
+ LEVEL_LIST_PLT_TEXT_X = LEVEL_LIST_PLT_RECT_X + 8,
+ LEVEL_LIST_PLT_TEXT_Y = LEVEL_LIST_PLT_RECT_Y + 8,
+ };
+
+ enum
+ {
+ LEVEL_LIST_SELECTION_RECT_X = LEVEL_LIST_TEXT_X,
+ LEVEL_LIST_SELECTION_RECT_Y = LEVEL_LIST_TEXT_Y,
+ LEVEL_LIST_SELECTION_RECT_W = LEVEL_LIST_RECT_W - 16,
+ LEVEL_LIST_SELECTION_RECT_H = 8,
};
GsGPoly4 levelListRect = {0};
+ GsGPoly4 levelListSelectionRect = {0};
uint8_t i;
levelListRect.x[0] = LEVEL_LIST_RECT_X;
@@ -446,6 +475,33 @@ void MainMenuRenderLevelList(void)
GsSortGPoly4(&levelListRect);
+ levelListSelectionRect.x[0] = LEVEL_LIST_SELECTION_RECT_X;
+ levelListSelectionRect.x[1] = LEVEL_LIST_SELECTION_RECT_X + LEVEL_LIST_SELECTION_RECT_W;
+ levelListSelectionRect.x[2] = levelListSelectionRect.x[0];
+ levelListSelectionRect.x[3] = levelListSelectionRect.x[1];
+
+ levelListSelectionRect.y[0] = LEVEL_LIST_SELECTION_RECT_Y + (short)(SelectedLevel << 3);
+ levelListSelectionRect.y[1] = levelListSelectionRect.y[0];
+ levelListSelectionRect.y[2] = LEVEL_LIST_SELECTION_RECT_Y + LEVEL_LIST_SELECTION_RECT_H + (short)(SelectedLevel << 3);
+ levelListSelectionRect.y[3] = levelListSelectionRect.y[2];
+
+ levelListSelectionRect.r[0] = LEVEL_LIST_RECT_B0;
+ levelListSelectionRect.r[1] = LEVEL_LIST_RECT_B1;
+ levelListSelectionRect.r[2] = LEVEL_LIST_RECT_B2;
+ levelListSelectionRect.r[3] = LEVEL_LIST_RECT_B3;
+
+ levelListSelectionRect.g[0] = LEVEL_LIST_RECT_B0;
+ levelListSelectionRect.g[1] = LEVEL_LIST_RECT_B1;
+ levelListSelectionRect.g[2] = LEVEL_LIST_RECT_B2;
+ levelListSelectionRect.g[3] = LEVEL_LIST_RECT_B3;
+
+ levelListSelectionRect.b[0] = LEVEL_LIST_RECT_B0;
+ levelListSelectionRect.b[1] = LEVEL_LIST_RECT_B1;
+ levelListSelectionRect.b[2] = LEVEL_LIST_RECT_B2;
+ levelListSelectionRect.b[3] = LEVEL_LIST_RECT_B3;
+
+ levelListSelectionRect.attribute |= ENABLE_TRANS | TRANS_MODE(0);
+
for (i = 0; i < (sizeof(MainMenuLevelList) / sizeof(MainMenuLevelList[0])); i++)
{
char baseName[32];
@@ -456,15 +512,40 @@ void MainMenuRenderLevelList(void)
FontPrintText(&SmallFont, LEVEL_LIST_TEXT_X, LEVEL_LIST_TEXT_Y + (i << 3), baseName);
- for (j = 0; j < (sizeof(MainMenuLevelPltList[i]) / sizeof(MainMenuLevelPltList[i][0])); j++)
+ if (i == SelectedLevel)
{
+ for (j = 0; j < (sizeof(MainMenuPltList) / sizeof(MainMenuPltList[0])); j++)
+ {
+ if (MainMenuPltList[i][j] != NULL)
+ {
+ // Update "baseName" with file name + extension.
+ SystemGetFileBasename(MainMenuPltList[i][j], baseName, sizeof(baseName) / sizeof(baseName[0]));
+ FontPrintText(&SmallFont, LEVEL_LIST_PLT_TEXT_X, LEVEL_LIST_PLT_TEXT_Y + (j << 3), baseName);
+ }
+ }
}
}
+
+ if (isLevelSelected == false)
+ {
+ GsSortGPoly4(&levelListSelectionRect);
+ }
+ else
+ {
+ levelListSelectionRect.y[0] = LEVEL_LIST_PLT_TEXT_Y + (short)(SelectedPlt << 3);
+ levelListSelectionRect.y[1] = levelListSelectionRect.y[0];
+ levelListSelectionRect.y[2] = LEVEL_LIST_PLT_TEXT_Y + LEVEL_LIST_SELECTION_RECT_H + (short)(SelectedPlt << 3);
+ levelListSelectionRect.y[3] = levelListSelectionRect.y[2];
+
+ GsSortGPoly4(&levelListSelectionRect);
+ }
}
void MainMenuRestoreInitValues(void)
{
+ uint8_t i;
+
menuLevel = PLAY_OPTIONS_LEVEL;
MainMenuMinimumBtn = PLAY_BUTTON_INDEX;
@@ -484,6 +565,16 @@ void MainMenuRestoreInitValues(void)
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].was_selected = false;
MainMenuBtn[TWO_PLAYER_BUTTON_INDEX].timer = 0;
+ SelectedLevel = LEVEL1;
+ SelectedPlt = 0;
+
+ memset(&GameCfg, 0, sizeof(TYPE_GAME_CONFIGURATION));
+
+ for (i = 0; i < MAIN_MENU_BUTTONS_MAX; i++)
+ {
+ MainMenuBtn[i].was_selected = false;
+ }
+
GfxSetGlobalLuminance(NORMAL_LUMINANCE);
SfxPlayTrack(INTRO_TRACK);
@@ -493,7 +584,7 @@ void MainMenuButtonHandler(void)
{
static uint8_t btn_selected = PLAY_BUTTON_INDEX;
static uint8_t previous_btn_selected = 0;
- uint8_t max_buttons;
+ uint8_t max_buttons = 0;
if (PadOneAnyKeyPressed() != false)
{
@@ -538,6 +629,56 @@ void MainMenuButtonHandler(void)
break;
+ case LEVEL_LIST_LEVEL:
+ if (PadOneKeySinglePress(PAD_UP) != false)
+ {
+ if (isLevelSelected == false)
+ {
+ if (SelectedLevel > 0)
+ {
+ SelectedLevel--;
+ SelectedPlt = 0;
+ }
+ }
+ else
+ {
+ if (SelectedPlt > 0)
+ {
+ SelectedPlt--;
+ }
+ }
+ }
+ else if (PadOneKeySinglePress(PAD_DOWN) != false)
+ {
+ if (isLevelSelected == false)
+ {
+ if (SelectedLevel < MAX_LEVELS)
+ {
+ SelectedLevel++;
+ SelectedPlt = 0;
+ }
+ }
+ else
+ {
+ if (MainMenuPltList[SelectedLevel][SelectedPlt + 1] != NULL)
+ {
+ SelectedPlt++;
+ }
+ }
+ }
+ else if (PadOneKeySinglePress(PAD_TRIANGLE) != false)
+ {
+ if (isLevelSelected == true)
+ {
+ isLevelSelected = false;
+ }
+ else
+ {
+ MainMenuRestoreInitValues();
+ }
+ }
+ break;
+
default:
max_buttons = 0;
break;
@@ -578,13 +719,31 @@ void MainMenuButtonHandler(void)
if (PadOneKeySinglePress(PAD_CROSS) )
{
- if(0)MainMenuRestoreInitValues();
- MainMenuBtn[btn_selected].f();
-
- if (menuLevel == ONE_TWO_PLAYERS_LEVEL)
+ if (menuLevel == LEVEL_LIST_LEVEL)
{
- btn_selected = PLAY_BUTTON_INDEX;
+ if (isLevelSelected == false)
+ {
+ isLevelSelected = true;
+ }
+ else
+ {
+ GameCfg.LVLPath = MainMenuLevelList[SelectedLevel];
+ GameCfg.PLTPath = MainMenuPltList[SelectedLevel][SelectedPlt];
+
+ EndAnimation();
+
+ // Start gameplay!
+ Game(&GameCfg);
+
+ MainMenuRestoreInitValues();
+ btn_selected = PLAY_BUTTON_INDEX;
+ isLevelSelected = false;
+ }
}
+ else
+ {
+ MainMenuBtn[btn_selected].f();
+ }
}
MainMenuBtn[btn_selected].selected = true;