joeylib2/examples/spacetaxi/assets/genSongData.py

76 lines
2.8 KiB
Python

#!/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 <stdint.h>
"""
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))