124 lines
4.3 KiB
C
124 lines
4.3 KiB
C
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
// See LICENSE.md for license information.
|
|
// SPDX-License-Identifier: MIT
|
|
//
|
|
// Palette-change probe (PALPROBE, a gate's program, not an example): how
|
|
// fast palette and SCB changes reach the screen, and whether they reach it
|
|
// right.
|
|
//
|
|
// It times, over PROBE_FRAMES frames each, a palette change followed by a
|
|
// present, and an SCB change followed by a present, on a screen of four SCB
|
|
// bands, and logs the rates. Then it paints the bands (colour 1 of palettes
|
|
// 0..3 red, green, blue, white), makes one palette change (palette 2's
|
|
// colour 1 to yellow) and one SCB change that keeps every band where it was
|
|
// (band 3 to palette 0), logs "PALPROBE: ready" and holds the screen for
|
|
// HOLD_FRAMES frames, so a gate can look at it: top to bottom red, green,
|
|
// yellow, red. scripts/verify-amiga-palette.sh is that gate.
|
|
|
|
#include <string.h>
|
|
|
|
#include <joey/joey.h>
|
|
|
|
#define PROBE_FRAMES 200u
|
|
#define HOLD_FRAMES 400u
|
|
#define BANDS 4u
|
|
#define BAND_LINES 50u
|
|
#define PAINT_COLOR 1u
|
|
#define MS_PER_SECOND 1000ul
|
|
#define COLOR_MASK 0x0FFFu
|
|
#define PALETTE_MASK 3u
|
|
#define SCB_SWAP_FIRST 0u
|
|
#define SCB_SWAP_LAST (BAND_LINES - 1u)
|
|
#define YELLOW 0xFF0u
|
|
#define CHANGED_PALETTE 2u
|
|
#define MOVED_BAND 3u
|
|
#define MOVED_TO 0u
|
|
|
|
static void check(void);
|
|
static void timeChanges(const char *name, bool scb);
|
|
|
|
|
|
// Paint the bands, make the two changes, and hold the screen.
|
|
static void check(void) {
|
|
static const uint16_t firsts[BANDS] = { 0xF00, 0x0F0, 0x00F, 0xFFF };
|
|
uint16_t colors[JL_SURFACE_COLORS_PER_PALETTE];
|
|
jlSurfaceT *stage;
|
|
uint16_t band;
|
|
uint16_t frame;
|
|
|
|
stage = jlStageGet();
|
|
for (band = 0; band < BANDS; band++) {
|
|
memset(colors, 0, sizeof(colors));
|
|
colors[PAINT_COLOR] = firsts[band];
|
|
jlPaletteSet(stage, (uint8_t)band, colors);
|
|
jlScbSetRange(stage, (uint16_t)(band * BAND_LINES), (uint16_t)(band * BAND_LINES + BAND_LINES - 1u), (uint8_t)band);
|
|
jlFillRect(stage, 0, (int16_t)(band * BAND_LINES), JL_SURFACE_WIDTH, BAND_LINES, PAINT_COLOR);
|
|
}
|
|
jlStagePresent();
|
|
jlWaitVBL();
|
|
memset(colors, 0, sizeof(colors));
|
|
colors[PAINT_COLOR] = YELLOW;
|
|
jlPaletteSet(stage, CHANGED_PALETTE, colors);
|
|
jlStagePresent();
|
|
jlScbSetRange(stage, (uint16_t)(MOVED_BAND * BAND_LINES), (uint16_t)(MOVED_BAND * BAND_LINES + BAND_LINES - 1u), MOVED_TO);
|
|
jlStagePresent();
|
|
jlLogF("PALPROBE: ready");
|
|
for (frame = 0; frame < HOLD_FRAMES; frame++) {
|
|
jlWaitVBL();
|
|
}
|
|
}
|
|
|
|
|
|
// PROBE_FRAMES frames of palette changes (or SCB changes), each presented.
|
|
static void timeChanges(const char *name, bool scb) {
|
|
uint16_t colors[JL_SURFACE_COLORS_PER_PALETTE];
|
|
jlSurfaceT *stage;
|
|
uint16_t start;
|
|
uint32_t ms0;
|
|
uint32_t elapsed;
|
|
unsigned long count;
|
|
|
|
stage = jlStageGet();
|
|
memset(colors, 0, sizeof(colors));
|
|
count = 0;
|
|
jlWaitVBL();
|
|
start = jlFrameCount();
|
|
ms0 = jlMillisElapsed();
|
|
while ((uint16_t)(jlFrameCount() - start) < PROBE_FRAMES) {
|
|
if (scb) {
|
|
jlScbSetRange(stage, SCB_SWAP_FIRST, SCB_SWAP_LAST, (uint8_t)(count & PALETTE_MASK));
|
|
} else {
|
|
colors[PAINT_COLOR] = (uint16_t)(count & COLOR_MASK);
|
|
jlPaletteSet(stage, (uint8_t)(count & PALETTE_MASK), colors);
|
|
}
|
|
jlStagePresent();
|
|
count++;
|
|
}
|
|
elapsed = jlMillisElapsed() - ms0;
|
|
jlLogF("PALPROBE: %s: %lu in %lu ms = %lu/s", name, count, (unsigned long)elapsed, (unsigned long)(count * MS_PER_SECOND / elapsed));
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
jlConfigT cfg;
|
|
jlSurfaceT *stage;
|
|
uint16_t band;
|
|
|
|
cfg.codegenBytes = 0;
|
|
cfg.noAudio = true;
|
|
if (!jlInit(&cfg)) {
|
|
return 1;
|
|
}
|
|
stage = jlStageGet();
|
|
for (band = 0; band < BANDS; band++) {
|
|
jlScbSetRange(stage, (uint16_t)(band * BAND_LINES), (uint16_t)(band * BAND_LINES + BAND_LINES - 1u), (uint8_t)band);
|
|
jlFillRect(stage, 0, (int16_t)(band * BAND_LINES), JL_SURFACE_WIDTH, BAND_LINES, (uint8_t)(band + 1u));
|
|
}
|
|
jlStagePresent();
|
|
timeChanges("palette+present", false);
|
|
timeChanges("scb+present", true);
|
|
check();
|
|
jlLogF("PALPROBE: done");
|
|
jlShutdown();
|
|
return 0;
|
|
}
|