Merge pull request 'fix(tools): every sylpheed.db reader honours $SYLPHEED_DB, and none needs a retired checkout' (#41) from fix/sylpheed-db-contract into main
Some checks failed
CI / Native — linux (push) Has been cancelled
CI / WASM — Web (push) Has been cancelled
CI / Formatting (push) Has been cancelled

Reviewed-on: #41
This commit was merged in pull request #41.
This commit is contained in:
2026-09-16 18:55:32 +00:00
4 changed files with 66 additions and 13 deletions

View File

@@ -11,7 +11,10 @@ N="${1:?usage: grab_tutorial.sh <index 0..5> <outfile>}"
OUT="${2:?}"
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
SD="$(cd "$(dirname "$0")" && pwd)"
RC="/home/fabi/RE - Project Sylpheed/sylpheed-reborn/tools/re-capture"
# This script lives in the helpers' own directory. It used to hardcode the
# retired `sylpheed-reborn` checkout, whose `skip_intro.sh` still calls the
# removed `vgamepad` and exits 0 having pressed nothing.
RC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# The container entrypoint's Xvfb/openbox do NOT restart on their own, and a
# dead Xvfb leaves a <defunct> entry that still matches `pgrep` -- so test the

View File

@@ -5,7 +5,32 @@ Each write is `stw rX, off(r1)` (a two-word stack pair) followed by
`ld r9, off(r1)` and `std r9, N(r31)`, where slot = (N - 32) / 8.
"""
import duckdb, re, sys
con=duckdb.connect('/work/xenia-rs/sylpheed.db', read_only=True)
def _resolve_db():
"""`$SYLPHEED_DB`, else `$SYLPH_XEXDB`, else `<repo root>/sylpheed.db`.
`SYLPHEED_DB` is the documented contract -- `docker/decoder/sylph-decoder` sets
it and `docs/agents/CONTAINER-NOTES.md` lists it -- but no reader honoured it:
this script hardcoded `/work/xenia-rs/sylpheed.db`, a path that has not
existed anywhere since `/work` became a clone, so it failed on every machine.
"""
import os, pathlib
for var in ('SYLPHEED_DB', 'SYLPH_XEXDB'):
v = os.environ.get(var)
if v:
p = pathlib.Path(v).expanduser()
if not p.is_file():
sys.exit(f'${var} is set but is not a file: {p}')
return str(p)
p = pathlib.Path(__file__).resolve().parents[2] / 'sylpheed.db'
if p.is_file():
return str(p)
sys.exit(f'no database: set $SYLPHEED_DB, or build {p} with '
'sylph-xexdb dis <xex|iso> --db sylpheed.db --analyze sql --quiet')
con=duckdb.connect(_resolve_db(), read_only=True)
rows=con.execute("select address, coalesce(ext_disasm,disasm) from instructions "
"where address>=? and address<? order by address",
[0x822FE040,0x822FE618]).fetchall()

View File

@@ -15,14 +15,36 @@ Regenerates docs/re/data/name-block-bases.txt.
"""
import sys, os, glob, collections, bisect
DB = '/work/xenia-rs/sylpheed.db'
def _resolve_db():
"""`$SYLPHEED_DB`, else `$SYLPH_XEXDB`, else `<repo root>/sylpheed.db`.
`SYLPHEED_DB` is the documented contract -- `docker/decoder/sylph-decoder` sets
it and `docs/agents/CONTAINER-NOTES.md` lists it -- but no reader honoured it:
this script hardcoded `/work/xenia-rs/sylpheed.db`, a path that has not
existed anywhere since `/work` became a clone, so it failed on every machine.
"""
import os, pathlib
for var in ('SYLPHEED_DB', 'SYLPH_XEXDB'):
v = os.environ.get(var)
if v:
p = pathlib.Path(v).expanduser()
if not p.is_file():
sys.exit(f'${var} is set but is not a file: {p}')
return str(p)
p = pathlib.Path(__file__).resolve().parents[2] / 'sylpheed.db'
if p.is_file():
return str(p)
sys.exit(f'no database: set $SYLPHEED_DB, or build {p} with '
'sylph-xexdb dis <xex|iso> --db sylpheed.db --analyze sql --quiet')
MIN_GROUP = 8 # displacements needed before a group is worth solving
MIN_RESOLVED = 12 # report a function only if the base explains this many
LOW, HIGH = 0x82000000, 0x82400000
def main():
import duckdb
con = duckdb.connect(DB, read_only=True)
con = duckdb.connect(_resolve_db(), read_only=True)
S = set(a for (a,) in con.execute("SELECT address FROM strings").fetchall())
txt = dict(con.execute("SELECT address, content FROM strings").fetchall())
funcs = con.execute(

View File

@@ -39,7 +39,7 @@ Usage:
A command that needs a table the current DB predates prints what to regenerate
rather than a SQL error.
The database is found via `$SYLPH_XEXDB`, else `<repo root>/sylpheed.db`. It is a
The database is found via `$SYLPHEED_DB` (alias `$SYLPH_XEXDB`), else `<repo root>/sylpheed.db`. It is a
build artefact, not a tracked file; if neither exists, zq.py says so and prints
the command that builds one.
"""
@@ -53,7 +53,7 @@ REGEN = "sylph-xexdb dis <xex|iso> --db sylpheed.db --analyze sql"
def _resolve_db():
"""Locate the database: `$SYLPH_XEXDB`, else `<repo root>/sylpheed.db`.
"""Locate the database: `$SYLPHEED_DB` / `$SYLPH_XEXDB`, else `<repo root>/sylpheed.db`.
🔴 This used to be one hardcoded absolute path, and it pointed *inside*
`xenia-rs` -- a repository `docs/agents/CONSOLIDATION.md` archives in Phase 5
@@ -66,12 +66,15 @@ def _resolve_db():
one, say so and print how to build it. A default that silently resolves to
the wrong database is worse than no default -- see issue #16.
"""
env = os.environ.get('SYLPH_XEXDB')
if env:
p = pathlib.Path(env).expanduser()
if not p.is_file():
sys.exit(f'$SYLPH_XEXDB is set but is not a file:\n {p}')
return p
# `SYLPHEED_DB` is the documented contract (the decoder container sets it);
# `SYLPH_XEXDB` was this script's own name for it and stays as an alias.
for var in ('SYLPHEED_DB', 'SYLPH_XEXDB'):
env = os.environ.get(var)
if env:
p = pathlib.Path(env).expanduser()
if not p.is_file():
sys.exit(f'${var} is set but is not a file:\n {p}')
return p
# Relative to this script, not to the caller's cwd: `zq.py` is run from
# wherever the investigation happens to be.
p = pathlib.Path(__file__).resolve().parent.parent / 'sylpheed.db'
@@ -80,7 +83,7 @@ def _resolve_db():
sys.exit(
f'no database found.\n'
f' looked for: {p}\n'
f' set $SYLPH_XEXDB to an existing one, or build it with:\n'
f' set $SYLPHEED_DB to an existing one, or build it with:\n'
f' {REGEN}'
)