feat: RFC 3339 timestamps, quoted switch names, buttons-only switch log
All GAMELOG lines (EV/SHOT/SCORES/AWARD in mode.log, the runtime's MODE START/END and AWARD lines) and every switch.log line now carry the wall clock as RFC 3339 UTC with millisecond precision; the +Nms stamps relative to runtime load are gone (dur= on MODE END stays: it is a duration). The timestamp comes from a new gl_rfc3339() in the runtime: clock_gettime (CLOCK_REALTIME) plus the civil-from-days algorithm, no libc time calls. switch.log now logs only the human-activated buttons (34 lockdown, 36 start, 62/63 flippers) with quoted names. The upper-flipper button switches (64/65) fire in parallel with the main flipper buttons on this cabinet and are left out with every non-button switch. Deployed and verified on the machine: the boot banner reads 2026-10-13T01:39:39.640Z against the machine's own UTC clock. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
+56
-15
@@ -7936,20 +7936,50 @@ static unsigned long gl_award_n;
|
||||
unsigned long gl_award_seq(void) { return gl_award_n; }
|
||||
unsigned gl_last_award_id(void) { return gl_award_v; }
|
||||
|
||||
/* the wall clock as RFC 3339 UTC with milliseconds, e.g. 2026-10-12T20:45:12.123Z, into buf.
|
||||
* The date is the civil-from-days algorithm (Hinnant); no libc time calls beyond clock_gettime. */
|
||||
struct gl_ts { long sec, nsec; };
|
||||
extern int clock_gettime(int, void *);
|
||||
#define GL_CLOCK_REALTIME 0
|
||||
|
||||
void gl_rfc3339(char *buf, unsigned cap)
|
||||
{
|
||||
struct gl_ts t;
|
||||
long days, rem, era, doe, yoe, doy, mp, y, m, d;
|
||||
if (clock_gettime(GL_CLOCK_REALTIME, &t) != 0) {
|
||||
pm_snprintf(buf, cap, "0000-00-00T00:00:00.000Z");
|
||||
return;
|
||||
}
|
||||
days = t.sec / 86400;
|
||||
rem = t.sec % 86400;
|
||||
days += 719468; /* days since 1970-01-01 -> days since 0000-03-01 */
|
||||
era = (days >= 0 ? days : days - 146096) / 146097;
|
||||
doe = days - era * 146097; /* [0, 146096] */
|
||||
yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; /* [0, 399] */
|
||||
doy = doe - (365 * yoe + yoe / 4 - yoe / 100); /* [0, 365] */
|
||||
mp = (5 * doy + 2) / 153; /* [0, 11] */
|
||||
d = doy - (153 * mp + 2) / 5 + 1;
|
||||
m = mp + (mp < 10 ? 3 : -9);
|
||||
y = yoe + era * 400 + (m <= 2 ? 1 : 0);
|
||||
pm_snprintf(buf, cap, "%04ld-%02ld-%02ldT%02ld:%02ld:%02ld.%03ldZ",
|
||||
y, m, d, rem / 3600, (rem / 60) % 60, rem % 60, t.nsec / 1000000);
|
||||
}
|
||||
|
||||
static void gamelog_mode_log(const char *kind, unsigned id, unsigned player,
|
||||
unsigned long long score, unsigned long dur)
|
||||
{
|
||||
char key[24];
|
||||
char key[24], tbuf[40];
|
||||
const char *nm;
|
||||
pm_snprintf(key, sizeof key, "block_name_%u", id);
|
||||
nm = pm_port_text(key);
|
||||
gl_rfc3339(tbuf, sizeof tbuf);
|
||||
if (dur)
|
||||
say("gamelog: MODE %s %u (%s) player=%u score=%llu mode_score=%llu dur=%lums",
|
||||
kind, id, nm ? nm : "?", player, score,
|
||||
say("gamelog: %s MODE %s %u (%s) player=%u score=%llu mode_score=%llu dur=%lums",
|
||||
tbuf, kind, id, nm ? nm : "?", player, score,
|
||||
score > gl_start_score[id] ? score - gl_start_score[id] : 0, dur);
|
||||
else
|
||||
say("gamelog: MODE %s %u (%s) player=%u score=%llu",
|
||||
kind, id, nm ? nm : "?", player, score);
|
||||
say("gamelog: %s MODE %s %u (%s) player=%u score=%llu",
|
||||
tbuf, kind, id, nm ? nm : "?", player, score);
|
||||
}
|
||||
|
||||
static void gamelog_stock_tick(void)
|
||||
@@ -7985,9 +8015,12 @@ static void gamelog_stock_tick(void)
|
||||
/* the game's award screens (extra ball, special, replay...): logged, never refused */
|
||||
static void on_award_screen(unsigned *r)
|
||||
{
|
||||
char tbuf[40];
|
||||
gl_award_v = r[0];
|
||||
gl_award_n++;
|
||||
say("gamelog: AWARD id=%u player=%u score=%llu", r[0], pm_player(), pm_score(pm_player()));
|
||||
gl_rfc3339(tbuf, sizeof tbuf);
|
||||
say("gamelog: %s AWARD id=%u player=%u score=%llu", tbuf, r[0], pm_player(),
|
||||
pm_score(pm_player()));
|
||||
}
|
||||
|
||||
static void gamelog_arm(void)
|
||||
@@ -8632,20 +8665,28 @@ static void on_switch_edge(unsigned *r)
|
||||
mask = edge.mode_mask ? *(const unsigned short *)(unsigned long)edge.mode_mask : 0u;
|
||||
hit = edge_is_hit(level, flags, pol, edge.mode_mask != 0, mask);
|
||||
playing = pm_in_game(); /* attract, a tilt: no player up for a mode to score */
|
||||
/* GAMELOG: every edge to /dump/switch.log (buttons included, attract included) */
|
||||
/* GAMELOG: the buttons a human presses, to /dump/switch.log (34 lockdown, 36 start, 62/63 the
|
||||
* flipper buttons). The upper-flipper button switches (64/65) are wired in parallel with the
|
||||
* main flipper buttons on this cabinet, so they are left out with every non-button switch. */
|
||||
{
|
||||
static const unsigned gl_buttons[] = { 34, 36, 62, 63 };
|
||||
static const struct { unsigned id; const char *name; } gl_sw[] = {
|
||||
#include "switch_names.inc"
|
||||
};
|
||||
unsigned k;
|
||||
char nm[40] = "?", line[160];
|
||||
int fd, len;
|
||||
for (k = 0; k < sizeof gl_sw / sizeof gl_sw[0]; k++)
|
||||
if (gl_sw[k].id == id) { pm_snprintf(nm, sizeof nm, "%s", gl_sw[k].name); break; }
|
||||
len = pm_snprintf(line, sizeof line, "%lu SW %u %s level=%u hit=%d game=%d\n",
|
||||
pm_ms(), id, nm, level & 1u, hit, playing);
|
||||
fd = open("/dump/switch.log", O_WRONLY | O_CREAT | O_APPEND, 0644);
|
||||
if (fd >= 0) { write(fd, line, len); close(fd); }
|
||||
char tbuf[40], nm[40] = "?", line[160];
|
||||
int fd, len, want = 0;
|
||||
for (k = 0; k < sizeof gl_buttons / sizeof gl_buttons[0]; k++)
|
||||
if (gl_buttons[k] == id) { want = 1; break; }
|
||||
if (want) {
|
||||
for (k = 0; k < sizeof gl_sw / sizeof gl_sw[0]; k++)
|
||||
if (gl_sw[k].id == id) { pm_snprintf(nm, sizeof nm, "%s", gl_sw[k].name); break; }
|
||||
gl_rfc3339(tbuf, sizeof tbuf);
|
||||
len = pm_snprintf(line, sizeof line, "%s SW %u \"%s\" level=%u hit=%d game=%d\n",
|
||||
tbuf, id, nm, level & 1u, hit, playing);
|
||||
fd = open("/dump/switch.log", O_WRONLY | O_CREAT | O_APPEND, 0644);
|
||||
if (fd >= 0) { write(fd, line, len); close(fd); }
|
||||
}
|
||||
}
|
||||
if (edge_log_left > 0 && __sync_sub_and_fetch(&edge_log_left, 1) >= 0)
|
||||
say("edge: switch %u level %u (flags 0x%04x, polarity 0x%04x, mode mask 0x%04x, in game %d)%s", id, level & 1u,
|
||||
|
||||
Reference in New Issue
Block a user