joeylib2/examples/save/save.c

170 lines
4.7 KiB
C

// Save-file demo: a launch counter that persists across runs, plus a free-disk
// bar -- no text assets. On start it reads SAVES/runs.dat, increments the
// count, and writes it back; the 16-bit count shows as lit/unlit cells (MSB
// left) and a lamp reports whether the save succeeded. A bar underneath is
// scaled to jlDiskFree(). SPACE erases the save (count back to 0), ESC quits.
//
// Run it twice: the count comes back one higher each launch (on the IIgs the
// SAVES/ directory is prestaged on the disk image). Files are opt-in -- reached
// through <joey/file.h>, which the umbrella <joey/joey.h> does not include.
#include <stdio.h>
#include <joey/joey.h>
#include <joey/file.h>
#define CELL_W 16
#define CELL_H 36
#define CELL_GAP 3
#define BITS 16
#define BITS_ORIGIN_X 12
#define BITS_ORIGIN_Y 28
#define LAMP_X 12
#define LAMP_Y 84
#define LAMP_W 40
#define LAMP_H 20
#define BAR_X 12
#define BAR_Y 128
#define BAR_H 18
#define BAR_MAX_W 280
#define BAR_BYTES_PER_PX 4096u // 1 pixel per 4 KB free
#define COLOR_BACKGROUND 0
#define COLOR_BIT_OFF 1
#define COLOR_BIT_ON 2
#define COLOR_SAVE_OK 3
#define COLOR_SAVE_FAIL 4
#define COLOR_BAR_BG 5
#define COLOR_BAR_FILL 6
#define SAVE_NAME "runs.dat"
static void buildPalette(jlSurfaceT *screen);
static void drawBar(jlSurfaceT *screen, uint32_t freeBytes);
static void drawBits(jlSurfaceT *screen, uint16_t value);
static void drawLamp(jlSurfaceT *screen, bool ok);
static uint16_t loadCount(void);
static bool storeCount(uint16_t count);
static void buildPalette(jlSurfaceT *screen) {
uint16_t colors[SURFACE_COLORS_PER_PALETTE];
uint16_t i;
for (i = 0; i < SURFACE_COLORS_PER_PALETTE; i++) {
colors[i] = 0x0000;
}
colors[COLOR_BACKGROUND] = 0x0000; // black
colors[COLOR_BIT_OFF] = 0x0114; // dim blue
colors[COLOR_BIT_ON] = 0x00FF; // bright cyan
colors[COLOR_SAVE_OK] = 0x00F0; // green
colors[COLOR_SAVE_FAIL] = 0x0F00; // red
colors[COLOR_BAR_BG] = 0x0222; // gray
colors[COLOR_BAR_FILL] = 0x00FA; // teal
jlPaletteSet(screen, 0, colors);
}
static void drawBar(jlSurfaceT *screen, uint32_t freeBytes) {
uint32_t px;
jlFillRect(screen, BAR_X, BAR_Y, BAR_MAX_W, BAR_H, COLOR_BAR_BG);
px = freeBytes / BAR_BYTES_PER_PX;
if (px > (uint32_t)BAR_MAX_W) {
px = (uint32_t)BAR_MAX_W;
}
if (px > 0u) {
jlFillRect(screen, BAR_X, BAR_Y, (int16_t)px, BAR_H, COLOR_BAR_FILL);
}
}
static void drawBits(jlSurfaceT *screen, uint16_t value) {
int16_t i;
for (i = 0; i < BITS; i++) {
int16_t x = (int16_t)(BITS_ORIGIN_X + i * (CELL_W + CELL_GAP));
bool set = (value & (0x8000u >> i)) != 0u;
jlFillRect(screen, x, BITS_ORIGIN_Y, CELL_W, CELL_H, set ? COLOR_BIT_ON : COLOR_BIT_OFF);
}
}
static void drawLamp(jlSurfaceT *screen, bool ok) {
jlFillRect(screen, LAMP_X, LAMP_Y, LAMP_W, LAMP_H, ok ? COLOR_SAVE_OK : COLOR_SAVE_FAIL);
}
static uint16_t loadCount(void) {
uint16_t count;
count = 0u;
// A short read (missing file) leaves count at 0 -- first launch.
jlSaveRead(SAVE_NAME, &count, (uint32_t)sizeof(count));
return count;
}
static bool storeCount(uint16_t count) {
return jlSaveWrite(SAVE_NAME, &count, (uint32_t)sizeof(count));
}
int main(void) {
jlConfigT config;
jlSurfaceT *screen;
uint16_t count;
bool saved;
config.codegenBytes = 8 * 1024;
config.audioBytes = 64UL * 1024;
if (!jlInit(&config)) {
fprintf(stderr, "jlInit failed: %s\n", jlLastError());
return 1;
}
screen = jlStageGet();
if (screen == NULL) {
fprintf(stderr, "jlStageGet returned NULL\n");
jlShutdown();
return 1;
}
// Persist: read the prior count, bump it, write it back.
count = (uint16_t)(loadCount() + 1u);
saved = storeCount(count);
buildPalette(screen);
jlScbSetRange(screen, 0, SURFACE_HEIGHT - 1, 0);
jlSurfaceClear(screen, COLOR_BACKGROUND);
drawBits(screen, count);
drawLamp(screen, saved);
drawBar(screen, jlDiskFree());
jlStagePresent();
jlInputPoll();
for (;;) {
jlInputPoll();
if (jlKeyPressed(KEY_ESCAPE)) {
break;
}
if (jlKeyPressed(KEY_SPACE)) {
// Erase the save and reset the counter to zero.
jlSaveDelete(SAVE_NAME);
count = 0u;
saved = storeCount(count);
drawBits(screen, count);
drawLamp(screen, saved);
drawBar(screen, jlDiskFree());
jlStagePresent();
}
}
jlShutdown();
return 0;
}