Arduboy-homemade-package/board-package-source/libraries/ArduboyFX/examples/loadGameState/loadGameState.ino

167 lines
6.8 KiB
Arduino
Raw Normal View History

/* *****************************************************************************
* FX gameState example v1.01 by Mr.Blinky Jan-Feb.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(Type gameState)
*
* void FX::saveGameState(Type gameState)
*
* 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 an object structure in RAM to where the game data will be loaded.
* If the size of the object in ram differes from the size of previously saved
* data, no data will be loaded.
*
* When 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 is an object structure in RAM which will be saved to external flash memory.
*
* 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(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(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.
}