diff options
| author | XaviDCR92 <xavi.dcr@gmail.com> | 2018-02-25 05:25:33 +0100 |
|---|---|---|
| committer | XaviDCR92 <xavi.dcr@gmail.com> | 2018-02-25 05:25:33 +0100 |
| commit | baa647ad7caf95ea2619d8456bcfd0f04a08a719 (patch) | |
| tree | 7a7f5408a8ae0cc18a70d7795a2a47af30cf59f5 /Source | |
| parent | 81d9242514b4e8e3fe97cf7063a15680f610bf2f (diff) | |
| download | airport-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.elf | bin | 330572 -> 332088 bytes | |||
| -rw-r--r-- | Source/Exe/AIRPORT.iso | bin | 1480704 -> 1484800 bytes | |||
| -rw-r--r-- | Source/Font.c | 86 | ||||
| -rw-r--r-- | Source/Font.h | 1 | ||||
| -rw-r--r-- | Source/Game.c | 60 | ||||
| -rw-r--r-- | Source/Gfx.c | 26 | ||||
| -rw-r--r-- | Source/Gfx.h | 3 | ||||
| -rw-r--r-- | Source/Makefile | 4 | ||||
| -rw-r--r-- | Source/MapEditor/MapEditor.pro.user | 2 | ||||
| -rw-r--r-- | Source/MapEditor/mainwindow.cpp | 43 | ||||
| -rw-r--r-- | Source/MapEditor/mainwindow.h | 8 | ||||
| -rw-r--r-- | Source/MapEditor/mainwindow.ui | 44 | ||||
| -rw-r--r-- | Source/MapEditor/settings.ini | 2 | ||||
| -rw-r--r-- | Source/Menu.c | 12 | ||||
| -rw-r--r-- | Source/Message.c | 187 | ||||
| -rw-r--r-- | Source/Message.h | 37 | ||||
| -rw-r--r-- | Source/PltParser.c | 123 | ||||
| -rw-r--r-- | Source/System.c | 2 |
18 files changed, 527 insertions, 113 deletions
diff --git a/Source/Exe/AIRPORT.elf b/Source/Exe/AIRPORT.elf Binary files differindex 72a9f0f..113100d 100755..100644 --- a/Source/Exe/AIRPORT.elf +++ b/Source/Exe/AIRPORT.elf diff --git a/Source/Exe/AIRPORT.iso b/Source/Exe/AIRPORT.iso Binary files differindex dc164f6..be2482d 100644 --- a/Source/Exe/AIRPORT.iso +++ b/Source/Exe/AIRPORT.iso 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 |
