170 lines
7.1 KiB
C++
170 lines
7.1 KiB
C++
/* *****************************************************************************
|
|
* FX gameState example v1.00 by Mr.Blinky Jan.2023 licenced under CC0
|
|
* *****************************************************************************
|
|
*
|
|
* This is a example showing how you can save and load game data to the FX flash
|
|
* chip.
|
|
*
|
|
* Before this example sketch is uploaded and run on the Arduboy FX, make sure
|
|
* the fxdata of this sketch has been built and uploaded to the Arduboy FX.
|
|
*
|
|
* If the Arduboy FX Arduino plugin has been installed you can simply choose the
|
|
* 'Build and upload Arduboy FX data' from the Arduino IDE Tools menu. Since the
|
|
* data has already been prebuild for this demo you may alsu choose the 'upload
|
|
* existing Arduboy FX data' option.
|
|
*
|
|
* Alternatively the fxdata.txt script file can be build using the fxdata-build.py
|
|
* Python script and the fxdata.bin file can be uploaded using the
|
|
* fxdata-upload.py, uploader-gui.py, or flash-writer.py (using the -d switch)
|
|
* Python scripts.
|
|
*
|
|
* *****************************************************************************
|
|
*
|
|
* The FX library has two functions for saving and loading game data:
|
|
*
|
|
* uint8_t FX::loadGameState(uint8_t* gameState, size_t size)
|
|
*
|
|
* void FX::saveGameState(uint8_t* gameState, size_t size)
|
|
*
|
|
* loadGameState
|
|
* -------------
|
|
*
|
|
* Loads previously saved game data. It returns 0 if there was no data to load
|
|
* or 1 if the data was successfully loaded.
|
|
*
|
|
* gameState is a pointer to an uint8_t array or to a structure in RAM containing
|
|
* your game data. When using a structure for the game data, the structure must be
|
|
* cast to an uint8_t array by putting (uint8_t*)& in front of the structures name.
|
|
*
|
|
* size is the size of the uint8_t array or structure in RAM and is usually
|
|
* determined by using the sizeof() operator.
|
|
*
|
|
* When there is no game data loaded (result 0), the contents of the gameState
|
|
* structure remains unchanged.
|
|
*
|
|
* saveGameState
|
|
* -------------
|
|
*
|
|
* Saves game data into a 4K flash block that is uniquely assigned to a program.
|
|
* On the first save, data is saved at the beginning of the block. Any save
|
|
* after that will be appended after previously saved data as a simple method to
|
|
* reduce flash wear. Once the new data doesn't fit into the 4K block, the block
|
|
* is erased and the new data is stored at the beginning of the block again.
|
|
* when an erase is necessary this function takes a bit longer to execute.
|
|
* This process is fully transparent and you do not need to worry about it.
|
|
* It just explains why sometimes this function may take a bit more time then usual.
|
|
*
|
|
* gameState and size are the same parameters as for the loadSaveData function.
|
|
*
|
|
* initilizing FX chip when using save capabilities
|
|
* ------------------------------------------------
|
|
*
|
|
* To let the FX library know your sketch makes use of save data the FX library
|
|
* must be initialized in setup with the following line:
|
|
*
|
|
* FX::begin(FX_DATA_PAGE, FX_SAVE_PAGE);
|
|
*
|
|
* The FX_DATA_PAGE, FX_SAVE_PAGE defines are defined in the fxdata.h file that
|
|
* will be created by the fxdata-build tool.
|
|
*
|
|
* creating a save data block
|
|
* --------------------------
|
|
*
|
|
* In order to use the loadGameState and saveGameState functions, a save section
|
|
* must be added to the fxdata.txt file located in the fxdata folder in your
|
|
* sketch folder. this save section can be added by typing the word 'savesection'
|
|
* (without the quotes)on a line at the end of the fxdata.txt file.
|
|
* Any data defined after that will be written into the default save data file.
|
|
|
|
* A minimum blank save data file can be generated by adding just two lines:
|
|
*
|
|
* savesection
|
|
* uint16_t 0xFFFF // No saved game state / end of game state
|
|
*
|
|
* Example of a predefined save data with 5 high scores:
|
|
*
|
|
* savesection
|
|
* uint16_t 30 //size of save data excluding length bytes
|
|
* uint16_t 50000 //high scores
|
|
* string "KVN"
|
|
* uint16_t 40000
|
|
* string "MRB"
|
|
* uint16_t 30000
|
|
* string "FLM"
|
|
* uint16_t 20000
|
|
* string "VMP"
|
|
* uint16_t 10000
|
|
* string "ADB"
|
|
* uint16_t 0xFFFF //end of save data / beginning of free space
|
|
* //not included in the save data length
|
|
*
|
|
* when there is a savesection in a fxdata.txt file, the fxbuild.by tool will
|
|
* generate 3 files:
|
|
*
|
|
* fxdata.bin this file is uploaded during development, when uploading
|
|
* a sketch through the Arduino IDE or using a emulator.
|
|
* It contains both the data and save sections.
|
|
*
|
|
* fxdata-data.bin contains only the data. This file is used when the sketch
|
|
* hexfile is made part of a flash image file.
|
|
* fxdata-save.bin contains only the save data. This file is used when the
|
|
* sketch hexfile is made part of a flash image file.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include <Arduboy2.h>
|
|
#include <ArduboyFX.h>
|
|
#include "fxdata/fxdata.h" //created by the fxdata-build.py python script.
|
|
|
|
Arduboy2 arduboy;
|
|
|
|
// First we create a structure that will contain all the relevant game data that
|
|
// needs to be saved.
|
|
|
|
struct GameState
|
|
{
|
|
char name[20]; // space for a text string
|
|
uint16_t count; // A counter that counts the number of times this sketch was
|
|
}; // run (and saved data)
|
|
|
|
GameState gameState; // This creates the actual gameState in ram.
|
|
|
|
void setup() {
|
|
arduboy.begin(); // initialize Arduboy.
|
|
|
|
FX::begin(FX_DATA_PAGE, FX_SAVE_PAGE); // Initialize FX chip. When using FX save data,
|
|
// FX_SAVE_PAGE must also be passed on in FX::begin.
|
|
|
|
if (!FX::loadGameState((uint8_t*) &gameState, sizeof(gameState))) // Load saveState from the 4K FX save data block. '(uint8_t*) &' is used
|
|
// here to cast a uint8_t pointer to the saveState structure.
|
|
{
|
|
// This code gets executed only when the function didn't load a saveState (function returned 0)
|
|
strcpy(gameState.name, "Hello World !!!"); // copy some introductory text to saveState.name
|
|
gameState.count = 1; // set count to 1 for 1st time this sketch is run.
|
|
}
|
|
else
|
|
{
|
|
// A previously saved gameState was loaded.
|
|
strcpy(gameState.name, "Save state loaded"); // change text
|
|
gameState.count ++; // increase the number of times this sketch was run.
|
|
}
|
|
|
|
FX::saveGameState((uint8_t*) &gameState, sizeof(gameState)); //Save the game state to 4K FX save block
|
|
|
|
arduboy.clear();
|
|
arduboy.setCursor(0,32 - 8);
|
|
arduboy.print(gameState.name);
|
|
arduboy.setCursor(0,32 + 8);
|
|
arduboy.print("Number of times this\nsketch is run: ");
|
|
arduboy.print(gameState.count);
|
|
FX::display();
|
|
}
|
|
|
|
void loop() {
|
|
|
|
if (!arduboy.nextFrame()) return; //waint for next frame
|
|
|
|
if (arduboy.buttonsState()) arduboy.exitToBootloader(); // exit to bootloader.
|
|
|
|
}
|