#!/usr/bin/env python3 # Bake examples/spacetaxi/assets/songs/song*.song into stSongData.h. # # python3 examples/spacetaxi/assets/genSongData.py # # The .song sources come from the game's own player run under a 6502 # emulator: assets/sidCapture.py logs every SID write per PAL frame and # assets/sidToSong.py turns that into songbake text. import os import subprocess import sys import tempfile here = os.path.dirname(os.path.abspath(__file__)) repo = os.path.abspath(os.path.join(here, "..", "..", "..")) songbake = os.path.join(repo, "tools", "songbake", "songbake.py") out = os.path.join(here, "..", "stSongData.h") count = 9 header = """// Space Taxi (C64) tunes as JoeyLib JYM1 streams. GENERATED by // assets/genSongData.py -- do not hand-edit. The songs were extracted by // running the game's own music player under a 6502 emulator // (assets/sidCapture.py logs every SID write per PAL frame; // assets/sidToSong.py turns that into songbake text in assets/songs/). // // Where the C64 plays them: // BLOCKING via $44CF (the game spins until the tune ends; the port // parks in ST_STATE_JINGLE with the sim frozen): // 0..3 start of every screen, rotating on $5E9B ($6906) // 4 level 25 start ($6935) and the bonus cab ($70B1) // 5 game over ($5C1F), after the two-second GAME OVER! wait // NON-BLOCKING via $CB02 (started and left to the IRQ player): // 6 the high-score name entry screen ($4E35) -- no port screen yet // 7 the high-score table ($4C1F, joystick UP on the title) // 8 the level intro while the cab flies in ($459C); endless, so // the source is trimmed to 30 s and looped #ifndef ST_SONG_DATA_H #define ST_SONG_DATA_H #include """ footer = """typedef struct { const uint8_t *data; uint16_t length; } StSongT; #define ST_SONG_COUNT %du #define ST_SONG_BONUS 4u #define ST_SONG_GAME_OVER 5u #define ST_SONG_NAME_ENTRY 6u #define ST_SONG_SCORES 7u #define ST_SONG_INTRO 8u static const StSongT kStSongs[ST_SONG_COUNT] = { %s}; #endif // ST_SONG_DATA_H """ parts = [] for n in range(count): src = os.path.join(here, "songs", "song%d.song" % n) with tempfile.NamedTemporaryFile(suffix=".h", delete=False) as tmp: path = tmp.name subprocess.run([sys.executable, songbake, "-c", "gStSong%d" % n, src, path], check=True, stderr=subprocess.DEVNULL) body = open(path).read() os.unlink(path) body = "\n".join(l for l in body.split("\n") if l.startswith("static") or l.startswith(" ") or l.startswith("}")) parts.append(body.rstrip() + "\n\n") table = "".join(" { gStSong%d, (uint16_t)sizeof(gStSong%d) },\n" % (n, n) for n in range(count)) with open(out, "w") as fp: fp.write(header + "".join(parts) + footer % (count, table)) print("wrote", os.path.normpath(out))