// 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 , which the umbrella does not include. #include #include #include #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; }