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:
@@ -1,6 +1,6 @@
|
||||
/* GAMELOG - a passive gameplay-event logger for Stern Spike 2.
|
||||
*
|
||||
* Logs, with millisecond timestamps, to /dump/mode.log:
|
||||
* Logs, with RFC 3339 UTC timestamps (millisecond precision), to /dump/mode.log:
|
||||
* EV <event name> - the game's bus events (game start, ball start/end,
|
||||
* bonus end, tilt warning, tilt), player, ball, score
|
||||
* SHOT <shot name> - every shot the game dispatches while a ball is up
|
||||
@@ -19,28 +19,11 @@
|
||||
|
||||
#include "pad_mode.h"
|
||||
|
||||
/* -nostdlib: the few libc symbols resolve from the game's own libc at load,
|
||||
* exactly as the runtime's and event_probe.c's do. */
|
||||
extern int clock_gettime(int, void *);
|
||||
|
||||
/* the runtime patch exposes the award screens it sees */
|
||||
/* the runtime patch exposes the award screens it sees and the wall clock */
|
||||
extern unsigned long gl_award_seq(void);
|
||||
extern unsigned gl_last_award_id(void);
|
||||
extern void gl_rfc3339(char *buf, unsigned cap);
|
||||
|
||||
#define CLOCK_MONOTONIC 1
|
||||
|
||||
struct ts {
|
||||
long sec, nsec;
|
||||
};
|
||||
|
||||
static unsigned long ms(void)
|
||||
{
|
||||
struct ts t;
|
||||
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||
return (unsigned long)t.sec * 1000ul + (unsigned long)t.nsec / 1000000ul;
|
||||
}
|
||||
|
||||
static unsigned long t0; /* ms at .init, so stamps start near 0 */
|
||||
static unsigned ball; /* ball in play, 1-based */
|
||||
static unsigned extras_pending; /* extra balls awarded, not yet played */
|
||||
static unsigned char in_game;
|
||||
@@ -57,22 +40,23 @@ static void score_str(char *out, unsigned cap, unsigned player)
|
||||
|
||||
static void scores_line(const char *tag)
|
||||
{
|
||||
char buf[128];
|
||||
char one[32];
|
||||
char tbuf[40], buf[128], one[32];
|
||||
unsigned p, n = 0;
|
||||
|
||||
gl_rfc3339(tbuf, sizeof tbuf);
|
||||
buf[0] = 0;
|
||||
for (p = 1; p <= 4; p++) {
|
||||
score_str(one, sizeof one, p);
|
||||
n += (unsigned)pm_snprintf(buf + n, sizeof buf - n, "%sP%u=%s",
|
||||
n ? " " : "", p, one);
|
||||
}
|
||||
pm_log("[GAMELOG] +%lums %s %s", ms() - t0, tag, buf);
|
||||
pm_log("[GAMELOG] %s %s %s", tbuf, tag, buf);
|
||||
}
|
||||
|
||||
static void on_init(void)
|
||||
{
|
||||
t0 = ms();
|
||||
char tbuf[40];
|
||||
|
||||
ball = 0;
|
||||
in_game = 0;
|
||||
extras_pending = 0;
|
||||
@@ -84,8 +68,9 @@ static void on_init(void)
|
||||
ev_bonus_end = pm_event("bonus_end");
|
||||
ev_tilt_warn = pm_event("tilt_warning");
|
||||
ev_tilt = pm_event("tilt");
|
||||
pm_log("[GAMELOG] up: game %s %s, %d named shots; event ids %d/%d/%d/%d/%d/%d; extra_ball_award=%u",
|
||||
pm_game(), pm_version(), pm_shot_count(),
|
||||
gl_rfc3339(tbuf, sizeof tbuf);
|
||||
pm_log("[GAMELOG] %s up: game %s %s, %d named shots; event ids %d/%d/%d/%d/%d/%d; extra_ball_award=%u",
|
||||
tbuf, pm_game(), pm_version(), pm_shot_count(),
|
||||
ev_game_start, ev_ball_start, ev_ball_end,
|
||||
ev_bonus_end, ev_tilt_warn, ev_tilt, extra_ball_award);
|
||||
}
|
||||
@@ -93,37 +78,38 @@ static void on_init(void)
|
||||
static void on_event(unsigned id)
|
||||
{
|
||||
const char *name = pm_event_name(id);
|
||||
char one[32];
|
||||
char tbuf[40], one[32];
|
||||
|
||||
gl_rfc3339(tbuf, sizeof tbuf);
|
||||
if (id == (unsigned)ev_game_start) {
|
||||
ball = 0;
|
||||
extras_pending = 0;
|
||||
in_game = 1;
|
||||
pm_log("[GAMELOG] +%lums EV %s - GAME START", ms() - t0,
|
||||
pm_log("[GAMELOG] %s EV %s - GAME START", tbuf,
|
||||
name ? name : "game_start");
|
||||
} else if (id == (unsigned)ev_ball_start) {
|
||||
score_str(one, sizeof one, pm_player());
|
||||
if (extras_pending) {
|
||||
extras_pending--;
|
||||
pm_log("[GAMELOG] +%lums EV %s player=%u ball=%u (EXTRA BALL) score=%s", ms() - t0,
|
||||
pm_log("[GAMELOG] %s EV %s player=%u ball=%u (EXTRA BALL) score=%s", tbuf,
|
||||
name ? name : "ball_start", pm_player(), ball, one);
|
||||
} else {
|
||||
ball++;
|
||||
pm_log("[GAMELOG] +%lums EV %s player=%u ball=%u score=%s", ms() - t0,
|
||||
pm_log("[GAMELOG] %s EV %s player=%u ball=%u score=%s", tbuf,
|
||||
name ? name : "ball_start", pm_player(), ball, one);
|
||||
}
|
||||
} else if (id == (unsigned)ev_ball_end) {
|
||||
score_str(one, sizeof one, pm_player());
|
||||
pm_log("[GAMELOG] +%lums EV %s player=%u ball=%u score=%s", ms() - t0,
|
||||
pm_log("[GAMELOG] %s EV %s player=%u ball=%u score=%s", tbuf,
|
||||
name ? name : "ball_end", pm_player(), ball, one);
|
||||
} else if (id == (unsigned)ev_bonus_end) {
|
||||
pm_log("[GAMELOG] +%lums EV %s", ms() - t0, name ? name : "bonus_end");
|
||||
pm_log("[GAMELOG] %s EV %s", tbuf, name ? name : "bonus_end");
|
||||
scores_line("SCORES");
|
||||
} else if (id == (unsigned)ev_tilt_warn) {
|
||||
pm_log("[GAMELOG] +%lums EV %s player=%u", ms() - t0,
|
||||
pm_log("[GAMELOG] %s EV %s player=%u", tbuf,
|
||||
name ? name : "tilt_warning", pm_player());
|
||||
} else if (id == (unsigned)ev_tilt) {
|
||||
pm_log("[GAMELOG] +%lums EV %s player=%u ball=%u", ms() - t0,
|
||||
pm_log("[GAMELOG] %s EV %s player=%u ball=%u", tbuf,
|
||||
name ? name : "tilt", pm_player(), ball);
|
||||
}
|
||||
}
|
||||
@@ -131,17 +117,18 @@ static void on_event(unsigned id)
|
||||
static void on_shot(unsigned long long shot)
|
||||
{
|
||||
const char *name;
|
||||
char one[32];
|
||||
char tbuf[40], one[32];
|
||||
|
||||
if (!in_game) /* attract-mode dispatches are noise */
|
||||
return;
|
||||
gl_rfc3339(tbuf, sizeof tbuf);
|
||||
name = pm_shot_name(shot);
|
||||
score_str(one, sizeof one, pm_player());
|
||||
if (name)
|
||||
pm_log("[GAMELOG] +%lums SHOT %s player=%u ball=%u score=%s", ms() - t0,
|
||||
pm_log("[GAMELOG] %s SHOT %s player=%u ball=%u score=%s", tbuf,
|
||||
name, pm_player(), ball, one);
|
||||
else
|
||||
pm_log("[GAMELOG] +%lums SHOT 0x%llx player=%u ball=%u score=%s", ms() - t0,
|
||||
pm_log("[GAMELOG] %s SHOT 0x%llx player=%u ball=%u score=%s", tbuf,
|
||||
shot, pm_player(), ball, one);
|
||||
}
|
||||
|
||||
@@ -149,15 +136,16 @@ static void on_tick(void)
|
||||
{
|
||||
/* award screens: the runtime hook counts them; log the new ones */
|
||||
while (award_seq_seen != gl_award_seq()) {
|
||||
char tbuf[40], one[32];
|
||||
award_seq_seen++;
|
||||
gl_rfc3339(tbuf, sizeof tbuf);
|
||||
if (gl_last_award_id() == extra_ball_award) {
|
||||
extras_pending++;
|
||||
pm_log("[GAMELOG] +%lums AWARD EXTRA BALL (id=%u) player=%u", ms() - t0,
|
||||
pm_log("[GAMELOG] %s AWARD EXTRA BALL (id=%u) player=%u", tbuf,
|
||||
gl_last_award_id(), pm_player());
|
||||
} else {
|
||||
char one[32];
|
||||
score_str(one, sizeof one, pm_player());
|
||||
pm_log("[GAMELOG] +%lums AWARD id=%u player=%u score=%s", ms() - t0,
|
||||
pm_log("[GAMELOG] %s AWARD id=%u player=%u score=%s", tbuf,
|
||||
gl_last_award_id(), pm_player(), one);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user