diff --git a/src/GameEngine.c b/src/GameEngine.c index dcf26ae..67a69c3 100644 --- a/src/GameEngine.c +++ b/src/GameEngine.c @@ -48,8 +48,7 @@ void GameEngine_Init(GameEngine *pGameEngine) for (level = 0; level < LevelCount; level++) { - // TODO: Load actual scores - pGameEngine->ScoresA[level] = 1; + pGameEngine->ScoresA[level] = 0; pGameEngine->ScoresB[level] = 0; } diff --git a/src/GameSave.c b/src/GameSave.c new file mode 100644 index 0000000..58ff5ba --- /dev/null +++ b/src/GameSave.c @@ -0,0 +1,80 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +/** + * @file GameSave.c + * + * This file provides implementations for GameSave.h. + */ + +#include "GameSave.h" +#include "MacCommon.h" + +/** The save resource type. */ +#define SaveResType 'SAVE' + +/** The save resource ID. */ +#define SaveResID 128 + +/** The save resource ID. */ +#define SaveResSize (sizeof(uint8_t) * SetCount * LevelCount) + +void GameSave_Init(GameSave *pGameSave) +{ + pGameSave->Save = GetOrAddResource(SaveResType, SaveResID, SaveResSize, EmptyString); + if (pGameSave->Save == nil) + { + ShowError("\pGame's SAVE resource couldn't be created!", true); + } +} + +void GameSave_LoadData(const GameSave *pSaveGame, GameEngine *pGameEngine) +{ + int8_t level, scoreA, scoreB; + bool resetA, resetB; + + HLock(pSaveGame->Save); + + resetA = false; + resetB = false; + + for (level = 0; level < LevelCount; level++) + { + scoreA = min(MaxHalfStars, (*pSaveGame->Save)[level]); + resetA = resetA || (scoreA < MinHalfStars); + pGameEngine->ScoresA[level] = resetA ? 0 : scoreA; + + scoreB = min(MaxHalfStars, (*pSaveGame->Save)[LevelCount + level]); + resetB = resetB || (scoreB < MinHalfStars); + pGameEngine->ScoresB[level] = resetB ? 0 : scoreB; + } + + HUnlock(pSaveGame->Save); +} + +void GameSave_SaveData(GameSave *pSaveGame, const GameEngine *pGameEngine) +{ + int8_t level; + bool dataChanged; + + HLock(pSaveGame->Save); + + dataChanged = false; + for (level = 0; level < LevelCount; level++) + { + dataChanged = dataChanged + || ((*pSaveGame->Save)[level] != pGameEngine->ScoresA[level]) + || ((*pSaveGame->Save)[LevelCount + level] != pGameEngine->ScoresB[level]); + + (*pSaveGame->Save)[level] = pGameEngine->ScoresA[level]; + (*pSaveGame->Save)[LevelCount + level] = pGameEngine->ScoresB[level]; + } + + HUnlock(pSaveGame->Save); + + if (dataChanged) + { + ChangedResource(pSaveGame->Save); + WriteResource(pSaveGame->Save); + } +} diff --git a/src/GameSave.h b/src/GameSave.h new file mode 100644 index 0000000..02c7c41 --- /dev/null +++ b/src/GameSave.h @@ -0,0 +1,41 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +/** + * @file GameSave.h + * + * This file provides a GameSave type which manages saving scores to disk. + */ + +#ifndef GAMESAVE_H +#define GAMESAVE_H + +#include "GameEngine.h" + +/** Struct containing handle to the save resource. */ +typedef struct sGameSave +{ + Handle Save; +} GameSave; + +/** + * Initializes the GameSave. + * @param pGameSave The GameSave. + */ +void GameSave_Init(GameSave *pSaveGame); + +/** + * Loads data from the GameSave into the GameEngine. + * @param pGameSave The GameSave. + * @param pGameEngine The GameEngine. + */ +void GameSave_LoadData(const GameSave *pSaveGame, GameEngine *pGameEngine); + +/** + * Saves data from the GameEngine into the GameSave. + * @param pGameSave The GameSave. + * @param pGameEngine The GameEngine. + */ +void GameSave_SaveData(GameSave *pSaveGame, const GameEngine *pGameEngine); + +#endif diff --git a/src/GameWindow.c b/src/GameWindow.c index 2b76bb7..3a89e94 100644 --- a/src/GameWindow.c +++ b/src/GameWindow.c @@ -34,6 +34,9 @@ void GameWindow_Init(GameWindow *pGameWindow) // Initialize game engine GameEngine_Init(&(pGameWindow->Engine)); + // Initialize game save + GameSave_Init(&(pGameWindow->GameSave)); + // Load PICT resources Bitmaps_Init(&(pGameWindow->Bitmaps)); @@ -44,6 +47,9 @@ void GameWindow_Init(GameWindow *pGameWindow) SetPort(pGameWindow->Window); FillRect(&(pGameWindow->Window->portRect), WindowPattern); + // Load data from saved game + GameSave_LoadData(&(pGameWindow->GameSave), &(pGameWindow->Engine)); + GameWindow_SetScene(pGameWindow, Title); } @@ -144,6 +150,7 @@ void GameWindow_ClearScores(GameWindow *pGameWindow) if (ShowConfirm("\pAre you sure you want to clear all scores?")) { GameEngine_ResetGame(&(pGameWindow->Engine)); + GameSave_SaveData(&(pGameWindow->GameSave), &(pGameWindow->Engine)); GameWindow_SetScene(pGameWindow, Title); } } diff --git a/src/GameWindow.h b/src/GameWindow.h index b0e616c..14d6376 100644 --- a/src/GameWindow.h +++ b/src/GameWindow.h @@ -17,6 +17,7 @@ #include "MacCommon.h" #include "WindowBuffer.h" #include "GameEngine.h" +#include "GameSave.h" #include "Bitmaps.h" #include "Sounds.h" #include "Scenes.h" @@ -30,6 +31,7 @@ typedef struct sGameWindow WindowPtr Window; WindowBuffer WindowBuffer; GameEngine Engine; + GameSave GameSave; Bitmaps Bitmaps; Sounds Sounds; SceneId CurrentSceneId; diff --git a/src/Levels.h b/src/Levels.h index 3c12f2f..75bae74 100644 --- a/src/Levels.h +++ b/src/Levels.h @@ -18,6 +18,9 @@ /** The number of levels in each set. */ #define LevelCount 50 +/** The number of sets. */ +#define SetCount 2 + /** * Gets the lights for a given set and level number. * @param level The level number. diff --git a/src/MacCommon.c b/src/MacCommon.c index 76fd6ea..ecf50fa 100644 --- a/src/MacCommon.c +++ b/src/MacCommon.c @@ -164,3 +164,28 @@ void DrawScaledPic(const PicHandle pic, const uint8_t scale) DrawPicture(pic, &destRect); MoveTo(destRect.right, destRect.top); } + +Handle GetOrAddResource(ResType resType, uint16_t resID, Size byteCount, Str255 resName) +{ + Handle result; + + result = GetResource(resType, resID); + + if (result != nil && GetHandleSize(result) != byteCount) + { + // Resource was the wrong size, delete it + RmveResource(result); + ReleaseResource(result); + result = nil; + } + + if (result == nil) + { + // Resource didn't exist, create it + result = NewHandleClear(byteCount); + HNoPurge(result); + AddResource(result, resType, resID, resName); + } + + return result; +} diff --git a/src/MacCommon.h b/src/MacCommon.h index 8d5751a..d178750 100644 --- a/src/MacCommon.h +++ b/src/MacCommon.h @@ -122,4 +122,14 @@ void GetScaledPicFrame(const PicHandle picHandle, const uint8_t scale, Rect *pDe */ void DrawScaledPic(const PicHandle pic, const uint8_t scale); +/** + * Gets the specified resource or creates it if it doesn't exist. + * @param resType The resource type. + * @param resID The resource ID. + * @param byteCount The size of the resource if it needs to be created. + * @param resName The resource name if it needs to be created. + * @return Handle to the resource. + */ +Handle GetOrAddResource(ResType resType, uint16_t resID, Size byteCount, Str255 resName); + #endif diff --git a/src/MacLO.c b/src/MacLO.c index ea9e324..e5dc074 100644 --- a/src/MacLO.c +++ b/src/MacLO.c @@ -313,5 +313,6 @@ void MacLO_Quit() if (ShowConfirm("\pAre you sure you want to quit MacLO?")) { gExitApp = true; + GameSave_SaveData(&(gGameWindow.GameSave), &(gGameWindow.Engine)); } } diff --git a/src/MacLO.pi.bin b/src/MacLO.pi.bin index c5f410f..4463d0e 100644 Binary files a/src/MacLO.pi.bin and b/src/MacLO.pi.bin differ diff --git a/src/MacLO.pi.rsrc.bin b/src/MacLO.pi.rsrc.bin index da1b709..9e8883e 100644 Binary files a/src/MacLO.pi.rsrc.bin and b/src/MacLO.pi.rsrc.bin differ diff --git a/src/PlayScene.c b/src/PlayScene.c index f376278..f268760 100644 --- a/src/PlayScene.c +++ b/src/PlayScene.c @@ -218,6 +218,7 @@ void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition) // Level was completed in the last click GameEngine_CompleteLevel(&(pGameWindow->Engine)); GameWindow_Draw(pGameWindow, false); + GameSave_SaveData(&(pGameWindow->GameSave), &(pGameWindow->Engine)); GameWindow_SetScene(pGameWindow, LevelEnd); Sounds_PlayDoneSnd(&(pGameWindow->Sounds)); } diff --git a/src/Sounds.c b/src/Sounds.c index ec6ea9f..de6fa40 100644 --- a/src/Sounds.c +++ b/src/Sounds.c @@ -10,10 +10,10 @@ #include "Sounds.h" /** The first snd resource ID. */ -#define SndBaseResId 8192 +#define SndBaseResID 8192 /** The click snd resource ID. */ -#define ClickSndResID SndBaseResId +#define ClickSndResID SndBaseResID /** The retry snd resource ID. */ #define RetrySndResID (ClickSndResID + 1) diff --git a/src/WindowBuffer.h b/src/WindowBuffer.h index a94ff5a..9530d29 100644 --- a/src/WindowBuffer.h +++ b/src/WindowBuffer.h @@ -38,4 +38,4 @@ void WindowBuffer_StartDraw(const WindowBuffer *pWindowBuffer); */ void WindowBuffer_EndDraw(const WindowBuffer *pWindowBuffer); -#endif \ No newline at end of file +#endif