aboutsummaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorXaviDCR92 <xavi.dcr@gmail.com>2018-02-25 05:25:33 +0100
committerXaviDCR92 <xavi.dcr@gmail.com>2018-02-25 05:25:33 +0100
commitbaa647ad7caf95ea2619d8456bcfd0f04a08a719 (patch)
tree7a7f5408a8ae0cc18a70d7795a2a47af30cf59f5 /Source
parent81d9242514b4e8e3fe97cf7063a15680f610bf2f (diff)
downloadairport-baa647ad7caf95ea2619d8456bcfd0f04a08a719.tar.gz
+ Added Message module, used for tutorials.
+ Added first tutorial level. * Font now inserts line feed automatically if the next word is too long to fit. * Gfx.c: added primitive list double buffering in order to gain some performance. * MapEditor: now airport can be defined inside the tool.
Diffstat (limited to 'Source')
-rw-r--r--[-rwxr-xr-x]Source/Exe/AIRPORT.elfbin330572 -> 332088 bytes
-rw-r--r--Source/Exe/AIRPORT.isobin1480704 -> 1484800 bytes
-rw-r--r--Source/Font.c86
-rw-r--r--Source/Font.h1
-rw-r--r--Source/Game.c60
-rw-r--r--Source/Gfx.c26
-rw-r--r--Source/Gfx.h3
-rw-r--r--Source/Makefile4
-rw-r--r--Source/MapEditor/MapEditor.pro.user2
-rw-r--r--Source/MapEditor/mainwindow.cpp43
-rw-r--r--Source/MapEditor/mainwindow.h8
-rw-r--r--Source/MapEditor/mainwindow.ui44
-rw-r--r--Source/MapEditor/settings.ini2
-rw-r--r--Source/Menu.c12
-rw-r--r--Source/Message.c187
-rw-r--r--Source/Message.h37
-rw-r--r--Source/PltParser.c123
-rw-r--r--Source/System.c2
18 files changed, 527 insertions, 113 deletions
diff --git a/Source/Exe/AIRPORT.elf b/Source/Exe/AIRPORT.elf
index 72a9f0f..113100d 100755..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 dc164f6..be2482d 100644
--- a/Source/Exe/AIRPORT.iso
+++ b/Source/Exe/AIRPORT.iso
Binary files differ
diff --git a/Source/Font.c b/Source/Font.c
index 3a216b8..4d7fd52 100644
--- a/Source/Font.c
+++ b/Source/Font.c
@@ -16,6 +16,21 @@
#define FONT_DEFAULT_INIT_CHAR '!'
/* *************************************
+ * Structs and enums
+ * *************************************/
+
+enum
+{
+ // We will use the most significant bit
+ // for internal purposes.
+
+ SQUARE_BTN_8BIT = 128,
+ CROSS_BTN_8BIT,
+ CIRCLE_BTN_8BIT,
+ TRIANGLE_BTN_8BIT
+};
+
+/* *************************************
* Local Prototypes
* *************************************/
@@ -88,6 +103,11 @@ void FontSetSize(TYPE_FONT * ptrFont, short size)
ptrFont->spr.h = ptrFont->char_h;
}
+void FontSetMaxCharPerLine(TYPE_FONT* ptrFont, uint8_t max)
+{
+ ptrFont->max_ch_wrap = max;
+}
+
void FontSetSpacing(TYPE_FONT* ptrFont, short spacing)
{
ptrFont->char_spacing = spacing;
@@ -101,7 +121,7 @@ void FontCyclic(void)
void FontPrintText(TYPE_FONT * ptrFont, short x, short y, char* str, ...)
{
uint16_t i;
- uint16_t line_count = 0;
+ uint8_t line_count = 0;
int result;
short orig_x = x;
@@ -133,7 +153,7 @@ void FontPrintText(TYPE_FONT * ptrFont, short x, short y, char* str, ...)
for (i = 0; i < result ; i++)
{
- char _ch = _internal_text[i];
+ unsigned char _ch = _internal_text[i];
if (_ch == '\0')
{
@@ -144,13 +164,73 @@ void FontPrintText(TYPE_FONT * ptrFont, short x, short y, char* str, ...)
switch(_ch)
{
case ' ':
- x += ptrFont->char_w;
+ {
+ bool linefeed_needed = false;
+
+ // Check if the next word fits on the same line
+ if ( (ptrFont->flags & FONT_WRAP_LINE) && (ptrFont->max_ch_wrap != 0) )
+ {
+ uint16_t j;
+ uint8_t aux_line_count = line_count;
+
+ for (j = i + 1; j < result; j++)
+ {
+ if (_internal_text[j] != ' ')
+ {
+ if (++aux_line_count >= ptrFont->max_ch_wrap)
+ {
+ line_count = 0;
+ x = orig_x;
+ y += ptrFont->char_h;
+ linefeed_needed = true;
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ if (linefeed_needed == false)
+ {
+ x += ptrFont->char_w;
+ }
+
continue;
+ }
case '\n':
x = orig_x;
y += ptrFont->char_h;
break;
+
+ case SQUARE_BTN_8BIT:
+ GfxDrawButton(x, y, PAD_SQUARE);
+
+ x += BUTTON_SIZE;
+ break;
+
+ case CIRCLE_BTN_8BIT:
+ GfxDrawButton(x, y, PAD_CIRCLE);
+
+ x += BUTTON_SIZE;
+ break;
+
+ case TRIANGLE_BTN_8BIT:
+ GfxDrawButton(x, y, PAD_TRIANGLE);
+
+ x += BUTTON_SIZE;
+ break;
+
+ case CROSS_BTN_8BIT:
+ GfxDrawButton(x, y, PAD_CROSS);
+
+ x += BUTTON_SIZE;
+ break;
+
default:
+
if ( (ptrFont->flags & FONT_WRAP_LINE) && (ptrFont->max_ch_wrap != 0) )
{
if (++line_count >= ptrFont->max_ch_wrap)
diff --git a/Source/Font.h b/Source/Font.h
index ca6be3c..d501a3e 100644
--- a/Source/Font.h
+++ b/Source/Font.h
@@ -27,6 +27,7 @@ void FontSetInitChar(TYPE_FONT * ptrFont, char c);
void FontSetFlags(TYPE_FONT * ptrFont, FONT_FLAGS flags);
void FontCyclic(void);
void FontSetSpacing(TYPE_FONT* ptrFont, short spacing);
+void FontSetMaxCharPerLine(TYPE_FONT* ptrFont, uint8_t max);
/* *************************************
* Global variables
diff --git a/Source/Game.c b/Source/Game.c
index 0263933..1c966ac 100644
--- a/Source/Game.c
+++ b/Source/Game.c
@@ -12,6 +12,7 @@
#include "EndAnimation.h"
#include "Sfx.h"
#include "Pad.h"
+#include "Message.h"
/* *************************************
* Defines
@@ -444,6 +445,9 @@ void GameInit(TYPE_GAME_CONFIGURATION* pGameCfg)
GameStartupFlag = true;
+ // Has to be initialized before loading *.PLT files inside LoadMenu().
+ MessageInit();
+
if (firstLoad != false)
{
firstLoad = false;
@@ -782,7 +786,7 @@ void GameEmergencyMode(void)
for (i = 0; i < MAX_PLAYERS; i++)
{
- if (disconnected_players & (1<<i) )
+ if (disconnected_players & (1 << i) )
{
FontPrintText( &SmallFont,
PAD_DISCONNECTED_TEXT_X,
@@ -803,11 +807,11 @@ void GameEmergencyMode(void)
if (PadXConnected[i]() == false)
{
enabled = true;
- disconnected_players |= 1<<i;
+ disconnected_players |= 1 << i;
}
else
{
- disconnected_players &= ~(1<<i);
+ disconnected_players &= ~(1 << i);
}
}
}
@@ -896,6 +900,7 @@ void GameCalculations(void)
GameGetAircraftTilemap(i);
}
+ MessageHandler();
AircraftHandler();
GameGuiCalculateSlowScore();
@@ -1057,12 +1062,11 @@ void GameClockFlights(uint8_t i)
void GameGraphics(void)
{
- int i;
+ uint8_t i;
bool split_screen = false;
- SystemAcknowledgeFrame();
-
- while ( (SystemRefreshNeeded() == false) || (GfxReadyForDMATransfer() == false) );
+ // Caution: blocking function!
+ MessageRender();
if (TwoPlayersActive != false)
{
@@ -1113,8 +1117,8 @@ void GameGraphics(void)
if (split_screen != false)
{
- GfxDrawScene_NoSwap();
- while (GfxIsGPUBusy() != false);
+ //~ GfxDrawScene_NoSwap();
+ //~ while (GsIsDrawing() != false);
}
}
}
@@ -1136,7 +1140,7 @@ void GameGraphics(void)
if (split_screen != false)
{
- GfxDrawScene_NoSwap();
+ //~ GfxDrawScene_NoSwap();
}
GfxDrawScene();
@@ -2739,8 +2743,6 @@ void GameAssignRunwaytoAircraft(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFli
// Remember that ptrPlayer->SelectedAircraft contains an index to
// be used with ptrFlightData.
- Serial_printf("aircraftIndex = %d\n",aircraftIndex);
-
if (ptrFlightData->State[aircraftIndex] == STATE_APPROACH)
{
uint8_t j;
@@ -2763,7 +2765,6 @@ void GameAssignRunwaytoAircraft(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFli
for (i = 0; i < GAME_MAX_RWY_LENGTH; i++)
{
rwyTiles[i] = GameLevelBuffer[rwyArray[i]];
- dprintf("rwyTiles[%d] = 0x%02X\n", i, rwyTiles[i]);
}
for (i = 0; (i < GAME_MAX_RWY_LENGTH) && (rwyExit == 0); i++)
@@ -2816,36 +2817,9 @@ void GameAssignRunwaytoAircraft(TYPE_PLAYER* ptrPlayer, TYPE_FLIGHT_DATA* ptrFli
targets[0] = rwyEntryData.rwyEntryTile;
targets[1] = targets[0] + rwyEntryData.rwyStep;
- Serial_printf("Added the following targets = ");
-
- for (i = 0; i < (sizeof(targets) / sizeof(targets[0])); i++)
- {
- Serial_printf("%d ", targets[i]);
- }
-
- Serial_printf("\n");
-
AircraftAddTargets(AircraftFromFlightDataIndex(aircraftIndex), targets);
ptrFlightData->State[aircraftIndex] = STATE_ENTERING_RWY;
-
- /*uint16_t i;
-
-
- i = rwyEntryData.rwyEntryTile;
-
- DEBUG_PRINT_VAR(rwyEntryData.rwyEntryTile);
- DEBUG_PRINT_VAR(rwyEntryData.rwyStep);
-
- while (GameLevelBuffer[i] != TILE_RWY_START_1)
- {
- if (i > rwyEntryData.rwyStep)
- {
- i -= rwyEntryData.rwyStep;
- }
- }
-
- GameGetSelectedRunwayArray(i);*/
}
}
@@ -2905,11 +2879,9 @@ short GameGetYFromTile_short(uint16_t tile)
tile /= GameLevelColumns;
- //retVal = (fix16_t)(tile << TILE_SIZE_BIT_SHIFT);
retVal = (tile << TILE_SIZE_BIT_SHIFT);
// Always point to tile center
- //retVal += TILE_SIZE >> 1;
retVal += TILE_SIZE >> 1;
return retVal;
@@ -3804,14 +3776,10 @@ void GameGetRunwayEntryTile(uint8_t aircraftIdx, TYPE_RWY_ENTRY_DATA* ptrRwyEntr
&&
((i - ptrRwyEntry->rwyStep) < GameLevelSize ) )
{
- DEBUG_PRINT_VAR(i);
i -= ptrRwyEntry->rwyStep;
}
ptrRwyEntry->rwyHeader = i;
-
- DEBUG_PRINT_VAR(ptrRwyEntry->rwyHeader);
- DEBUG_PRINT_VAR(ptrRwyEntry->rwyEntryTile);
}
else
{
diff --git a/Source/Gfx.c b/Source/Gfx.c
index d4de561..bc47ae9 100644
--- a/Source/Gfx.c
+++ b/Source/Gfx.c
@@ -26,8 +26,6 @@
enum
{
- BUTTON_SIZE = 16,
-
BUTTON_CROSS_U = 48,
BUTTON_CROSS_V = 0,
@@ -82,7 +80,7 @@ GsSprite PSXButtons;
/* *************************************
* Local Prototypes
* *************************************/
-
+void GfxSetPrimitiveList(unsigned int* ptrList);
/* *************************************
@@ -95,6 +93,9 @@ static GsDrawEnv DrawEnv;
static GsDispEnv DispEnv;
// Primitive list (it contains all the graphical data for the GPU)
static unsigned int prim_list[PRIMITIVE_LIST_SIZE];
+
+//Primitive list double buffering
+static unsigned int prim_list2[PRIMITIVE_LIST_SIZE];
// Tells other modules whether data is being loaded to GPU
static volatile bool gfx_busy;
// Dictates (R,G,B) brigthness to all sprites silently
@@ -213,9 +214,14 @@ void GfxInitDispEnv(void)
* used internally by PSXSDK).
*
* **********************************************************************/
-void GfxSetPrimitiveList(void)
+void GfxSetPrimitiveList(unsigned int* ptrList)
{
- GsSetList(prim_list);
+ GsSetList(ptrList);
+}
+
+void GfxSetDefaultPrimitiveList(void)
+{
+ GfxSetPrimitiveList(prim_list);
}
/* **********************************************************************
@@ -278,12 +284,18 @@ bool GfxReadyForDMATransfer(void)
* **********************************************************************/
void GfxDrawScene(void)
{
- while ( (SystemRefreshNeeded() == false)
- ||
+ static unsigned int* ptrPrimList = prim_list;
+
+ ptrPrimList = ((void*)ptrPrimList == (void*)&prim_list)? prim_list2 : prim_list;
+
+ while ( (SystemRefreshNeeded() == false)
+ ||
(GfxIsGPUBusy() != false) );
GfxDrawScene_Fast();
+ GfxSetPrimitiveList(ptrPrimList);
+
SystemCyclicHandler();
}
diff --git a/Source/Gfx.h b/Source/Gfx.h
index 1f8111e..db9d0bf 100644
--- a/Source/Gfx.h
+++ b/Source/Gfx.h
@@ -23,6 +23,7 @@
#define GFX_2HZ_FLASH (1<<8)
#define FULL_LUMINANCE 0xFF
#define ROTATE_BIT_SHIFT 12 // 4096 = 2^12
+#define BUTTON_SIZE 16
/* *************************************
* Global prototypes
@@ -30,7 +31,7 @@
void GfxInitDrawEnv(void);
void GfxInitDispEnv(void);
-void GfxSetPrimitiveList(void);
+void GfxSetDefaultPrimitiveList(void);
// Renders new scene. Use this function unless you know what you are doing!
void GfxDrawScene(void);
diff --git a/Source/Makefile b/Source/Makefile
index 7de5746..9eeb9d0 100644
--- a/Source/Makefile
+++ b/Source/Makefile
@@ -50,7 +50,7 @@ SRC_DIR = .
OBJECTS = $(addprefix $(OBJ_DIR)/, main.o System.o Menu.o Gfx.o Pad.o MainMenuBtnAni.o \
LoadMenu.o GameGui.o Sfx.o Camera.o EndAnimation.o \
PSXSDKIntro.o PltParser.o Game.o Font.o MemCard.o \
- Aircraft.o Serial.o Timer.o)
+ Aircraft.o Serial.o Timer.o Message.o)
# Source dependencies:
DEPS = $(OBJECTS:.o=.d)
@@ -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 EASY.PLT)
+LEVEL_OBJECTS = $(addprefix $(OBJ_LEVELS_DIR)/, LEVEL1.LVL LEVEL2.LVL LEVEL2.PLT LEVEL1.PLT EASY.PLT TUTORIA1.PLT)
# Sprite objects:
BMP2TIM = bmp2tim
diff --git a/Source/MapEditor/MapEditor.pro.user b/Source/MapEditor/MapEditor.pro.user
index aaf3a0c..48e1dbc 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, 2018-01-01T07:36:40. -->
+<!-- Written by QtCreator 4.0.3, 2018-02-23T20:22:49. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
diff --git a/Source/MapEditor/mainwindow.cpp b/Source/MapEditor/mainwindow.cpp
index ed0bdc9..2da1d1b 100644
--- a/Source/MapEditor/mainwindow.cpp
+++ b/Source/MapEditor/mainwindow.cpp
@@ -4,6 +4,8 @@
#include <QGraphicsPixmapItem>
#include <QInputDialog>
+#define DEFAULT_AIRPORT_NAME QByteArray("Default Airport\0")
+
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
@@ -11,13 +13,13 @@ MainWindow::MainWindow(QWidget *parent) :
selected_item(-1)
{
ui->setupUi(this);
-
- ui->centralWidget->setWindowTitle("Airport Map Editor");
+ this->setWindowTitle(APP_NAME + " " + APP_VERSION_STRING);
connect(ui->LoadMap_Btn, SIGNAL(released()), this, SLOT(onLoadMap()));
connect(ui->CreateMap_Btn, SIGNAL(released()), this, SLOT(onCreateMap()));
connect(ui->saveMap_Btn, SIGNAL(released()), this, SLOT(onSaveMap(void)));
connect(ui->showNumbers_Checkbox, SIGNAL(stateChanged(int)), this, SLOT(onShowNumbers(int)));
+ connect(ui->airportName_Label, SIGNAL(textChanged(QString)), this, SLOT(onAirportNameModified(QString)));
connect(gscene, SIGNAL(positionClicked(QPointF)), this, SLOT(onMapItemClicked(QPointF)));
connect(gscene, SIGNAL(noItemSelected(void)), this, SLOT(onNoItemSelected(void)));
@@ -161,15 +163,18 @@ void MainWindow::onCreateMap(void)
data.append((char)0x18);
}
- data.append("Default airport");
+ data.append(DEFAULT_AIRPORT_NAME);
+
+ for (int i = 0x04 + DEFAULT_AIRPORT_NAME.count(); i < 0x1C; i++)
+ {
+ data.append('\0');
+ }
for (int i = (data.count() - 1); i < DATA_HEADER_SIZE; i++)
{
data.append(0xFF);
}
- qDebug() << data.count();
-
int size_int = size.toInt(&ok, 10);
if (ok == false)
@@ -243,7 +248,13 @@ void MainWindow::onProcessMapFile(QByteArray data)
return;
}
- ds.skipRawData(0x3B);
+ char airportName[0x1A];
+
+ ds.readRawData(airportName, sizeof(airportName) / sizeof(airportName[0]));
+
+ ui->airportName_Label->setText(QString(airportName));
+
+ ds.skipRawData(0x3B - 0x1A);
gscene->clear();
gscene->clearFocus();
@@ -417,3 +428,23 @@ void MainWindow::loadTilesetData(void)
}
}
}
+
+void MainWindow::onAirportNameModified(QString name)
+{
+ if (map_buffer.isEmpty() == true)
+ {
+ return;
+ }
+
+ for (int i = 0x04, j = 0; i < 0x1C; i++)
+ {
+ if (j < name.count() )
+ {
+ map_buffer[i] = name.at(j++).toLatin1();
+ }
+ else
+ {
+ map_buffer[i] = '\0';
+ }
+ }
+}
diff --git a/Source/MapEditor/mainwindow.h b/Source/MapEditor/mainwindow.h
index 4926772..705404f 100644
--- a/Source/MapEditor/mainwindow.h
+++ b/Source/MapEditor/mainwindow.h
@@ -9,6 +9,9 @@
#include "mygraphicsscene.h"
#include "ui_mainwindow.h"
+#define APP_NAME QString("Airport Map Editor")
+#define APP_VERSION_STRING QString("0.2")
+
#define TILE_SIZE 64
#define DATA_HEADER_SIZE 0x3F
#define TILE_MIRROR_FLAG ((char) 0x80)
@@ -38,15 +41,16 @@ private:
int selected_item;
QHash<int, QString> tilesetData;
-protected slots:
+private slots:
void onLoadMap(void);
void onCreateMap(void);
- void onProcessMapFile(QByteArray data);
+ void onProcessMapFile(QByteArray);
void onMapItemClicked(QPointF);
void onNoItemSelected(void);
void onListItemSelected(void);
void onSaveMap(void);
void onShowNumbers(int);
+ void onAirportNameModified(QString);
};
#endif // MAINWINDOW_H
diff --git a/Source/MapEditor/mainwindow.ui b/Source/MapEditor/mainwindow.ui
index 098a9f8..f5f3514 100644
--- a/Source/MapEditor/mainwindow.ui
+++ b/Source/MapEditor/mainwindow.ui
@@ -24,7 +24,7 @@
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="1" column="0">
+ <item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="showNumbers_Checkbox">
@@ -45,17 +45,7 @@
</item>
</layout>
</item>
- <item row="0" column="2">
- <widget class="QGraphicsView" name="graphicsView">
- <property name="minimumSize">
- <size>
- <width>640</width>
- <height>480</height>
- </size>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
+ <item row="5" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="CreateMap_Btn">
@@ -80,7 +70,17 @@
</item>
</layout>
</item>
- <item row="0" column="0">
+ <item row="1" column="2">
+ <widget class="QGraphicsView" name="graphicsView">
+ <property name="minimumSize">
+ <size>
+ <width>640</width>
+ <height>480</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
<widget class="QListWidget" name="listWidget">
<property name="maximumSize">
<size>
@@ -90,6 +90,24 @@
</property>
</widget>
</item>
+ <item row="0" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Airport name:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="airportName_Label">
+ <property name="maxLength">
+ <number>18</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
diff --git a/Source/MapEditor/settings.ini b/Source/MapEditor/settings.ini
index af1583e..83bee36 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/TEST_LEVEL2.LVL
diff --git a/Source/Menu.c b/Source/Menu.c
index 325c0c4..a1f17ef 100644
--- a/Source/Menu.c
+++ b/Source/Menu.c
@@ -20,7 +20,7 @@
* Defines *
* *************************************/
-#define BUTTON_SIZE 64
+#define MAIN_MENU_BUTTON_SIZE 64
#define SELECTED_BUTTON_LUMINANCE 0xC0
/* **************************************
@@ -168,7 +168,11 @@ static const char* MainMenuFiles[] = { "cdrom:\\DATA\\SPRITES\\MAINMENU.TIM;1" ,
static const char* MainMenuLevelList[] = { [LEVEL1] = "cdrom:\\DATA\\LEVELS\\LEVEL1.LVL;1" ,
[LEVEL2] = "cdrom:\\DATA\\LEVELS\\LEVEL2.LVL;1" };
-static const char* MainMenuLevel1Plt[] = {"cdrom:\\DATA\\LEVELS\\LEVEL1.PLT;1", "cdrom:\\DATA\\LEVELS\\EASY.PLT;1", NULL};
+static const char* MainMenuLevel1Plt[] = { "cdrom:\\DATA\\LEVELS\\TUTORIA1.PLT;1",
+ "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};
@@ -751,8 +755,8 @@ void MainMenuButtonHandler(void)
void MainMenuDrawButton(TYPE_MMBtn * btn)
{
- MenuSpr.w = BUTTON_SIZE;
- MenuSpr.h = BUTTON_SIZE;
+ MenuSpr.w = MAIN_MENU_BUTTON_SIZE;
+ MenuSpr.h = MAIN_MENU_BUTTON_SIZE;
if ( (btn->timer) < (MainMenuBtnAni_sz - 1) )
{
diff --git a/Source/Message.c b/Source/Message.c
new file mode 100644
index 0000000..e481cf2
--- /dev/null
+++ b/Source/Message.c
@@ -0,0 +1,187 @@
+/* **************************************
+ * Includes *
+ * *************************************/
+
+#include "Message.h"
+#include "Gfx.h"
+#include "Pad.h"
+
+/* **************************************
+ * Defines *
+ * *************************************/
+
+#define NO_MESSAGE ((uint8_t)0xFF)
+#define MESSAGE_FIFO_SIZE 16
+
+/* **************************************
+ * Structs and enums *
+ * *************************************/
+
+/* **************************************
+ * Local prototypes *
+ * *************************************/
+
+/* **************************************
+ * Local variables *
+ * *************************************/
+
+static TYPE_MESSAGE_DATA tMessageFIFO[MESSAGE_FIFO_SIZE];
+static uint8_t MessageIdx;
+
+void MessageInit(void)
+{
+ bzero(tMessageFIFO, sizeof(tMessageFIFO));
+ MessageIdx = NO_MESSAGE;
+}
+
+bool MessageCreate(TYPE_MESSAGE_DATA* ptrMessage)
+{
+ uint8_t i;
+
+ for (i = 0; i < MESSAGE_FIFO_SIZE; i++)
+ {
+ TYPE_MESSAGE_DATA* m = &tMessageFIFO[i];
+
+ if (m->used == false)
+ {
+ memcpy(m, ptrMessage, sizeof(TYPE_MESSAGE_DATA));
+
+ m->used = true;
+
+ Serial_printf("Successfully allocated message into slot %d.\n", i);
+
+ return true;
+ }
+ }
+
+ Serial_printf("Could not allocate message resource to FIFO.\n");
+ return false;
+}
+
+void MessageHandler(void)
+{
+ uint8_t i;
+
+ if (System1SecondTick() != false)
+ {
+ for (i = 0; i < MESSAGE_FIFO_SIZE; i++)
+ {
+ TYPE_MESSAGE_DATA* ptrMessage = &tMessageFIFO[i];
+
+ if (ptrMessage->used != false)
+ {
+ if (ptrMessage->Timeout == 0)
+ {
+ ptrMessage->used = false;
+ MessageIdx = i;
+ }
+ else
+ {
+ ptrMessage->Timeout--;
+ }
+ }
+ }
+ }
+}
+
+void MessageRender(void)
+{
+ if (MessageIdx != NO_MESSAGE)
+ {
+ enum
+ {
+ MESSAGE_RECT_W = 256,
+ MESSAGE_RECT_H = 72,
+ MESSAGE_RECT_X = (X_SCREEN_RESOLUTION - MESSAGE_RECT_W) >> 1,
+ MESSAGE_RECT_Y = (Y_SCREEN_RESOLUTION - MESSAGE_RECT_H) >> 1,
+ };
+
+ GsGPoly4 messageRect = { .x[0] = MESSAGE_RECT_X,
+ .x[1] = MESSAGE_RECT_X + MESSAGE_RECT_W,
+ .x[2] = messageRect.x[0],
+ .x[3] = messageRect.x[1],
+
+ .y[0] = MESSAGE_RECT_Y,
+ .y[1] = messageRect.y[0],
+ .y[2] = MESSAGE_RECT_Y + MESSAGE_RECT_H,
+ .y[3] = messageRect.y[2] ,
+
+ .r[0] = 0,
+ .r[1] = 0,
+ .r[2] = 0,
+ .r[3] = 0,
+
+ .g[0] = NORMAL_LUMINANCE,
+ .g[1] = NORMAL_LUMINANCE,
+ .g[2] = NORMAL_LUMINANCE >> 1,
+ .g[3] = NORMAL_LUMINANCE >> 1,
+
+ .b[0] = NORMAL_LUMINANCE >> 2,
+ .b[1] = NORMAL_LUMINANCE >> 2,
+ .b[2] = NORMAL_LUMINANCE >> 3,
+ .b[3] = NORMAL_LUMINANCE >> 3,
+
+ .attribute = 0 };
+
+ GsSprite backgroundSpr = {0};
+
+ GfxSaveDisplayData(&backgroundSpr);
+
+ backgroundSpr.x = 0;
+ backgroundSpr.y = 0;
+
+ do
+ {
+ enum
+ {
+ MESSAGE_TEXT_X = MESSAGE_RECT_X + 8,
+ MESSAGE_TEXT_Y = MESSAGE_RECT_Y + 8,
+
+ CONTINUE_TEXT_X = MESSAGE_TEXT_X,
+ CONTINUE_TEXT_Y = MESSAGE_RECT_Y + MESSAGE_RECT_H - 16,
+ };
+
+ char* strMessage = MessageGetString();
+
+ GfxSortSprite(&backgroundSpr);
+
+ GsSortGPoly4(&messageRect);
+
+ if (strMessage != NULL)
+ {
+ enum
+ {
+ MAX_CH_PER_LINE = 32
+ };
+
+ FontSetFlags(&SmallFont, FONT_WRAP_LINE);
+ FontSetMaxCharPerLine(&SmallFont, MAX_CH_PER_LINE);
+
+ FontPrintText(&SmallFont, MESSAGE_TEXT_X, MESSAGE_TEXT_Y, strMessage);
+
+ // Restore default values
+ FontSetFlags(&SmallFont, FONT_NOFLAGS);
+ FontSetMaxCharPerLine(&SmallFont, 0);
+ }
+
+ FontPrintText(&SmallFont, CONTINUE_TEXT_X, CONTINUE_TEXT_Y, "Press to continue...");
+
+ GfxDrawButton(CONTINUE_TEXT_X + (strlen("Press") << 3) - 4, CONTINUE_TEXT_Y - 4, PAD_CROSS);
+
+ GfxDrawScene_Slow();
+
+ } while (PadOneKeySinglePress(PAD_CROSS) == false);
+
+ MessageIdx = NO_MESSAGE;
+ }
+}
+
+char* MessageGetString(void)
+{
+ if (MessageIdx != NO_MESSAGE)
+ {
+ return tMessageFIFO[MessageIdx].strMessage;
+ }
+
+ return NULL;
+}
diff --git a/Source/Message.h b/Source/Message.h
new file mode 100644
index 0000000..e6bbcce
--- /dev/null
+++ b/Source/Message.h
@@ -0,0 +1,37 @@
+#ifndef MESSAGE_HEADER__
+#define MESSAGE_HEADER__
+
+/* *************************************
+ * Includes
+ * *************************************/
+
+#include "Global_Inc.h"
+
+/* *************************************
+ * Defines
+ * *************************************/
+
+#define MAX_MESSAGE_STR_SIZE 256
+
+/* *************************************
+ * Structs and enums
+ * *************************************/
+
+typedef struct t_messagedata
+{
+ bool used;
+ uint32_t Timeout;
+ char strMessage[MAX_MESSAGE_STR_SIZE];
+}TYPE_MESSAGE_DATA;
+
+/* *************************************
+ * Global prototypes
+ * *************************************/
+
+void MessageInit(void);
+bool MessageCreate(TYPE_MESSAGE_DATA* ptrMessage);
+void MessageHandler(void);
+void MessageRender(void);
+char* MessageGetString(void);
+
+#endif // MESSAGE_HEADER__
diff --git a/Source/PltParser.c b/Source/PltParser.c
index 8bcbc0f..29d1692 100644
--- a/Source/PltParser.c
+++ b/Source/PltParser.c
@@ -5,12 +5,14 @@
#include "PltParser.h"
#include "System.h"
#include "Game.h"
+#include "Message.h"
/* *************************************
* Defines
* *************************************/
-#define LINE_MAX_CHARACTERS 100
+#define LINE_MAX_CHARACTERS MAX_MESSAGE_STR_SIZE
+#define MESSAGE_HEADER_STR "MESSAGE"
/* **************************************
* Structs and enums *
@@ -28,22 +30,12 @@ static void PltParserResetBuffers(TYPE_FLIGHT_DATA* ptrFlightData);
bool PltParserLoadFile(char* strPath, TYPE_FLIGHT_DATA* ptrFlightData)
{
- enum
- {
- DEPARTURE_ARRIVAL_INDEX = 0,
- FLIGHT_NUMBER_INDEX,
- PASSENGERS_INDEX,
- HOURS_MINUTES_INDEX,
- PARKING_INDEX,
- REMAINING_TIME_INDEX
- };
-
- enum
- {
- PLT_HOUR_MINUTE_CHARACTERS = 2,
- PLT_FIRST_LINE_CHARACTERS = 5,
- PLT_COLON_POSITION = 2
- };
+ enum
+ {
+ PLT_HOUR_MINUTE_CHARACTERS = 2,
+ PLT_FIRST_LINE_CHARACTERS = 5,
+ PLT_COLON_POSITION = 2
+ };
uint8_t i;
uint8_t j;
@@ -138,6 +130,15 @@ bool PltParserLoadFile(char* strPath, TYPE_FLIGHT_DATA* ptrFlightData)
}
else
{
+ typedef enum t_lineType
+ {
+ MESSAGE_INFO,
+ AIRCRAFT_DATA
+ }TYPE_LINE;
+
+ TYPE_LINE tLine = AIRCRAFT_DATA; // Default value
+ TYPE_MESSAGE_DATA tMessage = {0};
+
// File header (initial game time) has already been read
strncpy(lineBuffer, buffer, LINE_MAX_CHARACTERS);
@@ -151,6 +152,25 @@ bool PltParserLoadFile(char* strPath, TYPE_FLIGHT_DATA* ptrFlightData)
{
switch(i)
{
+ enum
+ {
+ DEPARTURE_ARRIVAL_INDEX = 0,
+ FLIGHT_NUMBER_INDEX,
+ PASSENGERS_INDEX,
+ HOURS_MINUTES_INDEX,
+ PARKING_INDEX,
+ REMAINING_TIME_INDEX
+ };
+
+ enum
+ {
+ MESSAGE_HEADER_INDEX = 0,
+ MESSAGE_TIMEOUT_INDEX,
+ MESSAGE_STR_INDEX
+ };
+
+ //case MESSAGE_HEADER_INDEX:
+ // Fall through
case DEPARTURE_ARRIVAL_INDEX:
if (strncmp(lineBufferPtr,"DEPARTURE",strlen("DEPARTURE") ) == 0)
@@ -163,21 +183,69 @@ bool PltParserLoadFile(char* strPath, TYPE_FLIGHT_DATA* ptrFlightData)
ptrFlightData->FlightDirection[aircraftIndex] = ARRIVAL;
Serial_printf("Aircraft %d set to ARRIVAL.\n",aircraftIndex);
}
+ else if (strncmp(lineBufferPtr, MESSAGE_HEADER_STR, strlen(MESSAGE_HEADER_STR) ) == 0)
+ {
+ tLine = MESSAGE_INFO;
+ }
else
{
Serial_printf("Flight direction is not correct!\n");
}
break;
+ //case MESSAGE_TIMEOUT_INDEX:
+ // Fall through
case FLIGHT_NUMBER_INDEX:
- strncpy(ptrFlightData->strFlightNumber[aircraftIndex],lineBufferPtr,GAME_MAX_CHARACTERS);
- ptrFlightData->strFlightNumber[aircraftIndex][GAME_MAX_CHARACTERS - 1] = '\0';
- Serial_printf("Aircraft %d flight number set to %s.\n",aircraftIndex,ptrFlightData->strFlightNumber[aircraftIndex]);
+
+ if (tLine == MESSAGE_INFO)
+ {
+ uint8_t Hours;
+ uint8_t Minutes;
+
+ if ( strlen(lineBufferPtr) != strlen("HH:MM") )
+ {
+ Serial_printf("Hour minute format is not correct! Read %s\n", lineBufferPtr);
+ break;
+ }
+
+ // Copy hour
+ strHour[0] = lineBufferPtr[0];
+ strHour[1] = lineBufferPtr[1];
+ // Copy minutes
+ strMinutes[0] = lineBufferPtr[3];
+ strMinutes[1] = lineBufferPtr[4];
+
+ Hours = (uint8_t)atoi(strHour);
+ Minutes = (uint8_t)atoi(strMinutes);
+
+ tMessage.Timeout = (uint32_t)(Hours * 60) + Minutes;
+
+ Serial_printf("Message timeout: %d seconds.\n", tMessage.Timeout);
+ }
+ else
+ {
+ strncpy(ptrFlightData->strFlightNumber[aircraftIndex],lineBufferPtr,GAME_MAX_CHARACTERS);
+ ptrFlightData->strFlightNumber[aircraftIndex][GAME_MAX_CHARACTERS - 1] = '\0';
+ Serial_printf("Aircraft %d flight number set to %s.\n",aircraftIndex,ptrFlightData->strFlightNumber[aircraftIndex]);
+ }
+
break;
+ // case MESSAGE_STR_INDEX:
+ // Fall through
case PASSENGERS_INDEX:
- ptrFlightData->Passengers[aircraftIndex] = atoi(lineBufferPtr);
- Serial_printf("Aircraft %d passengers set to %d.\n",aircraftIndex,ptrFlightData->Passengers[aircraftIndex]);
+ if (tLine == MESSAGE_INFO)
+ {
+ strncpy(tMessage.strMessage, lineBufferPtr, MAX_MESSAGE_STR_SIZE);
+ MessageCreate(&tMessage);
+
+ bzero(&tMessage, sizeof(tMessage));
+ }
+ else
+ {
+ ptrFlightData->Passengers[aircraftIndex] = atoi(lineBufferPtr);
+ Serial_printf("Aircraft %d passengers set to %d.\n",aircraftIndex,ptrFlightData->Passengers[aircraftIndex]);
+ }
break;
case PARKING_INDEX:
@@ -210,8 +278,8 @@ bool PltParserLoadFile(char* strPath, TYPE_FLIGHT_DATA* ptrFlightData)
ptrFlightData->Minutes[aircraftIndex] = (uint8_t)atoi(strMinutes);
Serial_printf("Aircraft %d time set to %.2d:%.2d.\n", aircraftIndex,
- ptrFlightData->Hours[aircraftIndex],
- ptrFlightData->Minutes[aircraftIndex] );
+ ptrFlightData->Hours[aircraftIndex],
+ ptrFlightData->Minutes[aircraftIndex] );
break;
case REMAINING_TIME_INDEX:
@@ -228,8 +296,11 @@ bool PltParserLoadFile(char* strPath, TYPE_FLIGHT_DATA* ptrFlightData)
i++;
}
- ptrFlightData->State[aircraftIndex] = STATE_IDLE;
- aircraftIndex++;
+ if (tLine == AIRCRAFT_DATA)
+ {
+ ptrFlightData->State[aircraftIndex] = STATE_IDLE;
+ aircraftIndex++;
+ }
}
buffer = strtok_r(NULL,"\n",&pltBufferSavePtr);
diff --git a/Source/System.c b/Source/System.c
index b7f9101..0c6657b 100644
--- a/Source/System.c
+++ b/Source/System.c
@@ -104,7 +104,7 @@ void SystemInit(void)
//Set VBlank Handler for screen refresh
SetVBlankHandler(&ISR_SystemDefaultVBlank);
//Set Primitive List
- GfxSetPrimitiveList();
+ GfxSetDefaultPrimitiveList();
// Init memory card
MemCardInit();
//Initial value for system_busy