joeylib2/tests/gate/keysCells.c

127 lines
4.4 KiB
C

// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// keysCells.c - read which of KEYS's named-key cells are lit off a
// screenshot.
//
// keysCells PNG [--at X,Y] [--scale S]
//
// KEYS (examples/keys) draws a cell for each named key, lit (colour 2,
// green) while jlKeyDown says it is down and dark grey (colour 1)
// otherwise. This reads the cells of its fourth row that a port gives a
// second physical key for -- Return, Ctrl, Alt, Up, Down, Left, and Right
// -- at the middle of each, and prints one digit a cell, in that order: 1
// lit, 0 not, ? neither colour.
//
// --at: where the stage's top left is in the screenshot (default 0,0).
// --scale: screen pixels a stage pixel (default 1). A point off the
// screenshot is fatal (exit 1); a bad command line exits 2.
#include <stdio.h>
#include <string.h>
#include "gateArg.h"
#include "gateImage.h"
#include "toolFile.h"
#define TOOL_NAME "keysCells"
// examples/keys: CELL_W x CELL_H cells GAP apart from (MARGIN_X,
// MARGIN_Y), the named keys in row 4 at these columns.
#define CELL_W 28
#define CELL_H 26
#define GAP 4
#define MARGIN_X 2
#define MARGIN_Y 2
#define ROW 4
#define COLUMN_COUNT 7u
// KEYS's colours 1 and 2, and how near a pixel must be: a 15- or 16-bit
// screen is off by at most 8 a gun.
#define UNLIT_INDEX 1u
#define LIT_INDEX 2u
#define MAX_DIST (3u * 9u * 9u)
// Return, Ctrl, Alt, Up, Down, Left, Right.
static const long kColumns[COLUMN_COUNT] = { 2, 3, 4, 5, 6, 7, 8 };
static const char *const kUsage[] = {
"keysCells - read which of KEYS's named-key cells are lit off a screenshot.",
"",
"KEYS (examples/keys) draws a cell for each named key, lit (colour 2, green)",
"while jlKeyDown says it is down and dark grey (colour 1) otherwise. This",
"reads the cells of its fourth row that a port gives a second physical key",
"for -- Return, Ctrl, Alt, Up, Down, Left, and Right -- at the middle of",
"each, and prints one digit a cell, in that order: 1 lit, 0 not, ? neither",
"colour.",
"",
" keysCells PNG [--at X,Y] [--scale S]",
"",
"--at: where the stage's top left is in the screenshot (default 0,0).",
"--scale: screen pixels a stage pixel (default 1)."
};
int main(int argc, char **argv) {
GateImageT img;
const char *png;
const uint8_t *pixel;
uint16_t words[GATE_KEYS_COLOURS];
uint8_t lit[GATE_RGB_BYTES];
uint8_t unlit[GATE_RGB_BYTES];
char digits[COLUMN_COUNT + 1u];
long atX;
long atY;
long scale;
long x;
long y;
uint32_t i;
int arg;
toolFileName(TOOL_NAME);
png = NULL;
atX = 0;
atY = 0;
scale = 1;
for (arg = 1; arg < argc; arg++) {
if (strcmp(argv[arg], "--at") == 0 && arg + 1 < argc) {
gateArgPair("at", argv[++arg], ',', &atX, &atY);
} else if (strcmp(argv[arg], "--scale") == 0 && arg + 1 < argc) {
scale = gateArgLong("scale", argv[++arg]);
if (scale < 1) {
gateArgBad("scale", argv[arg]);
}
} else if (argv[arg][0] == '-' || png != NULL) {
return gateUsage(kUsage, GATE_COUNT_OF(kUsage));
} else {
png = argv[arg];
}
}
if (png == NULL) {
return gateUsage(kUsage, GATE_COUNT_OF(kUsage));
}
gateImageLoad(png, &img);
gateKeysPalette(words);
gateRgb12(words[LIT_INDEX], lit);
gateRgb12(words[UNLIT_INDEX], unlit);
// Each cell's middle, on the screenshot.
y = atY + (MARGIN_Y + ROW * (CELL_H + GAP) + CELL_H / 2) * scale;
for (i = 0; i < COLUMN_COUNT; i++) {
x = atX + (MARGIN_X + kColumns[i] * (CELL_W + GAP) + CELL_W / 2) * scale;
if (!gateImageHas(&img, x, y)) {
toolFail("cell %u's middle, %ld,%ld, is off the %ux%u screenshot", (unsigned)i, x, y, (unsigned)img.width, (unsigned)img.height);
}
pixel = gateImagePixel(&img, (uint32_t)x, (uint32_t)y);
if (gateDistance(pixel, lit) <= MAX_DIST) {
digits[i] = '1';
} else if (gateDistance(pixel, unlit) <= MAX_DIST) {
digits[i] = '0';
} else {
digits[i] = '?';
}
}
digits[COLUMN_COUNT] = '\0';
printf("%s\n", digits);
gateImageFree(&img);
return 0;
}